Compare commits
2080 Commits
0.20.0
...
throw-erro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb7f7bb4d1 | ||
|
|
389e49183c | ||
|
|
4c1a5f84fa | ||
|
|
b0bb156918 | ||
|
|
5565204273 | ||
|
|
d950a0ef5d | ||
|
|
b2c0f7efc3 | ||
|
|
9e58bc19c4 | ||
|
|
0d7e2afba4 | ||
|
|
e0d063d306 | ||
|
|
ed0ad587dc | ||
|
|
56fe591eee | ||
|
|
7b9693bca4 | ||
|
|
fd0417b14c | ||
|
|
89c12f2585 | ||
|
|
5c71adb137 | ||
|
|
4c23062d1e | ||
|
|
190b45086c | ||
|
|
008983c8e3 | ||
|
|
cb8a375c5e | ||
|
|
848a60aa9b | ||
|
|
88ea794fdb | ||
|
|
870350fd61 | ||
|
|
1e25894f7e | ||
|
|
223e74569a | ||
|
|
0a4d793556 | ||
|
|
5503914abe | ||
|
|
906466d7fb | ||
|
|
e2532de766 | ||
|
|
3ac4390d11 | ||
|
|
389ae7a573 | ||
|
|
176247091d | ||
|
|
e22cc73f32 | ||
|
|
c23ad25899 | ||
|
|
9cc0418769 | ||
|
|
925a2c8e77 | ||
|
|
390734d86e | ||
|
|
218f7be1a7 | ||
|
|
246955b68a | ||
|
|
d24506baed | ||
|
|
b0be2237fa | ||
|
|
945394fb1a | ||
|
|
19886f71f5 | ||
|
|
23855c09dc | ||
|
|
618ab01cd7 | ||
|
|
349d90b60e | ||
|
|
9e7c2dcdbb | ||
|
|
f353589a53 | ||
|
|
fc97929dee | ||
|
|
3d77642a1e | ||
|
|
b55c1a35bf | ||
|
|
5df700a56e | ||
|
|
0c64a86ebe | ||
|
|
644ba46945 | ||
|
|
4ab54f284c | ||
|
|
210c2a8855 | ||
|
|
0ed4f1a9a4 | ||
|
|
7e648840a1 | ||
|
|
5e090778ae | ||
|
|
049ed114fd | ||
|
|
88007a08f2 | ||
|
|
6c4ed282bb | ||
|
|
c8765385df | ||
|
|
0ed22c0be0 | ||
|
|
3ffef4b9fb | ||
|
|
ceeebceb3a | ||
|
|
0338b26d5c | ||
|
|
6577cc0c8c | ||
|
|
586000ca3d | ||
|
|
abc81ebd08 | ||
|
|
cd6c73e487 | ||
|
|
69ad57338f | ||
|
|
cbcf31a4f9 | ||
|
|
b19beac5b4 | ||
|
|
dc6d088e30 | ||
|
|
b0ad27af23 | ||
|
|
5f23c6358a | ||
|
|
da776c935f | ||
|
|
0a315783ef | ||
|
|
65061b0514 | ||
|
|
063e5e359e | ||
|
|
f460afca35 | ||
|
|
66a08ace1d | ||
|
|
68e65e968a | ||
|
|
1ba0ab982b | ||
|
|
8752b8bb3f | ||
|
|
168f86ef89 | ||
|
|
85927853f9 | ||
|
|
57f60bf173 | ||
|
|
d16c3ed40a | ||
|
|
e90f4a2cbf | ||
|
|
d00839ec68 | ||
|
|
ea35d92493 | ||
|
|
beb9894c47 | ||
|
|
5556a996cd | ||
|
|
f7b1dcc271 | ||
|
|
eb226e1dcf | ||
|
|
8332ad0f16 | ||
|
|
06af5a004e | ||
|
|
ce32873ef8 | ||
|
|
99bc230fe6 | ||
|
|
0e3820b634 | ||
|
|
eba84dcd78 | ||
|
|
864f27ef72 | ||
|
|
a8b72d8342 | ||
|
|
15d2cfba90 | ||
|
|
2851d993ad | ||
|
|
3f1d88282e | ||
|
|
cc9ce916c6 | ||
|
|
c7d468578f | ||
|
|
e0f6988eb5 | ||
|
|
09ff370ddc | ||
|
|
32ecf30c82 | ||
|
|
a62adccd3d | ||
|
|
c75bf35f59 | ||
|
|
3013782b7b | ||
|
|
81abebd144 | ||
|
|
140b6c1227 | ||
|
|
ac685f65e9 | ||
|
|
f6b1cbd5d0 | ||
|
|
7db6e43e3f | ||
|
|
6c73614a47 | ||
|
|
b5c54b4e41 | ||
|
|
8f1c84e6d4 | ||
|
|
d1df4af734 | ||
|
|
23cd04fe88 | ||
|
|
dbc7c97e0b | ||
|
|
2313ca8f72 | ||
|
|
9418ba1687 | ||
|
|
233491940c | ||
|
|
7708e7ab08 | ||
|
|
600bd38630 | ||
|
|
f7290dfcb6 | ||
|
|
e22f7583eb | ||
|
|
c0e85f5687 | ||
|
|
3593f67eb6 | ||
|
|
1b251264a6 | ||
|
|
93c1a1d42e | ||
|
|
d7f6b6b018 | ||
|
|
fd99f20404 | ||
|
|
2b1e1b11a3 | ||
|
|
96ac7f9f35 | ||
|
|
33da64a669 | ||
|
|
38eb4ccbc4 | ||
|
|
a57414307e | ||
|
|
7ad111e2f6 | ||
|
|
a402128a7d | ||
|
|
d3ab4a5145 | ||
|
|
4ae77bcef9 | ||
|
|
e84416e56d | ||
|
|
59ccc9d73e | ||
|
|
1533a28817 | ||
|
|
7e4840867e | ||
|
|
f2f3f045e5 | ||
|
|
b12149bafd | ||
|
|
307c1b0b62 | ||
|
|
b201745988 | ||
|
|
352266481e | ||
|
|
c201ea53ba | ||
|
|
958867e92b | ||
|
|
b50de2f2ed | ||
|
|
ad37db4c82 | ||
|
|
c2d91c9544 | ||
|
|
6eedca6e7e | ||
|
|
0bd1d0bb05 | ||
|
|
1f359f5a13 | ||
|
|
fe53b5503c | ||
|
|
d66ef8fe22 | ||
|
|
6ff3a633f7 | ||
|
|
46891437e9 | ||
|
|
b729597728 | ||
|
|
f99d139025 | ||
|
|
b72b917af2 | ||
|
|
749869fdca | ||
|
|
e56a694878 | ||
|
|
8cb4d1dc28 | ||
|
|
68f1351507 | ||
|
|
66205286e4 | ||
|
|
32be373552 | ||
|
|
b1128c17f1 | ||
|
|
319bbd2f81 | ||
|
|
d8fb4f0a87 | ||
|
|
2e195575a6 | ||
|
|
28efeaa4f2 | ||
|
|
137534f901 | ||
|
|
c9594d46af | ||
|
|
1097648f0a | ||
|
|
17e6213448 | ||
|
|
2ea423032e | ||
|
|
2dead1a19b | ||
|
|
e18b10297b | ||
|
|
fd66084388 | ||
|
|
ca27e096f3 | ||
|
|
125997f45f | ||
|
|
da8a2c7bbb | ||
|
|
81ca205caa | ||
|
|
f06d5b973b | ||
|
|
fd890f9c0a | ||
|
|
835237382f | ||
|
|
7dd699370f | ||
|
|
ef8c7184de | ||
|
|
92026c1f98 | ||
|
|
9bd9dcc41c | ||
|
|
81b97ba52f | ||
|
|
ae36777d14 | ||
|
|
3d7ad82f3e | ||
|
|
059796c60d | ||
|
|
b0342b7449 | ||
|
|
b867dd82ca | ||
|
|
a122286d48 | ||
|
|
837db800bc | ||
|
|
44fe39821a | ||
|
|
fbc6b14424 | ||
|
|
9c00140464 | ||
|
|
00d8deda0e | ||
|
|
b84ce6a556 | ||
|
|
f5fb4c6c64 | ||
|
|
ac686fefe1 | ||
|
|
e690e166b0 | ||
|
|
6a02dd8842 | ||
|
|
66e2c01a3e | ||
|
|
7f2176d7fc | ||
|
|
4434889270 | ||
|
|
96afc1a45d | ||
|
|
dbe49610a1 | ||
|
|
62fadb54ee | ||
|
|
3832383936 | ||
|
|
595c3fb833 | ||
|
|
1d25c55c0b | ||
|
|
6376e78e0b | ||
|
|
1f08d2929c | ||
|
|
04953d97ad | ||
|
|
64fe4de3fb | ||
|
|
58008445e2 | ||
|
|
b7f0b054b8 | ||
|
|
3bbd709bd6 | ||
|
|
dbb1e3f5d8 | ||
|
|
8144308aee | ||
|
|
0503d2a9f3 | ||
|
|
fafd4d9396 | ||
|
|
3431a1b1de | ||
|
|
026ea52445 | ||
|
|
1e60b9a322 | ||
|
|
7450cb1f21 | ||
|
|
cdd5a9e935 | ||
|
|
c4cc50ca39 | ||
|
|
9b09d369d9 | ||
|
|
12ab11413f | ||
|
|
352f3640cf | ||
|
|
7940e91cbe | ||
|
|
577a2356a0 | ||
|
|
38ef0b10e7 | ||
|
|
c72d3c4a0e | ||
|
|
eb7e48b059 | ||
|
|
ab62fa1c4f | ||
|
|
a7cf1f6cca | ||
|
|
80d89f31fe | ||
|
|
a0f566fef3 | ||
|
|
c93d362dd4 | ||
|
|
db72f5d011 | ||
|
|
03704384a8 | ||
|
|
5b17ec0b56 | ||
|
|
d4acd03698 | ||
|
|
2ea986326d | ||
|
|
da53de2097 | ||
|
|
cf755dec22 | ||
|
|
d25e5e1849 | ||
|
|
593648780f | ||
|
|
bb04ff5942 | ||
|
|
12db276eb8 | ||
|
|
596fc3e908 | ||
|
|
9c54b94265 | ||
|
|
3c1cfce95a | ||
|
|
2f9f3142e2 | ||
|
|
92070e502c | ||
|
|
48b1154a71 | ||
|
|
bcdfb98454 | ||
|
|
f26c1f8095 | ||
|
|
790a24bdeb | ||
|
|
5d2b9392d5 | ||
|
|
6be242fc15 | ||
|
|
8158c5042b | ||
|
|
c70cdd88c7 | ||
|
|
bc6d6b6550 | ||
|
|
9584d8e16d | ||
|
|
4693c678d0 | ||
|
|
2c7d668f81 | ||
|
|
de2f963717 | ||
|
|
e83da76dc7 | ||
|
|
643730221d | ||
|
|
ab63f9ef31 | ||
|
|
dc870c4cc4 | ||
|
|
dd709dec18 | ||
|
|
cd5b71aedd | ||
|
|
d33cc025ee | ||
|
|
e7159f2803 | ||
|
|
56b8a18820 | ||
|
|
5832794034 | ||
|
|
a26b197687 | ||
|
|
12dba0955a | ||
|
|
7bd425bb3d | ||
|
|
845ad17a04 | ||
|
|
67e8fcaf93 | ||
|
|
aa07ee22cf | ||
|
|
3702e8c6fe | ||
|
|
21bd4edee4 | ||
|
|
31de39a7a4 | ||
|
|
d0fc2569ff | ||
|
|
4fd1631b30 | ||
|
|
0a1614a872 | ||
|
|
1f66d7ef74 | ||
|
|
84b6429ca6 | ||
|
|
212e5ebab5 | ||
|
|
a6106077bd | ||
|
|
fa4ce6b4e6 | ||
|
|
4130136718 | ||
|
|
c7c1b8d4f1 | ||
|
|
25b60a1b90 | ||
|
|
dda4dadfa3 | ||
|
|
570dbc7b47 | ||
|
|
6c122248f5 | ||
|
|
4a369bb3c0 | ||
|
|
95cf57e3bd | ||
|
|
0e6f7a4dc1 | ||
|
|
6f21834e71 | ||
|
|
cf6ad254fb | ||
|
|
fabbecf4c2 | ||
|
|
8262aa4138 | ||
|
|
95d86ebf22 | ||
|
|
6aa7db2358 | ||
|
|
5637c6e651 | ||
|
|
6f705b053a | ||
|
|
1f3f2788d4 | ||
|
|
ed3c202099 | ||
|
|
0396eec398 | ||
|
|
62dcec49e4 | ||
|
|
2f6afb5e86 | ||
|
|
a3a2b2aafb | ||
|
|
4900ce24fa | ||
|
|
135aaf56fd | ||
|
|
62d7abdd9e | ||
|
|
91b079f4df | ||
|
|
2c6cd74dc1 | ||
|
|
68ac18dc98 | ||
|
|
dbc74164ab | ||
|
|
76c7b2ee9c | ||
|
|
d6913c1eb9 | ||
|
|
9aa00b2f0a | ||
|
|
af02917766 | ||
|
|
d93a7b315d | ||
|
|
a813955ad3 | ||
|
|
1e3425fdee | ||
|
|
a2b326e306 | ||
|
|
0fa0e8e3f3 | ||
|
|
dbae7502e5 | ||
|
|
f47552c0c4 | ||
|
|
74836828c9 | ||
|
|
c152243b4d | ||
|
|
2a40c9a595 | ||
|
|
3cea493d49 | ||
|
|
6991d0851f | ||
|
|
fb2a331f79 | ||
|
|
c888524523 | ||
|
|
75c9dbaf6b | ||
|
|
c01a29fe76 | ||
|
|
80417281c4 | ||
|
|
f9b8bc006f | ||
|
|
2c22b0839f | ||
|
|
ec3e67e0d2 | ||
|
|
611e7e9dd8 | ||
|
|
f4e19ac05c | ||
|
|
70663af190 | ||
|
|
ed265cfdcd | ||
|
|
5b82370bc3 | ||
|
|
47690fffc1 | ||
|
|
aa09bbe23d | ||
|
|
a09fbad8b0 | ||
|
|
357ba2f4f6 | ||
|
|
b32dd746a6 | ||
|
|
b4ea1ccc23 | ||
|
|
2aecbfbb67 | ||
|
|
6d3b907307 | ||
|
|
55da1e3e92 | ||
|
|
f3aa0d6428 | ||
|
|
ad89be7523 | ||
|
|
49a7c16de5 | ||
|
|
e414476c6e | ||
|
|
391690d570 | ||
|
|
1be4af733b | ||
|
|
e3222d99ac | ||
|
|
5b19d33387 | ||
|
|
272c85c062 | ||
|
|
7101af764a | ||
|
|
e582d25654 | ||
|
|
9991c4507d | ||
|
|
37b3248202 | ||
|
|
0585131f78 | ||
|
|
7e351b21bc | ||
|
|
440549fcc5 | ||
|
|
f7b557eed1 | ||
|
|
bdfe317e20 | ||
|
|
19805b91d9 | ||
|
|
420c458b6a | ||
|
|
6de449811d | ||
|
|
081fd541af | ||
|
|
7dcd5035c0 | ||
|
|
0f1bb3fb3b | ||
|
|
78c447829a | ||
|
|
7f445f6167 | ||
|
|
bf599284ed | ||
|
|
a21c10e209 | ||
|
|
56ee44ee09 | ||
|
|
c6df54a103 | ||
|
|
575b039170 | ||
|
|
7a32269d7f | ||
|
|
004e371051 | ||
|
|
d5f43bae92 | ||
|
|
e215a20a0a | ||
|
|
919413e2b9 | ||
|
|
45839f8d59 | ||
|
|
55b62f9fde | ||
|
|
4c3529f3d5 | ||
|
|
ab7580c0da | ||
|
|
25c079fded | ||
|
|
d8bb75be63 | ||
|
|
a8021e09a7 | ||
|
|
16530ac6de | ||
|
|
5d1a1fef0f | ||
|
|
6082887070 | ||
|
|
8da336b7aa | ||
|
|
3da0287ede | ||
|
|
ea3331840d | ||
|
|
3fc0f72f3a | ||
|
|
ea3abe6069 | ||
|
|
897f871f99 | ||
|
|
2f335b3d2c | ||
|
|
3b1837a99b | ||
|
|
cc59de0c93 | ||
|
|
997d936e9c | ||
|
|
253256bf37 | ||
|
|
e60a1836fe | ||
|
|
e66b317f02 | ||
|
|
b417ea8e3a | ||
|
|
aa8758dec2 | ||
|
|
b58b0440d6 | ||
|
|
ad6b29c09f | ||
|
|
09a585c93b | ||
|
|
a9d2d2211a | ||
|
|
fe057c7873 | ||
|
|
dfcaed93ea | ||
|
|
5e3fcad1fb | ||
|
|
8e4959a621 | ||
|
|
555bb711c9 | ||
|
|
afa3eff313 | ||
|
|
9e91fd5241 | ||
|
|
d90d347006 | ||
|
|
385fe4be22 | ||
|
|
7ec88741a6 | ||
|
|
86cb68413d | ||
|
|
05c5d293eb | ||
|
|
fd0ac3a671 | ||
|
|
f109d812a1 | ||
|
|
5d2f2690e2 | ||
|
|
505a81d087 | ||
|
|
dfab62ce48 | ||
|
|
31699468fc | ||
|
|
857096ba5f | ||
|
|
36c7d4270b | ||
|
|
d77586d02d | ||
|
|
c8fbb74835 | ||
|
|
dfee375b98 | ||
|
|
9268258773 | ||
|
|
9031ca5c3f | ||
|
|
18d68184a9 | ||
|
|
3816f92095 | ||
|
|
fd55b08a1d | ||
|
|
d0d8ba0068 | ||
|
|
18197e7e3e | ||
|
|
f75a81c9ee | ||
|
|
9979a1b910 | ||
|
|
dbba9d7687 | ||
|
|
1e3f4ed398 | ||
|
|
d199b7264e | ||
|
|
b4c532f062 | ||
|
|
b24a89f820 | ||
|
|
7112f35793 | ||
|
|
7048193f00 | ||
|
|
17ae2648ed | ||
|
|
c952754c8c | ||
|
|
85ba04b715 | ||
|
|
8af202e86b | ||
|
|
57353fe0c6 | ||
|
|
6c116e34c4 | ||
|
|
9ff26ea4d4 | ||
|
|
2194bd2812 | ||
|
|
1e6cd0b18f | ||
|
|
85d178ff8b | ||
|
|
e0d09c3cda | ||
|
|
47f529dc09 | ||
|
|
dde850a2e9 | ||
|
|
34e1a465be | ||
|
|
7d756209b1 | ||
|
|
60e870b277 | ||
|
|
bf054dfda5 | ||
|
|
59654289cb | ||
|
|
cf13c11236 | ||
|
|
ddf1e84f7c | ||
|
|
ec183e3c9a | ||
|
|
01135db80a | ||
|
|
955e3de56d | ||
|
|
cdd473e195 | ||
|
|
34fe7f04fa | ||
|
|
55c280af5d | ||
|
|
ea5a4f6d6e | ||
|
|
d169f91d64 | ||
|
|
8b29895ef3 | ||
|
|
3cfc5c164d | ||
|
|
4e55d9937c | ||
|
|
03fe8d1716 | ||
|
|
d6d7d209c1 | ||
|
|
fa044a2971 | ||
|
|
72fce387db | ||
|
|
da10cdd5ab | ||
|
|
83de3a51ea | ||
|
|
8faf8b8e57 | ||
|
|
5a349ae88b | ||
|
|
8ec992a8a3 | ||
|
|
e2fc64296d | ||
|
|
ec55b905cb | ||
|
|
492d1144e0 | ||
|
|
4f4b19a962 | ||
|
|
febd785428 | ||
|
|
8642c66710 | ||
|
|
76cc8ac66b | ||
|
|
53d349a648 | ||
|
|
b344e1aadb | ||
|
|
3c882cff6e | ||
|
|
f73aef33f0 | ||
|
|
d12dff9dcf | ||
|
|
99d770be64 | ||
|
|
71a8867a4a | ||
|
|
2bbd424fce | ||
|
|
ef8dc7272b | ||
|
|
ad4a06fca5 | ||
|
|
c04f45d5e3 | ||
|
|
fb36155022 | ||
|
|
7ace3fc989 | ||
|
|
170e754998 | ||
|
|
6a75fa08dc | ||
|
|
1c5db46a4d | ||
|
|
7e4690e43c | ||
|
|
f8b29674b2 | ||
|
|
fe55141a7b | ||
|
|
9205ccc124 | ||
|
|
698a6f3886 | ||
|
|
1668e4187e | ||
|
|
00df3e2c40 | ||
|
|
a2578ac6b4 | ||
|
|
1fee636afa | ||
|
|
154bca4635 | ||
|
|
c584e31657 | ||
|
|
66340281e6 | ||
|
|
df599c0fc3 | ||
|
|
e98aeaf293 | ||
|
|
5026698ebf | ||
|
|
bd221b7b2c | ||
|
|
ba37259258 | ||
|
|
eca8d2e7d7 | ||
|
|
cb0f7bf6b0 | ||
|
|
1ec15dc073 | ||
|
|
f124e8cf93 | ||
|
|
9621175dc9 | ||
|
|
e6ddd6d6c1 | ||
|
|
d7ebd763f5 | ||
|
|
99091e919c | ||
|
|
6ddbccbc95 | ||
|
|
0ca333715b | ||
|
|
4e44a91d08 | ||
|
|
fc5f84a0cd | ||
|
|
2289f98c1e | ||
|
|
49edf0ee33 | ||
|
|
8532727d54 | ||
|
|
336653b02c | ||
|
|
d546f1870e | ||
|
|
15c66e2b01 | ||
|
|
be92bfd4af | ||
|
|
f5cb7ba96c | ||
|
|
f013a6b1d7 | ||
|
|
519c227c4f | ||
|
|
6f4665588f | ||
|
|
eba311baa9 | ||
|
|
e92b3779ad | ||
|
|
a82d21ff78 | ||
|
|
63e1165936 | ||
|
|
84cc732281 | ||
|
|
971b6ec96f | ||
|
|
46f7ca9ffa | ||
|
|
e85bc3e0f6 | ||
|
|
dee20f92a7 | ||
|
|
12b818a83c | ||
|
|
1c91110464 | ||
|
|
4cd7a3e83f | ||
|
|
fa99c9aa85 | ||
|
|
2d949834e9 | ||
|
|
c7b74aa8b4 | ||
|
|
5e3c9cf290 | ||
|
|
508f137b30 | ||
|
|
67dd2b419a | ||
|
|
0749baae4b | ||
|
|
df9f897ebe | ||
|
|
8ef1e81294 | ||
|
|
d755d05f88 | ||
|
|
ce4a52325b | ||
|
|
714a001332 | ||
|
|
c78f84d5c6 | ||
|
|
a6c9b263da | ||
|
|
5ad2fc64b4 | ||
|
|
2ae074a9a4 | ||
|
|
c5967ad572 | ||
|
|
5ece07a807 | ||
|
|
e00f9a869d | ||
|
|
662cf2f633 | ||
|
|
16f1a23c54 | ||
|
|
fb364b532c | ||
|
|
2bebf578c7 | ||
|
|
a5b9c83256 | ||
|
|
dc0e242a63 | ||
|
|
178e317d11 | ||
|
|
3aa740d877 | ||
|
|
951d7d8339 | ||
|
|
b5bd1f507e | ||
|
|
7b9368ae75 | ||
|
|
b2c3d9fb0a | ||
|
|
6bd48ca645 | ||
|
|
cdc007c83c | ||
|
|
7dbbe27cdd | ||
|
|
b91874355c | ||
|
|
8b0ed8b110 | ||
|
|
574e35a720 | ||
|
|
32ae38b933 | ||
|
|
56e505164d | ||
|
|
d4f3139b73 | ||
|
|
97dceb3a5a | ||
|
|
212f6d6bf5 | ||
|
|
36904fa72e | ||
|
|
8c2495a399 | ||
|
|
2d1f6128be | ||
|
|
9233f71549 | ||
|
|
b2a738cf13 | ||
|
|
34a79c5f1e | ||
|
|
fd30f5775a | ||
|
|
a2600acfa9 | ||
|
|
fa2c8f42b3 | ||
|
|
db4e36ad9b | ||
|
|
38697ade31 | ||
|
|
2cf3c7eb41 | ||
|
|
4ea932dc1f | ||
|
|
7b587d8e00 | ||
|
|
9612a4d0de | ||
|
|
7141a716e7 | ||
|
|
0d33566bbc | ||
|
|
2d341c53f2 | ||
|
|
b20443241d | ||
|
|
fb28431cdc | ||
|
|
2602df8ef7 | ||
|
|
9e7ff8f8f5 | ||
|
|
5b5473e794 | ||
|
|
73c000fd44 | ||
|
|
ef51661f5d | ||
|
|
6bb9e8442a | ||
|
|
9b1721f8ad | ||
|
|
15532fdb11 | ||
|
|
39e0b3f6c5 | ||
|
|
329bf7895e | ||
|
|
61feb5a851 | ||
|
|
da06560fa9 | ||
|
|
fd120ab275 | ||
|
|
14a57fd229 | ||
|
|
0be2ab582d | ||
|
|
d00037d1d4 | ||
|
|
e10827bf1c | ||
|
|
98a5a7cb4f | ||
|
|
748282cff3 | ||
|
|
f3df1e8d3c | ||
|
|
a93058d385 | ||
|
|
89135a9cf5 | ||
|
|
47a02e3423 | ||
|
|
c9fd8167f5 | ||
|
|
c9b9ded518 | ||
|
|
250a9191cb | ||
|
|
6fab5d0554 | ||
|
|
461fae4f77 | ||
|
|
8aed1e11c3 | ||
|
|
6cf6c56dd1 | ||
|
|
042ff8da64 | ||
|
|
8b72481b8c | ||
|
|
aa0724f204 | ||
|
|
eff8b23f57 | ||
|
|
81a2300af8 | ||
|
|
2a541cb4d5 | ||
|
|
0120f44fd6 | ||
|
|
b65dced646 | ||
|
|
e7394fe7a1 | ||
|
|
fb673639f9 | ||
|
|
dc62b6ffdb | ||
|
|
1f2ccac8a0 | ||
|
|
46e4d35ccd | ||
|
|
eb7e79fdf7 | ||
|
|
37c953e633 | ||
|
|
5bb2cb7d71 | ||
|
|
692f4e5be2 | ||
|
|
7bb1471207 | ||
|
|
4752e16ad2 | ||
|
|
2a156e7313 | ||
|
|
0314dd44ea | ||
|
|
b80a3d5401 | ||
|
|
8c4ef9f955 | ||
|
|
67d2635e41 | ||
|
|
71a1ad307c | ||
|
|
9a48fd81a3 | ||
|
|
d928b9eaad | ||
|
|
790b7afcca | ||
|
|
7b9f5d74dc | ||
|
|
6eadba784d | ||
|
|
3a39045617 | ||
|
|
67cb8b7107 | ||
|
|
4962c00ba8 | ||
|
|
6764185543 | ||
|
|
0a66a68db8 | ||
|
|
8d47ec714e | ||
|
|
9607fe03af | ||
|
|
62057e676a | ||
|
|
43ff3be751 | ||
|
|
7cbd79fee5 | ||
|
|
3fba342ed2 | ||
|
|
2419c4d8ae | ||
|
|
e37fb09d41 | ||
|
|
86b1357a68 | ||
|
|
b782ab5787 | ||
|
|
6c0486646f | ||
|
|
dffe8fc49e | ||
|
|
1336ecbef2 | ||
|
|
d00e430f50 | ||
|
|
5a728243a2 | ||
|
|
37f38dbf6c | ||
|
|
2eb7c5c037 | ||
|
|
ba0bc72d0b | ||
|
|
e1219cbdef | ||
|
|
bf0a48847c | ||
|
|
3bb7fbb2f1 | ||
|
|
326a362eb8 | ||
|
|
fdc380e7f7 | ||
|
|
db04f1556e | ||
|
|
444b1c99d0 | ||
|
|
3b1a286290 | ||
|
|
6c8a5a1e7f | ||
|
|
1769b0fdce | ||
|
|
68cbc11810 | ||
|
|
edcc155482 | ||
|
|
8231216371 | ||
|
|
e1215584b4 | ||
|
|
a905175e8c | ||
|
|
e98ed41656 | ||
|
|
fd139841f4 | ||
|
|
dac0f42777 | ||
|
|
f0788162a4 | ||
|
|
c963e50cde | ||
|
|
b4a4767fb3 | ||
|
|
d6918b2976 | ||
|
|
47e273c402 | ||
|
|
ba25e8e720 | ||
|
|
058ae5cc29 | ||
|
|
f8be5d2559 | ||
|
|
792d25594c | ||
|
|
9f9020e422 | ||
|
|
302fecbdcb | ||
|
|
d74873fed1 | ||
|
|
40ed4a0506 | ||
|
|
c25d664edc | ||
|
|
9bad7e2940 | ||
|
|
6704ce3214 | ||
|
|
914cfbd953 | ||
|
|
85cf27119c | ||
|
|
7691f53520 | ||
|
|
094f835642 | ||
|
|
92eea3b18b | ||
|
|
c021b93b5c | ||
|
|
d94d4c2045 | ||
|
|
46d08237c6 | ||
|
|
3deafe9f8d | ||
|
|
998edba6f0 | ||
|
|
4f219362fe | ||
|
|
c427444946 | ||
|
|
d59323a601 | ||
|
|
a779cdd463 | ||
|
|
73a142fd9b | ||
|
|
0453d08eed | ||
|
|
a18068aedf | ||
|
|
12fba3bb7a | ||
|
|
fc2b9031d4 | ||
|
|
28a6589a1e | ||
|
|
cf9c790499 | ||
|
|
3d6dceae10 | ||
|
|
130a14d0d9 | ||
|
|
f07b4f8fc4 | ||
|
|
75f655aafc | ||
|
|
a3fd9ccea7 | ||
|
|
4136ac633a | ||
|
|
2724456882 | ||
|
|
b396a2cbfd | ||
|
|
ddb06b0cac | ||
|
|
f54e247eb4 | ||
|
|
2ac19eb8fc | ||
|
|
6cdaafdc37 | ||
|
|
ed6476b5ea | ||
|
|
b90bceb2dc | ||
|
|
f31bd5ffb9 | ||
|
|
5abe7fe123 | ||
|
|
b6792cf02e | ||
|
|
1261323c66 | ||
|
|
2a45b4eba0 | ||
|
|
a6a0bbf398 | ||
|
|
7f3ef12297 | ||
|
|
da2f592de6 | ||
|
|
ee91effb7a | ||
|
|
b13f9c25b3 | ||
|
|
f85563eb66 | ||
|
|
7b689a186d | ||
|
|
092d7df761 | ||
|
|
6c444707d7 | ||
|
|
81c006cc04 | ||
|
|
7cbd1e413f | ||
|
|
f34f8ef188 | ||
|
|
c3eb385cd3 | ||
|
|
be34f03157 | ||
|
|
4964785b13 | ||
|
|
1b7757c14f | ||
|
|
58c9f20226 | ||
|
|
f19be0c3ce | ||
|
|
f236a6872b | ||
|
|
3e0096f360 | ||
|
|
438b334320 | ||
|
|
4aa96ecab9 | ||
|
|
e5557b515e | ||
|
|
7b9d26d688 | ||
|
|
8d4b4cd14c | ||
|
|
342fc202a7 | ||
|
|
4436359d07 | ||
|
|
91f8395222 | ||
|
|
de00e86cd5 | ||
|
|
c6e086c6ff | ||
|
|
82f3eda82b | ||
|
|
05f9613e14 | ||
|
|
50bb591826 | ||
|
|
2ca23c714d | ||
|
|
b030d822f1 | ||
|
|
65b5183f01 | ||
|
|
33431844b7 | ||
|
|
325a67155d | ||
|
|
6876f88f43 | ||
|
|
ad9d3f4425 | ||
|
|
5eca7a8a30 | ||
|
|
de153ece4e | ||
|
|
2d8964d37d | ||
|
|
ceb1feb350 | ||
|
|
2ea0590b03 | ||
|
|
80a513baa5 | ||
|
|
ba48f68fc3 | ||
|
|
319587e2f1 | ||
|
|
bf7952d9c7 | ||
|
|
f29ab53aff | ||
|
|
b5b0c58de7 | ||
|
|
a1bb421eec | ||
|
|
139786b9ef | ||
|
|
301444563b | ||
|
|
9966c21c6b | ||
|
|
12c219ee6c | ||
|
|
008f79df61 | ||
|
|
fd54cf2d05 | ||
|
|
e0d26f4055 | ||
|
|
6c2170960b | ||
|
|
950deaca40 | ||
|
|
2bd286f195 | ||
|
|
75792bfa7b | ||
|
|
737c49b689 | ||
|
|
2c447a42f2 | ||
|
|
dad8f9a0ce | ||
|
|
2eac23a0b3 | ||
|
|
6a204753c0 | ||
|
|
19bb26a789 | ||
|
|
00904ae3f2 | ||
|
|
d214a0b333 | ||
|
|
4940759627 | ||
|
|
be1a390b50 | ||
|
|
f707f990e6 | ||
|
|
a120f143d7 | ||
|
|
65fbdbff6a | ||
|
|
6ec4dcfafd | ||
|
|
48191aca6e | ||
|
|
83556bace2 | ||
|
|
814c9e6c3a | ||
|
|
547abe17d9 | ||
|
|
6b8450558d | ||
|
|
c3747c2d49 | ||
|
|
245122104a | ||
|
|
b0f127d4d8 | ||
|
|
d379a36c0e | ||
|
|
a12571e748 | ||
|
|
21879da80d | ||
|
|
6cabc96f75 | ||
|
|
f4f9e75c27 | ||
|
|
2f235adadf | ||
|
|
afb284fa9b | ||
|
|
93252f33ff | ||
|
|
6cf0ff6b49 | ||
|
|
86f75758a7 | ||
|
|
0ec94405ce | ||
|
|
33780f1995 | ||
|
|
1cb715ac9f | ||
|
|
f65b628bf3 | ||
|
|
60fa552469 | ||
|
|
437bdedb07 | ||
|
|
a531f4f057 | ||
|
|
bb396a310e | ||
|
|
66e7285108 | ||
|
|
2b81a82620 | ||
|
|
b555df8377 | ||
|
|
232730e909 | ||
|
|
2c1b4b0dd8 | ||
|
|
1e0712625a | ||
|
|
88752f32bd | ||
|
|
7a93d4c7e4 | ||
|
|
c3c767eed8 | ||
|
|
6f19a3a21e | ||
|
|
06be0fb351 | ||
|
|
e2bbc9a6fa | ||
|
|
17e481c107 | ||
|
|
b8f27a42a7 | ||
|
|
575c66efd3 | ||
|
|
88ad7c8d8d | ||
|
|
1adcac175e | ||
|
|
dd8c412abc | ||
|
|
e969c1490a | ||
|
|
e91421253e | ||
|
|
35d15c7c2b | ||
|
|
20cb751ff6 | ||
|
|
0614b52f03 | ||
|
|
a629521c37 | ||
|
|
5eb83bb39c | ||
|
|
0e17d026f2 | ||
|
|
ea0b1fdf44 | ||
|
|
1d78d67af3 | ||
|
|
d9c58c4837 | ||
|
|
129779a757 | ||
|
|
c8a985cc77 | ||
|
|
db7e7aae46 | ||
|
|
cb9b84f940 | ||
|
|
33d9be0ffb | ||
|
|
2571e420f3 | ||
|
|
e17c8b1f4d | ||
|
|
8805ee7c8c | ||
|
|
7df2fd0bc8 | ||
|
|
f7f0910953 | ||
|
|
d300797e22 | ||
|
|
56dbe15943 | ||
|
|
736d63c08f | ||
|
|
5f65e92500 | ||
|
|
a65b9b2b53 | ||
|
|
cc10e8ca5d | ||
|
|
dfe0c738d6 | ||
|
|
21b96a3159 | ||
|
|
888c7e2c29 | ||
|
|
d6eaeef8a6 | ||
|
|
961c5740b7 | ||
|
|
22e8f7e287 | ||
|
|
c26b383a1b | ||
|
|
2cec1fe4bb | ||
|
|
9da1c6c6de | ||
|
|
806ddf1aca | ||
|
|
0ad2793b68 | ||
|
|
585e4617e8 | ||
|
|
76c6886791 | ||
|
|
91bc6599c6 | ||
|
|
4d44b2c3a4 | ||
|
|
b49b5fbda9 | ||
|
|
17e6093abb | ||
|
|
3dc980e800 | ||
|
|
c44c1003af | ||
|
|
39c27f0c66 | ||
|
|
678b10dbcf | ||
|
|
a1d6411f1f | ||
|
|
c4c8a10507 | ||
|
|
ee94ccdeb0 | ||
|
|
e3df9f9ead | ||
|
|
62dc629337 | ||
|
|
dccdf38ce7 | ||
|
|
84124b837d | ||
|
|
6176da3cbb | ||
|
|
24bc3e2704 | ||
|
|
f13fb80b42 | ||
|
|
0a9e19646a | ||
|
|
65e45c4079 | ||
|
|
440105976f | ||
|
|
7eba7fbcc7 | ||
|
|
d9bfb3d305 | ||
|
|
4246c7a523 | ||
|
|
e3054ccdd2 | ||
|
|
df968d1919 | ||
|
|
7661c3c061 | ||
|
|
57ed047025 | ||
|
|
bda3a26423 | ||
|
|
080d9a8dc7 | ||
|
|
984a4acc7b | ||
|
|
b10f37bea9 | ||
|
|
0947c26612 | ||
|
|
f5e7fe34a5 | ||
|
|
c6f088d6ca | ||
|
|
21e29411af | ||
|
|
f85930700b | ||
|
|
707ef1d0f7 | ||
|
|
adc12addfa | ||
|
|
bfef9d4b6e | ||
|
|
fd29cb9023 | ||
|
|
d806310665 | ||
|
|
4982bff74d | ||
|
|
347c189f3f | ||
|
|
81b12b8001 | ||
|
|
3e781b7d13 | ||
|
|
9c44e41a4c | ||
|
|
402bb01151 | ||
|
|
82a1d9dffa | ||
|
|
570541ba49 | ||
|
|
73eabb6ca2 | ||
|
|
5a52b4fe45 | ||
|
|
caa08a6379 | ||
|
|
cd02078e26 | ||
|
|
0341faeb13 | ||
|
|
77131cff91 | ||
|
|
0c7726d4e1 | ||
|
|
1f1e14fba5 | ||
|
|
9be8263f26 | ||
|
|
7b2aa5f98e | ||
|
|
26b28cea49 | ||
|
|
23049e026f | ||
|
|
9ab242ca2e | ||
|
|
aa59925374 | ||
|
|
43ea8fa706 | ||
|
|
6df85718e6 | ||
|
|
82e6f6e095 | ||
|
|
9ba3e1cdb4 | ||
|
|
b20f72b963 | ||
|
|
092b8a4e52 | ||
|
|
e5f07dedbf | ||
|
|
ca9eb0d539 | ||
|
|
142317c2be | ||
|
|
3dea670091 | ||
|
|
8435e79913 | ||
|
|
30e85b40f9 | ||
|
|
be1a43a337 | ||
|
|
abca8f7a7c | ||
|
|
7b60dac526 | ||
|
|
ea6434662d | ||
|
|
0b7a108a59 | ||
|
|
57c63f3598 | ||
|
|
ae30f32c36 | ||
|
|
a50f64f6e9 | ||
|
|
1323b94b7a | ||
|
|
6d68fbc31d | ||
|
|
d97e128dc0 | ||
|
|
86ca568d6d | ||
|
|
92b04a30f3 | ||
|
|
2b0bb69a4f | ||
|
|
67b01506c9 | ||
|
|
b20b802a8d | ||
|
|
87f46a7532 | ||
|
|
45a1407144 | ||
|
|
4a0359c04e | ||
|
|
4e629ca858 | ||
|
|
c32cae00d5 | ||
|
|
02431b3f98 | ||
|
|
0323202a03 | ||
|
|
b6670a7e3d | ||
|
|
62c1991b88 | ||
|
|
3a6085ad31 | ||
|
|
6e1b62aedf | ||
|
|
2451497b31 | ||
|
|
6699c80357 | ||
|
|
1af1474d04 | ||
|
|
06a1d2ac41 | ||
|
|
f47b588b91 | ||
|
|
262131f68e | ||
|
|
ceae48088e | ||
|
|
e655af251c | ||
|
|
3351ad8197 | ||
|
|
5054510d15 | ||
|
|
947fe4fbb3 | ||
|
|
50c8afb525 | ||
|
|
a539de4f97 | ||
|
|
8d5a867271 | ||
|
|
6a1954f8f7 | ||
|
|
0044178d49 | ||
|
|
387bddb51b | ||
|
|
41ba19b615 | ||
|
|
0e37e42abd | ||
|
|
a28945273d | ||
|
|
fd6f03655e | ||
|
|
8b62c05fe2 | ||
|
|
0e92a63d14 | ||
|
|
a4ff0b62ce | ||
|
|
dd141daefd | ||
|
|
a1001ada47 | ||
|
|
f938aa530e | ||
|
|
8d419da277 | ||
|
|
8e3ff79f22 | ||
|
|
d0c12caae9 | ||
|
|
17a99a524b | ||
|
|
41a757c3be | ||
|
|
61fc6539c2 | ||
|
|
99f04012a7 | ||
|
|
891116f13b | ||
|
|
4fcd0964cd | ||
|
|
5005212bec | ||
|
|
a279d6f433 | ||
|
|
5c74196f60 | ||
|
|
33724d40a8 | ||
|
|
d78e5281fe | ||
|
|
fceb8093f1 | ||
|
|
d984a898d4 | ||
|
|
52688106e4 | ||
|
|
66b45a8fe2 | ||
|
|
0db23f9252 | ||
|
|
23b2abc273 | ||
|
|
0350d0784a | ||
|
|
83219a499c | ||
|
|
3f4d5bc85c | ||
|
|
83b790950c | ||
|
|
16b10ec3d7 | ||
|
|
1d4dd4484d | ||
|
|
8bd2669d3d | ||
|
|
b5d2eb5c70 | ||
|
|
25362f16a0 | ||
|
|
39b34eece8 | ||
|
|
b3426fdc94 | ||
|
|
6aa65593ef | ||
|
|
66becbf46f | ||
|
|
cbf3d75087 | ||
|
|
0b0036813f | ||
|
|
c06a20e085 | ||
|
|
c60fccd7f6 | ||
|
|
46f8b04e40 | ||
|
|
12b46bbd41 | ||
|
|
f2b69fd812 | ||
|
|
0aae728e33 | ||
|
|
cea38de4ad | ||
|
|
3e4fab7070 | ||
|
|
6745ca7775 | ||
|
|
88c5e3b6fa | ||
|
|
2fdb2c7c9a | ||
|
|
7afa027b95 | ||
|
|
637a5cc14f | ||
|
|
81e77693b2 | ||
|
|
d49f884f69 | ||
|
|
34eeb29436 | ||
|
|
0495347c64 | ||
|
|
023f9b44d3 | ||
|
|
5248814053 | ||
|
|
7ddab5b8cd | ||
|
|
a26adb162c | ||
|
|
ef5df36a8a | ||
|
|
9b74cf3225 | ||
|
|
1321c90920 | ||
|
|
4b46313e19 | ||
|
|
e9add69e26 | ||
|
|
5b020e81ca | ||
|
|
c76bd7b45b | ||
|
|
21b7ae3ac3 | ||
|
|
e45da7161f | ||
|
|
7a3c000955 | ||
|
|
f75c5db372 | ||
|
|
7cd1d82d26 | ||
|
|
0085c3b0d8 | ||
|
|
4251c6cb99 | ||
|
|
ac973df8e7 | ||
|
|
a76a955a1b | ||
|
|
c89b98a1e0 | ||
|
|
dda4596c0c | ||
|
|
4ac863203d | ||
|
|
be5831d9bd | ||
|
|
1e2fa27af7 | ||
|
|
fcbaf2a978 | ||
|
|
b5c172974e | ||
|
|
7bb70924c1 | ||
|
|
a62fb6dcd1 | ||
|
|
e9c06237f2 | ||
|
|
bdb1eca741 | ||
|
|
29000a5209 | ||
|
|
88f0867442 | ||
|
|
3de06174bf | ||
|
|
5187894add | ||
|
|
d58f7bb935 | ||
|
|
84594b0e1e | ||
|
|
578bbcd181 | ||
|
|
0cdf13742a | ||
|
|
b00d24579d | ||
|
|
5c76cdaad9 | ||
|
|
5d994d179e | ||
|
|
8930020776 | ||
|
|
0637bf0dcb | ||
|
|
2abec5b62f | ||
|
|
bc937a6434 | ||
|
|
3a84e3abcf | ||
|
|
e4c223ca59 | ||
|
|
31de2d304c | ||
|
|
c83113d49b | ||
|
|
d95980b3ba | ||
|
|
08a88af965 | ||
|
|
4d4f61c922 | ||
|
|
110b77f453 | ||
|
|
ba0d205457 | ||
|
|
1ee4cae802 | ||
|
|
095c894548 | ||
|
|
9f5f5da894 | ||
|
|
aa3608f0af | ||
|
|
56ebef4352 | ||
|
|
3e5c353298 | ||
|
|
0d57a887ea | ||
|
|
b5fdd29cd5 | ||
|
|
ae61662f61 | ||
|
|
b633f8d207 | ||
|
|
c4c813fd0a | ||
|
|
f9c4cc274a | ||
|
|
cc45a0ca28 | ||
|
|
9ed1d28f76 | ||
|
|
7ca2acd24e | ||
|
|
fdca468049 | ||
|
|
c0e8feb66e | ||
|
|
0dd710c195 | ||
|
|
39110ad21c | ||
|
|
57bb8c610a | ||
|
|
cf619f24a9 | ||
|
|
fd313f0d66 | ||
|
|
67a18dcff6 | ||
|
|
54b19a04bb | ||
|
|
ca4df29670 | ||
|
|
7da0b2fd7f | ||
|
|
cfcb64c516 | ||
|
|
135ae11c20 | ||
|
|
ce68d09d26 | ||
|
|
aa55e67389 | ||
|
|
f7992d2d09 | ||
|
|
eecfc155b8 | ||
|
|
9cef7945c0 | ||
|
|
1b1932f787 | ||
|
|
9e4fd193c6 | ||
|
|
d16a748f37 | ||
|
|
f616b8e518 | ||
|
|
97b469f59c | ||
|
|
7ec93825b6 | ||
|
|
4a4867deeb | ||
|
|
965a8ea9fd | ||
|
|
3e8ddabcc1 | ||
|
|
50267a6dd6 | ||
|
|
5a8825d016 | ||
|
|
e6bdcff0dd | ||
|
|
4803285e50 | ||
|
|
bab263f426 | ||
|
|
03d5509b44 | ||
|
|
4a5f193e94 | ||
|
|
fdd66f12f0 | ||
|
|
349f073b8e | ||
|
|
84e271be4b | ||
|
|
f215fa936b | ||
|
|
75d04a92c8 | ||
|
|
90c907710c | ||
|
|
00425670d7 | ||
|
|
cb525af0a2 | ||
|
|
09f7e38eed | ||
|
|
7c49a0ba7a | ||
|
|
45e57f1ad3 | ||
|
|
eb911de928 | ||
|
|
b393e31b76 | ||
|
|
4a095eb98e | ||
|
|
d793d4ba78 | ||
|
|
2f54ec4e18 | ||
|
|
b9cd40fe1e | ||
|
|
173cd7c15e | ||
|
|
950c8f7104 | ||
|
|
b63bebb519 | ||
|
|
cf72b34866 | ||
|
|
d06cf2a07b | ||
|
|
10804927bb | ||
|
|
f178297452 | ||
|
|
311e7684b2 | ||
|
|
37ff2ac2b9 | ||
|
|
4786d586cf | ||
|
|
b7aaae4a19 | ||
|
|
008598b56f | ||
|
|
f3bc55e37e | ||
|
|
31fa3dfd59 | ||
|
|
5b47438b71 | ||
|
|
c33ee83d87 | ||
|
|
835dd1abcc | ||
|
|
576f5496c0 | ||
|
|
ff460c7736 | ||
|
|
22adbe2073 | ||
|
|
b8f0b4b583 | ||
|
|
f88e5f09b4 | ||
|
|
2b9c6c95b1 | ||
|
|
3f34db549f | ||
|
|
f4c0ee49a7 | ||
|
|
2fc0a6df93 | ||
|
|
0a9c804940 | ||
|
|
96faa9d12b | ||
|
|
42d9fd9c88 | ||
|
|
908bc7561b | ||
|
|
3de92b337d | ||
|
|
31466785ad | ||
|
|
e38b602b7d | ||
|
|
a2f5342a83 | ||
|
|
d432732959 | ||
|
|
4eb3de7b4e | ||
|
|
2e6adfb44a | ||
|
|
c85c6d0ac5 | ||
|
|
6c9dd8deb6 | ||
|
|
fe64e6dbf2 | ||
|
|
4fd51ec880 | ||
|
|
0323c521be | ||
|
|
992125febc | ||
|
|
f0bd0abc0f | ||
|
|
5c0d4c4408 | ||
|
|
5f8e47a14d | ||
|
|
9407b91060 | ||
|
|
a6e38e2ad2 | ||
|
|
8701de64ce | ||
|
|
114cac99e7 | ||
|
|
78194599e2 | ||
|
|
49d9491fda | ||
|
|
392a363d02 | ||
|
|
0a87ba6930 | ||
|
|
065c104f27 | ||
|
|
7f272f1293 | ||
|
|
e67f50f157 | ||
|
|
dd13392e36 | ||
|
|
2638c66638 | ||
|
|
1d40225159 | ||
|
|
08f11d2f22 | ||
|
|
ee20ab3041 | ||
|
|
e0402919e1 | ||
|
|
086e156a02 | ||
|
|
d0b9292aee | ||
|
|
7b0cb69938 | ||
|
|
479dd684f8 | ||
|
|
573738443c | ||
|
|
0268629c3b | ||
|
|
cf9e6c5d06 | ||
|
|
ad44c6eeee | ||
|
|
2b79d76541 | ||
|
|
cfaf3180f9 | ||
|
|
7881efa269 | ||
|
|
1ac52ce18f | ||
|
|
bb123ae0df | ||
|
|
4859b67a7b | ||
|
|
586e8b1479 | ||
|
|
5a526e2077 | ||
|
|
d3452775b3 | ||
|
|
d82734641b | ||
|
|
abbc2bad35 | ||
|
|
b491d69eec | ||
|
|
d93514d327 | ||
|
|
49ed485145 | ||
|
|
1a2ca8634d | ||
|
|
60cceabaa6 | ||
|
|
56df6b5e08 | ||
|
|
ca5d5668d9 | ||
|
|
4a45d10a8b | ||
|
|
82e1e9f0e5 | ||
|
|
2e1b93b857 | ||
|
|
37e9cefc52 | ||
|
|
1807b1492e | ||
|
|
460a6b4e99 | ||
|
|
96d87a288f | ||
|
|
a0d00410ca | ||
|
|
445ff856fe | ||
|
|
b7fe212a18 | ||
|
|
cbabf0ae7e | ||
|
|
344ccf3b03 | ||
|
|
26a7e1b049 | ||
|
|
43bd331e48 | ||
|
|
8bbb016fa4 | ||
|
|
ea43ba7124 | ||
|
|
5a59bd9998 | ||
|
|
993d731c92 | ||
|
|
f529948d81 | ||
|
|
4f3f51c583 | ||
|
|
5ba9a1f87d | ||
|
|
a0fb75efcb | ||
|
|
6e6f4d5a37 | ||
|
|
f06053b1cf | ||
|
|
df0cd30236 | ||
|
|
8806c57c63 | ||
|
|
f66cfa1299 | ||
|
|
9e84a4dbab | ||
|
|
59ab066518 | ||
|
|
960bd2a6be | ||
|
|
2cdaef1371 | ||
|
|
9b6c5c08d8 | ||
|
|
268ce4fefc | ||
|
|
bca8dace80 | ||
|
|
75e5b49c3a | ||
|
|
3cf08dc451 | ||
|
|
76c9cf62ff | ||
|
|
7a93af1786 | ||
|
|
6f899d998f | ||
|
|
73da8463ca | ||
|
|
b38fab9738 | ||
|
|
45e4d64b20 | ||
|
|
e6fba5d802 | ||
|
|
50ba3c5d5c | ||
|
|
65663fb857 | ||
|
|
8df2f38d34 | ||
|
|
c5fae84263 | ||
|
|
533d0a1fd4 | ||
|
|
a0fe229c7a | ||
|
|
f876cd5a6a | ||
|
|
62e9e9a662 | ||
|
|
a51c5c3ae7 | ||
|
|
26636eda0d | ||
|
|
074df7637b | ||
|
|
4fc8905ebf | ||
|
|
8cbb2278a7 | ||
|
|
fe7f8c3c3a | ||
|
|
91430738e7 | ||
|
|
d6585d7583 | ||
|
|
1924d75c2b | ||
|
|
06b27d932d | ||
|
|
ac1ac2cfed | ||
|
|
53cdb04be7 | ||
|
|
c106de02e9 | ||
|
|
8bc91ced4f | ||
|
|
2d0b9597cc | ||
|
|
b92fbb893b | ||
|
|
957a40df1f | ||
|
|
1eea5b350d | ||
|
|
c8e7080d1d | ||
|
|
629d0e441f | ||
|
|
5cfb878131 | ||
|
|
bfd02ac13d | ||
|
|
bd50bb1aa4 | ||
|
|
1045062147 | ||
|
|
492def3b76 | ||
|
|
afde9ac8a3 | ||
|
|
d977258c6c | ||
|
|
62943f8803 | ||
|
|
22e0859538 | ||
|
|
2c47ef31c0 | ||
|
|
d69b9f9cf8 | ||
|
|
a52e9be3e8 | ||
|
|
21f9141500 | ||
|
|
0e000e44aa | ||
|
|
ad9fe3be09 | ||
|
|
3829bdf198 | ||
|
|
6933a049b1 | ||
|
|
e3544bf4bc | ||
|
|
d5d0cb6a0c | ||
|
|
cac5f20a28 | ||
|
|
beea32661a | ||
|
|
b9e57d0283 | ||
|
|
5c0458a887 | ||
|
|
65942cd46c | ||
|
|
9a8f1a0b0a | ||
|
|
edb37c95e1 | ||
|
|
896882958d | ||
|
|
45d687c4e1 | ||
|
|
42be1321b2 | ||
|
|
f2cc16009f | ||
|
|
4336a55c2e | ||
|
|
bc5c0f65b8 | ||
|
|
b7eba3bc17 | ||
|
|
661d715446 | ||
|
|
d2c166243b | ||
|
|
5ed5eabbfe | ||
|
|
18b4b141d9 | ||
|
|
cd1e478b95 | ||
|
|
cf0ecaaf41 | ||
|
|
5f466eed79 | ||
|
|
93198438b8 | ||
|
|
1057d0eaa6 | ||
|
|
73b1284234 | ||
|
|
5f2e87f0e3 | ||
|
|
d9528f5cc3 | ||
|
|
877bb5c821 | ||
|
|
ae353cef2e | ||
|
|
909606826d | ||
|
|
e6e2d51b58 | ||
|
|
ea16c01fa2 | ||
|
|
f20d420aa7 | ||
|
|
a8649f286c | ||
|
|
fe879e6d94 | ||
|
|
94f285695e | ||
|
|
428747ab69 | ||
|
|
049e8e07ef | ||
|
|
716a845e92 | ||
|
|
47dfd4e681 | ||
|
|
555108c7fd | ||
|
|
e1af3d9bf3 | ||
|
|
e864c7541c | ||
|
|
b4a6cbbd09 | ||
|
|
fe4eef5855 | ||
|
|
c0997f951c | ||
|
|
cb378c1754 | ||
|
|
20b961c1c8 | ||
|
|
c4c2e01213 | ||
|
|
4b6d0fb517 | ||
|
|
62e46b7a36 | ||
|
|
052c5c67b8 | ||
|
|
b794c5cfcf | ||
|
|
be8a4013a7 | ||
|
|
87c25f83a4 | ||
|
|
e08bea5f51 | ||
|
|
739f610507 | ||
|
|
608313c1d1 | ||
|
|
2c1cf42994 | ||
|
|
196db1e1d0 | ||
|
|
a2f5435c48 | ||
|
|
75ec0b4fcf | ||
|
|
b4bfe27786 | ||
|
|
7617382114 | ||
|
|
b2f67cb154 | ||
|
|
c5107ddd3d | ||
|
|
8b75590d3e | ||
|
|
a7624d4724 | ||
|
|
b3099001be | ||
|
|
533c6cefee | ||
|
|
acfa9e8a55 | ||
|
|
8823753b46 | ||
|
|
c5ccefe6f7 | ||
|
|
148071a744 | ||
|
|
56fab9d178 | ||
|
|
f422a77014 | ||
|
|
e248e7ebaf | ||
|
|
aa4c623a06 | ||
|
|
cbdba66ef3 | ||
|
|
d652ab9920 | ||
|
|
e49aaa0216 | ||
|
|
61d49a1215 | ||
|
|
c481ca924b | ||
|
|
23e5b6ba72 | ||
|
|
3e88b72316 | ||
|
|
7566243151 | ||
|
|
aaefa38602 | ||
|
|
de6db4141f | ||
|
|
a61735e29a | ||
|
|
9bdfb0a32b | ||
|
|
94ecd29e35 | ||
|
|
980f5f1299 | ||
|
|
f99d62a2bc | ||
|
|
89be1975ea | ||
|
|
fec82df451 | ||
|
|
89fd35e02d | ||
|
|
3286328de4 | ||
|
|
977c34c0d7 | ||
|
|
5ec23df460 | ||
|
|
7f307e3bea | ||
|
|
fa050fb8a8 | ||
|
|
d741cbf6fd | ||
|
|
fa09327403 | ||
|
|
e27aaf9ba1 | ||
|
|
c0063ea09b | ||
|
|
e3e07aa3e6 | ||
|
|
502e8daedd | ||
|
|
3035f0119f | ||
|
|
48a3c3a0c1 | ||
|
|
fab9ae64a0 | ||
|
|
b56ebd13b6 | ||
|
|
3de39698dd | ||
|
|
b86476410f | ||
|
|
57ea45ff51 | ||
|
|
ec30f7c5d4 | ||
|
|
3cc9114f81 | ||
|
|
790167e914 | ||
|
|
9687d432fd | ||
|
|
378c0d049e | ||
|
|
abe283b38e | ||
|
|
3af42079e0 | ||
|
|
eb4843649c | ||
|
|
9432efeba5 | ||
|
|
4a3ed75ae5 | ||
|
|
fc8c555519 | ||
|
|
44f30c0e05 | ||
|
|
83b5fd252e | ||
|
|
9ae18b0b3b | ||
|
|
84487b2e52 | ||
|
|
9689376de6 | ||
|
|
a2f79a163f | ||
|
|
489d0151ad | ||
|
|
bcb44ab600 | ||
|
|
1a78bb4b58 | ||
|
|
2600695927 | ||
|
|
705e4fca06 | ||
|
|
a4ba4cf6ce | ||
|
|
0b2109576a | ||
|
|
c8cdc50d29 | ||
|
|
b29e60a97a | ||
|
|
209a986fe4 | ||
|
|
295e5c9731 | ||
|
|
08c93e94e4 | ||
|
|
ec28e9fb27 | ||
|
|
7081e8a226 | ||
|
|
01a2383d7b | ||
|
|
903b569f6c | ||
|
|
9b79e35d52 | ||
|
|
237100da18 | ||
|
|
1e33c0c288 | ||
|
|
cbc7603248 | ||
|
|
8d53f3abb8 | ||
|
|
2dcfec2639 | ||
|
|
dacb1a70ee | ||
|
|
93200c00f2 | ||
|
|
3b484c362e | ||
|
|
fbee9fe51e | ||
|
|
c451aab150 | ||
|
|
48bff9a5d2 | ||
|
|
db36d80669 | ||
|
|
6c8d3232a0 | ||
|
|
e6418fe79b | ||
|
|
34a0bb04f7 | ||
|
|
28302c82a3 | ||
|
|
5025c40ab2 | ||
|
|
6fdd30d97f | ||
|
|
b7c000e435 | ||
|
|
5ef2bbe5d6 | ||
|
|
e1d37c3b98 | ||
|
|
ec475e5783 | ||
|
|
c4b67b4cae | ||
|
|
b2cfebcce2 | ||
|
|
2bf445e165 | ||
|
|
121224b1b0 | ||
|
|
55ce1ce3ec | ||
|
|
2b14633047 | ||
|
|
88042d27ec | ||
|
|
148f3002ec | ||
|
|
ec82c1f957 | ||
|
|
9919520c28 | ||
|
|
689795e8bc | ||
|
|
5c8ab35f55 | ||
|
|
ddd7f3f384 | ||
|
|
c2f74879da | ||
|
|
5311683d43 | ||
|
|
5f03a583d1 | ||
|
|
a6970e02f9 | ||
|
|
1f7f013e0a | ||
|
|
991a04dc2a | ||
|
|
685902adab | ||
|
|
26ce0eb4b9 | ||
|
|
b30db728cc | ||
|
|
5eb098b5aa | ||
|
|
a2995ea03a | ||
|
|
82da5cfd01 | ||
|
|
909285ea46 | ||
|
|
a0bc0641c7 | ||
|
|
e7ada61881 | ||
|
|
79e99908de | ||
|
|
f1d7644184 | ||
|
|
5f365927b3 | ||
|
|
bd893cb24c | ||
|
|
e3352c3658 | ||
|
|
63d3d6049e | ||
|
|
668810858d | ||
|
|
b7131a5cd5 | ||
|
|
c9a316ad35 | ||
|
|
ec8fe21485 | ||
|
|
4a0b10984a | ||
|
|
69406b00d1 | ||
|
|
a1f3ae730a | ||
|
|
fedaef5d17 | ||
|
|
e35345f135 | ||
|
|
d0dbbd1cb1 | ||
|
|
70e14f92a4 | ||
|
|
b45f371911 | ||
|
|
f1a7ee997b | ||
|
|
51ebec7c13 | ||
|
|
c3ed1ad040 | ||
|
|
85ebf2e484 | ||
|
|
1996e6afaa | ||
|
|
799f97e847 | ||
|
|
dd2a7f91cc | ||
|
|
c86e9dfc8a | ||
|
|
40a2579821 | ||
|
|
380b64071e | ||
|
|
5ce0b1c18e | ||
|
|
a00453e151 | ||
|
|
a1aa40f500 | ||
|
|
1ad4685bb7 | ||
|
|
d8629e61d6 | ||
|
|
d4ddd7204d | ||
|
|
5f18799d8f | ||
|
|
15ba3325d9 | ||
|
|
3046350cb2 | ||
|
|
ffa9e5dfab | ||
|
|
8584654f11 | ||
|
|
c7e65ce795 | ||
|
|
cc3f019b28 | ||
|
|
920785631b | ||
|
|
b7fe1db89a | ||
|
|
5a08dfa72f | ||
|
|
c28b1f6fb9 | ||
|
|
c81ca187f8 | ||
|
|
ba148d749f | ||
|
|
606dd11b4f | ||
|
|
e254d2de8e | ||
|
|
b0b8ba7000 | ||
|
|
4d512d908d | ||
|
|
168376b046 | ||
|
|
df9e7f284c | ||
|
|
6365ee7487 | ||
|
|
7a8620a570 | ||
|
|
2c24bf3222 | ||
|
|
e036d89a86 | ||
|
|
36e9fb9d68 | ||
|
|
8b56a038b7 | ||
|
|
d5f0e23e29 | ||
|
|
3a2bd4e928 | ||
|
|
c5136ca4d6 | ||
|
|
28dac81a90 | ||
|
|
c89632d2a8 | ||
|
|
82c8f3b556 | ||
|
|
29278ff916 | ||
|
|
608b9e66f4 | ||
|
|
ac0ed14eae | ||
|
|
a06dfaf82a | ||
|
|
dfd5e30015 | ||
|
|
b19524d56a | ||
|
|
e0d25ff887 | ||
|
|
198dfffaeb | ||
|
|
c4ef055248 | ||
|
|
420ceffbb0 | ||
|
|
eeeecf9763 | ||
|
|
8df591e8d4 | ||
|
|
702ed5bfa8 | ||
|
|
75c6844b66 | ||
|
|
b39f01dcdf | ||
|
|
dba7dc4e96 | ||
|
|
ef96a50cea | ||
|
|
eed78c960d | ||
|
|
eea7ca9b72 | ||
|
|
c7c732ebc0 | ||
|
|
fb06482916 | ||
|
|
1bb24efbbc | ||
|
|
13800589a9 | ||
|
|
848add1b1b | ||
|
|
fc67dd18d0 | ||
|
|
b3e9b92344 | ||
|
|
a291b29c6f | ||
|
|
b566c4ba1a | ||
|
|
2349a6ab0c | ||
|
|
70eaf41acb | ||
|
|
912091981e | ||
|
|
aca42ff6a5 | ||
|
|
3fd885a188 | ||
|
|
2dacdf0210 | ||
|
|
5e8856e65b | ||
|
|
d42539949e | ||
|
|
28ca5b2b57 | ||
|
|
eea6f5cbfa | ||
|
|
b55dcc16ae | ||
|
|
0cb442d40e | ||
|
|
680dc1f962 | ||
|
|
30c92ce1b7 | ||
|
|
e55a09241e | ||
|
|
5f02237119 | ||
|
|
68552b6d65 | ||
|
|
44a4cea3a2 | ||
|
|
77c13e10ec | ||
|
|
0f66ff50a4 | ||
|
|
af515856c2 | ||
|
|
62e8c09183 | ||
|
|
cb40a74aaf | ||
|
|
a2c3ef94ec | ||
|
|
4184fb3ae7 | ||
|
|
20d2d141e4 | ||
|
|
0cfc3bfb79 | ||
|
|
2de206cb81 | ||
|
|
64c6dfd307 | ||
|
|
03d0b296e1 | ||
|
|
ca4408b343 | ||
|
|
527f408f6a | ||
|
|
adccca366e | ||
|
|
76cad41382 | ||
|
|
501db8f276 | ||
|
|
cc684ff0b1 | ||
|
|
7823c07f1a | ||
|
|
eb6d3d68a9 | ||
|
|
c98c7d47db | ||
|
|
194694a59b | ||
|
|
555cee3500 | ||
|
|
f4bb854372 | ||
|
|
d04b8e2fc6 | ||
|
|
21c1450e4a | ||
|
|
2b6b0e62f4 | ||
|
|
4fb360b19f | ||
|
|
0fa1567793 | ||
|
|
d7377015a2 | ||
|
|
139017ba7c | ||
|
|
ff3b53e34a | ||
|
|
b409cdece5 | ||
|
|
2478e67d16 | ||
|
|
dd35877eda | ||
|
|
4acfd2c342 | ||
|
|
df3f9a2ae8 | ||
|
|
78ae9ff093 | ||
|
|
ca781651cb | ||
|
|
417fa3cf3c | ||
|
|
92bb477f68 | ||
|
|
0f08cc5aa9 | ||
|
|
3dac33ffba | ||
|
|
fe73eccb90 | ||
|
|
b9544d9534 | ||
|
|
99ba9874b1 | ||
|
|
b41ca72d2b | ||
|
|
1ba17a0e14 | ||
|
|
480d31eb5e | ||
|
|
1973f93d4a | ||
|
|
3a2f4d4def | ||
|
|
192d2b86b6 | ||
|
|
6ca948ac3c | ||
|
|
5f932e9749 | ||
|
|
ff46c18164 | ||
|
|
de777907f2 | ||
|
|
72c4fd868a | ||
|
|
4bc2cd003d | ||
|
|
c9c6c1f769 | ||
|
|
bb7d8735cb | ||
|
|
557b0d76ab | ||
|
|
13073411cc | ||
|
|
0530045536 | ||
|
|
6d29e9c1b7 | ||
|
|
d3e4739745 | ||
|
|
3379f3ef61 | ||
|
|
9da7919062 | ||
|
|
aeed7deb2d | ||
|
|
38b617d848 | ||
|
|
dda02f783f | ||
|
|
cda322e311 | ||
|
|
934d3178a2 | ||
|
|
2cded8dcac | ||
|
|
babe0c31ad | ||
|
|
aa2ae37365 | ||
|
|
9a8b81fcbe | ||
|
|
138f38aade | ||
|
|
42914bff6f | ||
|
|
59acf95bf5 | ||
|
|
31c1046771 | ||
|
|
ec4a22687f | ||
|
|
22d9d16a7a | ||
|
|
0520e67303 | ||
|
|
d571573e52 | ||
|
|
0f643daac6 | ||
|
|
989317e5d3 | ||
|
|
cce6db4aeb | ||
|
|
46109abde5 | ||
|
|
2e16774190 | ||
|
|
812a21bce6 | ||
|
|
17e0207120 | ||
|
|
e02608edf8 | ||
|
|
1a7e160956 | ||
|
|
59d966356e | ||
|
|
5937e0289e | ||
|
|
85c212aee3 | ||
|
|
1978c3d3bd | ||
|
|
30a2c28d74 | ||
|
|
94a330532d | ||
|
|
f65e57ee82 | ||
|
|
750064c06f | ||
|
|
651fd79325 | ||
|
|
b53f988fca | ||
|
|
1595eaeb74 | ||
|
|
a54cbe896d | ||
|
|
9995a8d53f | ||
|
|
b88872d54b | ||
|
|
f02ac01f7e | ||
|
|
3ab3a5a236 | ||
|
|
fa3eb185ab | ||
|
|
4a56ba34d4 | ||
|
|
b860c69fd7 | ||
|
|
8408ceffe8 | ||
|
|
da9133c3c3 | ||
|
|
4a6e920d0e | ||
|
|
13f58d602f | ||
|
|
45fda595c3 | ||
|
|
1f15ea0bd8 | ||
|
|
99eebfa10f | ||
|
|
ccbbe81141 | ||
|
|
ad2da5969e | ||
|
|
2ce82f3da5 | ||
|
|
6bc9479e00 | ||
|
|
740e52229f | ||
|
|
1efd2390e3 | ||
|
|
564328abf9 | ||
|
|
926f819e31 | ||
|
|
45f0b9ac45 | ||
|
|
9a82e86ce9 | ||
|
|
0ad974c57b | ||
|
|
62f015fc34 | ||
|
|
b508787037 | ||
|
|
176ef19cca | ||
|
|
db83ede73c | ||
|
|
452d1e8307 | ||
|
|
92f337c67e | ||
|
|
1e4022680a | ||
|
|
e16d951da0 | ||
|
|
7b2b19b4ba | ||
|
|
8ebfaed546 | ||
|
|
0b52d52f4a | ||
|
|
6901d10d54 | ||
|
|
7caa2ae9bc | ||
|
|
cc50859912 | ||
|
|
6c16780144 | ||
|
|
b5f79444f9 | ||
|
|
b73c6e94c0 | ||
|
|
07616a9d34 | ||
|
|
e88ee26e3b | ||
|
|
7422c38e66 | ||
|
|
8ed1c77e47 | ||
|
|
8c65b8c16f | ||
|
|
1f435522b4 | ||
|
|
eb880e8de0 | ||
|
|
83b1d80a5b | ||
|
|
529aff3126 | ||
|
|
bf2bd519eb | ||
|
|
38c7dda00f | ||
|
|
056e7432bd | ||
|
|
074497b0f6 | ||
|
|
1eca969cf6 | ||
|
|
c1cbdae5ee | ||
|
|
4d4b6a2fa0 | ||
|
|
d30a972a90 | ||
|
|
24013af3bb | ||
|
|
338dc3223c | ||
|
|
c422a6dd4f | ||
|
|
8305af8f10 | ||
|
|
6435c7b921 | ||
|
|
af7c57b082 | ||
|
|
80941eacbd | ||
|
|
ceb252986e | ||
|
|
5d8de5fde2 | ||
|
|
750ef296c6 | ||
|
|
454ae8656a | ||
|
|
75450dcdbc | ||
|
|
bd2c7e3bb9 | ||
|
|
9d23cf33fd | ||
|
|
97eb01a28d | ||
|
|
9a2a636aed | ||
|
|
61c8256ef0 | ||
|
|
8e1791570e | ||
|
|
aa30d1f359 | ||
|
|
326f4bd681 | ||
|
|
7690c6c33d | ||
|
|
fece1077f2 | ||
|
|
75fc7db50d | ||
|
|
96da04576e | ||
|
|
001ec3663e | ||
|
|
21a00b77bd | ||
|
|
408f3852ec | ||
|
|
61150c74d2 | ||
|
|
7bb7003c9d | ||
|
|
920463f2ff | ||
|
|
ca1185d0be | ||
|
|
be655ee328 | ||
|
|
02d4186b11 | ||
|
|
3f97bebd69 | ||
|
|
2e378da922 | ||
|
|
b37f51bd7f | ||
|
|
eb8b0f72cc | ||
|
|
d8fe9a4d29 | ||
|
|
c97cdf551e | ||
|
|
80fc60b5e2 | ||
|
|
3b2e142542 | ||
|
|
0e58d99f4e | ||
|
|
92798abb5d | ||
|
|
bd7950b757 | ||
|
|
59a15ceef6 | ||
|
|
4011a113cc | ||
|
|
70cbe91776 | ||
|
|
f92027c44b | ||
|
|
1443335315 | ||
|
|
6ff2229a09 | ||
|
|
bb72672dd9 | ||
|
|
d96dee3aa6 | ||
|
|
bd0aaa343b | ||
|
|
3126e1ac94 | ||
|
|
a117d87f33 | ||
|
|
9dc4f8a1aa | ||
|
|
0d536d11e3 | ||
|
|
72a4962fd0 | ||
|
|
a3045a3953 | ||
|
|
c620a22017 | ||
|
|
e3593fe197 | ||
|
|
856ec03cc7 | ||
|
|
c80c5631f0 | ||
|
|
ef70668a77 | ||
|
|
ebd4691462 | ||
|
|
28554235be | ||
|
|
efbbb6fd20 | ||
|
|
9de57021a3 | ||
|
|
e21f770485 | ||
|
|
697c00dccf | ||
|
|
1caf6a3298 | ||
|
|
02fd02d482 | ||
|
|
239fb0db94 | ||
|
|
fe1d73c3e5 | ||
|
|
43da06a354 | ||
|
|
fea6b67067 | ||
|
|
f065ae54d5 | ||
|
|
3cf417766d | ||
|
|
0fb41b10e9 | ||
|
|
bc9dc3bf1e | ||
|
|
3cde5e28a8 | ||
|
|
cb8e7181c4 | ||
|
|
9a3becdecc | ||
|
|
e3c10d779d | ||
|
|
dd9f1024f4 | ||
|
|
9841f74adc | ||
|
|
b56e493d92 | ||
|
|
a2c5211b20 | ||
|
|
b7a7abed48 | ||
|
|
72bfdfd925 | ||
|
|
b80d34612a | ||
|
|
648cc0f006 | ||
|
|
1fc9506442 | ||
|
|
830692dd60 | ||
|
|
95a6759381 | ||
|
|
960b37b1c2 | ||
|
|
b1d17dea4f | ||
|
|
6b06471953 | ||
|
|
4ca957d3eb | ||
|
|
eb9b63477c | ||
|
|
80c01b055c | ||
|
|
50aec67069 | ||
|
|
7baced75e5 | ||
|
|
99743a94fb | ||
|
|
9bdfd6025b | ||
|
|
91400d2ce0 | ||
|
|
7b88d0efe3 | ||
|
|
4aada65dae | ||
|
|
0560d2cfb7 | ||
|
|
58c1a68ad9 | ||
|
|
588fc6df85 | ||
|
|
2c9e4ded40 | ||
|
|
88a538e71b | ||
|
|
513363504f | ||
|
|
0e844edacb | ||
|
|
5751bb2481 | ||
|
|
28669d940a | ||
|
|
3d87bdb6b4 | ||
|
|
1499ce43bf | ||
|
|
4d22b43d65 | ||
|
|
823603650f | ||
|
|
062867a38d | ||
|
|
f3e0c5d653 | ||
|
|
fc7f48b7db | ||
|
|
04d56420d1 | ||
|
|
a017574f74 | ||
|
|
ae24360c02 | ||
|
|
3fea1976c8 | ||
|
|
cf97dd9fcd | ||
|
|
0e3a48ff76 | ||
|
|
48cbe45a9d | ||
|
|
276bf09238 | ||
|
|
05988c1c49 | ||
|
|
d46b26e3bc | ||
|
|
236c172c6f | ||
|
|
59fcb56972 | ||
|
|
c07cd3a856 | ||
|
|
37766347a5 | ||
|
|
79da61782b | ||
|
|
8af87f1a8b | ||
|
|
494c954cbb | ||
|
|
71bc9eea28 | ||
|
|
e3b2bcfd06 | ||
|
|
142d974641 |
88
.ameba.yml
Normal file
88
.ameba.yml
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#
|
||||||
|
# Lint
|
||||||
|
#
|
||||||
|
|
||||||
|
# Exclude assigns for ECR files
|
||||||
|
Lint/UselessAssign:
|
||||||
|
Excluded:
|
||||||
|
- src/invidious.cr
|
||||||
|
- src/invidious/helpers/errors.cr
|
||||||
|
- src/invidious/routes/**/*.cr
|
||||||
|
|
||||||
|
# Ignore false negative (if !db.query_one?...)
|
||||||
|
Lint/UnreachableCode:
|
||||||
|
Excluded:
|
||||||
|
- src/invidious/database/base.cr
|
||||||
|
|
||||||
|
# Ignore shadowed variable `key` (it works for now, and that's
|
||||||
|
# a sensitive part of the code)
|
||||||
|
Lint/ShadowingOuterLocalVar:
|
||||||
|
Excluded:
|
||||||
|
- src/invidious/helpers/tokens.cr
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Style
|
||||||
|
#
|
||||||
|
|
||||||
|
Style/RedundantBegin:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
Style/RedundantReturn:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Metrics
|
||||||
|
#
|
||||||
|
|
||||||
|
# Ignore function complexity (number of if/else & case/when branches)
|
||||||
|
# For some functions that can hardly be simplified for now
|
||||||
|
Metrics/CyclomaticComplexity:
|
||||||
|
Excluded:
|
||||||
|
# get_about_info(ucid, locale) => [17/10]
|
||||||
|
- src/invidious/channels/about.cr
|
||||||
|
|
||||||
|
# fetch_channel_community(ucid, continuation, ...) => [34/10]
|
||||||
|
- src/invidious/channels/community.cr
|
||||||
|
|
||||||
|
# create_notification_stream(env, topics, connection_channel) => [14/10]
|
||||||
|
- src/invidious/helpers/helpers.cr:84:5
|
||||||
|
|
||||||
|
# get_index(plural_form, count) => [25/10]
|
||||||
|
- src/invidious/helpers/i18next.cr
|
||||||
|
|
||||||
|
# call(context) => [18/10]
|
||||||
|
- src/invidious/helpers/static_file_handler.cr
|
||||||
|
|
||||||
|
# show(env) => [38/10]
|
||||||
|
- src/invidious/routes/embed.cr
|
||||||
|
|
||||||
|
# get_video_playback(env) => [45/10]
|
||||||
|
- src/invidious/routes/video_playback.cr
|
||||||
|
|
||||||
|
# handle(env) => [40/10]
|
||||||
|
- src/invidious/routes/watch.cr
|
||||||
|
|
||||||
|
# playlist_ajax(env) => [24/10]
|
||||||
|
- src/invidious/routes/playlists.cr
|
||||||
|
|
||||||
|
# fetch_youtube_comments(id, cursor, ....) => [40/10]
|
||||||
|
# template_youtube_comments(comments, locale, ...) => [16/10]
|
||||||
|
# content_to_comment_html(content) => [14/10]
|
||||||
|
- src/invidious/comments.cr
|
||||||
|
|
||||||
|
# to_json(locale, json) => [21/10]
|
||||||
|
# extract_video_info(video_id, ...) => [44/10]
|
||||||
|
# process_video_params(query, preferences) => [20/10]
|
||||||
|
- src/invidious/videos.cr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#src/invidious/playlists.cr:327:5
|
||||||
|
#[C] Metrics/CyclomaticComplexity: Cyclomatic complexity too high [19/10]
|
||||||
|
# fetch_playlist(plid : String)
|
||||||
|
|
||||||
|
#src/invidious/playlists.cr:436:5
|
||||||
|
#[C] Metrics/CyclomaticComplexity: Cyclomatic complexity too high [11/10]
|
||||||
|
# extract_playlist_videos(initial_data : Hash(String, JSON::Any))
|
||||||
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# https://github.community/t/how-to-change-the-category/2261/3
|
||||||
|
videojs-*.js linguist-detectable=false
|
||||||
|
video.min.js linguist-detectable=false
|
||||||
18
.github/CODEOWNERS
vendored
Normal file
18
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Default and lowest precedence. If none of the below matches, @iv-org/developers would be requested for review.
|
||||||
|
* @iv-org/developers
|
||||||
|
|
||||||
|
docker-compose.yml @unixfox
|
||||||
|
docker/ @unixfox
|
||||||
|
kubernetes/ @unixfox
|
||||||
|
|
||||||
|
README.md @thefrenchghosty
|
||||||
|
config/config.example.yml @thefrenchghosty @SamantazFox @unixfox
|
||||||
|
|
||||||
|
scripts/ @syeopite
|
||||||
|
shards.lock @syeopite
|
||||||
|
shards.yml @syeopite
|
||||||
|
|
||||||
|
locales/ @SamantazFox
|
||||||
|
src/invidious/helpers/i18n.cr @SamantazFox
|
||||||
|
|
||||||
|
src/invidious/helpers/youtube_api.cr @SamantazFox
|
||||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
custom: https://invidious.io/donate/
|
||||||
42
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
42
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a bug report to help us improve Invidious
|
||||||
|
title: '[Bug] '
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
BEFORE TRYING TO REPORT A BUG:
|
||||||
|
|
||||||
|
* Read the FAQ!
|
||||||
|
* Use the search function to check if there is already an issue open for your problem!
|
||||||
|
|
||||||
|
If you want to suggest a new feature please use "Feature request" instead
|
||||||
|
If you want to suggest an enhancement to an existing feature please use "Enhancement" instead
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
<!-- A clear and concise description of what the bug is. -->
|
||||||
|
|
||||||
|
**Steps to Reproduce**
|
||||||
|
<!-- Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
-->
|
||||||
|
|
||||||
|
**Logs**
|
||||||
|
<!-- If applicable, copy the log that appear in the browser page where the error is reported. -->
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
<!-- Add any other context about the problem here.
|
||||||
|
- Browser (if applicable):
|
||||||
|
- OS (if applicable):
|
||||||
|
-->
|
||||||
24
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: Enhancement
|
||||||
|
about: Suggest an enhancement for an existing feature
|
||||||
|
title: '[Enhancement] '
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Please use the search function to check if the desired function has already been requested by someone else -->
|
||||||
|
<!-- If you want to suggest a new feature please use "Feature request" instead -->
|
||||||
|
<!-- If you want to report a bug, please use "Bug report" instead -->
|
||||||
|
|
||||||
|
**Is your enhancement request related to a problem? Please describe.**
|
||||||
|
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
<!-- A clear and concise description of what you want to happen. -->
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
<!-- Add any other context or screenshots about the enhancement here. -->
|
||||||
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: '[Feature request] '
|
||||||
|
labels: feature-request
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Please use the search function to check if the desired function has already been requested by someone else -->
|
||||||
|
<!-- If you want to suggest an enhancement to an existing feature please use "Enhancement" instead -->
|
||||||
|
<!-- If you want to report a bug, please use "Bug report" instead -->
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
<!-- A clear and concise description of what you want to happen. -->
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
<!-- Add any other context or screenshots about the feature request here. -->
|
||||||
127
.github/workflows/ci.yml
vendored
Normal file
127
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
name: Invidious CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *" # Every day at 00:00
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "master"
|
||||||
|
- "api-only"
|
||||||
|
pull_request:
|
||||||
|
branches: "*"
|
||||||
|
paths-ignore:
|
||||||
|
- "*.md"
|
||||||
|
- LICENCE
|
||||||
|
- TRANSLATION
|
||||||
|
- invidious.service
|
||||||
|
- .git*
|
||||||
|
- .editorconfig
|
||||||
|
|
||||||
|
- screenshots/*
|
||||||
|
- assets/**
|
||||||
|
- locales/*
|
||||||
|
- config/**
|
||||||
|
- .github/ISSUE_TEMPLATE/*
|
||||||
|
- kubernetes/**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
name: "build - crystal: ${{ matrix.crystal }}, stable: ${{ matrix.stable }}"
|
||||||
|
|
||||||
|
continue-on-error: ${{ !matrix.stable }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
stable: [true]
|
||||||
|
crystal:
|
||||||
|
- 1.2.2
|
||||||
|
- 1.3.2
|
||||||
|
- 1.4.0
|
||||||
|
- 1.5.0
|
||||||
|
include:
|
||||||
|
- crystal: nightly
|
||||||
|
stable: false
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Install Crystal
|
||||||
|
uses: crystal-lang/install-crystal@v1.6.0
|
||||||
|
with:
|
||||||
|
crystal: ${{ matrix.crystal }}
|
||||||
|
|
||||||
|
- name: Cache Shards
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ./lib
|
||||||
|
key: shards-${{ hashFiles('shard.lock') }}
|
||||||
|
|
||||||
|
- name: Install Shards
|
||||||
|
run: |
|
||||||
|
if ! shards check; then
|
||||||
|
shards install
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: crystal spec
|
||||||
|
|
||||||
|
- name: Run lint
|
||||||
|
run: |
|
||||||
|
if ! crystal tool format --check; then
|
||||||
|
crystal tool format
|
||||||
|
git diff
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: crystal build --warnings all --error-on-warnings --error-trace src/invidious.cr
|
||||||
|
|
||||||
|
build-docker:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Build Docker
|
||||||
|
run: docker-compose build --build-arg release=0
|
||||||
|
|
||||||
|
- name: Run Docker
|
||||||
|
run: docker-compose up -d
|
||||||
|
|
||||||
|
- name: Test Docker
|
||||||
|
run: while curl -Isf http://localhost:3000; do sleep 1; done
|
||||||
|
|
||||||
|
build-docker-arm64:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
with:
|
||||||
|
platforms: arm64
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Build Docker ARM64 image
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: docker/Dockerfile.arm64
|
||||||
|
platforms: linux/arm64/v8
|
||||||
|
build-args: release=0
|
||||||
|
|
||||||
|
- name: Test Docker
|
||||||
|
run: while curl -Isf http://localhost:3000; do sleep 1; done
|
||||||
|
|
||||||
|
|
||||||
77
.github/workflows/container-release.yml
vendored
Normal file
77
.github/workflows/container-release.yml
vendored
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
name: Build and release container
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "master"
|
||||||
|
paths-ignore:
|
||||||
|
- "*.md"
|
||||||
|
- LICENCE
|
||||||
|
- TRANSLATION
|
||||||
|
- invidious.service
|
||||||
|
- .git*
|
||||||
|
- .editorconfig
|
||||||
|
|
||||||
|
- screenshots/*
|
||||||
|
- .github/ISSUE_TEMPLATE/*
|
||||||
|
- kubernetes/**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install Crystal
|
||||||
|
uses: crystal-lang/install-crystal@v1.6.0
|
||||||
|
with:
|
||||||
|
crystal: 1.5.0
|
||||||
|
|
||||||
|
- name: Run lint
|
||||||
|
run: |
|
||||||
|
if ! crystal tool format --check; then
|
||||||
|
crystal tool format
|
||||||
|
git diff
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
with:
|
||||||
|
platforms: arm64
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Login to registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: quay.io
|
||||||
|
username: ${{ secrets.QUAY_USERNAME }}
|
||||||
|
password: ${{ secrets.QUAY_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push Docker AMD64 image for Push Event
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: docker/Dockerfile
|
||||||
|
platforms: linux/amd64
|
||||||
|
labels: quay.expires-after=12w
|
||||||
|
push: true
|
||||||
|
tags: quay.io/invidious/invidious:${{ github.sha }},quay.io/invidious/invidious:latest
|
||||||
|
build-args: release=1
|
||||||
|
|
||||||
|
- name: Build and push Docker ARM64 image for Push Event
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: docker/Dockerfile.arm64
|
||||||
|
platforms: linux/arm64/v8
|
||||||
|
labels: quay.expires-after=12w
|
||||||
|
push: true
|
||||||
|
tags: quay.io/invidious/invidious:${{ github.sha }}-arm64,quay.io/invidious/invidious:latest-arm64
|
||||||
|
build-args: release=1
|
||||||
24
.github/workflows/stale.yml
vendored
Normal file
24
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Documentation: https://github.com/marketplace/actions/close-stale-issues
|
||||||
|
|
||||||
|
name: "Stale issue handler"
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 */12 * * *"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v5
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
days-before-stale: 365
|
||||||
|
days-before-pr-stale: 45 # PRs should be active. Anything that hasn't had activity in more than 45 days should be considered abandoned.
|
||||||
|
days-before-close: 30
|
||||||
|
exempt-pr-labels: blocked
|
||||||
|
stale-issue-message: 'This issue has been automatically marked as stale and will be closed in 30 days because it has not had recent activity and is much likely outdated. If you think this issue is still relevant and applicable, you just have to post a comment and it will be unmarked.'
|
||||||
|
stale-pr-message: 'This pull request has been automatically marked as stale and will be closed in 30 days because it has not had recent activity and is much likely abandoned or outdated. If you think this pull request is still relevant and applicable, you just have to post a comment and it will be unmarked.'
|
||||||
|
stale-issue-label: "stale"
|
||||||
|
stale-pr-label: "stale"
|
||||||
|
ascending: true
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,4 +6,4 @@
|
|||||||
/.vscode/
|
/.vscode/
|
||||||
/invidious
|
/invidious
|
||||||
/sentry
|
/sentry
|
||||||
shard.lock
|
/config/config.yml
|
||||||
|
|||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "mocks"]
|
||||||
|
path = mocks
|
||||||
|
url = ../mocks
|
||||||
34
.travis.yml
34
.travis.yml
@@ -1,34 +0,0 @@
|
|||||||
dist: bionic
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- stage: build
|
|
||||||
# TODO: Shallowly clone again once the .git folder is no longer required for building
|
|
||||||
git:
|
|
||||||
depth: false
|
|
||||||
language: crystal
|
|
||||||
crystal: latest
|
|
||||||
before_install:
|
|
||||||
- shards update
|
|
||||||
- shards install
|
|
||||||
install:
|
|
||||||
- crystal build --warnings all --error-on-warnings src/invidious.cr
|
|
||||||
script:
|
|
||||||
- crystal tool format --check
|
|
||||||
- crystal spec
|
|
||||||
|
|
||||||
- stage: build_docker
|
|
||||||
# TODO: Shallowly clone again once the .git folder is no longer required for building
|
|
||||||
git:
|
|
||||||
depth: false
|
|
||||||
language: minimal
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
install:
|
|
||||||
- docker-compose build
|
|
||||||
script:
|
|
||||||
- docker-compose up -d
|
|
||||||
- sleep 15 # Wait for cluster to become ready, TODO: do not sleep
|
|
||||||
- HEADERS="$(curl -I -s http://localhost:3000/)"
|
|
||||||
- STATUS="$(echo $HEADERS | head -n1)"
|
|
||||||
- if [[ "$STATUS" != *"200 OK"* ]]; then echo "$HEADERS"; exit 1; fi
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# Note: This is no longer updated and links to omarroths repo, which doesn't exist anymore.
|
||||||
|
|
||||||
# 0.20.0 (2019-011-06)
|
# 0.20.0 (2019-011-06)
|
||||||
|
|
||||||
# Version 0.20.0: Custom Playlists
|
# Version 0.20.0: Custom Playlists
|
||||||
@@ -400,7 +402,7 @@ An `/api/v1/stats` endpoint has been added with [#356](https://github.com/omarro
|
|||||||
|
|
||||||
## For Developers
|
## For Developers
|
||||||
|
|
||||||
`/api/v1/channels/:ucid` now provides an `autoGenerated` tag, which returns true for [topic channels](https://www.youtube.com/channel/UCE80FOXpJydkkMo-BYoJdEg), and larger [genre channels](https://www.youtube.com/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ) generated by YouTube. These channels don't have any videos of their own, so `latestVideos` will be empty. It is recommended instead to display a list of playlists generated by YouTube.
|
`/api/v1/channels/:ucid` now provides an `autoGenerated` tag, which returns true for topic channels, and larger genre channels generated by YouTube. These channels don't have any videos of their own, so `latestVideos` will be empty. It is recommended instead to display a list of playlists generated by YouTube.
|
||||||
|
|
||||||
You can now pull a list of playlists from a channel with `/api/v1/channels/playlists/:ucid`. Supported options are documented in the [wiki](https://github.com/omarroth/invidious/wiki/API#get-apiv1channelsplaylistsucid-apiv1channelsucidplaylists). Pagination is handled with a `continuation` token, which is generated on each call. Of note is that auto-generated channels currently have one page of results, and subsequent calls will be empty.
|
You can now pull a list of playlists from a channel with `/api/v1/channels/playlists/:ucid`. Supported options are documented in the [wiki](https://github.com/omarroth/invidious/wiki/API#get-apiv1channelsplaylistsucid-apiv1channelsucidplaylists). Pagination is handled with a `continuation` token, which is generated on each call. Of note is that auto-generated channels currently have one page of results, and subsequent calls will be empty.
|
||||||
|
|
||||||
|
|||||||
119
Makefile
Normal file
119
Makefile
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# -----------------------
|
||||||
|
# Compilation options
|
||||||
|
# -----------------------
|
||||||
|
|
||||||
|
RELEASE := 1
|
||||||
|
STATIC := 0
|
||||||
|
|
||||||
|
DISABLE_QUIC := 0
|
||||||
|
NO_DBG_SYMBOLS := 0
|
||||||
|
|
||||||
|
|
||||||
|
FLAGS ?=
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(RELEASE), 1)
|
||||||
|
FLAGS += --release
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(STATIC), 1)
|
||||||
|
FLAGS += --static
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(NO_DBG_SYMBOLS), 1)
|
||||||
|
FLAGS += --no-debug
|
||||||
|
else
|
||||||
|
FLAGS += --debug
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(DISABLE_QUIC), 1)
|
||||||
|
FLAGS += -Ddisable_quic
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------
|
||||||
|
# Main
|
||||||
|
# -----------------------
|
||||||
|
|
||||||
|
all: invidious
|
||||||
|
|
||||||
|
get-libs:
|
||||||
|
shards install --production
|
||||||
|
|
||||||
|
# TODO: add support for ARM64 via cross-compilation
|
||||||
|
invidious: get-libs
|
||||||
|
crystal build src/invidious.cr $(FLAGS) --progress --stats --error-trace
|
||||||
|
|
||||||
|
|
||||||
|
run: invidious
|
||||||
|
./invidious
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------
|
||||||
|
# Development
|
||||||
|
# -----------------------
|
||||||
|
|
||||||
|
|
||||||
|
format:
|
||||||
|
crystal tool format
|
||||||
|
|
||||||
|
test:
|
||||||
|
crystal spec
|
||||||
|
|
||||||
|
verify:
|
||||||
|
crystal build src/invidious.cr -Dskip_videojs_download \
|
||||||
|
--no-codegen --progress --stats --error-trace
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------
|
||||||
|
# (Un)Install
|
||||||
|
# -----------------------
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------
|
||||||
|
# Cleaning
|
||||||
|
# -----------------------
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm invidious
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
rm -rf libs
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------
|
||||||
|
# Help page
|
||||||
|
# -----------------------
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Targets available in this Makefile:"
|
||||||
|
@echo ""
|
||||||
|
@echo " get-libs Fetch Crystal libraries"
|
||||||
|
@echo " invidious Build Invidious"
|
||||||
|
@echo " run Launch Invidious"
|
||||||
|
@echo ""
|
||||||
|
@echo " format Run the Crystal formatter"
|
||||||
|
@echo " test Run tests"
|
||||||
|
@echo " verify Just make sure that the code compiles, but without"
|
||||||
|
@echo " generating any binaries. Useful to search for errors"
|
||||||
|
@echo ""
|
||||||
|
@echo " clean Remove build artifacts"
|
||||||
|
@echo " distclean Remove build artifacts and libraries"
|
||||||
|
@echo ""
|
||||||
|
@echo ""
|
||||||
|
@echo "Build options available for this Makefile:"
|
||||||
|
@echo ""
|
||||||
|
@echo " RELEASE Make a release build (Default: 1)"
|
||||||
|
@echo " STATIC Link libraries statically (Default: 0)"
|
||||||
|
@echo ""
|
||||||
|
@echo " DISABLE_QUIC Disable support for QUIC (Default: 0)"
|
||||||
|
@echo " NO_DBG_SYMBOLS Strip debug symbols (Default: 0)"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# No targets generates an output named after themselves
|
||||||
|
.PHONY: all get-libs build amd64 run
|
||||||
|
.PHONY: format test verify clean distclean help
|
||||||
342
README.md
342
README.md
@@ -1,235 +1,179 @@
|
|||||||
# Invidious
|
<div align="center">
|
||||||
|
<img src="assets/invidious-colored-vector.svg" width="192" height="192" alt="Invidious logo">
|
||||||
|
<h1>Invidious</h1>
|
||||||
|
|
||||||
[](https://travis-ci.org/omarroth/invidious)
|
<a href="https://www.gnu.org/licenses/agpl-3.0.en.html">
|
||||||
|
<img alt="License: AGPLv3" src="https://shields.io/badge/License-AGPL%20v3-blue.svg">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/iv-org/invidious/actions">
|
||||||
|
<img alt="Build Status" src="https://github.com/iv-org/invidious/workflows/Invidious%20CI/badge.svg">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/iv-org/invidious/commits/master">
|
||||||
|
<img alt="GitHub commits" src="https://img.shields.io/github/commit-activity/y/iv-org/invidious?color=red&label=commits">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/iv-org/invidious/issues">
|
||||||
|
<img alt="GitHub issues" src="https://img.shields.io/github/issues/iv-org/invidious?color=important">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/iv-org/invidious/pulls">
|
||||||
|
<img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/iv-org/invidious?color=blueviolet">
|
||||||
|
</a>
|
||||||
|
<a href="https://hosted.weblate.org/engage/invidious/">
|
||||||
|
<img alt="Translation Status" src="https://hosted.weblate.org/widgets/invidious/-/translations/svg-badge.svg">
|
||||||
|
</a>
|
||||||
|
|
||||||
## Invidious is an alternative front-end to YouTube
|
<a href="https://github.com/humanetech-community/awesome-humane-tech">
|
||||||
|
<img alt="Awesome Humane Tech" src="https://raw.githubusercontent.com/humanetech-community/awesome-humane-tech/main/humane-tech-badge.svg?sanitize=true">
|
||||||
|
</a>
|
||||||
|
|
||||||
- Audio-only mode (and no need to keep window open on mobile)
|
<h3>An open source alternative front-end to YouTube</h3>
|
||||||
- [Free software](https://github.com/omarroth/invidious) (AGPLv3 licensed)
|
|
||||||
- No ads
|
|
||||||
- No need to create a Google account to save subscriptions
|
|
||||||
- Lightweight (homepage is ~4 KB compressed)
|
|
||||||
- Tools for managing subscriptions:
|
|
||||||
- Only show unseen videos
|
|
||||||
- Only show latest (or latest unseen) video from each channel
|
|
||||||
- Delivers notifications from all subscribed channels
|
|
||||||
- Automatically redirect homepage to feed
|
|
||||||
- Import subscriptions from YouTube
|
|
||||||
- Dark mode
|
|
||||||
- Embed support
|
|
||||||
- Set default player options (speed, quality, autoplay, loop)
|
|
||||||
- Does not require JS to play videos
|
|
||||||
- Support for Reddit comments in place of YT comments
|
|
||||||
- Import/Export subscriptions, watch history, preferences
|
|
||||||
- Does not use any of the official YouTube APIs
|
|
||||||
- Developer [API](https://github.com/omarroth/invidious/wiki/API)
|
|
||||||
|
|
||||||
Liberapay: https://liberapay.com/omarroth
|
<a href="https://invidious.io/">Website</a>
|
||||||
BTC: 356DpZyMXu6rYd55Yqzjs29n79kGKWcYrY
|
•
|
||||||
BCH: qq4ptclkzej5eza6a50et5ggc58hxsq5aylqut2npk
|
<a href="https://instances.invidious.io/">Instances list</a>
|
||||||
|
•
|
||||||
|
<a href="https://docs.invidious.io/faq/">FAQ</a>
|
||||||
|
•
|
||||||
|
<a href="https://docs.invidious.io/">Documentation</a>
|
||||||
|
•
|
||||||
|
<a href="#contribute">Contribute</a>
|
||||||
|
•
|
||||||
|
<a href="https://invidious.io/donate/">Donate</a>
|
||||||
|
|
||||||
## Invidious Instances
|
<h5>Chat with us:</h5>
|
||||||
|
<a href="https://matrix.to/#/#invidious:matrix.org">
|
||||||
|
<img alt="Matrix" src="https://img.shields.io/matrix/invidious:matrix.org?label=Matrix&color=darkgreen">
|
||||||
|
</a>
|
||||||
|
<a href="https://web.libera.chat/?channel=#invidious">
|
||||||
|
<img alt="Libera.chat (IRC)" src="https://img.shields.io/badge/IRC%20%28Libera.chat%29-%23invidious-darkgreen">
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<a rel="me" href="https://social.tchncs.de/@invidious">
|
||||||
|
<img alt="Fediverse: @invidious@social.tchncs.de" src="https://img.shields.io/badge/Fediverse-%40invidious%40social.tchncs.de-darkgreen">
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<a href="https://invidious.io/contact/">
|
||||||
|
<img alt="E-mail" src="https://img.shields.io/badge/E%2d%2dmail-darkgreen">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
See [Invidious Instances](https://github.com/omarroth/invidious/wiki/Invidious-Instances) for a full list of publicly available instances.
|
|
||||||
|
|
||||||
### Official Instances
|
|
||||||
|
|
||||||
- [invidio.us](https://invidio.us) 🇺🇸
|
|
||||||
Issuer: Let's Encrypt, [SSLLabs Verification](https://www.ssllabs.com/ssltest/analyze.html?d=invidio.us)
|
|
||||||
- [kgg2m7yk5aybusll.onion](http://kgg2m7yk5aybusll.onion)
|
|
||||||
- [axqzx4s6s54s32yentfqojs3x5i7faxza6xo3ehd4bzzsg2ii4fv2iid.onion](http://axqzx4s6s54s32yentfqojs3x5i7faxza6xo3ehd4bzzsg2ii4fv2iid.onion)
|
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
| Player | Preferences | Subscriptions |
|
| Player | Preferences | Subscriptions |
|
||||||
| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|-------------------------------------|-------------------------------------|---------------------------------------|
|
||||||
| [<img src="screenshots/01_player.png?raw=true" height="140" width="280">](screenshots/01_player.png?raw=true) | [<img src="screenshots/02_preferences.png?raw=true" height="140" width="280">](screenshots/02_preferences.png?raw=true) | [<img src="screenshots/03_subscriptions.png?raw=true" height="140" width="280">](screenshots/03_subscriptions.png?raw=true) |
|
|  |  |  |
|
||||||
| [<img src="screenshots/04_description.png?raw=true" height="140" width="280">](screenshots/04_description.png?raw=true) | [<img src="screenshots/05_preferences.png?raw=true" height="140" width="280">](screenshots/05_preferences.png?raw=true) | [<img src="screenshots/06_subscriptions.png?raw=true" height="140" width="280">](screenshots/06_subscriptions.png?raw=true) |
|
|  |  |  |
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
See [Invidious-Updater](https://github.com/tmiland/Invidious-Updater) for a self-contained script that can automatically install and update Invidious.
|
## Features
|
||||||
|
|
||||||
### Docker:
|
**User features**
|
||||||
|
- Lightweight
|
||||||
|
- No ads
|
||||||
|
- No tracking
|
||||||
|
- No JavaScript required
|
||||||
|
- Light/Dark themes
|
||||||
|
- Customizable homepage
|
||||||
|
- Subscriptions independent from Google
|
||||||
|
- Notifications for all subscribed channels
|
||||||
|
- Audio-only mode (with background play on mobile)
|
||||||
|
- Support for Reddit comments
|
||||||
|
- [Available in many languages](locales/), thanks to [our translators](#contribute)
|
||||||
|
|
||||||
#### Build and start cluster:
|
**Data import/export**
|
||||||
|
- Import subscriptions from YouTube, NewPipe and Freetube
|
||||||
|
- Import watch history from NewPipe
|
||||||
|
- Export subscriptions to NewPipe and Freetube
|
||||||
|
- Import/Export Invidious user data
|
||||||
|
|
||||||
```bash
|
**Technical features**
|
||||||
$ docker-compose up
|
- Embedded video support
|
||||||
```
|
- [Developer API](https://docs.invidious.io/api/)
|
||||||
|
- Does not use official YouTube APIs
|
||||||
|
- No Contributor License Agreement (CLA)
|
||||||
|
|
||||||
And visit `localhost:3000` in your browser.
|
|
||||||
|
|
||||||
#### Rebuild cluster:
|
## Quick start
|
||||||
|
|
||||||
```bash
|
**Using invidious:**
|
||||||
$ docker-compose build
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Delete data and rebuild:
|
- [Select a public instance from the list](https://instances.invidious.io) and start watching videos right now!
|
||||||
|
|
||||||
```bash
|
**Hosting invidious:**
|
||||||
$ docker volume rm invidious_postgresdata
|
|
||||||
$ docker-compose build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Linux:
|
- [Follow the installation instructions](https://docs.invidious.io/installation/)
|
||||||
|
|
||||||
#### Install dependencies
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Arch Linux
|
|
||||||
$ sudo pacman -S shards crystal librsvg postgresql
|
|
||||||
|
|
||||||
# Ubuntu or Debian
|
|
||||||
# First you have to add the repository to your APT configuration. For easy setup just run in your command line:
|
|
||||||
$ curl -sSL https://dist.crystal-lang.org/apt/setup.sh | sudo bash
|
|
||||||
# That will add the signing key and the repository configuration. If you prefer to do it manually, execute the following commands:
|
|
||||||
$ curl -sL "https://keybase.io/crystal/pgp_keys.asc" | sudo apt-key add -
|
|
||||||
$ echo "deb https://dist.crystal-lang.org/apt crystal main" | sudo tee /etc/apt/sources.list.d/crystal.list
|
|
||||||
$ sudo apt-get update
|
|
||||||
$ sudo apt install crystal libssl-dev libxml2-dev libyaml-dev libgmp-dev libreadline-dev postgresql librsvg2-bin libsqlite3-dev
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Add invidious user and clone repository
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ useradd -m invidious
|
|
||||||
$ sudo -i -u invidious
|
|
||||||
$ git clone https://github.com/omarroth/invidious
|
|
||||||
$ exit
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Setup PostgresSQL
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ sudo systemctl enable postgresql
|
|
||||||
$ sudo systemctl start postgresql
|
|
||||||
$ sudo -i -u postgres
|
|
||||||
$ psql -c "CREATE USER kemal WITH PASSWORD 'kemal';" # Change 'kemal' here to a stronger password, and update `password` in config/config.yml
|
|
||||||
$ createdb -O kemal invidious
|
|
||||||
$ psql invidious kemal < /home/invidious/invidious/config/sql/channels.sql
|
|
||||||
$ psql invidious kemal < /home/invidious/invidious/config/sql/videos.sql
|
|
||||||
$ psql invidious kemal < /home/invidious/invidious/config/sql/channel_videos.sql
|
|
||||||
$ psql invidious kemal < /home/invidious/invidious/config/sql/users.sql
|
|
||||||
$ psql invidious kemal < /home/invidious/invidious/config/sql/session_ids.sql
|
|
||||||
$ psql invidious kemal < /home/invidious/invidious/config/sql/nonces.sql
|
|
||||||
$ psql invidious kemal < /home/invidious/invidious/config/sql/annotations.sql
|
|
||||||
$ exit
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Setup Invidious
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ sudo -i -u invidious
|
|
||||||
$ cd invidious
|
|
||||||
$ shards update && shards install
|
|
||||||
$ crystal build src/invidious.cr --release
|
|
||||||
# test compiled binary
|
|
||||||
$ ./invidious # stop with ctrl c
|
|
||||||
$ exit
|
|
||||||
```
|
|
||||||
|
|
||||||
#### systemd service
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ sudo cp /home/invidious/invidious/invidious.service /etc/systemd/system/invidious.service
|
|
||||||
$ sudo systemctl enable invidious.service
|
|
||||||
$ sudo systemctl start invidious.service
|
|
||||||
```
|
|
||||||
|
|
||||||
### OSX:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install dependencies
|
|
||||||
$ brew update
|
|
||||||
$ brew install shards crystal postgres imagemagick librsvg
|
|
||||||
|
|
||||||
# Clone repository and setup postgres database
|
|
||||||
$ git clone https://github.com/omarroth/invidious
|
|
||||||
$ cd invidious
|
|
||||||
$ brew services start postgresql
|
|
||||||
$ psql -c "CREATE ROLE kemal WITH PASSWORD 'kemal';" # Change 'kemal' here to a stronger password, and update `password` in config/config.yml
|
|
||||||
$ createdb -O kemal invidious
|
|
||||||
$ psql invidious kemal < config/sql/channels.sql
|
|
||||||
$ psql invidious kemal < config/sql/videos.sql
|
|
||||||
$ psql invidious kemal < config/sql/channel_videos.sql
|
|
||||||
$ psql invidious kemal < config/sql/users.sql
|
|
||||||
$ psql invidious kemal < config/sql/session_ids.sql
|
|
||||||
$ psql invidious kemal < config/sql/nonces.sql
|
|
||||||
$ psql invidious kemal < config/sql/annotations.sql
|
|
||||||
|
|
||||||
# Setup Invidious
|
|
||||||
$ shards update && shards install
|
|
||||||
$ crystal build src/invidious.cr --release
|
|
||||||
```
|
|
||||||
|
|
||||||
## Update Invidious
|
|
||||||
|
|
||||||
You can see how to update Invidious [here](https://github.com/omarroth/invidious/wiki/Updating).
|
|
||||||
|
|
||||||
## Usage:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ ./invidious -h
|
|
||||||
Usage: invidious [arguments]
|
|
||||||
-b HOST, --bind HOST Host to bind (defaults to 0.0.0.0)
|
|
||||||
-p PORT, --port PORT Port to listen for connections (defaults to 3000)
|
|
||||||
-s, --ssl Enables SSL
|
|
||||||
--ssl-key-file FILE SSL key file
|
|
||||||
--ssl-cert-file FILE SSL certificate file
|
|
||||||
-h, --help Shows this help
|
|
||||||
-c THREADS, --channel-threads=THREADS
|
|
||||||
Number of threads for refreshing channels (default: 1)
|
|
||||||
-f THREADS, --feed-threads=THREADS
|
|
||||||
Number of threads for refreshing feeds (default: 1)
|
|
||||||
-o OUTPUT, --output=OUTPUT Redirect output (default: STDOUT)
|
|
||||||
-v, --version Print version
|
|
||||||
```
|
|
||||||
|
|
||||||
Or for development:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ curl -fsSLo- https://raw.githubusercontent.com/samueleaton/sentry/master/install.cr | crystal eval
|
|
||||||
$ ./sentry
|
|
||||||
🤖 Your SentryBot is vigilant. beep-boop...
|
|
||||||
```
|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
[Documentation](https://github.com/omarroth/invidious/wiki) can be found in the wiki.
|
The full documentation can be accessed online at https://docs.invidious.io/
|
||||||
|
|
||||||
## Extensions
|
The documentation's source code is available in this repository:
|
||||||
|
https://github.com/iv-org/documentation
|
||||||
|
|
||||||
[Extensions](https://github.com/omarroth/invidious/wiki/Extensions) can be found in the wiki, as well as documentation for integrating it into other projects.
|
### Extensions
|
||||||
|
|
||||||
## Made with Invidious
|
We highly recommend the use of [Privacy Redirect](https://github.com/SimonBrazell/privacy-redirect#get),
|
||||||
|
a browser extension that automatically redirects Youtube URLs to any Invidious instance and replaces
|
||||||
|
embedded youtube videos on other websites with invidious.
|
||||||
|
|
||||||
- [FreeTube](https://github.com/FreeTubeApp/FreeTube): An Open Source YouTube app for privacy.
|
The documentation contains a list of browser extensions that we recommended to use along with Invidious.
|
||||||
- [CloudTube](https://cadence.moe/cloudtube/subscriptions): A JS-rich alternate YouTube player
|
|
||||||
- [PeerTubeify](https://gitlab.com/Ealhad/peertubeify): On YouTube, displays a link to the same video on PeerTube, if it exists.
|
|
||||||
- [MusicPiped](https://github.com/deep-gaurav/MusicPiped): A materialistic music player that streams music from YouTube.
|
|
||||||
|
|
||||||
## Contributing
|
You can read more here: https://docs.invidious.io/applications/
|
||||||
|
|
||||||
1. Fork it ( https://github.com/omarroth/invidious/fork )
|
|
||||||
2. Create your feature branch (git checkout -b my-new-feature)
|
|
||||||
3. Commit your changes (git commit -am 'Add some feature')
|
|
||||||
4. Push to the branch (git push origin my-new-feature)
|
|
||||||
5. Create a new Pull Request
|
|
||||||
|
|
||||||
## Contact
|
## Contribute
|
||||||
|
|
||||||
Feel free to send an email to omarroth@protonmail.com or join our [Matrix Server](https://riot.im/app/#/room/#invidious:matrix.org), or #invidious on Freenode.
|
### Code
|
||||||
|
|
||||||
You can also view release notes on the [releases](https://github.com/omarroth/invidious/releases) page or in the CHANGELOG.md included in the repository.
|
1. Fork it ( https://github.com/iv-org/invidious/fork ).
|
||||||
|
1. Create your feature branch (`git checkout -b my-new-feature`).
|
||||||
|
1. Stage your files (`git add .`).
|
||||||
|
1. Commit your changes (`git commit -am 'Add some feature'`).
|
||||||
|
1. Push to the branch (`git push origin my-new-feature`).
|
||||||
|
1. Create a new pull request ( https://github.com/iv-org/invidious/compare ).
|
||||||
|
|
||||||
## License
|
### Translations
|
||||||
|
|
||||||
[](http://www.gnu.org/licenses/agpl-3.0.en.html)
|
We use [Weblate](https://weblate.org) to manage Invidious translations.
|
||||||
|
|
||||||
Invidious is Free Software: You can use, study share and improve it at your
|
You can suggest new translations and/or correction here: https://hosted.weblate.org/engage/invidious/.
|
||||||
will. Specifically you can redistribute and/or modify it under the terms of the
|
|
||||||
[GNU Affero General Public License](https://www.gnu.org/licenses/agpl.html) as
|
Creating an account is not required, but recommended, especially if you want to contribute regularly.
|
||||||
published by the Free Software Foundation, either version 3 of the License, or
|
Weblate also allows you to log-in with major SSO providers like Github, Gitlab, BitBucket, Google, ...
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
|
## Projects using Invidious
|
||||||
|
|
||||||
|
- [FreeTube](https://github.com/FreeTubeApp/FreeTube): A libre software YouTube app for privacy.
|
||||||
|
- [CloudTube](https://sr.ht/~cadence/tube/): A JavaScript-rich alternate YouTube player.
|
||||||
|
- [PeerTubeify](https://gitlab.com/Cha_deL/peertubeify): On YouTube, displays a link to the same video on PeerTube, if it exists.
|
||||||
|
- [MusicPiped](https://github.com/deep-gaurav/MusicPiped): A material design music player that streams music from YouTube.
|
||||||
|
- [HoloPlay](https://github.com/stephane-r/HoloPlay): Funny Android application connecting on Invidious API's with search, playlists and favorites.
|
||||||
|
- [WatchTube](https://github.com/WatchTubeTeam/WatchTube): Powerful YouTube client for Apple Watch.
|
||||||
|
- [Yattee](https://github.com/yattee/yattee): Alternative YouTube frontend for iPhone, iPad, Mac and Apple TV.
|
||||||
|
- [TubiTui](https://codeberg.org/777/TubiTui): A lightweight, libre, TUI-based YouTube client.
|
||||||
|
- [Ytfzf](https://github.com/pystardust/ytfzf): A posix script to find and watch youtube videos from the terminal. (Without API)
|
||||||
|
|
||||||
|
|
||||||
|
## Liability
|
||||||
|
|
||||||
|
We take no responsibility for the use of our tool, or external instances
|
||||||
|
provided by third parties. We strongly recommend you abide by the valid
|
||||||
|
official regulations in your country. Furthermore, we refuse liability
|
||||||
|
for any inappropriate use of Invidious, such as illegal downloading.
|
||||||
|
This tool is provided to you in the spirit of free, open software.
|
||||||
|
|
||||||
|
You may view the LICENSE in which this software is provided to you [here](./LICENSE).
|
||||||
|
|
||||||
|
> 16. Limitation of Liability.
|
||||||
|
>
|
||||||
|
> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|||||||
1
TRANSLATION
Normal file
1
TRANSLATION
Normal file
@@ -0,0 +1 @@
|
|||||||
|
https://hosted.weblate.org/projects/invidious/
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
a:hover,
|
|
||||||
a:active {
|
|
||||||
color: rgb(0, 182, 240);
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #a0a0a0;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: rgba(35, 35, 35, 1);
|
|
||||||
color: #f0f0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pure-form legend {
|
|
||||||
color: #f0f0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pure-menu-heading {
|
|
||||||
color: #f0f0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
select,
|
|
||||||
textarea {
|
|
||||||
color: rgba(35, 35, 35, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pure-form input[type="file"] {
|
|
||||||
color: #f0f0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar > .searchbar input {
|
|
||||||
background-color: inherit;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
@@ -5,14 +5,26 @@ body {
|
|||||||
Arial, sans-serif;
|
Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#contents {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
.deleted {
|
.deleted {
|
||||||
background-color: rgb(255, 0, 0, 0.5);
|
background-color: rgb(255, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.underlined {
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.channel-profile > * {
|
.channel-profile > * {
|
||||||
font-size: 1.17em;
|
font-size: 1.17em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-profile > img {
|
.channel-profile > img {
|
||||||
@@ -20,7 +32,7 @@ body {
|
|||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-owner {
|
body a.channel-owner {
|
||||||
background-color: #008bec;
|
background-color: #008bec;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-radius: 9px;
|
border-radius: 9px;
|
||||||
@@ -60,6 +72,22 @@ body {
|
|||||||
color: rgb(255, 0, 0);
|
color: rgb(255, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.feed-menu {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feed-menu-item {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 640px) {
|
||||||
|
.feed-menu-item {
|
||||||
|
flex: 0 0 40%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.h-box {
|
.h-box {
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
@@ -85,15 +113,19 @@ div {
|
|||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body a.pure-button {
|
||||||
|
color: rgba(0,0,0,.8);
|
||||||
|
}
|
||||||
|
|
||||||
button.pure-button-primary,
|
button.pure-button-primary,
|
||||||
a.pure-button-primary,
|
body a.pure-button-primary,
|
||||||
.channel-owner:hover {
|
.channel-owner:hover {
|
||||||
background-color: #a0a0a0;
|
background-color: #a0a0a0;
|
||||||
color: rgba(35, 35, 35, 1);
|
color: rgba(35, 35, 35, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.pure-button-primary:hover,
|
button.pure-button-primary:hover,
|
||||||
a.pure-button-primary:hover {
|
body a.pure-button-primary:hover {
|
||||||
background-color: rgba(0, 182, 240, 1);
|
background-color: rgba(0, 182, 240, 1);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
@@ -152,7 +184,7 @@ img.thumbnail {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar > .searchbar {
|
.searchbar {
|
||||||
flex-grow: 2; /* take double the space of the other items */
|
flex-grow: 2; /* take double the space of the other items */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,20 +197,26 @@ img.thumbnail {
|
|||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar > .searchbar .pure-form input[type="search"] {
|
.searchbar .pure-form fieldset { padding: 0; }
|
||||||
margin-bottom: 1px;
|
|
||||||
|
|
||||||
border-top: 0;
|
.searchbar input[type="search"] {
|
||||||
border-left: 0;
|
width: 100%;
|
||||||
border-right: 0;
|
margin: 1px;
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
border-radius: 0;
|
|
||||||
|
|
||||||
padding: initial 0;
|
border: 1px solid;
|
||||||
|
border-color: rgba(0,0,0,0);
|
||||||
|
border-bottom-color: #CCC;
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
-webkit-appearance: none;
|
.searchbar input[type="search"]:focus {
|
||||||
|
margin: 0 0 0.5px 0;
|
||||||
|
border: 2px solid;
|
||||||
|
border-color: rgba(0,0,0,0);
|
||||||
|
border-bottom-color: #FED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* https://stackoverflow.com/a/55170420 */
|
/* https://stackoverflow.com/a/55170420 */
|
||||||
@@ -190,16 +228,6 @@ input[type="search"]::-webkit-search-cancel-button {
|
|||||||
background-size: 14px;
|
background-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar > .searchbar .pure-form fieldset {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* attract focus to the searchbar by adding a subtle transition */
|
|
||||||
.navbar > .searchbar .pure-form input[type="search"]:focus {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
border-bottom: 2px solid #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-field {
|
.user-field {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -208,7 +236,7 @@ input[type="search"]::-webkit-search-cancel-button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.user-field div {
|
.user-field div {
|
||||||
width: initial;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-field div:not(:last-child) {
|
.user-field div:not(:last-child) {
|
||||||
@@ -256,21 +284,43 @@ input[type="search"]::-webkit-search-cancel-button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Video "cards" (results/playlist/channel videos)
|
||||||
|
*/
|
||||||
|
|
||||||
|
.video-card-row { margin: 15px 0; }
|
||||||
|
|
||||||
|
.flexible { display: flex; }
|
||||||
|
.flex-left { flex: 1 1 100%; flex-wrap: wrap; }
|
||||||
|
.flex-right { flex: 1 0 auto; flex-wrap: nowrap; }
|
||||||
|
|
||||||
|
p.channel-name { margin: 0; }
|
||||||
|
p.video-data { margin: 0; font-weight: bold; font-size: 80%; }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Footer
|
* Footer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.footer {
|
footer {
|
||||||
color: #666666;
|
color: #919191;
|
||||||
margin: 2em 0;
|
margin-top: auto;
|
||||||
|
padding: 1.5em 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
max-height: 30vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer a {
|
footer a {
|
||||||
color: inherit;
|
color: #919191 !important;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
footer span {
|
||||||
|
margin: 4px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
/* keyframes */
|
/* keyframes */
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
@@ -282,190 +332,206 @@ input[type="search"]::-webkit-search-cancel-button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Control Bar */
|
|
||||||
@media screen and (max-width: 640px) {
|
|
||||||
.video-js .vjs-control-bar,
|
|
||||||
.vjs-menu-button-popup .vjs-menu .vjs-menu-content {
|
|
||||||
overflow-x: scroll;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.vjs-menu-content::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-user-inactive {
|
|
||||||
cursor: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-js .vjs-text-track-display > div > div > div {
|
|
||||||
background-color: rgba(0, 0, 0, 0.75) !important;
|
|
||||||
border-radius: 9px !important;
|
|
||||||
padding: 5px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-play-control,
|
|
||||||
.vjs-volume-panel,
|
|
||||||
.vjs-current-time,
|
|
||||||
.vjs-time-control,
|
|
||||||
.vjs-duration,
|
|
||||||
.vjs-progress-control,
|
|
||||||
.vjs-remaining-time {
|
|
||||||
order: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-captions-button {
|
|
||||||
order: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-quality-selector,
|
|
||||||
.video-js .vjs-http-source-selector {
|
|
||||||
order: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-playback-rate {
|
|
||||||
order: 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-share-control {
|
|
||||||
order: 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-fullscreen-control {
|
|
||||||
order: 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-playback-rate > .vjs-menu {
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-control-bar {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-control-bar::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-js .vjs-icon-cog {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-js .vjs-control-bar,
|
|
||||||
.vjs-menu-button-popup .vjs-menu .vjs-menu-content {
|
|
||||||
background-color: rgba(35, 35, 35, 0.75);
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-menu li.vjs-menu-item:focus,
|
|
||||||
.vjs-menu li.vjs-menu-item:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.75);
|
|
||||||
color: rgba(49, 49, 51, 0.75);
|
|
||||||
}
|
|
||||||
|
|
||||||
.vjs-menu li.vjs-selected,
|
|
||||||
.vjs-menu li.vjs-selected:focus,
|
|
||||||
.vjs-menu li.vjs-selected:hover {
|
|
||||||
background-color: rgba(0, 182, 240, 0.75);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Progress Bar */
|
|
||||||
.video-js .vjs-slider {
|
|
||||||
background-color: rgba(15, 15, 15, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset > select,
|
fieldset > select,
|
||||||
span > select {
|
span > select {
|
||||||
color: rgba(49, 49, 51, 1);
|
color: rgba(49, 49, 51, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-js .vjs-load-progress,
|
|
||||||
.video-js .vjs-load-progress div {
|
|
||||||
background: rgba(87, 87, 88, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-js .vjs-slider:hover,
|
|
||||||
.video-js button:hover {
|
|
||||||
color: rgba(0, 182, 240, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-js .vjs-play-progress {
|
|
||||||
background-color: rgba(0, 182, 240, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Overlay */
|
|
||||||
.video-js .vjs-overlay {
|
|
||||||
background-color: rgba(35, 35, 35, 0.75);
|
|
||||||
color: rgba(255, 255, 255, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ProgressBar marker */
|
|
||||||
.vjs-marker {
|
|
||||||
background-color: rgba(255, 255, 255, 1);
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Big "Play" Button */
|
|
||||||
.video-js .vjs-big-play-button {
|
|
||||||
background-color: rgba(35, 35, 35, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-js:hover .vjs-big-play-button {
|
|
||||||
background-color: rgba(35, 35, 35, 0.75);
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-js .vjs-current-time,
|
|
||||||
.video-js .vjs-time-divider,
|
|
||||||
.video-js .vjs-duration {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-js .vjs-time-divider {
|
|
||||||
min-width: 0px;
|
|
||||||
padding-left: 0px;
|
|
||||||
padding-right: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-js .vjs-poster {
|
|
||||||
background-size: cover;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-dimensions.vjs-fluid {
|
|
||||||
padding-top: 82vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
video.video-js {
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#player-container {
|
|
||||||
position: relative;
|
|
||||||
padding-bottom: 82vh;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pure-control-group label {
|
.pure-control-group label {
|
||||||
word-wrap: normal;
|
word-wrap: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-js.player-style-invidious {
|
/*
|
||||||
/* This is already the default */
|
* Light theme
|
||||||
|
*/
|
||||||
|
|
||||||
|
.light-theme a:hover,
|
||||||
|
.light-theme a:active,
|
||||||
|
.light-theme summary:hover {
|
||||||
|
color: #075A9E !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-js.player-style-youtube .vjs-control-bar {
|
.light-theme a.pure-button-primary:hover {
|
||||||
display: flex;
|
color: #fff !important;
|
||||||
flex-direction: row;
|
|
||||||
}
|
}
|
||||||
.video-js.player-style-youtube .vjs-big-play-button {
|
|
||||||
/*
|
.light-theme a {
|
||||||
Styles copied from video-js.min.css, definition of
|
color: #335d7a;
|
||||||
.vjs-big-play-centered .vjs-big-play-button
|
text-decoration: none;
|
||||||
*/
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
margin-top: -0.81666em;
|
|
||||||
margin-left: -1.5em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* All links that do not fit with the default color goes here */
|
||||||
|
.light-theme a:not([data-id]) > .icon,
|
||||||
|
.light-theme .pure-u-lg-1-5 > .h-box > a[href^="/watch?"],
|
||||||
|
.light-theme .playlist-restricted > ol > li > a {
|
||||||
|
color: #303030;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-theme .pure-menu-heading {
|
||||||
|
color: #565d64;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
.no-theme a:hover,
|
||||||
|
.no-theme a:active,
|
||||||
|
.no-theme summary:hover {
|
||||||
|
color: #075A9E !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-theme a.pure-button-primary:hover {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-theme a {
|
||||||
|
color: #335d7a;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All links that do not fit with the default color goes here */
|
||||||
|
.no-theme a:not([data-id]) > .icon,
|
||||||
|
.no-theme .pure-u-lg-1-5 > .h-box > a[href^="/watch?"],
|
||||||
|
.no-theme .playlist-restricted > ol > li > a {
|
||||||
|
color: #303030;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-theme .pure-menu-heading {
|
||||||
|
color: #565d64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dark theme
|
||||||
|
*/
|
||||||
|
|
||||||
|
.dark-theme a:hover,
|
||||||
|
.dark-theme a:active,
|
||||||
|
.dark-theme summary:hover {
|
||||||
|
color: rgb(0, 182, 240);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-theme a {
|
||||||
|
color: #a0a0a0;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-theme {
|
||||||
|
background-color: rgba(35, 35, 35, 1);
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-theme .pure-form legend {
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-theme .pure-menu-heading {
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-theme input,
|
||||||
|
.dark-theme select,
|
||||||
|
.dark-theme textarea {
|
||||||
|
color: rgba(35, 35, 35, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-theme .pure-form input[type="file"] {
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-theme .searchbar input {
|
||||||
|
background-color: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.no-theme a:hover,
|
||||||
|
.no-theme a:active {
|
||||||
|
color: rgb(0, 182, 240);
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-theme a {
|
||||||
|
color: #a0a0a0;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.no-theme {
|
||||||
|
background-color: rgba(35, 35, 35, 1);
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-theme .pure-form legend {
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-theme .pure-menu-heading {
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-theme input,
|
||||||
|
.no-theme select,
|
||||||
|
.no-theme textarea {
|
||||||
|
color: rgba(35, 35, 35, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-theme .pure-form input[type="file"] {
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-theme .searchbar input {
|
||||||
|
background-color: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*With commit d9528f5 all contents of the page is now within a flexbox. However,
|
||||||
|
the hr element is rendered improperly within one.
|
||||||
|
See https://stackoverflow.com/a/34372979 for more info */
|
||||||
|
hr {
|
||||||
|
margin: 10px 0 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Description Expansion Styling*/
|
||||||
|
#descexpansionbutton {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
#descexpansionbutton ~ div {
|
||||||
|
overflow: hidden;
|
||||||
|
height: 8.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#descexpansionbutton:checked ~ div {
|
||||||
|
overflow: unset;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#descexpansionbutton ~ label {
|
||||||
|
order: 1;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bidi (bidirectional text) support */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
p,
|
||||||
|
#descriptionWrapper,
|
||||||
|
#description-box {
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#descriptionWrapper {
|
||||||
|
max-width: 600px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Center the "invidious" logo on the search page */
|
||||||
|
#logo > h1 { text-align: center; }
|
||||||
|
|
||||||
|
/* IE11 fixes */
|
||||||
|
:-ms-input-placeholder { color: #888; }
|
||||||
|
|
||||||
|
/* Wider settings name to less word wrap */
|
||||||
|
.pure-form-aligned .pure-control-group label { width: 19em; }
|
||||||
|
|||||||
26
assets/css/embed.css
Normal file
26
assets/css/embed.css
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#player {
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
z-index: -100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.watch-on-invidious {
|
||||||
|
font-size: 1.3em !important;
|
||||||
|
font-weight: bold;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin: 0 1em 0 1em !important;
|
||||||
|
order: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.watch-on-invidious > a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.watch-on-invidious > a:hover {
|
||||||
|
color: rgba(0, 182, 240, 1);;
|
||||||
|
}
|
||||||
16
assets/css/empty.css
Normal file
16
assets/css/empty.css
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#search-widget {
|
||||||
|
text-align: center;
|
||||||
|
margin: 20vh 0 50px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logo > h1 {
|
||||||
|
font-size: 3.5em;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1500px) and (max-height: 1000px) {
|
||||||
|
#logo > h1 {
|
||||||
|
font-size: 10vmin;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
a:hover,
|
|
||||||
a:active {
|
|
||||||
color: #167ac6 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #61809b;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All links that do not fit with the default color goes here */
|
|
||||||
a:not([data-id]) > .icon,
|
|
||||||
.pure-u-lg-1-5 > .h-box > a[href^="/watch?"],
|
|
||||||
.playlist-restricted > ol > li > a {
|
|
||||||
color: #303030;
|
|
||||||
}
|
|
||||||
261
assets/css/player.css
Normal file
261
assets/css/player.css
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
/* Youtube player style */
|
||||||
|
.video-js.player-style-youtube .vjs-progress-control {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-progress-control .vjs-progress-holder, .video-js.player-style-youtube .vjs-progress-control {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-control-bar {
|
||||||
|
background: linear-gradient(rgba(0,0,0,0.1), rgba(0, 0, 0,0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-slider {
|
||||||
|
background-color: rgba(255,255,255,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-load-progress > div {
|
||||||
|
background-color: rgba(255,255,255,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-play-progress {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-progress-control:hover .vjs-progress-holder {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-control-bar > .vjs-spacer {
|
||||||
|
flex: 1;
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-play-progress .vjs-time-tooltip {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-play-progress::before {
|
||||||
|
color: red;
|
||||||
|
font-size: 0.85em;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-progress-holder:hover .vjs-play-progress::before {
|
||||||
|
display: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-control-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-big-play-button {
|
||||||
|
/*
|
||||||
|
Styles copied from video-js.min.css, definition of
|
||||||
|
.vjs-big-play-centered .vjs-big-play-button
|
||||||
|
*/
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin-top: -0.81666em;
|
||||||
|
margin-left: -1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-menu-button-popup .vjs-menu {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-youtube .vjs-progress-control .vjs-progress-holder, .video-js.player-style-youtube .vjs-progress-control {height: 5px;
|
||||||
|
margin-bottom: 10px;}
|
||||||
|
|
||||||
|
ul.vjs-menu-content::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-user-inactive {
|
||||||
|
cursor: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js .vjs-text-track-display > div > div > div {
|
||||||
|
background-color: rgba(0, 0, 0, 0.75) !important;
|
||||||
|
border-radius: 9px !important;
|
||||||
|
padding: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-play-control,
|
||||||
|
.vjs-volume-panel,
|
||||||
|
.vjs-current-time,
|
||||||
|
.vjs-time-control,
|
||||||
|
.vjs-duration,
|
||||||
|
.vjs-progress-control,
|
||||||
|
.vjs-remaining-time {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-captions-button {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-audio-button {
|
||||||
|
order: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-quality-selector,
|
||||||
|
.video-js .vjs-http-source-selector {
|
||||||
|
order: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-playback-rate {
|
||||||
|
order: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-share-control {
|
||||||
|
order: 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-fullscreen-control {
|
||||||
|
order: 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-playback-rate > .vjs-menu {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-control-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-control-bar::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js .vjs-icon-cog {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js .vjs-control-bar,
|
||||||
|
.vjs-menu-button-popup .vjs-menu .vjs-menu-content {
|
||||||
|
background-color: rgba(35, 35, 35, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-menu li.vjs-menu-item:focus,
|
||||||
|
.vjs-menu li.vjs-menu-item:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.75);
|
||||||
|
color: rgba(49, 49, 51, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-menu li.vjs-selected,
|
||||||
|
.vjs-menu li.vjs-selected:focus,
|
||||||
|
.vjs-menu li.vjs-selected:hover {
|
||||||
|
background-color: rgba(0, 182, 240, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Progress Bar */
|
||||||
|
.video-js .vjs-slider {
|
||||||
|
background-color: rgba(15, 15, 15, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js .vjs-load-progress,
|
||||||
|
.video-js .vjs-load-progress div {
|
||||||
|
background: rgba(87, 87, 88, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js .vjs-slider:hover,
|
||||||
|
.video-js button:hover {
|
||||||
|
color: rgba(0, 182, 240, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js.player-style-invidious .vjs-play-progress {
|
||||||
|
background-color: rgba(0, 182, 240, 1);
|
||||||
|
}
|
||||||
|
vjs-menu-content
|
||||||
|
/* Overlay */
|
||||||
|
.video-js .vjs-overlay {
|
||||||
|
background-color: rgba(35, 35, 35, 0.75);
|
||||||
|
color: rgba(255, 255, 255, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ProgressBar marker */
|
||||||
|
.vjs-marker {
|
||||||
|
background-color: rgba(255, 255, 255, 1);
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Big "Play" Button */
|
||||||
|
.video-js .vjs-big-play-button {
|
||||||
|
background-color: rgba(35, 35, 35, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js:hover .vjs-big-play-button {
|
||||||
|
background-color: rgba(35, 35, 35, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js .vjs-current-time,
|
||||||
|
.video-js .vjs-time-divider,
|
||||||
|
.video-js .vjs-duration {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js .vjs-time-divider {
|
||||||
|
min-width: 0px;
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-js .vjs-poster {
|
||||||
|
background-size: cover;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-dimensions.vjs-fluid {
|
||||||
|
padding-top: 82vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
video.video-js {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#player-container {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-right: 1em;
|
||||||
|
padding-bottom: 82vh;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-operations-bar {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 1px !important;
|
||||||
|
left: initial !important;
|
||||||
|
width: initial !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-operations-bar ul {
|
||||||
|
position: absolute !important;
|
||||||
|
bottom: unset !important;
|
||||||
|
top: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 700px) {
|
||||||
|
.video-js .vjs-share {
|
||||||
|
justify-content: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 650px) {
|
||||||
|
.vjs-modal-dialog-content {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
121
assets/css/search.css
Normal file
121
assets/css/search.css
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
summary {
|
||||||
|
/* This should hide the marker */
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
font-size: 1.17em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 auto 10px auto;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary::-webkit-details-marker,
|
||||||
|
summary::marker { display: none; }
|
||||||
|
|
||||||
|
summary:before {
|
||||||
|
border-radius: 5px;
|
||||||
|
content: "[ + ]";
|
||||||
|
margin: -2px 10px 0 10px;
|
||||||
|
padding: 1px 0 3px 0;
|
||||||
|
text-align: center;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
details[open] > summary:before { content: "[ − ]"; }
|
||||||
|
|
||||||
|
|
||||||
|
#filters-box {
|
||||||
|
padding: 10px 20px 20px 10px;
|
||||||
|
margin: 10px 15px;
|
||||||
|
}
|
||||||
|
#filters-flex {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-content: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fieldset, legend {
|
||||||
|
display: contents !important;
|
||||||
|
border: none !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.filter-column {
|
||||||
|
display: inline-block;
|
||||||
|
display: inline-flex;
|
||||||
|
width: max-content;
|
||||||
|
min-width: max-content;
|
||||||
|
max-width: 16em;
|
||||||
|
margin: 15px;
|
||||||
|
flex-grow: 2;
|
||||||
|
flex-basis: auto;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.filter-name, .filter-options {
|
||||||
|
display: block;
|
||||||
|
padding: 5px 10px;
|
||||||
|
margin: 0;
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-options div { margin: 6px 0; }
|
||||||
|
.filter-options div * { vertical-align: middle; }
|
||||||
|
.filter-options label { margin: 0 10px; }
|
||||||
|
|
||||||
|
|
||||||
|
#filters-apply {
|
||||||
|
text-align: right; /* IE11 only */
|
||||||
|
text-align: end; /* Override for compatible browsers */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error message */
|
||||||
|
|
||||||
|
.no-results-error {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 180%;
|
||||||
|
font-size: 110%;
|
||||||
|
padding: 15px 15px 125px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive rules */
|
||||||
|
|
||||||
|
@media only screen and (max-width: 800px) {
|
||||||
|
summary { font-size: 1.30em; }
|
||||||
|
#filters-box {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#filters-apply {
|
||||||
|
text-align: center;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light theme */
|
||||||
|
|
||||||
|
.light-theme #filters-box {
|
||||||
|
background: #dfdfdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
.no-theme #filters-box {
|
||||||
|
background: #dfdfdf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark theme */
|
||||||
|
|
||||||
|
.dark-theme #filters-box {
|
||||||
|
background: #373737;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.no-theme #filters-box {
|
||||||
|
background: #373737;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
assets/css/video-js.min.css
vendored
1
assets/css/video-js.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* videojs-http-source-selector
|
|
||||||
* @version 1.1.6
|
|
||||||
* @copyright 2019 Justin Fujita <Justin@pivotshare.com>
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
.video-js.vjs-http-source-selector{display:block}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
.video-js .vjs-overlay{color:#fff;position:absolute;text-align:center}.video-js .vjs-overlay-no-background{max-width:33%}.video-js .vjs-overlay-background{background-color:#646464;background-color:rgba(255,255,255,0.4);border-radius:3px;padding:10px;width:33%}.video-js .vjs-overlay-top-left{top:5px;left:5px}.video-js .vjs-overlay-top{left:50%;margin-left:-16.5%;top:5px}.video-js .vjs-overlay-top-right{right:5px;top:5px}.video-js .vjs-overlay-right{right:5px;top:50%;transform:translateY(-50%)}.video-js .vjs-overlay-bottom-right{bottom:3.5em;right:5px}.video-js .vjs-overlay-bottom{bottom:3.5em;left:50%;margin-left:-16.5%}.video-js .vjs-overlay-bottom-left{bottom:3.5em;left:5px}.video-js .vjs-overlay-left{left:5px;top:50%;transform:translateY(-50%)}.video-js .vjs-overlay-center{left:50%;margin-left:-16.5%;top:50%;transform:translateY(-50%)}.video-js .vjs-no-flex .vjs-overlay-left,.video-js .vjs-no-flex .vjs-overlay-center,.video-js .vjs-no-flex .vjs-overlay-right{margin-top:-15px}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* videojs-share
|
|
||||||
* @version 3.2.1
|
|
||||||
* @copyright 2019 Mikhail Khazov <mkhazov.work@gmail.com>
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
.video-js.vjs-videojs-share_open .vjs-modal-dialog .vjs-modal-dialog-content{display:flex;align-items:center;padding:0;background-image:linear-gradient(to bottom, rgba(0,0,0,0.77), rgba(0,0,0,0.75))}.video-js.vjs-videojs-share_open .vjs-modal-dialog .vjs-close-button{position:absolute;right:0;top:5px;width:30px;height:30px;color:#fff;cursor:pointer;opacity:0.9;transition:opacity 0.25s ease-out}.video-js.vjs-videojs-share_open .vjs-modal-dialog .vjs-close-button:before{content:'×';font-size:20px;line-height:15px}.video-js.vjs-videojs-share_open .vjs-modal-dialog .vjs-close-button:hover{opacity:1}.video-js .vjs-share{display:flex;flex-direction:column;justify-content:space-around;align-items:center;width:100%;height:100%;max-height:400px}.video-js .vjs-share__top,.video-js .vjs-share__middle,.video-js .vjs-share__bottom{display:flex}.video-js .vjs-share__top,.video-js .vjs-share__middle{flex-direction:column;justify-content:space-between}.video-js .vjs-share__middle{padding:0 25px}.video-js .vjs-share__title{align-self:center;font-size:22px;color:#fff}.video-js .vjs-share__subtitle{width:100%;margin:0 auto 12px;font-size:16px;color:#fff;opacity:0.7}.video-js .vjs-share__short-link-wrapper{position:relative;display:block;width:100%;height:40px;margin:0 auto;margin-bottom:15px;border:0;color:rgba(255,255,255,0.65);background-color:#363636;outline:none;overflow:hidden;flex-shrink:0}.video-js .vjs-share__short-link{display:block;width:100%;height:100%;padding:0 40px 0 15px;border:0;color:rgba(255,255,255,0.65);background-color:#363636;outline:none}.video-js .vjs-share__btn{position:absolute;right:0;bottom:0;height:40px;width:40px;display:flex;align-items:center;padding:0 11px;border:0;color:#fff;background-color:#2e2e2e;background-size:18px 19px;background-position:center;background-repeat:no-repeat;cursor:pointer;outline:none;transition:width 0.3s ease-out, padding 0.3s ease-out}.video-js .vjs-share__btn svg{flex-shrink:0}.video-js .vjs-share__btn span{position:relative;padding-left:10px;opacity:0;transition:opacity 0.3s ease-out}.video-js .vjs-share__btn:hover{justify-content:center;width:100%;padding:0 40px;background-image:none}.video-js .vjs-share__btn:hover span{opacity:1}.video-js .vjs-share__socials{display:flex;flex-wrap:wrap;justify-content:center;align-content:flex-start;transition:width 0.3s ease-out, height 0.3s ease-out}.video-js .vjs-share__social{display:flex;justify-content:center;align-items:center;flex-shrink:0;width:32px;height:32px;margin-right:6px;margin-bottom:6px;cursor:pointer;font-size:8px;transition:transform 0.3s ease-out, filter 0.2s ease-out;border:none;outline:none}.video-js .vjs-share__social:hover{filter:brightness(115%)}.video-js .vjs-share__social svg{overflow:visible;max-height:24px}.video-js .vjs-share__social_vk{background-color:#5d7294}.video-js .vjs-share__social_ok{background-color:#ed7c20}.video-js .vjs-share__social_mail,.video-js .vjs-share__social_email{background-color:#134785}.video-js .vjs-share__social_tw{background-color:#76aaeb}.video-js .vjs-share__social_reddit{background-color:#ff4500}.video-js .vjs-share__social_fbFeed{background-color:#475995}.video-js .vjs-share__social_messenger{background-color:#0084ff}.video-js .vjs-share__social_gp{background-color:#d53f35}.video-js .vjs-share__social_linkedin{background-color:#0077b5}.video-js .vjs-share__social_viber{background-color:#766db5}.video-js .vjs-share__social_telegram{background-color:#4bb0e2}.video-js .vjs-share__social_whatsapp{background-color:#78c870}.video-js .vjs-share__bottom{justify-content:center}@media (max-height: 220px){.video-js .vjs-share .hidden-xs{display:none}}@media (max-height: 350px){.video-js .vjs-share .hidden-sm{display:none}}@media (min-height: 400px){.video-js .vjs-share__title{margin-bottom:15px}.video-js .vjs-share__short-link-wrapper{margin-bottom:30px}}@media (min-width: 320px){.video-js.vjs-videojs-share_open .vjs-modal-dialog .vjs-close-button{right:5px;top:10px}}@media (min-width: 660px){.video-js.vjs-videojs-share_open .vjs-modal-dialog .vjs-close-button{right:20px;top:20px}.video-js .vjs-share__social{width:40px;height:40px}}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* videojs-vtt-thumbnails
|
|
||||||
* @version 0.0.13
|
|
||||||
* @copyright 2019 Chris Boustead <chris@forgemotion.com>
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
.video-js.vjs-vtt-thumbnails{display:block}.video-js .vjs-vtt-thumbnail-display{position:absolute;bottom:85%;pointer-events:none;box-shadow:0 0 7px rgba(0,0,0,0.6)}
|
|
||||||
1
assets/css/videojs.markers.min.css
vendored
1
assets/css/videojs.markers.min.css
vendored
@@ -1 +0,0 @@
|
|||||||
.vjs-marker{position:absolute;left:0;bottom:0;opacity:1;height:100%;transition:opacity .2s ease;-webkit-transition:opacity .2s ease;-moz-transition:opacity .2s ease;z-index:100}.vjs-marker:hover{cursor:pointer;-webkit-transform:scale(1.3,1.3);-moz-transform:scale(1.3,1.3);-o-transform:scale(1.3,1.3);-ms-transform:scale(1.3,1.3);transform:scale(1.3,1.3)}.vjs-tip{visibility:hidden;display:block;opacity:.8;padding:5px;font-size:10px;position:absolute;bottom:14px;z-index:100000}.vjs-tip .vjs-tip-arrow{background:url(data:image/gif;base64,R0lGODlhCQAJAIABAAAAAAAAACH5BAEAAAEALAAAAAAJAAkAAAIRjAOnwIrcDJxvwkplPtchVQAAOw==) no-repeat top left;bottom:0;left:50%;margin-left:-4px;background-position:bottom left;position:absolute;width:9px;height:5px}.vjs-tip .vjs-tip-inner{border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;padding:5px 8px 4px 8px;background-color:#000;color:#fff;max-width:200px;text-align:center}.vjs-break-overlay{visibility:hidden;position:absolute;z-index:100000;top:0}.vjs-break-overlay .vjs-break-overlay-text{padding:9px;text-align:center}
|
|
||||||
2
assets/invidious-colored-vector.svg
Normal file
2
assets/invidious-colored-vector.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="512pt" height="512pt" version="1.0" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><g><rect x="-.0072516" y=".00056299" width="512.01" height="512.02" fill="#575757" stroke-width=".063019"/><path d="m247.17 455.95c-19.792-0.78921-38.719-4.2564-57.154-10.47-60.968-20.55-108.68-68.579-127-127.86-7.8955-25.538-10.062-53.943-6.2586-82.067 3.7105-27.439 13.603-53.515 29.342-77.344 12.069-18.273 29.138-36.277 47.228-49.816 36.891-27.61 85.944-42.49 132.38-40.157 25.88 1.3001 49.939 6.765 73.106 16.606 8.1948 3.481 20.024 9.6845 27.696 14.525 14.15 8.9272 22.367 15.498 34.482 27.573 13.254 13.211 22.128 24.276 30.398 37.906 7.2081 11.879 14.099 27.15 18.229 40.397 1.5996 5.1305 4.442 16.456 5.6852 22.653 2.3908 11.917 2.6998 15.722 2.7049 33.312 6e-3 18.515-0.46256 24.413-2.9166 36.758-9.3274 46.92-35.58 88.167-74.872 117.64-22.814 17.112-50.027 29.535-78.547 35.858-16.714 3.7059-35.421 5.2453-54.498 4.4846zm-35.1-78.786c-5.3e-4 -0.52647-0.0741-2.0564-0.16311-3.3999l-0.16178-2.4427-4.7018-0.26271c-4.0477-0.22614-4.7968-0.33363-5.3847-0.77253-2.0235-1.5108-1.4679-6.0695 2.2494-18.457 0.8637-2.8781 3.3371-11.321 5.4966-18.762 2.1594-7.4409 5.2002-17.836 6.7573-23.101 1.5571-5.2648 4.1948-14.282 5.8615-20.038 1.6667-5.7562 3.6145-12.4 4.3284-14.764 0.71391-2.3641 3.2583-11.037 5.6542-19.272 4.9475-17.007 8.1626-27.723 8.9438-29.811 0.51852-1.3858 0.54785-1.4139 0.99761-0.95317 0.25486 0.26106 3.8462 7.3667 7.9807 15.79 4.1345 8.4236 13.089 26.573 19.898 40.331 17.188 34.73 37.849 76.578 43.261 87.622l4.5356 9.257 11.359-0.0895c6.2475-0.0492 11.615-0.19623 11.929-0.32672 0.5614-0.23385 0.54167-0.2959-1.3723-4.3176-1.068-2.2442-8.1436-16.601-15.724-31.904-48.687-98.293-61.22-123.86-67.889-138.48-4.7022-10.309-6.9031-14.807-7.7139-15.762-0.82931-0.97742-1.6319-1.0638-2.3704-0.25525-1.1993 1.313-4.1046 10.063-9.3869 28.27-2.0569 7.0899-6.5372 22.425-9.9562 34.077-6.6396 22.629-8.5182 29.037-14.33 48.883-2.0354 6.9495-4.7977 16.369-6.1385 20.931-1.3408 4.5628-4.033 13.81-5.9826 20.549-4.304 14.877-6.136 20.889-7.3886 24.25-2.1371 5.7334-2.5723 6.3292-4.9216 6.7384-0.88855 0.15472-2.4102 0.28196-3.3815 0.28275-2.1993 3e-3 -3.5494 0.36339-4.0558 1.0863-0.42176 0.60215-0.56421 4.8802-0.18251 5.4812 0.20573 0.32388 2.4672 0.37414 23.34 0.51873l8.6151 0.0597-7e-4 -0.95723zm36.751-205.59c4.3282-0.92335 8.4607-4.943 9.4374-9.1796 0.36569-1.5862 0.32543-4.9758-0.077-6.4799-0.85108-3.1813-3.2688-6.291-6.039-7.7675-3.8111-2.0313-9.456-2.0295-13.272 5e-3 -5.9828 3.1888-8.1556 11.089-4.7878 17.408 2.6995 5.0648 8.3611 7.3754 14.738 6.015z" fill="#f0f0f0" stroke-width=".025526"/></g><g transform="matrix(.069892 0 0 -.069892 44.236 474.48)"><path d="m2787 4669c-124-65-123-255 3-319 86-44 196-16 247 62 58 87 26 211-67 258-51 26-132 26-183-1z" fill="#00b6f0" stroke="#00b6f0" stroke-width="4.25"/><path d="m2882 4108c-12-16-63-166-102-303-30-104-101-350-165-565-20-69-58-199-85-290-26-91-64-221-85-290-20-69-58-199-85-290-26-91-64-221-85-290-20-69-57-195-81-280-59-207-93-299-115-310-10-6-35-10-56-10-73 0-84-8-81-54l3-41 228-3 228-2-3 47-3 48-73 3c-66 3-74 5-84 27-13 28 0 104 37 225 13 41 47 156 75 255s66 230 85 290c18 61 56 191 85 290 28 99 66 230 85 290 18 61 56 191 85 290 85 297 123 419 131 429 5 5 17-11 28-35 10-24 192-393 403-819s447-902 523-1058l139-282h168c92 0 168 4 168 8s-75 158-166 342c-588 1183-969 1958-1033 2100-29 63-69 151-89 195-44 95-58 110-80 83z" fill="#575757"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 3.4 KiB |
249
assets/js/_helpers.js
Normal file
249
assets/js/_helpers.js
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
'use strict';
|
||||||
|
// Contains only auxiliary methods
|
||||||
|
// May be included and executed unlimited number of times without any consequences
|
||||||
|
|
||||||
|
// Polyfills for IE11
|
||||||
|
Array.prototype.find = Array.prototype.find || function (condition) {
|
||||||
|
return this.filter(condition)[0];
|
||||||
|
};
|
||||||
|
Array.from = Array.from || function (source) {
|
||||||
|
return Array.prototype.slice.call(source);
|
||||||
|
};
|
||||||
|
NodeList.prototype.forEach = NodeList.prototype.forEach || function (callback) {
|
||||||
|
Array.from(this).forEach(callback);
|
||||||
|
};
|
||||||
|
String.prototype.includes = String.prototype.includes || function (searchString) {
|
||||||
|
return this.indexOf(searchString) >= 0;
|
||||||
|
};
|
||||||
|
String.prototype.startsWith = String.prototype.startsWith || function (prefix) {
|
||||||
|
return this.substr(0, prefix.length) === prefix;
|
||||||
|
};
|
||||||
|
Math.sign = Math.sign || function(x) {
|
||||||
|
x = +x;
|
||||||
|
if (!x) return x; // 0 and NaN
|
||||||
|
return x > 0 ? 1 : -1;
|
||||||
|
};
|
||||||
|
if (!window.hasOwnProperty('HTMLDetailsElement') && !window.hasOwnProperty('mockHTMLDetailsElement')) {
|
||||||
|
window.mockHTMLDetailsElement = true;
|
||||||
|
const style = 'details:not([open]) > :not(summary) {display: none}';
|
||||||
|
document.head.appendChild(document.createElement('style')).textContent = style;
|
||||||
|
|
||||||
|
addEventListener('click', function (e) {
|
||||||
|
if (e.target.nodeName !== 'SUMMARY') return;
|
||||||
|
const details = e.target.parentElement;
|
||||||
|
if (details.hasAttribute('open'))
|
||||||
|
details.removeAttribute('open');
|
||||||
|
else
|
||||||
|
details.setAttribute('open', '');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monstrous global variable for handy code
|
||||||
|
// Includes: clamp, xhr, storage.{get,set,remove}
|
||||||
|
window.helpers = window.helpers || {
|
||||||
|
/**
|
||||||
|
* https://en.wikipedia.org/wiki/Clamping_(graphics)
|
||||||
|
* @param {Number} num Source number
|
||||||
|
* @param {Number} min Low border
|
||||||
|
* @param {Number} max High border
|
||||||
|
* @returns {Number} Clamped value
|
||||||
|
*/
|
||||||
|
clamp: function (num, min, max) {
|
||||||
|
if (max < min) {
|
||||||
|
var t = max; max = min; min = t; // swap max and min
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max < num)
|
||||||
|
return max;
|
||||||
|
if (min > num)
|
||||||
|
return min;
|
||||||
|
return num;
|
||||||
|
},
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
_xhr: function (method, url, options, callbacks) {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open(method, url);
|
||||||
|
|
||||||
|
// Default options
|
||||||
|
xhr.responseType = 'json';
|
||||||
|
xhr.timeout = 10000;
|
||||||
|
// Default options redefining
|
||||||
|
if (options.responseType)
|
||||||
|
xhr.responseType = options.responseType;
|
||||||
|
if (options.timeout)
|
||||||
|
xhr.timeout = options.timeout;
|
||||||
|
|
||||||
|
if (method === 'POST')
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||||
|
|
||||||
|
// better than onreadystatechange because of 404 codes https://stackoverflow.com/a/36182963
|
||||||
|
xhr.onloadend = function () {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
if (callbacks.on200) {
|
||||||
|
// fix for IE11. It doesn't convert response to JSON
|
||||||
|
if (xhr.responseType === '' && typeof(xhr.response) === 'string')
|
||||||
|
callbacks.on200(JSON.parse(xhr.response));
|
||||||
|
else
|
||||||
|
callbacks.on200(xhr.response);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// handled by onerror
|
||||||
|
if (xhr.status === 0) return;
|
||||||
|
|
||||||
|
if (callbacks.onNon200)
|
||||||
|
callbacks.onNon200(xhr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.ontimeout = function () {
|
||||||
|
if (callbacks.onTimeout)
|
||||||
|
callbacks.onTimeout(xhr);
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = function () {
|
||||||
|
if (callbacks.onError)
|
||||||
|
callbacks.onError(xhr);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.payload)
|
||||||
|
xhr.send(options.payload);
|
||||||
|
else
|
||||||
|
xhr.send();
|
||||||
|
},
|
||||||
|
/** @private */
|
||||||
|
_xhrRetry: function(method, url, options, callbacks) {
|
||||||
|
if (options.retries <= 0) {
|
||||||
|
console.warn('Failed to pull', options.entity_name);
|
||||||
|
if (callbacks.onTotalFail)
|
||||||
|
callbacks.onTotalFail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
helpers._xhr(method, url, options, callbacks);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @callback callbackXhrOn200
|
||||||
|
* @param {Object} response - xhr.response
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @callback callbackXhrError
|
||||||
|
* @param {XMLHttpRequest} xhr
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @param {'GET'|'POST'} method - 'GET' or 'POST'
|
||||||
|
* @param {String} url - URL to send request to
|
||||||
|
* @param {Object} options - other XHR options
|
||||||
|
* @param {XMLHttpRequestBodyInit} [options.payload=null] - payload for POST-requests
|
||||||
|
* @param {'arraybuffer'|'blob'|'document'|'json'|'text'} [options.responseType=json]
|
||||||
|
* @param {Number} [options.timeout=10000]
|
||||||
|
* @param {Number} [options.retries=1]
|
||||||
|
* @param {String} [options.entity_name='unknown'] - string to log
|
||||||
|
* @param {Number} [options.retry_timeout=1000]
|
||||||
|
* @param {Object} callbacks - functions to execute on events fired
|
||||||
|
* @param {callbackXhrOn200} [callbacks.on200]
|
||||||
|
* @param {callbackXhrError} [callbacks.onNon200]
|
||||||
|
* @param {callbackXhrError} [callbacks.onTimeout]
|
||||||
|
* @param {callbackXhrError} [callbacks.onError]
|
||||||
|
* @param {callbackXhrError} [callbacks.onTotalFail] - if failed after all retries
|
||||||
|
*/
|
||||||
|
xhr: function(method, url, options, callbacks) {
|
||||||
|
if (!options.retries || options.retries <= 1) {
|
||||||
|
helpers._xhr(method, url, options, callbacks);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.entity_name) options.entity_name = 'unknown';
|
||||||
|
if (!options.retry_timeout) options.retry_timeout = 1000;
|
||||||
|
const retries_total = options.retries;
|
||||||
|
let currentTry = 1;
|
||||||
|
|
||||||
|
const retry = function () {
|
||||||
|
console.warn('Pulling ' + options.entity_name + ' failed... ' + (currentTry++) + '/' + retries_total);
|
||||||
|
setTimeout(function () {
|
||||||
|
options.retries--;
|
||||||
|
helpers._xhrRetry(method, url, options, callbacks);
|
||||||
|
}, options.retry_timeout);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pack retry() call into error handlers
|
||||||
|
callbacks._onError = callbacks.onError;
|
||||||
|
callbacks.onError = function (xhr) {
|
||||||
|
if (callbacks._onError)
|
||||||
|
callbacks._onError(xhr);
|
||||||
|
retry();
|
||||||
|
};
|
||||||
|
callbacks._onTimeout = callbacks.onTimeout;
|
||||||
|
callbacks.onTimeout = function (xhr) {
|
||||||
|
if (callbacks._onTimeout)
|
||||||
|
callbacks._onTimeout(xhr);
|
||||||
|
retry();
|
||||||
|
};
|
||||||
|
|
||||||
|
helpers._xhrRetry(method, url, options, callbacks);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} invidiousStorage
|
||||||
|
* @property {(key:String) => Object} get
|
||||||
|
* @property {(key:String, value:Object)} set
|
||||||
|
* @property {(key:String)} remove
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Universal storage, stores and returns JS objects. Uses inside localStorage or cookies
|
||||||
|
* @type {invidiousStorage}
|
||||||
|
*/
|
||||||
|
storage: (function () {
|
||||||
|
// access to localStorage throws exception in Tor Browser, so try is needed
|
||||||
|
let localStorageIsUsable = false;
|
||||||
|
try{localStorageIsUsable = !!localStorage.setItem;}catch(e){}
|
||||||
|
|
||||||
|
if (localStorageIsUsable) {
|
||||||
|
return {
|
||||||
|
get: function (key) {
|
||||||
|
if (!localStorage[key]) return;
|
||||||
|
try {
|
||||||
|
return JSON.parse(decodeURIComponent(localStorage[key]));
|
||||||
|
} catch(e) {
|
||||||
|
// Erase non parsable value
|
||||||
|
helpers.storage.remove(key);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set: function (key, value) { localStorage[key] = encodeURIComponent(JSON.stringify(value)); },
|
||||||
|
remove: function (key) { localStorage.removeItem(key); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: fire 'storage' event for cookies
|
||||||
|
console.info('Storage: localStorage is disabled or unaccessible. Cookies used as fallback');
|
||||||
|
return {
|
||||||
|
get: function (key) {
|
||||||
|
const cookiePrefix = key + '=';
|
||||||
|
function findCallback(cookie) {return cookie.startsWith(cookiePrefix);}
|
||||||
|
const matchedCookie = document.cookie.split('; ').find(findCallback);
|
||||||
|
if (matchedCookie) {
|
||||||
|
const cookieBody = matchedCookie.replace(cookiePrefix, '');
|
||||||
|
if (cookieBody.length === 0) return;
|
||||||
|
try {
|
||||||
|
return JSON.parse(decodeURIComponent(cookieBody));
|
||||||
|
} catch(e) {
|
||||||
|
// Erase non parsable value
|
||||||
|
helpers.storage.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set: function (key, value) {
|
||||||
|
const cookie_data = encodeURIComponent(JSON.stringify(value));
|
||||||
|
|
||||||
|
// Set expiration in 2 year
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear()+2);
|
||||||
|
|
||||||
|
document.cookie = key + '=' + cookie_data + '; expires=' + date.toGMTString();
|
||||||
|
},
|
||||||
|
remove: function (key) {
|
||||||
|
document.cookie = key + '=; Max-Age=0';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})()
|
||||||
|
};
|
||||||
@@ -1,17 +1,13 @@
|
|||||||
String.prototype.supplant = function (o) {
|
'use strict';
|
||||||
return this.replace(/{([^{}]*)}/g, function (a, b) {
|
var community_data = JSON.parse(document.getElementById('community_data').textContent);
|
||||||
var r = o[b];
|
|
||||||
return typeof r === 'string' || typeof r === 'number' ? r : a;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function hide_youtube_replies(event) {
|
function hide_youtube_replies(event) {
|
||||||
var target = event.target;
|
var target = event.target;
|
||||||
|
|
||||||
sub_text = target.getAttribute('data-inner-text');
|
var sub_text = target.getAttribute('data-inner-text');
|
||||||
inner_text = target.getAttribute('data-sub-text');
|
var inner_text = target.getAttribute('data-sub-text');
|
||||||
|
|
||||||
body = target.parentNode.parentNode.children[1];
|
var body = target.parentNode.parentNode.children[1];
|
||||||
body.style.display = 'none';
|
body.style.display = 'none';
|
||||||
|
|
||||||
target.innerHTML = sub_text;
|
target.innerHTML = sub_text;
|
||||||
@@ -23,10 +19,10 @@ function hide_youtube_replies(event) {
|
|||||||
function show_youtube_replies(event) {
|
function show_youtube_replies(event) {
|
||||||
var target = event.target;
|
var target = event.target;
|
||||||
|
|
||||||
sub_text = target.getAttribute('data-inner-text');
|
var sub_text = target.getAttribute('data-inner-text');
|
||||||
inner_text = target.getAttribute('data-sub-text');
|
var inner_text = target.getAttribute('data-sub-text');
|
||||||
|
|
||||||
body = target.parentNode.parentNode.children[1];
|
var body = target.parentNode.parentNode.children[1];
|
||||||
body.style.display = '';
|
body.style.display = '';
|
||||||
|
|
||||||
target.innerHTML = sub_text;
|
target.innerHTML = sub_text;
|
||||||
@@ -35,13 +31,6 @@ function show_youtube_replies(event) {
|
|||||||
target.setAttribute('data-sub-text', sub_text);
|
target.setAttribute('data-sub-text', sub_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
function number_with_separator(val) {
|
|
||||||
while (/(\d+)(\d{3})/.test(val.toString())) {
|
|
||||||
val = val.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_youtube_replies(target, load_more) {
|
function get_youtube_replies(target, load_more) {
|
||||||
var continuation = target.getAttribute('data-continuation');
|
var continuation = target.getAttribute('data-continuation');
|
||||||
|
|
||||||
@@ -55,47 +44,39 @@ function get_youtube_replies(target, load_more) {
|
|||||||
'&hl=' + community_data.preferences.locale +
|
'&hl=' + community_data.preferences.locale +
|
||||||
'&thin_mode=' + community_data.preferences.thin_mode +
|
'&thin_mode=' + community_data.preferences.thin_mode +
|
||||||
'&continuation=' + continuation;
|
'&continuation=' + continuation;
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('GET', url, true);
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
helpers.xhr('GET', url, {}, {
|
||||||
if (xhr.readyState == 4) {
|
on200: function (response) {
|
||||||
if (xhr.status == 200) {
|
if (load_more) {
|
||||||
if (load_more) {
|
body = body.parentNode.parentNode;
|
||||||
body = body.parentNode.parentNode;
|
body.removeChild(body.lastElementChild);
|
||||||
body.removeChild(body.lastElementChild);
|
body.innerHTML += response.contentHtml;
|
||||||
body.innerHTML += xhr.response.contentHtml;
|
|
||||||
} else {
|
|
||||||
body.removeChild(body.lastElementChild);
|
|
||||||
|
|
||||||
var p = document.createElement('p');
|
|
||||||
var a = document.createElement('a');
|
|
||||||
p.appendChild(a);
|
|
||||||
|
|
||||||
a.href = 'javascript:void(0)';
|
|
||||||
a.onclick = hide_youtube_replies;
|
|
||||||
a.setAttribute('data-sub-text', community_data.hide_replies_text);
|
|
||||||
a.setAttribute('data-inner-text', community_data.show_replies_text);
|
|
||||||
a.innerText = community_data.hide_replies_text;
|
|
||||||
|
|
||||||
var div = document.createElement('div');
|
|
||||||
div.innerHTML = xhr.response.contentHtml;
|
|
||||||
|
|
||||||
body.appendChild(p);
|
|
||||||
body.appendChild(div);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
body.innerHTML = fallback;
|
body.removeChild(body.lastElementChild);
|
||||||
|
|
||||||
|
var p = document.createElement('p');
|
||||||
|
var a = document.createElement('a');
|
||||||
|
p.appendChild(a);
|
||||||
|
|
||||||
|
a.href = 'javascript:void(0)';
|
||||||
|
a.onclick = hide_youtube_replies;
|
||||||
|
a.setAttribute('data-sub-text', community_data.hide_replies_text);
|
||||||
|
a.setAttribute('data-inner-text', community_data.show_replies_text);
|
||||||
|
a.textContent = community_data.hide_replies_text;
|
||||||
|
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.innerHTML = response.contentHtml;
|
||||||
|
|
||||||
|
body.appendChild(p);
|
||||||
|
body.appendChild(div);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onNon200: function (xhr) {
|
||||||
|
body.innerHTML = fallback;
|
||||||
|
},
|
||||||
|
onTimeout: function (xhr) {
|
||||||
|
console.warn('Pulling comments failed');
|
||||||
|
body.innerHTML = fallback;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
|
||||||
console.log('Pulling comments failed.');
|
|
||||||
body.innerHTML = fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,100 +1,62 @@
|
|||||||
function get_playlist(plid, retries) {
|
'use strict';
|
||||||
if (retries == undefined) retries = 5;
|
var video_data = JSON.parse(document.getElementById('video_data').textContent);
|
||||||
|
|
||||||
if (retries <= 0) {
|
|
||||||
console.log('Failed to pull playlist');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
function get_playlist(plid) {
|
||||||
|
var plid_url;
|
||||||
if (plid.startsWith('RD')) {
|
if (plid.startsWith('RD')) {
|
||||||
var plid_url = '/api/v1/mixes/' + plid +
|
plid_url = '/api/v1/mixes/' + plid +
|
||||||
'?continuation=' + video_data.id +
|
'?continuation=' + video_data.id +
|
||||||
'&format=html&hl=' + video_data.preferences.locale;
|
'&format=html&hl=' + video_data.preferences.locale;
|
||||||
} else {
|
} else {
|
||||||
var plid_url = '/api/v1/playlists/' + plid +
|
plid_url = '/api/v1/playlists/' + plid +
|
||||||
'?index=' + video_data.index +
|
'?index=' + video_data.index +
|
||||||
'&continuation' + video_data.id +
|
'&continuation' + video_data.id +
|
||||||
'&format=html&hl=' + video_data.preferences.locale;
|
'&format=html&hl=' + video_data.preferences.locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
helpers.xhr('GET', plid_url, {retries: 5, entity_name: 'playlist'}, {
|
||||||
xhr.responseType = 'json';
|
on200: function (response) {
|
||||||
xhr.timeout = 10000;
|
if (!response.nextVideo)
|
||||||
xhr.open('GET', plid_url, true);
|
return;
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
player.on('ended', function () {
|
||||||
if (xhr.readyState === 4) {
|
var url = new URL('https://example.com/embed/' + response.nextVideo);
|
||||||
if (xhr.status === 200) {
|
|
||||||
if (xhr.response.nextVideo) {
|
|
||||||
player.on('ended', function () {
|
|
||||||
var url = new URL('https://example.com/embed/' + xhr.response.nextVideo);
|
|
||||||
|
|
||||||
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
|
url.searchParams.set('list', plid);
|
||||||
url.searchParams.set('autoplay', '1');
|
if (!plid.startsWith('RD'))
|
||||||
}
|
url.searchParams.set('index', response.index);
|
||||||
|
if (video_data.params.autoplay || video_data.params.continue_autoplay)
|
||||||
|
url.searchParams.set('autoplay', '1');
|
||||||
|
if (video_data.params.listen !== video_data.preferences.listen)
|
||||||
|
url.searchParams.set('listen', video_data.params.listen);
|
||||||
|
if (video_data.params.speed !== video_data.preferences.speed)
|
||||||
|
url.searchParams.set('speed', video_data.params.speed);
|
||||||
|
if (video_data.params.local !== video_data.preferences.local)
|
||||||
|
url.searchParams.set('local', video_data.params.local);
|
||||||
|
|
||||||
if (video_data.params.listen !== video_data.preferences.listen) {
|
location.assign(url.pathname + url.search);
|
||||||
url.searchParams.set('listen', video_data.params.listen);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if (video_data.params.speed !== video_data.preferences.speed) {
|
|
||||||
url.searchParams.set('speed', video_data.params.speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (video_data.params.local !== video_data.preferences.local) {
|
|
||||||
url.searchParams.set('local', video_data.params.local);
|
|
||||||
}
|
|
||||||
|
|
||||||
url.searchParams.set('list', plid);
|
|
||||||
if (!plid.startsWith('RD')) {
|
|
||||||
url.searchParams.set('index', xhr.response.index);
|
|
||||||
}
|
|
||||||
location.assign(url.pathname + url.search);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
xhr.onerror = function () {
|
|
||||||
console.log('Pulling playlist failed... ' + retries + '/5');
|
|
||||||
setTimeout(function () { get_playlist(plid, retries - 1) }, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
|
||||||
console.log('Pulling playlist failed... ' + retries + '/5');
|
|
||||||
get_playlist(plid, retries - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('load', function (e) {
|
addEventListener('load', function (e) {
|
||||||
if (video_data.plid) {
|
if (video_data.plid) {
|
||||||
get_playlist(video_data.plid);
|
get_playlist(video_data.plid);
|
||||||
} else if (video_data.video_series) {
|
} else if (video_data.video_series) {
|
||||||
player.on('ended', function () {
|
player.on('ended', function () {
|
||||||
var url = new URL('https://example.com/embed/' + video_data.video_series.shift());
|
var url = new URL('https://example.com/embed/' + video_data.video_series.shift());
|
||||||
|
|
||||||
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
|
if (video_data.params.autoplay || video_data.params.continue_autoplay)
|
||||||
url.searchParams.set('autoplay', '1');
|
url.searchParams.set('autoplay', '1');
|
||||||
}
|
if (video_data.params.listen !== video_data.preferences.listen)
|
||||||
|
|
||||||
if (video_data.params.listen !== video_data.preferences.listen) {
|
|
||||||
url.searchParams.set('listen', video_data.params.listen);
|
url.searchParams.set('listen', video_data.params.listen);
|
||||||
}
|
if (video_data.params.speed !== video_data.preferences.speed)
|
||||||
|
|
||||||
if (video_data.params.speed !== video_data.preferences.speed) {
|
|
||||||
url.searchParams.set('speed', video_data.params.speed);
|
url.searchParams.set('speed', video_data.params.speed);
|
||||||
}
|
if (video_data.params.local !== video_data.preferences.local)
|
||||||
|
|
||||||
if (video_data.params.local !== video_data.preferences.local) {
|
|
||||||
url.searchParams.set('local', video_data.params.local);
|
url.searchParams.set('local', video_data.params.local);
|
||||||
}
|
if (video_data.video_series.length !== 0)
|
||||||
|
url.searchParams.set('playlist', video_data.video_series.join(','));
|
||||||
if (video_data.video_series.length !== 0) {
|
|
||||||
url.searchParams.set('playlist', video_data.video_series.join(','))
|
|
||||||
}
|
|
||||||
|
|
||||||
location.assign(url.pathname + url.search);
|
location.assign(url.pathname + url.search);
|
||||||
});
|
});
|
||||||
|
|||||||
149
assets/js/handlers.js
Normal file
149
assets/js/handlers.js
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
var video_player = document.getElementById('player_html5_api');
|
||||||
|
if (video_player) {
|
||||||
|
video_player.onmouseenter = function () { video_player['data-title'] = video_player['title']; video_player['title'] = ''; };
|
||||||
|
video_player.onmouseleave = function () { video_player['title'] = video_player['data-title']; video_player['data-title'] = ''; };
|
||||||
|
video_player.oncontextmenu = function () { video_player['title'] = video_player['data-title']; };
|
||||||
|
}
|
||||||
|
|
||||||
|
// For dynamically inserted elements
|
||||||
|
addEventListener('click', function (e) {
|
||||||
|
if (!e || !e.target) return;
|
||||||
|
|
||||||
|
var t = e.target;
|
||||||
|
var handler_name = t.getAttribute('data-onclick');
|
||||||
|
|
||||||
|
switch (handler_name) {
|
||||||
|
case 'jump_to_time':
|
||||||
|
e.preventDefault();
|
||||||
|
var time = t.getAttribute('data-jump-time');
|
||||||
|
player.currentTime(time);
|
||||||
|
break;
|
||||||
|
case 'get_youtube_replies':
|
||||||
|
var load_more = t.getAttribute('data-load-more') !== null;
|
||||||
|
var load_replies = t.getAttribute('data-load-replies') !== null;
|
||||||
|
get_youtube_replies(t, load_more, load_replies);
|
||||||
|
break;
|
||||||
|
case 'toggle_parent':
|
||||||
|
e.preventDefault();
|
||||||
|
toggle_parent(t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('[data-mouse="switch_classes"]').forEach(function (el) {
|
||||||
|
var classes = el.getAttribute('data-switch-classes').split(',');
|
||||||
|
var classOnEnter = classes[0];
|
||||||
|
var classOnLeave = classes[1];
|
||||||
|
function toggle_classes(toAdd, toRemove) {
|
||||||
|
el.classList.add(toAdd);
|
||||||
|
el.classList.remove(toRemove);
|
||||||
|
}
|
||||||
|
el.onmouseenter = function () { toggle_classes(classOnEnter, classOnLeave); };
|
||||||
|
el.onmouseleave = function () { toggle_classes(classOnLeave, classOnEnter); };
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('[data-onsubmit="return_false"]').forEach(function (el) {
|
||||||
|
el.onsubmit = function () { return false; };
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('[data-onclick="mark_watched"]').forEach(function (el) {
|
||||||
|
el.onclick = function () { mark_watched(el); };
|
||||||
|
});
|
||||||
|
document.querySelectorAll('[data-onclick="mark_unwatched"]').forEach(function (el) {
|
||||||
|
el.onclick = function () { mark_unwatched(el); };
|
||||||
|
});
|
||||||
|
document.querySelectorAll('[data-onclick="add_playlist_video"]').forEach(function (el) {
|
||||||
|
el.onclick = function () { add_playlist_video(el); };
|
||||||
|
});
|
||||||
|
document.querySelectorAll('[data-onclick="add_playlist_item"]').forEach(function (el) {
|
||||||
|
el.onclick = function () { add_playlist_item(el); };
|
||||||
|
});
|
||||||
|
document.querySelectorAll('[data-onclick="remove_playlist_item"]').forEach(function (el) {
|
||||||
|
el.onclick = function () { remove_playlist_item(el); };
|
||||||
|
});
|
||||||
|
document.querySelectorAll('[data-onclick="revoke_token"]').forEach(function (el) {
|
||||||
|
el.onclick = function () { revoke_token(el); };
|
||||||
|
});
|
||||||
|
document.querySelectorAll('[data-onclick="remove_subscription"]').forEach(function (el) {
|
||||||
|
el.onclick = function () { remove_subscription(el); };
|
||||||
|
});
|
||||||
|
document.querySelectorAll('[data-onclick="notification_requestPermission"]').forEach(function (el) {
|
||||||
|
el.onclick = function () { Notification.requestPermission(); };
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('[data-onrange="update_volume_value"]').forEach(function (el) {
|
||||||
|
function update_volume_value() {
|
||||||
|
document.getElementById('volume-value').textContent = el.value;
|
||||||
|
}
|
||||||
|
el.oninput = update_volume_value;
|
||||||
|
el.onchange = update_volume_value;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function revoke_token(target) {
|
||||||
|
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||||
|
row.style.display = 'none';
|
||||||
|
var count = document.getElementById('count');
|
||||||
|
count.textContent--;
|
||||||
|
|
||||||
|
var url = '/token_ajax?action_revoke_token=1&redirect=false' +
|
||||||
|
'&referer=' + encodeURIComponent(location.href) +
|
||||||
|
'&session=' + target.getAttribute('data-session');
|
||||||
|
|
||||||
|
var payload = 'csrf_token=' + target.parentNode.querySelector('input[name="csrf_token"]').value;
|
||||||
|
|
||||||
|
helpers.xhr('POST', url, {payload: payload}, {
|
||||||
|
onNon200: function (xhr) {
|
||||||
|
count.textContent++;
|
||||||
|
row.style.display = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_subscription(target) {
|
||||||
|
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||||
|
row.style.display = 'none';
|
||||||
|
var count = document.getElementById('count');
|
||||||
|
count.textContent--;
|
||||||
|
|
||||||
|
var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' +
|
||||||
|
'&referer=' + encodeURIComponent(location.href) +
|
||||||
|
'&c=' + target.getAttribute('data-ucid');
|
||||||
|
|
||||||
|
var payload = 'csrf_token=' + target.parentNode.querySelector('input[name="csrf_token"]').value;
|
||||||
|
|
||||||
|
helpers.xhr('POST', url, {payload: payload}, {
|
||||||
|
onNon200: function (xhr) {
|
||||||
|
count.textContent++;
|
||||||
|
row.style.display = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle keypresses
|
||||||
|
addEventListener('keydown', function (event) {
|
||||||
|
// Ignore modifier keys
|
||||||
|
if (event.ctrlKey || event.metaKey) return;
|
||||||
|
|
||||||
|
// Ignore shortcuts if any text input is focused
|
||||||
|
let focused_tag = document.activeElement.tagName.toLowerCase();
|
||||||
|
const allowed = /^(button|checkbox|file|radio|submit)$/;
|
||||||
|
|
||||||
|
if (focused_tag === 'textarea') return;
|
||||||
|
if (focused_tag === 'input') {
|
||||||
|
let focused_type = document.activeElement.type.toLowerCase();
|
||||||
|
if (!focused_type.match(allowed)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus search bar on '/'
|
||||||
|
if (event.key === '/') {
|
||||||
|
document.getElementById('searchbox').focus();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -1,44 +1,30 @@
|
|||||||
|
'use strict';
|
||||||
|
var notification_data = JSON.parse(document.getElementById('notification_data').textContent);
|
||||||
|
|
||||||
|
/** Boolean meaning 'some tab have stream' */
|
||||||
|
const STORAGE_KEY_STREAM = 'stream';
|
||||||
|
/** Number of notifications. May be increased or reset */
|
||||||
|
const STORAGE_KEY_NOTIF_COUNT = 'notification_count';
|
||||||
|
|
||||||
var notifications, delivered;
|
var notifications, delivered;
|
||||||
|
var notifications_mock = { close: function () { } };
|
||||||
|
|
||||||
function get_subscriptions(callback, retries) {
|
function get_subscriptions() {
|
||||||
if (retries == undefined) retries = 5;
|
helpers.xhr('GET', '/api/v1/auth/subscriptions?fields=authorId', {
|
||||||
|
retries: 5,
|
||||||
if (retries <= 0) {
|
entity_name: 'subscriptions'
|
||||||
return;
|
}, {
|
||||||
}
|
on200: create_notification_stream
|
||||||
|
});
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('GET', '/api/v1/auth/subscriptions?fields=authorId', true);
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
|
||||||
if (xhr.readyState === 4) {
|
|
||||||
if (xhr.status === 200) {
|
|
||||||
subscriptions = xhr.response;
|
|
||||||
callback(subscriptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.onerror = function () {
|
|
||||||
console.log('Pulling subscriptions failed... ' + retries + '/5');
|
|
||||||
setTimeout(function () { get_subscriptions(callback, retries - 1) }, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
|
||||||
console.log('Pulling subscriptions failed... ' + retries + '/5');
|
|
||||||
get_subscriptions(callback, retries - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function create_notification_stream(subscriptions) {
|
function create_notification_stream(subscriptions) {
|
||||||
|
// sse.js can't be replaced to EventSource in place as it lack support of payload and headers
|
||||||
|
// see https://developer.mozilla.org/en-US/docs/Web/API/EventSource/EventSource
|
||||||
notifications = new SSE(
|
notifications = new SSE(
|
||||||
'/api/v1/auth/notifications?fields=videoId,title,author,authorId,publishedText,published,authorThumbnails,liveNow', {
|
'/api/v1/auth/notifications?fields=videoId,title,author,authorId,publishedText,published,authorThumbnails,liveNow', {
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
payload: 'topics=' + subscriptions.map(function (subscription) { return subscription.authorId }).join(','),
|
payload: 'topics=' + subscriptions.map(function (subscription) { return subscription.authorId; }).join(','),
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||||
});
|
});
|
||||||
delivered = [];
|
delivered = [];
|
||||||
@@ -46,96 +32,100 @@ function create_notification_stream(subscriptions) {
|
|||||||
var start_time = Math.round(new Date() / 1000);
|
var start_time = Math.round(new Date() / 1000);
|
||||||
|
|
||||||
notifications.onmessage = function (event) {
|
notifications.onmessage = function (event) {
|
||||||
if (!event.id) {
|
if (!event.id) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var notification = JSON.parse(event.data);
|
var notification = JSON.parse(event.data);
|
||||||
console.log('Got notification:', notification);
|
console.info('Got notification:', notification);
|
||||||
|
|
||||||
if (start_time < notification.published && !delivered.includes(notification.videoId)) {
|
// Ignore not actual and delivered notifications
|
||||||
if (Notification.permission === 'granted') {
|
if (start_time > notification.published || delivered.includes(notification.videoId)) return;
|
||||||
var system_notification =
|
|
||||||
new Notification((notification.liveNow ? notification_data.live_now_text : notification_data.upload_text).replace('`x`', notification.author), {
|
|
||||||
body: notification.title,
|
|
||||||
icon: '/ggpht' + new URL(notification.authorThumbnails[2].url).pathname,
|
|
||||||
img: '/ggpht' + new URL(notification.authorThumbnails[4].url).pathname,
|
|
||||||
tag: notification.videoId
|
|
||||||
});
|
|
||||||
|
|
||||||
system_notification.onclick = function (event) {
|
delivered.push(notification.videoId);
|
||||||
window.open('/watch?v=' + event.currentTarget.tag, '_blank');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delivered.push(notification.videoId);
|
let notification_count = helpers.storage.get(STORAGE_KEY_NOTIF_COUNT) || 0;
|
||||||
localStorage.setItem('notification_count', parseInt(localStorage.getItem('notification_count') || '0') + 1);
|
notification_count++;
|
||||||
var notification_ticker = document.getElementById('notification_ticker');
|
helpers.storage.set(STORAGE_KEY_NOTIF_COUNT, notification_count);
|
||||||
|
|
||||||
if (parseInt(localStorage.getItem('notification_count')) > 0) {
|
update_ticker_count();
|
||||||
notification_ticker.innerHTML =
|
|
||||||
'<span id="notification_count">' + localStorage.getItem('notification_count') + '</span> <i class="icon ion-ios-notifications"></i>';
|
// permission for notifications handled on settings page. JS handler is in handlers.js
|
||||||
} else {
|
if (window.Notification && Notification.permission === 'granted') {
|
||||||
notification_ticker.innerHTML =
|
var notification_text = notification.liveNow ? notification_data.live_now_text : notification_data.upload_text;
|
||||||
'<i class="icon ion-ios-notifications-outline"></i>';
|
notification_text = notification_text.replace('`x`', notification.author);
|
||||||
}
|
|
||||||
|
var system_notification = new Notification(notification_text, {
|
||||||
|
body: notification.title,
|
||||||
|
icon: '/ggpht' + new URL(notification.authorThumbnails[2].url).pathname,
|
||||||
|
img: '/ggpht' + new URL(notification.authorThumbnails[4].url).pathname
|
||||||
|
});
|
||||||
|
|
||||||
|
system_notification.onclick = function (e) {
|
||||||
|
open('/watch?v=' + notification.videoId, '_blank');
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
notifications.addEventListener('error', function (e) {
|
||||||
|
console.warn('Something went wrong with notifications, trying to reconnect...');
|
||||||
|
notifications = notifications_mock;
|
||||||
|
setTimeout(get_subscriptions, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
notifications.addEventListener('error', handle_notification_error);
|
|
||||||
notifications.stream();
|
notifications.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handle_notification_error(event) {
|
function update_ticker_count() {
|
||||||
console.log('Something went wrong with notifications, trying to reconnect...');
|
var notification_ticker = document.getElementById('notification_ticker');
|
||||||
notifications = { close: function () { } };
|
|
||||||
setTimeout(function () { get_subscriptions(create_notification_stream) }, 1000);
|
const notification_count = helpers.storage.get(STORAGE_KEY_STREAM);
|
||||||
|
if (notification_count > 0) {
|
||||||
|
notification_ticker.innerHTML =
|
||||||
|
'<span id="notification_count">' + notification_count + '</span> <i class="icon ion-ios-notifications"></i>';
|
||||||
|
} else {
|
||||||
|
notification_ticker.innerHTML =
|
||||||
|
'<i class="icon ion-ios-notifications-outline"></i>';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('load', function (e) {
|
function start_stream_if_needed() {
|
||||||
localStorage.setItem('notification_count', document.getElementById('notification_count') ? document.getElementById('notification_count').innerText : '0');
|
// random wait for other tabs set 'stream' flag
|
||||||
|
setTimeout(function () {
|
||||||
if (localStorage.getItem('stream')) {
|
if (!helpers.storage.get(STORAGE_KEY_STREAM)) {
|
||||||
localStorage.removeItem('stream');
|
// if no one set 'stream', set it by yourself and start stream
|
||||||
} else {
|
helpers.storage.set(STORAGE_KEY_STREAM, true);
|
||||||
setTimeout(function () {
|
notifications = notifications_mock;
|
||||||
if (!localStorage.getItem('stream')) {
|
get_subscriptions();
|
||||||
notifications = { close: function () { } };
|
|
||||||
localStorage.setItem('stream', true);
|
|
||||||
get_subscriptions(create_notification_stream);
|
|
||||||
}
|
|
||||||
}, Math.random() * 1000 + 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('storage', function (e) {
|
|
||||||
if (e.key === 'stream' && !e.newValue) {
|
|
||||||
if (notifications) {
|
|
||||||
localStorage.setItem('stream', true);
|
|
||||||
} else {
|
|
||||||
setTimeout(function () {
|
|
||||||
if (!localStorage.getItem('stream')) {
|
|
||||||
notifications = { close: function () { } };
|
|
||||||
localStorage.setItem('stream', true);
|
|
||||||
get_subscriptions(create_notification_stream);
|
|
||||||
}
|
|
||||||
}, Math.random() * 1000 + 50);
|
|
||||||
}
|
|
||||||
} else if (e.key === 'notification_count') {
|
|
||||||
var notification_ticker = document.getElementById('notification_ticker');
|
|
||||||
|
|
||||||
if (parseInt(e.newValue) > 0) {
|
|
||||||
notification_ticker.innerHTML =
|
|
||||||
'<span id="notification_count">' + e.newValue + '</span> <i class="icon ion-ios-notifications"></i>';
|
|
||||||
} else {
|
|
||||||
notification_ticker.innerHTML =
|
|
||||||
'<i class="icon ion-ios-notifications-outline"></i>';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}, Math.random() * 1000 + 50); // [0.050 .. 1.050) second
|
||||||
});
|
}
|
||||||
|
|
||||||
window.addEventListener('unload', function (e) {
|
|
||||||
if (notifications) {
|
addEventListener('storage', function (e) {
|
||||||
localStorage.removeItem('stream');
|
if (e.key === STORAGE_KEY_NOTIF_COUNT)
|
||||||
|
update_ticker_count();
|
||||||
|
|
||||||
|
// if 'stream' key was removed
|
||||||
|
if (e.key === STORAGE_KEY_STREAM && !helpers.storage.get(STORAGE_KEY_STREAM)) {
|
||||||
|
if (notifications) {
|
||||||
|
// restore it if we have active stream
|
||||||
|
helpers.storage.set(STORAGE_KEY_STREAM, true);
|
||||||
|
} else {
|
||||||
|
start_stream_if_needed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addEventListener('load', function () {
|
||||||
|
var notification_count_el = document.getElementById('notification_count');
|
||||||
|
var notification_count = notification_count_el ? parseInt(notification_count_el.textContent) : 0;
|
||||||
|
helpers.storage.set(STORAGE_KEY_NOTIF_COUNT, notification_count);
|
||||||
|
|
||||||
|
if (helpers.storage.get(STORAGE_KEY_STREAM))
|
||||||
|
helpers.storage.remove(STORAGE_KEY_STREAM);
|
||||||
|
start_stream_if_needed();
|
||||||
|
});
|
||||||
|
|
||||||
|
addEventListener('unload', function () {
|
||||||
|
// let chance to other tabs to be a streamer via firing 'storage' event
|
||||||
|
if (notifications) helpers.storage.remove(STORAGE_KEY_STREAM);
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
'use strict';
|
||||||
|
var player_data = JSON.parse(document.getElementById('player_data').textContent);
|
||||||
|
var video_data = JSON.parse(document.getElementById('video_data').textContent);
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
preload: 'auto',
|
preload: 'auto',
|
||||||
liveui: true,
|
liveui: true,
|
||||||
@@ -11,13 +15,21 @@ var options = {
|
|||||||
'durationDisplay',
|
'durationDisplay',
|
||||||
'progressControl',
|
'progressControl',
|
||||||
'remainingTimeDisplay',
|
'remainingTimeDisplay',
|
||||||
|
'Spacer',
|
||||||
'captionsButton',
|
'captionsButton',
|
||||||
|
'audioTrackButton',
|
||||||
'qualitySelector',
|
'qualitySelector',
|
||||||
'playbackRateMenuButton',
|
'playbackRateMenuButton',
|
||||||
'fullscreenToggle'
|
'fullscreenToggle'
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
html5: {
|
||||||
|
preloadTextTracks: false,
|
||||||
|
vhs: {
|
||||||
|
overrideNative: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if (player_data.aspect_ratio) {
|
if (player_data.aspect_ratio) {
|
||||||
options.aspectRatio = player_data.aspect_ratio;
|
options.aspectRatio = player_data.aspect_ratio;
|
||||||
@@ -25,62 +37,166 @@ if (player_data.aspect_ratio) {
|
|||||||
|
|
||||||
var embed_url = new URL(location);
|
var embed_url = new URL(location);
|
||||||
embed_url.searchParams.delete('v');
|
embed_url.searchParams.delete('v');
|
||||||
short_url = location.origin + '/' + video_data.id + embed_url.search;
|
var short_url = location.origin + '/' + video_data.id + embed_url.search;
|
||||||
embed_url = location.origin + '/embed/' + video_data.id + embed_url.search;
|
embed_url = location.origin + '/embed/' + video_data.id + embed_url.search;
|
||||||
|
|
||||||
var shareOptions = {
|
var save_player_pos_key = 'save_player_pos';
|
||||||
socials: ['fbFeed', 'tw', 'reddit', 'email'],
|
|
||||||
|
|
||||||
url: short_url,
|
videojs.Vhs.xhr.beforeRequest = function(options) {
|
||||||
title: player_data.title,
|
// set local if requested not videoplayback
|
||||||
description: player_data.description,
|
if (!options.uri.includes('videoplayback')) {
|
||||||
image: player_data.thumbnail,
|
if (!options.uri.includes('local=true'))
|
||||||
embedCode: "<iframe id='ivplayer' type='text/html' width='640' height='360' src='" + embed_url + "' frameborder='0'></iframe>"
|
options.uri += '?local=true';
|
||||||
}
|
}
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
|
||||||
var player = videojs('player', options);
|
var player = videojs('player', options);
|
||||||
|
|
||||||
if (location.pathname.startsWith('/embed/')) {
|
player.on('error', function () {
|
||||||
player.overlay({
|
if (video_data.params.quality === 'dash') return;
|
||||||
overlays: [{
|
|
||||||
start: 'loadstart',
|
|
||||||
content: '<h1><a rel="noopener" target="_blank" href="' + location.origin + '/watch?v=' + video_data.id + '">' + player_data.title + '</a></h1>',
|
|
||||||
end: 'playing',
|
|
||||||
align: 'top'
|
|
||||||
}, {
|
|
||||||
start: 'pause',
|
|
||||||
content: '<h1><a rel="noopener" target="_blank" href="' + location.origin + '/watch?v=' + video_data.id + '">' + player_data.title + '</a></h1>',
|
|
||||||
end: 'playing',
|
|
||||||
align: 'top'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
player.on('error', function (event) {
|
var localNotDisabled = (
|
||||||
if (player.error().code === 2 || player.error().code === 4) {
|
!player.currentSrc().includes('local=true') && !video_data.local_disabled
|
||||||
setInterval(setTimeout(function (event) {
|
);
|
||||||
console.log('An error occured in the player, reloading...');
|
var reloadMakesSense = (
|
||||||
|
player.error().code === MediaError.MEDIA_ERR_NETWORK ||
|
||||||
|
player.error().code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED
|
||||||
|
);
|
||||||
|
|
||||||
|
if (localNotDisabled) {
|
||||||
|
// add local=true to all current sources
|
||||||
|
player.src(player.currentSources().map(function (source) {
|
||||||
|
source.src += '&local=true';
|
||||||
|
return source;
|
||||||
|
}));
|
||||||
|
} else if (reloadMakesSense) {
|
||||||
|
setTimeout(function () {
|
||||||
|
console.warn('An error occurred in the player, reloading...');
|
||||||
|
|
||||||
|
// After load() all parameters are reset. Save them
|
||||||
var currentTime = player.currentTime();
|
var currentTime = player.currentTime();
|
||||||
var playbackRate = player.playbackRate();
|
var playbackRate = player.playbackRate();
|
||||||
var paused = player.paused();
|
var paused = player.paused();
|
||||||
|
|
||||||
player.load();
|
player.load();
|
||||||
|
|
||||||
if (currentTime > 0.5) {
|
if (currentTime > 0.5) currentTime -= 0.5;
|
||||||
currentTime -= 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.currentTime(currentTime);
|
player.currentTime(currentTime);
|
||||||
player.playbackRate(playbackRate);
|
player.playbackRate(playbackRate);
|
||||||
|
if (!paused) player.play();
|
||||||
if (!paused) {
|
}, 5000);
|
||||||
player.play();
|
|
||||||
}
|
|
||||||
}, 5000), 5000);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (video_data.params.quality === 'dash') {
|
||||||
|
player.reloadSourceOnError({
|
||||||
|
errorInterval: 10
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function for add time argument to url
|
||||||
|
* @param {String} url
|
||||||
|
* @returns {URL} urlWithTimeArg
|
||||||
|
*/
|
||||||
|
function addCurrentTimeToURL(url) {
|
||||||
|
var urlUsed = new URL(url);
|
||||||
|
urlUsed.searchParams.delete('start');
|
||||||
|
var currentTime = Math.ceil(player.currentTime());
|
||||||
|
if (currentTime > 0)
|
||||||
|
urlUsed.searchParams.set('t', currentTime);
|
||||||
|
else if (urlUsed.searchParams.has('t'))
|
||||||
|
urlUsed.searchParams.delete('t');
|
||||||
|
return urlUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
var shareOptions = {
|
||||||
|
socials: ['fbFeed', 'tw', 'reddit', 'email'],
|
||||||
|
|
||||||
|
get url() {
|
||||||
|
return addCurrentTimeToURL(short_url);
|
||||||
|
},
|
||||||
|
title: player_data.title,
|
||||||
|
description: player_data.description,
|
||||||
|
image: player_data.thumbnail,
|
||||||
|
get embedCode() {
|
||||||
|
// Single quotes inside here required. HTML inserted as is into value attribute of input
|
||||||
|
return "<iframe id='ivplayer' width='640' height='360' src='" +
|
||||||
|
addCurrentTimeToURL(embed_url) + "' style='border:none;'></iframe>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (location.pathname.startsWith('/embed/')) {
|
||||||
|
var overlay_content = '<h1><a rel="noopener" target="_blank" href="' + location.origin + '/watch?v=' + video_data.id + '">' + player_data.title + '</a></h1>';
|
||||||
|
player.overlay({
|
||||||
|
overlays: [
|
||||||
|
{ start: 'loadstart', content: overlay_content, end: 'playing', align: 'top'},
|
||||||
|
{ start: 'pause', content: overlay_content, end: 'playing', align: 'top'}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect mobile users and initialize mobileUi for better UX
|
||||||
|
// Detection code taken from https://stackoverflow.com/a/20293441
|
||||||
|
|
||||||
|
function isMobile() {
|
||||||
|
try{ document.createEvent('TouchEvent'); return true; }
|
||||||
|
catch(e){ return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMobile()) {
|
||||||
|
player.mobileUi({ touchControls: { seekSeconds: 5 * player.playbackRate() } });
|
||||||
|
|
||||||
|
var buttons = ['playToggle', 'volumePanel', 'captionsButton'];
|
||||||
|
|
||||||
|
if (!video_data.params.listen && video_data.params.quality === 'dash') buttons.push('audioTrackButton');
|
||||||
|
if (video_data.params.listen || video_data.params.quality !== 'dash') buttons.push('qualitySelector');
|
||||||
|
|
||||||
|
// Create new control bar object for operation buttons
|
||||||
|
const ControlBar = videojs.getComponent('controlBar');
|
||||||
|
let operations_bar = new ControlBar(player, {
|
||||||
|
children: [],
|
||||||
|
playbackRates: [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0]
|
||||||
|
});
|
||||||
|
buttons.slice(1).forEach(function (child) {operations_bar.addChild(child);});
|
||||||
|
|
||||||
|
// Remove operation buttons from primary control bar
|
||||||
|
var primary_control_bar = player.getChild('controlBar');
|
||||||
|
buttons.forEach(function (child) {primary_control_bar.removeChild(child);});
|
||||||
|
|
||||||
|
var operations_bar_element = operations_bar.el();
|
||||||
|
operations_bar_element.classList.add('mobile-operations-bar');
|
||||||
|
player.addChild(operations_bar);
|
||||||
|
|
||||||
|
// Playback menu doesn't work when it's initialized outside of the primary control bar
|
||||||
|
var playback_element = document.getElementsByClassName('vjs-playback-rate')[0];
|
||||||
|
operations_bar_element.append(playback_element);
|
||||||
|
|
||||||
|
// The share and http source selector element can't be fetched till the players ready.
|
||||||
|
player.one('playing', function () {
|
||||||
|
var share_element = document.getElementsByClassName('vjs-share-control')[0];
|
||||||
|
operations_bar_element.append(share_element);
|
||||||
|
|
||||||
|
if (!video_data.params.listen && video_data.params.quality === 'dash') {
|
||||||
|
var http_source_selector = document.getElementsByClassName('vjs-http-source-selector vjs-menu-button')[0];
|
||||||
|
operations_bar_element.append(http_source_selector);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable VR video support
|
||||||
|
if (!video_data.params.listen && video_data.vr && video_data.params.vr_mode) {
|
||||||
|
player.crossOrigin('anonymous');
|
||||||
|
switch (video_data.projection_type) {
|
||||||
|
case 'EQUIRECTANGULAR':
|
||||||
|
player.vr({projection: 'equirectangular'});
|
||||||
|
default: // Should only be 'MESH' but we'll use this as a fallback.
|
||||||
|
player.vr({projection: 'EAC'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add markers
|
// Add markers
|
||||||
if (video_data.params.video_start > 0 || video_data.params.video_end > 0) {
|
if (video_data.params.video_start > 0 || video_data.params.video_end > 0) {
|
||||||
var markers = [{ time: video_data.params.video_start, text: 'Start' }];
|
var markers = [{ time: video_data.params.video_start, text: 'Start' }];
|
||||||
@@ -93,13 +209,8 @@ if (video_data.params.video_start > 0 || video_data.params.video_end > 0) {
|
|||||||
|
|
||||||
player.markers({
|
player.markers({
|
||||||
onMarkerReached: function (marker) {
|
onMarkerReached: function (marker) {
|
||||||
if (marker.text === 'End') {
|
if (marker.text === 'End')
|
||||||
if (player.loop()) {
|
player.loop() ? player.markers.prev('Start') : player.pause();
|
||||||
player.markers.prev('Start');
|
|
||||||
} else {
|
|
||||||
player.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
markers: markers
|
markers: markers
|
||||||
});
|
});
|
||||||
@@ -110,9 +221,76 @@ if (video_data.params.video_start > 0 || video_data.params.video_end > 0) {
|
|||||||
player.volume(video_data.params.volume / 100);
|
player.volume(video_data.params.volume / 100);
|
||||||
player.playbackRate(video_data.params.speed);
|
player.playbackRate(video_data.params.speed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method for getting the contents of a cookie
|
||||||
|
*
|
||||||
|
* @param {String} name Name of cookie
|
||||||
|
* @returns {String|null} cookieValue
|
||||||
|
*/
|
||||||
|
function getCookieValue(name) {
|
||||||
|
var cookiePrefix = name + '=';
|
||||||
|
var matchedCookie = document.cookie.split(';').find(function (item) {return item.includes(cookiePrefix);});
|
||||||
|
if (matchedCookie)
|
||||||
|
return matchedCookie.replace(cookiePrefix, '');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method for updating the 'PREFS' cookie (or creating it if missing)
|
||||||
|
*
|
||||||
|
* @param {number} newVolume New volume defined (null if unchanged)
|
||||||
|
* @param {number} newSpeed New speed defined (null if unchanged)
|
||||||
|
*/
|
||||||
|
function updateCookie(newVolume, newSpeed) {
|
||||||
|
var volumeValue = newVolume !== null ? newVolume : video_data.params.volume;
|
||||||
|
var speedValue = newSpeed !== null ? newSpeed : video_data.params.speed;
|
||||||
|
|
||||||
|
var cookieValue = getCookieValue('PREFS');
|
||||||
|
var cookieData;
|
||||||
|
|
||||||
|
if (cookieValue !== null) {
|
||||||
|
var cookieJson = JSON.parse(decodeURIComponent(cookieValue));
|
||||||
|
cookieJson.volume = volumeValue;
|
||||||
|
cookieJson.speed = speedValue;
|
||||||
|
cookieData = encodeURIComponent(JSON.stringify(cookieJson));
|
||||||
|
} else {
|
||||||
|
cookieData = encodeURIComponent(JSON.stringify({ 'volume': volumeValue, 'speed': speedValue }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set expiration in 2 year
|
||||||
|
var date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() + 2);
|
||||||
|
|
||||||
|
var ipRegex = /^((\d+\.){3}\d+|[A-Fa-f0-9]*:[A-Fa-f0-9:]*:[A-Fa-f0-9:]+)$/;
|
||||||
|
var domainUsed = location.hostname;
|
||||||
|
|
||||||
|
// Fix for a bug in FF where the leading dot in the FQDN is not ignored
|
||||||
|
if (domainUsed.charAt(0) !== '.' && !ipRegex.test(domainUsed) && domainUsed !== 'localhost')
|
||||||
|
domainUsed = '.' + location.hostname;
|
||||||
|
|
||||||
|
var secure = location.protocol.startsWith("https") ? " Secure;" : "";
|
||||||
|
|
||||||
|
document.cookie = 'PREFS=' + cookieData + '; SameSite=Lax; path=/; domain=' +
|
||||||
|
domainUsed + '; expires=' + date.toGMTString() + ';' + secure;
|
||||||
|
|
||||||
|
video_data.params.volume = volumeValue;
|
||||||
|
video_data.params.speed = speedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.on('ratechange', function () {
|
||||||
|
updateCookie(null, player.playbackRate());
|
||||||
|
if (isMobile()) {
|
||||||
|
player.mobileUi({ touchControls: { seekSeconds: 5 * player.playbackRate() } });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
player.on('volumechange', function () {
|
||||||
|
updateCookie(Math.ceil(player.volume() * 100), null);
|
||||||
|
});
|
||||||
|
|
||||||
player.on('waiting', function () {
|
player.on('waiting', function () {
|
||||||
if (player.playbackRate() > 1 && player.liveTracker.isLive() && player.liveTracker.atLiveEdge()) {
|
if (player.playbackRate() > 1 && player.liveTracker.isLive() && player.liveTracker.atLiveEdge()) {
|
||||||
console.log('Player has caught up to source, resetting playbackRate.')
|
console.info('Player has caught up to source, resetting playbackRate');
|
||||||
player.playbackRate(1);
|
player.playbackRate(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -121,19 +299,39 @@ if (video_data.premiere_timestamp && Math.round(new Date() / 1000) < video_data.
|
|||||||
player.getChild('bigPlayButton').hide();
|
player.getChild('bigPlayButton').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (video_data.params.save_player_pos) {
|
||||||
|
const url = new URL(location);
|
||||||
|
const hasTimeParam = url.searchParams.has('t');
|
||||||
|
const rememberedTime = get_video_time();
|
||||||
|
let lastUpdated = 0;
|
||||||
|
|
||||||
|
if(!hasTimeParam) set_seconds_after_start(rememberedTime);
|
||||||
|
|
||||||
|
player.on('timeupdate', function () {
|
||||||
|
const raw = player.currentTime();
|
||||||
|
const time = Math.floor(raw);
|
||||||
|
|
||||||
|
if(lastUpdated !== time && raw <= video_data.length_seconds - 15) {
|
||||||
|
save_video_time(time);
|
||||||
|
lastUpdated = time;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else remove_all_video_times();
|
||||||
|
|
||||||
if (video_data.params.autoplay) {
|
if (video_data.params.autoplay) {
|
||||||
var bpb = player.getChild('bigPlayButton');
|
var bpb = player.getChild('bigPlayButton');
|
||||||
bpb.hide();
|
bpb.hide();
|
||||||
|
|
||||||
player.ready(function () {
|
player.ready(function () {
|
||||||
new Promise(function (resolve, reject) {
|
new Promise(function (resolve, reject) {
|
||||||
setTimeout(() => resolve(1), 1);
|
setTimeout(function () {resolve(1);}, 1);
|
||||||
}).then(function (result) {
|
}).then(function (result) {
|
||||||
var promise = player.play();
|
var promise = player.play();
|
||||||
|
|
||||||
if (promise !== undefined) {
|
if (promise !== undefined) {
|
||||||
promise.then(_ => {
|
promise.then(function () {
|
||||||
}).catch(error => {
|
}).catch(function (error) {
|
||||||
bpb.show();
|
bpb.show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -143,38 +341,48 @@ if (video_data.params.autoplay) {
|
|||||||
|
|
||||||
if (!video_data.params.listen && video_data.params.quality === 'dash') {
|
if (!video_data.params.listen && video_data.params.quality === 'dash') {
|
||||||
player.httpSourceSelector();
|
player.httpSourceSelector();
|
||||||
|
|
||||||
|
if (video_data.params.quality_dash !== 'auto') {
|
||||||
|
player.ready(function () {
|
||||||
|
player.on('loadedmetadata', function () {
|
||||||
|
const qualityLevels = Array.from(player.qualityLevels()).sort(function (a, b) {return a.height - b.height;});
|
||||||
|
let targetQualityLevel;
|
||||||
|
switch (video_data.params.quality_dash) {
|
||||||
|
case 'best':
|
||||||
|
targetQualityLevel = qualityLevels.length - 1;
|
||||||
|
break;
|
||||||
|
case 'worst':
|
||||||
|
targetQualityLevel = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const targetHeight = parseInt(video_data.params.quality_dash);
|
||||||
|
for (let i = 0; i < qualityLevels.length; i++) {
|
||||||
|
if (qualityLevels[i].height <= targetHeight)
|
||||||
|
targetQualityLevel = i;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qualityLevels.forEach(function (level, index) {
|
||||||
|
level.enabled = (index === targetQualityLevel);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player.vttThumbnails({
|
player.vttThumbnails({
|
||||||
src: location.origin + '/api/v1/storyboards/' + video_data.id + '?height=90'
|
src: '/api/v1/storyboards/' + video_data.id + '?height=90',
|
||||||
|
showTimestamp: true
|
||||||
});
|
});
|
||||||
|
|
||||||
// Enable annotations
|
// Enable annotations
|
||||||
if (!video_data.params.listen && video_data.params.annotations) {
|
if (!video_data.params.listen && video_data.params.annotations) {
|
||||||
window.addEventListener('load', function (e) {
|
addEventListener('load', function (e) {
|
||||||
var video_container = document.getElementById('player');
|
addEventListener('__ar_annotation_click', function (e) {
|
||||||
let xhr = new XMLHttpRequest();
|
const url = e.detail.url,
|
||||||
xhr.responseType = 'text';
|
target = e.detail.target,
|
||||||
xhr.timeout = 60000;
|
seconds = e.detail.seconds;
|
||||||
xhr.open('GET', '/api/v1/annotations/' + video_data.id, true);
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
|
||||||
if (xhr.readyState === 4) {
|
|
||||||
if (xhr.status === 200) {
|
|
||||||
videojs.registerPlugin('youtubeAnnotationsPlugin', youtubeAnnotationsPlugin);
|
|
||||||
if (!player.paused()) {
|
|
||||||
player.youtubeAnnotationsPlugin({ annotationXml: xhr.response, videoContainer: video_container });
|
|
||||||
} else {
|
|
||||||
player.one('play', function (event) {
|
|
||||||
player.youtubeAnnotationsPlugin({ annotationXml: xhr.response, videoContainer: video_container });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('__ar_annotation_click', e => {
|
|
||||||
const { url, target, seconds } = e.detail;
|
|
||||||
var path = new URL(url);
|
var path = new URL(url);
|
||||||
|
|
||||||
if (path.href.startsWith('https://www.youtube.com/watch?') && seconds) {
|
if (path.href.startsWith('https://www.youtube.com/watch?') && seconds) {
|
||||||
@@ -184,75 +392,104 @@ if (!video_data.params.listen && video_data.params.annotations) {
|
|||||||
path = path.pathname + path.search;
|
path = path.pathname + path.search;
|
||||||
|
|
||||||
if (target === 'current') {
|
if (target === 'current') {
|
||||||
window.location.href = path;
|
location.href = path;
|
||||||
} else if (target === 'new') {
|
} else if (target === 'new') {
|
||||||
window.open(path, '_blank');
|
open(path, '_blank');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
helpers.xhr('GET', '/api/v1/annotations/' + video_data.id, {
|
||||||
|
responseType: 'text',
|
||||||
|
timeout: 60000
|
||||||
|
}, {
|
||||||
|
on200: function (response) {
|
||||||
|
var video_container = document.getElementById('player');
|
||||||
|
videojs.registerPlugin('youtubeAnnotationsPlugin', youtubeAnnotationsPlugin);
|
||||||
|
if (player.paused()) {
|
||||||
|
player.one('play', function (event) {
|
||||||
|
player.youtubeAnnotationsPlugin({ annotationXml: response, videoContainer: video_container });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
player.youtubeAnnotationsPlugin({ annotationXml: response, videoContainer: video_container });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function increase_volume(delta) {
|
function change_volume(delta) {
|
||||||
const curVolume = player.volume();
|
const curVolume = player.volume();
|
||||||
let newVolume = curVolume + delta;
|
let newVolume = curVolume + delta;
|
||||||
if (newVolume > 1) {
|
newVolume = helpers.clamp(newVolume, 0, 1);
|
||||||
newVolume = 1;
|
|
||||||
} else if (newVolume < 0) {
|
|
||||||
newVolume = 0;
|
|
||||||
}
|
|
||||||
player.volume(newVolume);
|
player.volume(newVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle_muted() {
|
function toggle_muted() {
|
||||||
const isMuted = player.muted();
|
player.muted(!player.muted());
|
||||||
player.muted(!isMuted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function skip_seconds(delta) {
|
function skip_seconds(delta) {
|
||||||
const duration = player.duration();
|
const duration = player.duration();
|
||||||
const curTime = player.currentTime();
|
const curTime = player.currentTime();
|
||||||
let newTime = curTime + delta;
|
let newTime = curTime + delta;
|
||||||
if (newTime > duration) {
|
newTime = helpers.clamp(newTime, 0, duration);
|
||||||
newTime = duration;
|
|
||||||
} else if (newTime < 0) {
|
|
||||||
newTime = 0;
|
|
||||||
}
|
|
||||||
player.currentTime(newTime);
|
player.currentTime(newTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function set_seconds_after_start(delta) {
|
||||||
|
const start = video_data.params.video_start;
|
||||||
|
player.currentTime(start + delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
function save_video_time(seconds) {
|
||||||
|
const all_video_times = get_all_video_times();
|
||||||
|
all_video_times[video_data.id] = seconds;
|
||||||
|
helpers.storage.set(save_player_pos_key, all_video_times);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_video_time() {
|
||||||
|
return get_all_video_times()[video_data.id] || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_all_video_times() {
|
||||||
|
return helpers.storage.get(save_player_pos_key) || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_all_video_times() {
|
||||||
|
helpers.storage.remove(save_player_pos_key);
|
||||||
|
}
|
||||||
|
|
||||||
function set_time_percent(percent) {
|
function set_time_percent(percent) {
|
||||||
const duration = player.duration();
|
const duration = player.duration();
|
||||||
const newTime = duration * (percent / 100);
|
const newTime = duration * (percent / 100);
|
||||||
player.currentTime(newTime);
|
player.currentTime(newTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle_play() {
|
function play() { player.play(); }
|
||||||
if (player.paused()) {
|
function pause() { player.pause(); }
|
||||||
player.play();
|
function stop() { player.pause(); player.currentTime(0); }
|
||||||
} else {
|
function toggle_play() { player.paused() ? play() : pause(); }
|
||||||
player.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const toggle_captions = (function () {
|
const toggle_captions = (function () {
|
||||||
let toggledTrack = null;
|
let toggledTrack = null;
|
||||||
const onChange = function (e) {
|
|
||||||
toggledTrack = null;
|
function bindChange(onOrOff) {
|
||||||
};
|
player.textTracks()[onOrOff]('change', function (e) {
|
||||||
const bindChange = function (onOrOff) {
|
toggledTrack = null;
|
||||||
player.textTracks()[onOrOff]('change', onChange);
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
// Wrapper function to ignore our own emitted events and only listen
|
// Wrapper function to ignore our own emitted events and only listen
|
||||||
// to events emitted by Video.js on click on the captions menu items.
|
// to events emitted by Video.js on click on the captions menu items.
|
||||||
const setMode = function (track, mode) {
|
function setMode(track, mode) {
|
||||||
bindChange('off');
|
bindChange('off');
|
||||||
track.mode = mode;
|
track.mode = mode;
|
||||||
window.setTimeout(function () {
|
setTimeout(function () {
|
||||||
bindChange('on');
|
bindChange('on');
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
}
|
||||||
|
|
||||||
bindChange('on');
|
bindChange('on');
|
||||||
return function () {
|
return function () {
|
||||||
if (toggledTrack !== null) {
|
if (toggledTrack !== null) {
|
||||||
@@ -272,9 +509,7 @@ const toggle_captions = (function () {
|
|||||||
const tracks = player.textTracks();
|
const tracks = player.textTracks();
|
||||||
for (let i = 0; i < tracks.length; i++) {
|
for (let i = 0; i < tracks.length; i++) {
|
||||||
const track = tracks[i];
|
const track = tracks[i];
|
||||||
if (track.kind !== 'captions') {
|
if (track.kind !== 'captions') continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fallbackCaptionsTrack === null) {
|
if (fallbackCaptionsTrack === null) {
|
||||||
fallbackCaptionsTrack = track;
|
fallbackCaptionsTrack = track;
|
||||||
@@ -295,26 +530,18 @@ const toggle_captions = (function () {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
function toggle_fullscreen() {
|
function toggle_fullscreen() {
|
||||||
if (player.isFullscreen()) {
|
player.isFullscreen() ? player.exitFullscreen() : player.requestFullscreen();
|
||||||
player.exitFullscreen();
|
|
||||||
} else {
|
|
||||||
player.requestFullscreen();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function increase_playback_rate(steps) {
|
function increase_playback_rate(steps) {
|
||||||
const maxIndex = options.playbackRates.length - 1;
|
const maxIndex = options.playbackRates.length - 1;
|
||||||
const curIndex = options.playbackRates.indexOf(player.playbackRate());
|
const curIndex = options.playbackRates.indexOf(player.playbackRate());
|
||||||
let newIndex = curIndex + steps;
|
let newIndex = curIndex + steps;
|
||||||
if (newIndex > maxIndex) {
|
newIndex = helpers.clamp(newIndex, 0, maxIndex);
|
||||||
newIndex = maxIndex;
|
|
||||||
} else if (newIndex < 0) {
|
|
||||||
newIndex = 0;
|
|
||||||
}
|
|
||||||
player.playbackRate(options.playbackRates[newIndex]);
|
player.playbackRate(options.playbackRates[newIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('keydown', e => {
|
addEventListener('keydown', function (e) {
|
||||||
if (e.target.tagName.toLowerCase() === 'input') {
|
if (e.target.tagName.toLowerCase() === 'input') {
|
||||||
// Ignore input when focus is on certain elements, e.g. form fields.
|
// Ignore input when focus is on certain elements, e.g. form fields.
|
||||||
return;
|
return;
|
||||||
@@ -338,18 +565,19 @@ window.addEventListener('keydown', e => {
|
|||||||
switch (decoratedKey) {
|
switch (decoratedKey) {
|
||||||
case ' ':
|
case ' ':
|
||||||
case 'k':
|
case 'k':
|
||||||
|
case 'MediaPlayPause':
|
||||||
action = toggle_play;
|
action = toggle_play;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'MediaPlay': action = play; break;
|
||||||
|
case 'MediaPause': action = pause; break;
|
||||||
|
case 'MediaStop': action = stop; break;
|
||||||
|
|
||||||
case 'ArrowUp':
|
case 'ArrowUp':
|
||||||
if (isPlayerFocused) {
|
if (isPlayerFocused) action = change_volume.bind(this, 0.1);
|
||||||
action = increase_volume.bind(this, 0.1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'ArrowDown':
|
case 'ArrowDown':
|
||||||
if (isPlayerFocused) {
|
if (isPlayerFocused) action = change_volume.bind(this, -0.1);
|
||||||
action = increase_volume.bind(this, -0.1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
@@ -357,16 +585,18 @@ window.addEventListener('keydown', e => {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'ArrowRight':
|
case 'ArrowRight':
|
||||||
action = skip_seconds.bind(this, 5);
|
case 'MediaFastForward':
|
||||||
|
action = skip_seconds.bind(this, 5 * player.playbackRate());
|
||||||
break;
|
break;
|
||||||
case 'ArrowLeft':
|
case 'ArrowLeft':
|
||||||
action = skip_seconds.bind(this, -5);
|
case 'MediaTrackPrevious':
|
||||||
|
action = skip_seconds.bind(this, -5 * player.playbackRate());
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
action = skip_seconds.bind(this, 10);
|
action = skip_seconds.bind(this, 10 * player.playbackRate());
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
action = skip_seconds.bind(this, -10);
|
action = skip_seconds.bind(this, -10 * player.playbackRate());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '0':
|
case '0':
|
||||||
@@ -379,37 +609,33 @@ window.addEventListener('keydown', e => {
|
|||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
|
// Ignore numpad numbers
|
||||||
|
if (code > 57) break;
|
||||||
|
|
||||||
const percent = (code - 48) * 10;
|
const percent = (code - 48) * 10;
|
||||||
action = set_time_percent.bind(this, percent);
|
action = set_time_percent.bind(this, percent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c': action = toggle_captions; break;
|
||||||
action = toggle_captions;
|
case 'f': action = toggle_fullscreen; break;
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
action = toggle_fullscreen;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'N':
|
case 'N':
|
||||||
|
case 'MediaTrackNext':
|
||||||
action = next_video;
|
action = next_video;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
|
case 'MediaTrackPrevious':
|
||||||
// TODO: Add support to play back previous video.
|
// TODO: Add support to play back previous video.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.':
|
// TODO: More precise step. Now FPS is taken equal to 29.97
|
||||||
// TODO: Add support for next-frame-stepping.
|
// Common FPS: https://forum.videohelp.com/threads/81868#post323588
|
||||||
break;
|
// Possible solution is new HTMLVideoElement.requestVideoFrameCallback() https://wicg.github.io/video-rvfc/
|
||||||
case ',':
|
case ',': action = function () { pause(); skip_seconds(-1/29.97); }; break;
|
||||||
// TODO: Add support for previous-frame-stepping.
|
case '.': action = function () { pause(); skip_seconds( 1/29.97); }; break;
|
||||||
break;
|
|
||||||
|
|
||||||
case '>':
|
case '>': action = increase_playback_rate.bind(this, 1); break;
|
||||||
action = increase_playback_rate.bind(this, 1);
|
case '<': action = increase_playback_rate.bind(this, -1); break;
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
action = increase_playback_rate.bind(this, -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.info('Unhandled key down event: %s:', decoratedKey, e);
|
console.info('Unhandled key down event: %s:', decoratedKey, e);
|
||||||
@@ -425,47 +651,77 @@ window.addEventListener('keydown', e => {
|
|||||||
// Add support for controlling the player volume by scrolling over it. Adapted from
|
// Add support for controlling the player volume by scrolling over it. Adapted from
|
||||||
// https://github.com/ctd1500/videojs-hotkeys/blob/bb4a158b2e214ccab87c2e7b95f42bc45c6bfd87/videojs.hotkeys.js#L292-L328
|
// https://github.com/ctd1500/videojs-hotkeys/blob/bb4a158b2e214ccab87c2e7b95f42bc45c6bfd87/videojs.hotkeys.js#L292-L328
|
||||||
(function () {
|
(function () {
|
||||||
const volumeStep = 0.05;
|
|
||||||
const enableVolumeScroll = true;
|
|
||||||
const enableHoverScroll = true;
|
|
||||||
const doc = document;
|
|
||||||
const pEl = document.getElementById('player');
|
const pEl = document.getElementById('player');
|
||||||
|
|
||||||
var volumeHover = false;
|
var volumeHover = false;
|
||||||
var volumeSelector = pEl.querySelector('.vjs-volume-menu-button') || pEl.querySelector('.vjs-volume-panel');
|
var volumeSelector = pEl.querySelector('.vjs-volume-menu-button') || pEl.querySelector('.vjs-volume-panel');
|
||||||
if (volumeSelector != null) {
|
if (volumeSelector !== null) {
|
||||||
volumeSelector.onmouseover = function () { volumeHover = true; };
|
volumeSelector.onmouseover = function () { volumeHover = true; };
|
||||||
volumeSelector.onmouseout = function () { volumeHover = false; };
|
volumeSelector.onmouseout = function () { volumeHover = false; };
|
||||||
}
|
}
|
||||||
|
|
||||||
var mouseScroll = function mouseScroll(event) {
|
function mouseScroll(event) {
|
||||||
var activeEl = doc.activeElement;
|
|
||||||
if (enableHoverScroll) {
|
|
||||||
// If we leave this undefined then it can match non-existent elements below
|
|
||||||
activeEl = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When controls are disabled, hotkeys will be disabled as well
|
// When controls are disabled, hotkeys will be disabled as well
|
||||||
if (player.controls()) {
|
if (!player.controls() || !volumeHover) return;
|
||||||
if (volumeHover) {
|
|
||||||
if (enableVolumeScroll) {
|
|
||||||
event = window.event || event;
|
|
||||||
var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if (delta == 1) {
|
event.preventDefault();
|
||||||
increase_volume(volumeStep);
|
var wheelMove = event.wheelDelta || -event.detail;
|
||||||
} else if (delta == -1) {
|
var volumeSign = Math.sign(wheelMove);
|
||||||
increase_volume(-volumeStep);
|
|
||||||
}
|
change_volume(volumeSign * 0.05); // decrease/increase by 5%
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
player.on('mousewheel', mouseScroll);
|
player.on('mousewheel', mouseScroll);
|
||||||
player.on("DOMMouseScroll", mouseScroll);
|
player.on('DOMMouseScroll', mouseScroll);
|
||||||
}());
|
}());
|
||||||
|
|
||||||
// Since videojs-share can sometimes be blocked, we defer it until last
|
// Since videojs-share can sometimes be blocked, we defer it until last
|
||||||
player.share(shareOptions);
|
if (player.share) player.share(shareOptions);
|
||||||
|
|
||||||
|
// show the preferred caption by default
|
||||||
|
if (player_data.preferred_caption_found) {
|
||||||
|
player.ready(function () {
|
||||||
|
if (!video_data.params.listen && video_data.params.quality === 'dash') {
|
||||||
|
// play.textTracks()[0] on DASH mode is showing some debug messages
|
||||||
|
player.textTracks()[1].mode = 'showing';
|
||||||
|
} else {
|
||||||
|
player.textTracks()[0].mode = 'showing';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safari audio double duration fix
|
||||||
|
if (navigator.vendor === 'Apple Computer, Inc.' && video_data.params.listen) {
|
||||||
|
player.on('loadedmetadata', function () {
|
||||||
|
player.on('timeupdate', function () {
|
||||||
|
if (player.remainingTime() < player.duration() / 2 && player.remainingTime() >= 2) {
|
||||||
|
player.currentTime(player.duration() - 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch on Invidious link
|
||||||
|
if (location.pathname.startsWith('/embed/')) {
|
||||||
|
const Button = videojs.getComponent('Button');
|
||||||
|
let watch_on_invidious_button = new Button(player);
|
||||||
|
|
||||||
|
// Create hyperlink for current instance
|
||||||
|
var redirect_element = document.createElement('a');
|
||||||
|
redirect_element.setAttribute('href', location.pathname.replace('/embed/', '/watch?v='));
|
||||||
|
redirect_element.appendChild(document.createTextNode('Invidious'));
|
||||||
|
|
||||||
|
watch_on_invidious_button.el().appendChild(redirect_element);
|
||||||
|
watch_on_invidious_button.addClass('watch-on-invidious');
|
||||||
|
|
||||||
|
var cb = player.getChild('ControlBar');
|
||||||
|
cb.addChild(watch_on_invidious_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener('DOMContentLoaded', function () {
|
||||||
|
// Save time during redirection on another instance
|
||||||
|
const changeInstanceLink = document.querySelector('#watch-on-another-invidious-instance > a');
|
||||||
|
if (changeInstanceLink) changeInstanceLink.addEventListener('click', function () {
|
||||||
|
changeInstanceLink.href = addCurrentTimeToURL(changeInstanceLink.href);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
var playlist_data = JSON.parse(document.getElementById('playlist_data').textContent);
|
||||||
|
var payload = 'csrf_token=' + playlist_data.csrf_token;
|
||||||
|
|
||||||
|
function add_playlist_video(target) {
|
||||||
|
var select = target.parentNode.children[0].children[1];
|
||||||
|
var option = select.children[select.selectedIndex];
|
||||||
|
|
||||||
|
var url = '/playlist_ajax?action_add_video=1&redirect=false' +
|
||||||
|
'&video_id=' + target.getAttribute('data-id') +
|
||||||
|
'&playlist_id=' + option.getAttribute('data-plid');
|
||||||
|
|
||||||
|
helpers.xhr('POST', url, {payload: payload}, {
|
||||||
|
on200: function (response) {
|
||||||
|
option.textContent = '✓' + option.textContent;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function add_playlist_item(target) {
|
function add_playlist_item(target) {
|
||||||
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||||
tile.style.display = 'none';
|
tile.style.display = 'none';
|
||||||
@@ -5,21 +24,12 @@ function add_playlist_item(target) {
|
|||||||
var url = '/playlist_ajax?action_add_video=1&redirect=false' +
|
var url = '/playlist_ajax?action_add_video=1&redirect=false' +
|
||||||
'&video_id=' + target.getAttribute('data-id') +
|
'&video_id=' + target.getAttribute('data-id') +
|
||||||
'&playlist_id=' + target.getAttribute('data-plid');
|
'&playlist_id=' + target.getAttribute('data-plid');
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('POST', url, true);
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
helpers.xhr('POST', url, {payload: payload}, {
|
||||||
if (xhr.readyState == 4) {
|
onNon200: function (xhr) {
|
||||||
if (xhr.status != 200) {
|
tile.style.display = '';
|
||||||
tile.style.display = '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
xhr.send('csrf_token=' + playlist_data.csrf_token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove_playlist_item(target) {
|
function remove_playlist_item(target) {
|
||||||
@@ -29,19 +39,10 @@ function remove_playlist_item(target) {
|
|||||||
var url = '/playlist_ajax?action_remove_video=1&redirect=false' +
|
var url = '/playlist_ajax?action_remove_video=1&redirect=false' +
|
||||||
'&set_video_id=' + target.getAttribute('data-index') +
|
'&set_video_id=' + target.getAttribute('data-index') +
|
||||||
'&playlist_id=' + target.getAttribute('data-plid');
|
'&playlist_id=' + target.getAttribute('data-plid');
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('POST', url, true);
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
helpers.xhr('POST', url, {payload: payload}, {
|
||||||
if (xhr.readyState == 4) {
|
onNon200: function (xhr) {
|
||||||
if (xhr.status != 200) {
|
tile.style.display = '';
|
||||||
tile.style.display = '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
xhr.send('csrf_token=' + playlist_data.csrf_token);
|
|
||||||
}
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,9 @@
|
|||||||
|
'use strict';
|
||||||
|
var subscribe_data = JSON.parse(document.getElementById('subscribe_data').textContent);
|
||||||
|
var payload = 'csrf_token=' + subscribe_data.csrf_token;
|
||||||
|
|
||||||
var subscribe_button = document.getElementById('subscribe');
|
var subscribe_button = document.getElementById('subscribe');
|
||||||
subscribe_button.parentNode['action'] = 'javascript:void(0)';
|
subscribe_button.parentNode.action = 'javascript:void(0)';
|
||||||
|
|
||||||
if (subscribe_button.getAttribute('data-type') === 'subscribe') {
|
if (subscribe_button.getAttribute('data-type') === 'subscribe') {
|
||||||
subscribe_button.onclick = subscribe;
|
subscribe_button.onclick = subscribe;
|
||||||
@@ -7,82 +11,34 @@ if (subscribe_button.getAttribute('data-type') === 'subscribe') {
|
|||||||
subscribe_button.onclick = unsubscribe;
|
subscribe_button.onclick = unsubscribe;
|
||||||
}
|
}
|
||||||
|
|
||||||
function subscribe(retries = 5) {
|
function subscribe() {
|
||||||
if (retries <= 0) {
|
|
||||||
console.log('Failed to subscribe.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = '/subscription_ajax?action_create_subscription_to_channel=1&redirect=false' +
|
|
||||||
'&c=' + subscribe_data.ucid;
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('POST', url, true);
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
|
|
||||||
var fallback = subscribe_button.innerHTML;
|
var fallback = subscribe_button.innerHTML;
|
||||||
subscribe_button.onclick = unsubscribe;
|
subscribe_button.onclick = unsubscribe;
|
||||||
subscribe_button.innerHTML = '<b>' + subscribe_data.unsubscribe_text + ' | ' + subscribe_data.sub_count_text + '</b>';
|
subscribe_button.innerHTML = '<b>' + subscribe_data.unsubscribe_text + ' | ' + subscribe_data.sub_count_text + '</b>';
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
var url = '/subscription_ajax?action_create_subscription_to_channel=1&redirect=false' +
|
||||||
if (xhr.readyState == 4) {
|
'&c=' + subscribe_data.ucid;
|
||||||
if (xhr.status != 200) {
|
|
||||||
subscribe_button.onclick = subscribe;
|
helpers.xhr('POST', url, {payload: payload, retries: 5, entity_name: 'subscribe request'}, {
|
||||||
subscribe_button.innerHTML = fallback;
|
onNon200: function (xhr) {
|
||||||
}
|
subscribe_button.onclick = subscribe;
|
||||||
|
subscribe_button.innerHTML = fallback;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
xhr.onerror = function () {
|
|
||||||
console.log('Subscribing failed... ' + retries + '/5');
|
|
||||||
setTimeout(function () { subscribe(retries - 1) }, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
|
||||||
console.log('Subscribing failed... ' + retries + '/5');
|
|
||||||
subscribe(retries - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send('csrf_token=' + subscribe_data.csrf_token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function unsubscribe(retries = 5) {
|
function unsubscribe() {
|
||||||
if (retries <= 0) {
|
|
||||||
console.log('Failed to subscribe');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' +
|
|
||||||
'&c=' + subscribe_data.ucid;
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('POST', url, true);
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
|
|
||||||
var fallback = subscribe_button.innerHTML;
|
var fallback = subscribe_button.innerHTML;
|
||||||
subscribe_button.onclick = subscribe;
|
subscribe_button.onclick = subscribe;
|
||||||
subscribe_button.innerHTML = '<b>' + subscribe_data.subscribe_text + ' | ' + subscribe_data.sub_count_text + '</b>';
|
subscribe_button.innerHTML = '<b>' + subscribe_data.subscribe_text + ' | ' + subscribe_data.sub_count_text + '</b>';
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' +
|
||||||
if (xhr.readyState == 4) {
|
'&c=' + subscribe_data.ucid;
|
||||||
if (xhr.status != 200) {
|
|
||||||
subscribe_button.onclick = unsubscribe;
|
helpers.xhr('POST', url, {payload: payload, retries: 5, entity_name: 'unsubscribe request'}, {
|
||||||
subscribe_button.innerHTML = fallback;
|
onNon200: function (xhr) {
|
||||||
}
|
subscribe_button.onclick = unsubscribe;
|
||||||
|
subscribe_button.innerHTML = fallback;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
xhr.onerror = function () {
|
|
||||||
console.log('Unsubscribing failed... ' + retries + '/5');
|
|
||||||
setTimeout(function () { unsubscribe(retries - 1) }, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
|
||||||
console.log('Unsubscribing failed... ' + retries + '/5');
|
|
||||||
unsubscribe(retries - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send('csrf_token=' + subscribe_data.csrf_token);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +1,44 @@
|
|||||||
|
'use strict';
|
||||||
var toggle_theme = document.getElementById('toggle_theme');
|
var toggle_theme = document.getElementById('toggle_theme');
|
||||||
toggle_theme.href = 'javascript:void(0);';
|
toggle_theme.href = 'javascript:void(0)';
|
||||||
|
|
||||||
|
const STORAGE_KEY_THEME = 'dark_mode';
|
||||||
|
const THEME_DARK = 'dark';
|
||||||
|
const THEME_LIGHT = 'light';
|
||||||
|
|
||||||
|
// TODO: theme state controlled by system
|
||||||
toggle_theme.addEventListener('click', function () {
|
toggle_theme.addEventListener('click', function () {
|
||||||
var dark_mode = document.getElementById('dark_theme').media === 'none';
|
const isDarkTheme = helpers.storage.get(STORAGE_KEY_THEME) === THEME_DARK;
|
||||||
|
const newTheme = isDarkTheme ? THEME_LIGHT : THEME_DARK;
|
||||||
var url = '/toggle_theme?redirect=false';
|
setTheme(newTheme);
|
||||||
var xhr = new XMLHttpRequest();
|
helpers.storage.set(STORAGE_KEY_THEME, newTheme);
|
||||||
xhr.responseType = 'json';
|
helpers.xhr('GET', '/toggle_theme?redirect=false', {}, {});
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('GET', url, true);
|
|
||||||
|
|
||||||
set_mode(dark_mode);
|
|
||||||
window.localStorage.setItem('dark_mode', dark_mode ? 'dark' : 'light');
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('storage', function (e) {
|
/** @param {THEME_DARK|THEME_LIGHT} theme */
|
||||||
if (e.key === 'dark_mode') {
|
function setTheme(theme) {
|
||||||
update_mode(e.newValue);
|
// By default body element has .no-theme class that uses OS theme via CSS @media rules
|
||||||
}
|
// It rewrites using hard className below
|
||||||
});
|
if (theme === THEME_DARK) {
|
||||||
|
toggle_theme.children[0].className = 'icon ion-ios-sunny';
|
||||||
window.addEventListener('load', function () {
|
document.body.className = 'dark-theme';
|
||||||
window.localStorage.setItem('dark_mode', document.getElementById('dark_mode_pref').textContent);
|
|
||||||
// Update localStorage if dark mode preference changed on preferences page
|
|
||||||
update_mode(window.localStorage.dark_mode);
|
|
||||||
});
|
|
||||||
|
|
||||||
function set_mode (bool) {
|
|
||||||
document.getElementById('dark_theme').media = !bool ? 'none' : '';
|
|
||||||
document.getElementById('light_theme').media = bool ? 'none' : '';
|
|
||||||
|
|
||||||
if (bool) {
|
|
||||||
toggle_theme.children[0].setAttribute('class', 'icon ion-ios-sunny');
|
|
||||||
} else {
|
} else {
|
||||||
toggle_theme.children[0].setAttribute('class', 'icon ion-ios-moon');
|
toggle_theme.children[0].className = 'icon ion-ios-moon';
|
||||||
|
document.body.className = 'light-theme';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_mode (mode) {
|
// Handles theme change event caused by other tab
|
||||||
if (mode === 'true' /* for backwards compatibility */ || mode === 'dark') {
|
addEventListener('storage', function (e) {
|
||||||
// If preference for dark mode indicated
|
if (e.key === STORAGE_KEY_THEME)
|
||||||
set_mode(true);
|
setTheme(helpers.storage.get(STORAGE_KEY_THEME));
|
||||||
}
|
});
|
||||||
else if (mode === 'false' /* for backwards compaibility */ || mode === 'light') {
|
|
||||||
// If preference for light mode indicated
|
|
||||||
set_mode(false);
|
|
||||||
}
|
|
||||||
else if (document.getElementById('dark_mode_pref').textContent === '' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
||||||
// If no preference indicated here and no preference indicated on the preferences page (backend), but the browser tells us that the operating system has a dark theme
|
|
||||||
set_mode(true);
|
|
||||||
}
|
|
||||||
// else do nothing, falling back to the mode defined by the `dark_mode` preference on the preferences page (backend)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
// Set theme from preferences on page load
|
||||||
|
addEventListener('DOMContentLoaded', function () {
|
||||||
|
const prefTheme = document.getElementById('dark_mode_pref').textContent;
|
||||||
|
if (prefTheme) {
|
||||||
|
setTheme(prefTheme);
|
||||||
|
helpers.storage.set(STORAGE_KEY_THEME, prefTheme);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
20
assets/js/video.min.js
vendored
20
assets/js/video.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
|||||||
/*! @name videojs-contrib-quality-levels @version 2.0.9 @license Apache-2.0 */
|
|
||||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("video.js"),require("global/document")):"function"==typeof define&&define.amd?define(["video.js","global/document"],t):e.videojsContribQualityLevels=t(e.videojs,e.document)}(this,function(e,t){"use strict";function n(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}e=e&&e.hasOwnProperty("default")?e.default:e,t=t&&t.hasOwnProperty("default")?t.default:t;var r=function(r){var i,l;function o(){var i,l=n(n(i=r.call(this)||this));if(e.browser.IS_IE8)for(var s in l=t.createElement("custom"),o.prototype)"constructor"!==s&&(l[s]=o.prototype[s]);return l.levels_=[],l.selectedIndex_=-1,Object.defineProperty(l,"selectedIndex",{get:function(){return l.selectedIndex_}}),Object.defineProperty(l,"length",{get:function(){return l.levels_.length}}),l||n(i)}l=r,(i=o).prototype=Object.create(l.prototype),i.prototype.constructor=i,i.__proto__=l;var s=o.prototype;return s.addQualityLevel=function(n){var r=this.getQualityLevelById(n.id);if(r)return r;var i=this.levels_.length;return r=new function n(r){var i=this;if(e.browser.IS_IE8)for(var l in i=t.createElement("custom"),n.prototype)"constructor"!==l&&(i[l]=n.prototype[l]);return i.id=r.id,i.label=i.id,i.width=r.width,i.height=r.height,i.bitrate=r.bandwidth,i.enabled_=r.enabled,Object.defineProperty(i,"enabled",{get:function(){return i.enabled_()},set:function(e){i.enabled_(e)}}),i}(n),""+i in this||Object.defineProperty(this,i,{get:function(){return this.levels_[i]}}),this.levels_.push(r),this.trigger({qualityLevel:r,type:"addqualitylevel"}),r},s.removeQualityLevel=function(e){for(var t=null,n=0,r=this.length;n<r;n++)if(this[n]===e){t=this.levels_.splice(n,1)[0],this.selectedIndex_===n?this.selectedIndex_=-1:this.selectedIndex_>n&&this.selectedIndex_--;break}return t&&this.trigger({qualityLevel:e,type:"removequalitylevel"}),t},s.getQualityLevelById=function(e){for(var t=0,n=this.length;t<n;t++){var r=this[t];if(r.id===e)return r}return null},s.dispose=function(){this.selectedIndex_=-1,this.levels_.length=0},o}(e.EventTarget);for(var i in r.prototype.allowedEvents_={change:"change",addqualitylevel:"addqualitylevel",removequalitylevel:"removequalitylevel"},r.prototype.allowedEvents_)r.prototype["on"+i]=null;var l=function(t){return n=this,e.mergeOptions({},t),i=n.qualityLevels,l=new r,n.on("dispose",function e(){l.dispose(),n.qualityLevels=i,n.off("dispose",e)}),n.qualityLevels=function(){return l},n.qualityLevels.VERSION="2.0.9",l;var n,i,l};return(e.registerPlugin||e.plugin)("qualityLevels",l),l.VERSION="2.0.9",l});
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* videojs-http-source-selector
|
|
||||||
* @version 1.1.6
|
|
||||||
* @copyright 2019 Justin Fujita <Justin@pivotshare.com>
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("video.js")):"function"==typeof define&&define.amd?define(["video.js"],t):(e=e||self)["videojs-http-source-selector"]=t(e.videojs)}(this,function(r){"use strict";function o(e,t){e.prototype=Object.create(t.prototype),(e.prototype.constructor=e).__proto__=t}function s(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var e=(r=r&&r.hasOwnProperty("default")?r.default:r).getComponent("MenuItem"),t=r.getComponent("Component"),a=function(n){function e(e,t){return t.selectable=!0,t.multiSelectable=!1,n.call(this,e,t)||this}o(e,n);var t=e.prototype;return t.handleClick=function(){var e=this.options_;console.log("Changing quality to:",e.label),n.prototype.handleClick.call(this);for(var t=this.player().qualityLevels(),o=0;o<t.length;o++)e.index==t.length?t[o].enabled=!0:e.index==o?t[o].enabled=!0:t[o].enabled=!1},t.update=function(){var e=this.player().qualityLevels().selectedIndex;this.selected(this.options_.index==e)},e}(e);t.registerComponent("SourceMenuItem",a);var u=r.getComponent("MenuButton"),n=function(i){function e(e,t){var o;o=i.call(this,e,t)||this,u.apply(s(o),arguments);var n=o.player().qualityLevels();if(t&&t.default)if("low"==t.default)for(var l=0;l<n.length;l++)n[l].enabled=0==l;else if(t.default="high")for(l=0;l<n.length;l++)n[l].enabled=l==n.length-1;return o.player().qualityLevels().on(["change","addqualitylevel"],r.bind(s(o),o.update)),o}o(e,i);var t=e.prototype;return t.createEl=function(){return r.dom.createEl("div",{className:"vjs-http-source-selector vjs-menu-button vjs-menu-button-popup vjs-control vjs-button"})},t.buildCSSClass=function(){return u.prototype.buildCSSClass.call(this)+" vjs-icon-cog"},t.update=function(){return u.prototype.update.call(this)},t.createItems=function(){for(var e=[],t=this.player().qualityLevels(),o=[],n=0;n<t.length;n++){var l=t.length-(n+1),i=l===t.selectedIndex,r=""+l,s=l;t[l].height?(r=t[l].height+"p",s=parseInt(t[l].height,10)):t[l].bitrate&&(r=Math.floor(t[l].bitrate/1e3)+" kbps",s=parseInt(t[l].bitrate,10)),0<=o.indexOf(r)||(o.push(r),e.push(new a(this.player_,{label:r,index:l,selected:i,sortVal:s})))}return 1<t.length&&e.push(new a(this.player_,{label:"Auto",index:t.length,selected:!1,sortVal:99999})),e.sort(function(e,t){return e.options_.sortVal<t.options_.sortVal?1:e.options_.sortVal>t.options_.sortVal?-1:0}),e},e}(u),l={},i=r.registerPlugin||r.plugin,c=function(e){var t=this;this.ready(function(){!function(n,e){if(n.addClass("vjs-http-source-selector"),console.log("videojs-http-source-selector initialized!"),console.log("player.techName_:"+n.techName_),"Html5"!=n.techName_)return;n.on(["loadedmetadata"],function(e){if(n.qualityLevels(),r.log("loadmetadata event"),"undefined"==n.videojs_http_source_selector_initialized||1==n.videojs_http_source_selector_initialized)console.log("player.videojs_http_source_selector_initialized == true");else{console.log("player.videojs_http_source_selector_initialized == false"),n.videojs_http_source_selector_initialized=!0;var t=n.controlBar,o=t.getChild("fullscreenToggle").el();t.el().insertBefore(t.addChild("SourceMenuButton").el(),o)}})}(t,r.mergeOptions(l,e))}),r.registerComponent("SourceMenuButton",n),r.registerComponent("SourceMenuItem",a)};return i("httpSourceSelector",c),c.VERSION="1.1.6",c});
|
|
||||||
4
assets/js/videojs-markers.min.js
vendored
4
assets/js/videojs-markers.min.js
vendored
File diff suppressed because one or more lines are too long
2
assets/js/videojs-overlay.min.js
vendored
2
assets/js/videojs-overlay.min.js
vendored
@@ -1,2 +0,0 @@
|
|||||||
/*! @name videojs-overlay @version 2.1.4 @license Apache-2.0 */
|
|
||||||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("video.js"),require("global/window")):"function"==typeof define&&define.amd?define(["video.js","global/window"],e):t.videojsOverlay=e(t.videojs,t.window)}(this,function(t,e){"use strict";function n(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}t=t&&t.hasOwnProperty("default")?t.default:t,e=e&&e.hasOwnProperty("default")?e.default:e;var r={align:"top-left",class:"",content:"This overlay will show up while the video is playing",debug:!1,showBackground:!0,attachToControlBar:!1,overlays:[{start:"playing",end:"paused"}]},i=t.getComponent("Component"),o=t.dom||t,s=t.registerPlugin||t.plugin,a=function(t){return"number"==typeof t&&t==t},h=function(t){return"string"==typeof t&&/^\S+$/.test(t)},d=function(r){var i,s;function d(t,e){var i;return i=r.call(this,t,e)||this,["start","end"].forEach(function(t){var e=i.options_[t];if(a(e))i[t+"Event_"]="timeupdate";else if(h(e))i[t+"Event_"]=e;else if("start"===t)throw new Error('invalid "start" option; expected number or string')}),["endListener_","rewindListener_","startListener_"].forEach(function(t){i[t]=function(e){return d.prototype[t].call(n(n(i)),e)}}),"timeupdate"===i.startEvent_&&i.on(t,"timeupdate",i.rewindListener_),i.debug('created, listening to "'+i.startEvent_+'" for "start" and "'+(i.endEvent_||"nothing")+'" for "end"'),i.hide(),i}s=r,(i=d).prototype=Object.create(s.prototype),i.prototype.constructor=i,i.__proto__=s;var l=d.prototype;return l.createEl=function(){var t=this.options_,n=t.content,r=t.showBackground?"vjs-overlay-background":"vjs-overlay-no-background",i=o.createEl("div",{className:"\n vjs-overlay\n vjs-overlay-"+t.align+"\n "+t.class+"\n "+r+"\n vjs-hidden\n "});return"string"==typeof n?i.innerHTML=n:n instanceof e.DocumentFragment?i.appendChild(n):o.appendContent(i,n),i},l.debug=function(){if(this.options_.debug){for(var e=t.log,n=e,r=arguments.length,i=new Array(r),o=0;o<r;o++)i[o]=arguments[o];e.hasOwnProperty(i[0])&&"function"==typeof e[i[0]]&&(n=e[i.shift()]),n.apply(void 0,["overlay#"+this.id()+": "].concat(i))}},l.hide=function(){return r.prototype.hide.call(this),this.debug("hidden"),this.debug('bound `startListener_` to "'+this.startEvent_+'"'),this.endEvent_&&(this.debug('unbound `endListener_` from "'+this.endEvent_+'"'),this.off(this.player(),this.endEvent_,this.endListener_)),this.on(this.player(),this.startEvent_,this.startListener_),this},l.shouldHide_=function(t,e){var n=this.options_.end;return a(n)?t>=n:n===e},l.show=function(){return r.prototype.show.call(this),this.off(this.player(),this.startEvent_,this.startListener_),this.debug("shown"),this.debug('unbound `startListener_` from "'+this.startEvent_+'"'),this.endEvent_&&(this.debug('bound `endListener_` to "'+this.endEvent_+'"'),this.on(this.player(),this.endEvent_,this.endListener_)),this},l.shouldShow_=function(t,e){var n=this.options_.start,r=this.options_.end;return a(n)?a(r)?t>=n&&t<r:this.hasShownSinceSeek_?Math.floor(t)===n:(this.hasShownSinceSeek_=!0,t>=n):n===e},l.startListener_=function(t){var e=this.player().currentTime();this.shouldShow_(e,t.type)&&this.show()},l.endListener_=function(t){var e=this.player().currentTime();this.shouldHide_(e,t.type)&&this.hide()},l.rewindListener_=function(t){var e=this.player().currentTime(),n=this.previousTime_,r=this.options_.start,i=this.options_.end;e<n&&(this.debug("rewind detected"),a(i)&&!this.shouldShow_(e)?(this.debug("hiding; "+i+" is an integer and overlay should not show at this time"),this.hasShownSinceSeek_=!1,this.hide()):h(i)&&e<r&&(this.debug("hiding; show point ("+r+") is before now ("+e+") and end point ("+i+") is an event"),this.hasShownSinceSeek_=!1,this.hide())),this.previousTime_=e},d}(i);t.registerComponent("Overlay",d);var l=function(e){var n=this,i=t.mergeOptions(r,e);Array.isArray(this.overlays_)&&this.overlays_.forEach(function(t){n.removeChild(t),n.controlBar&&n.controlBar.removeChild(t),t.dispose()});var o=i.overlays;delete i.overlays,this.overlays_=o.map(function(e){var r=t.mergeOptions(i,e),o="string"==typeof r.attachToControlBar||!0===r.attachToControlBar;if(!n.controls()||!n.controlBar)return n.addChild("overlay",r);if(o&&-1!==r.align.indexOf("bottom")){var s=n.controlBar.children()[0];if(void 0!==n.controlBar.getChild(r.attachToControlBar)&&(s=n.controlBar.getChild(r.attachToControlBar)),s){var a=n.controlBar.addChild("overlay",r);return n.controlBar.el().insertBefore(a.el(),s.el()),a}}var h=n.addChild("overlay",r);return n.el().insertBefore(h.el(),n.controlBar.el()),h})};return l.VERSION="2.1.4",s("overlay",l),l});
|
|
||||||
7
assets/js/videojs-share.min.js
vendored
7
assets/js/videojs-share.min.js
vendored
File diff suppressed because one or more lines are too long
7
assets/js/videojs-vtt-thumbnails.min.js
vendored
7
assets/js/videojs-vtt-thumbnails.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,30 +1,35 @@
|
|||||||
|
'use strict';
|
||||||
|
var video_data = JSON.parse(document.getElementById('video_data').textContent);
|
||||||
|
var spinnerHTML = '<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
|
||||||
|
var spinnerHTMLwithHR = spinnerHTML + '<hr>';
|
||||||
|
|
||||||
String.prototype.supplant = function (o) {
|
String.prototype.supplant = function (o) {
|
||||||
return this.replace(/{([^{}]*)}/g, function (a, b) {
|
return this.replace(/{([^{}]*)}/g, function (a, b) {
|
||||||
var r = o[b];
|
var r = o[b];
|
||||||
return typeof r === 'string' || typeof r === 'number' ? r : a;
|
return typeof r === 'string' || typeof r === 'number' ? r : a;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
function toggle_parent(target) {
|
function toggle_parent(target) {
|
||||||
body = target.parentNode.parentNode.children[1];
|
var body = target.parentNode.parentNode.children[1];
|
||||||
if (body.style.display === null || body.style.display === '') {
|
if (body.style.display === 'none') {
|
||||||
target.innerHTML = '[ + ]';
|
target.textContent = '[ − ]';
|
||||||
body.style.display = 'none';
|
|
||||||
} else {
|
|
||||||
target.innerHTML = '[ - ]';
|
|
||||||
body.style.display = '';
|
body.style.display = '';
|
||||||
|
} else {
|
||||||
|
target.textContent = '[ + ]';
|
||||||
|
body.style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle_comments(event) {
|
function toggle_comments(event) {
|
||||||
var target = event.target;
|
var target = event.target;
|
||||||
body = target.parentNode.parentNode.parentNode.children[1];
|
var body = target.parentNode.parentNode.parentNode.children[1];
|
||||||
if (body.style.display === null || body.style.display === '') {
|
if (body.style.display === 'none') {
|
||||||
target.innerHTML = '[ + ]';
|
target.textContent = '[ − ]';
|
||||||
body.style.display = 'none';
|
|
||||||
} else {
|
|
||||||
target.innerHTML = '[ - ]';
|
|
||||||
body.style.display = '';
|
body.style.display = '';
|
||||||
|
} else {
|
||||||
|
target.textContent = '[ + ]';
|
||||||
|
body.style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,13 +46,13 @@ function swap_comments(event) {
|
|||||||
function hide_youtube_replies(event) {
|
function hide_youtube_replies(event) {
|
||||||
var target = event.target;
|
var target = event.target;
|
||||||
|
|
||||||
sub_text = target.getAttribute('data-inner-text');
|
var sub_text = target.getAttribute('data-inner-text');
|
||||||
inner_text = target.getAttribute('data-sub-text');
|
var inner_text = target.getAttribute('data-sub-text');
|
||||||
|
|
||||||
body = target.parentNode.parentNode.children[1];
|
var body = target.parentNode.parentNode.children[1];
|
||||||
body.style.display = 'none';
|
body.style.display = 'none';
|
||||||
|
|
||||||
target.innerHTML = sub_text;
|
target.textContent = sub_text;
|
||||||
target.onclick = show_youtube_replies;
|
target.onclick = show_youtube_replies;
|
||||||
target.setAttribute('data-inner-text', inner_text);
|
target.setAttribute('data-inner-text', inner_text);
|
||||||
target.setAttribute('data-sub-text', sub_text);
|
target.setAttribute('data-sub-text', sub_text);
|
||||||
@@ -56,13 +61,13 @@ function hide_youtube_replies(event) {
|
|||||||
function show_youtube_replies(event) {
|
function show_youtube_replies(event) {
|
||||||
var target = event.target;
|
var target = event.target;
|
||||||
|
|
||||||
sub_text = target.getAttribute('data-inner-text');
|
var sub_text = target.getAttribute('data-inner-text');
|
||||||
inner_text = target.getAttribute('data-sub-text');
|
var inner_text = target.getAttribute('data-sub-text');
|
||||||
|
|
||||||
body = target.parentNode.parentNode.children[1];
|
var body = target.parentNode.parentNode.children[1];
|
||||||
body.style.display = '';
|
body.style.display = '';
|
||||||
|
|
||||||
target.innerHTML = sub_text;
|
target.textContent = sub_text;
|
||||||
target.onclick = hide_youtube_replies;
|
target.onclick = hide_youtube_replies;
|
||||||
target.setAttribute('data-inner-text', inner_text);
|
target.setAttribute('data-inner-text', inner_text);
|
||||||
target.setAttribute('data-sub-text', sub_text);
|
target.setAttribute('data-sub-text', sub_text);
|
||||||
@@ -76,373 +81,259 @@ if (continue_button) {
|
|||||||
function next_video() {
|
function next_video() {
|
||||||
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
|
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
|
||||||
|
|
||||||
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
|
if (video_data.params.autoplay || video_data.params.continue_autoplay)
|
||||||
url.searchParams.set('autoplay', '1');
|
url.searchParams.set('autoplay', '1');
|
||||||
}
|
if (video_data.params.listen !== video_data.preferences.listen)
|
||||||
|
|
||||||
if (video_data.params.listen !== video_data.preferences.listen) {
|
|
||||||
url.searchParams.set('listen', video_data.params.listen);
|
url.searchParams.set('listen', video_data.params.listen);
|
||||||
}
|
if (video_data.params.speed !== video_data.preferences.speed)
|
||||||
|
|
||||||
if (video_data.params.speed !== video_data.preferences.speed) {
|
|
||||||
url.searchParams.set('speed', video_data.params.speed);
|
url.searchParams.set('speed', video_data.params.speed);
|
||||||
}
|
if (video_data.params.local !== video_data.preferences.local)
|
||||||
|
|
||||||
if (video_data.params.local !== video_data.preferences.local) {
|
|
||||||
url.searchParams.set('local', video_data.params.local);
|
url.searchParams.set('local', video_data.params.local);
|
||||||
}
|
|
||||||
|
|
||||||
url.searchParams.set('continue', '1');
|
url.searchParams.set('continue', '1');
|
||||||
|
|
||||||
location.assign(url.pathname + url.search);
|
location.assign(url.pathname + url.search);
|
||||||
}
|
}
|
||||||
|
|
||||||
function continue_autoplay(event) {
|
function continue_autoplay(event) {
|
||||||
if (event.target.checked) {
|
if (event.target.checked) {
|
||||||
player.on('ended', function () {
|
player.on('ended', next_video);
|
||||||
next_video();
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
player.off('ended');
|
player.off('ended');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function number_with_separator(val) {
|
function get_playlist(plid) {
|
||||||
while (/(\d+)(\d{3})/.test(val.toString())) {
|
var playlist = document.getElementById('playlist');
|
||||||
val = val.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_playlist(plid, retries) {
|
playlist.innerHTML = spinnerHTMLwithHR;
|
||||||
if (retries == undefined) retries = 5;
|
|
||||||
playlist = document.getElementById('playlist');
|
|
||||||
|
|
||||||
if (retries <= 0) {
|
|
||||||
console.log('Failed to pull playlist');
|
|
||||||
playlist.innerHTML = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
playlist.innerHTML = ' \
|
|
||||||
<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3> \
|
|
||||||
<hr>'
|
|
||||||
|
|
||||||
|
var plid_url;
|
||||||
if (plid.startsWith('RD')) {
|
if (plid.startsWith('RD')) {
|
||||||
var plid_url = '/api/v1/mixes/' + plid +
|
plid_url = '/api/v1/mixes/' + plid +
|
||||||
'?continuation=' + video_data.id +
|
'?continuation=' + video_data.id +
|
||||||
'&format=html&hl=' + video_data.preferences.locale;
|
'&format=html&hl=' + video_data.preferences.locale;
|
||||||
} else {
|
} else {
|
||||||
var plid_url = '/api/v1/playlists/' + plid +
|
plid_url = '/api/v1/playlists/' + plid +
|
||||||
'?index=' + video_data.index +
|
'?index=' + video_data.index +
|
||||||
'&continuation=' + video_data.id +
|
'&continuation=' + video_data.id +
|
||||||
'&format=html&hl=' + video_data.preferences.locale;
|
'&format=html&hl=' + video_data.preferences.locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
helpers.xhr('GET', plid_url, {retries: 5, entity_name: 'playlist'}, {
|
||||||
xhr.responseType = 'json';
|
on200: function (response) {
|
||||||
xhr.timeout = 10000;
|
playlist.innerHTML = response.playlistHtml;
|
||||||
xhr.open('GET', plid_url, true);
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
if (!response.nextVideo) return;
|
||||||
if (xhr.readyState == 4) {
|
|
||||||
if (xhr.status == 200) {
|
|
||||||
playlist.innerHTML = xhr.response.playlistHtml;
|
|
||||||
|
|
||||||
if (xhr.response.nextVideo) {
|
var nextVideo = document.getElementById(response.nextVideo);
|
||||||
player.on('ended', function () {
|
nextVideo.parentNode.parentNode.scrollTop = nextVideo.offsetTop;
|
||||||
var url = new URL('https://example.com/watch?v=' + xhr.response.nextVideo);
|
|
||||||
|
|
||||||
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
|
player.on('ended', function () {
|
||||||
url.searchParams.set('autoplay', '1');
|
var url = new URL('https://example.com/watch?v=' + response.nextVideo);
|
||||||
}
|
|
||||||
|
|
||||||
if (video_data.params.listen !== video_data.preferences.listen) {
|
url.searchParams.set('list', plid);
|
||||||
url.searchParams.set('listen', video_data.params.listen);
|
if (!plid.startsWith('RD'))
|
||||||
}
|
url.searchParams.set('index', response.index);
|
||||||
|
if (video_data.params.autoplay || video_data.params.continue_autoplay)
|
||||||
|
url.searchParams.set('autoplay', '1');
|
||||||
|
if (video_data.params.listen !== video_data.preferences.listen)
|
||||||
|
url.searchParams.set('listen', video_data.params.listen);
|
||||||
|
if (video_data.params.speed !== video_data.preferences.speed)
|
||||||
|
url.searchParams.set('speed', video_data.params.speed);
|
||||||
|
if (video_data.params.local !== video_data.preferences.local)
|
||||||
|
url.searchParams.set('local', video_data.params.local);
|
||||||
|
|
||||||
if (video_data.params.speed !== video_data.preferences.speed) {
|
location.assign(url.pathname + url.search);
|
||||||
url.searchParams.set('speed', video_data.params.speed);
|
});
|
||||||
}
|
},
|
||||||
|
onNon200: function (xhr) {
|
||||||
if (video_data.params.local !== video_data.preferences.local) {
|
playlist.innerHTML = '';
|
||||||
url.searchParams.set('local', video_data.params.local);
|
document.getElementById('continue').style.display = '';
|
||||||
}
|
},
|
||||||
|
onError: function (xhr) {
|
||||||
url.searchParams.set('list', plid);
|
playlist.innerHTML = spinnerHTMLwithHR;
|
||||||
if (!plid.startsWith('RD')) {
|
},
|
||||||
url.searchParams.set('index', xhr.response.index);
|
onTimeout: function (xhr) {
|
||||||
}
|
playlist.innerHTML = spinnerHTMLwithHR;
|
||||||
location.assign(url.pathname + url.search);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
playlist.innerHTML = '';
|
|
||||||
document.getElementById('continue').style.display = '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
xhr.onerror = function () {
|
|
||||||
playlist = document.getElementById('playlist');
|
|
||||||
playlist.innerHTML =
|
|
||||||
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3><hr>';
|
|
||||||
|
|
||||||
console.log('Pulling playlist timed out... ' + retries + '/5');
|
|
||||||
setTimeout(function () { get_playlist(plid, retries - 1) }, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
|
||||||
playlist = document.getElementById('playlist');
|
|
||||||
playlist.innerHTML =
|
|
||||||
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3><hr>';
|
|
||||||
|
|
||||||
console.log('Pulling playlist timed out... ' + retries + '/5');
|
|
||||||
get_playlist(plid, retries - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_reddit_comments(retries) {
|
function get_reddit_comments() {
|
||||||
if (retries == undefined) retries = 5;
|
var comments = document.getElementById('comments');
|
||||||
comments = document.getElementById('comments');
|
|
||||||
|
|
||||||
if (retries <= 0) {
|
|
||||||
console.log('Failed to pull comments');
|
|
||||||
comments.innerHTML = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fallback = comments.innerHTML;
|
var fallback = comments.innerHTML;
|
||||||
comments.innerHTML =
|
comments.innerHTML = spinnerHTML;
|
||||||
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
|
|
||||||
|
|
||||||
var url = '/api/v1/comments/' + video_data.id +
|
var url = '/api/v1/comments/' + video_data.id +
|
||||||
'?source=reddit&format=html' +
|
'?source=reddit&format=html' +
|
||||||
'&hl=' + video_data.preferences.locale;
|
'&hl=' + video_data.preferences.locale;
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('GET', url, true);
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
var onNon200 = function (xhr) { comments.innerHTML = fallback; };
|
||||||
if (xhr.readyState == 4) {
|
if (video_data.params.comments[1] === 'youtube')
|
||||||
if (xhr.status == 200) {
|
onNon200 = function (xhr) {};
|
||||||
comments.innerHTML = ' \
|
|
||||||
<div> \
|
helpers.xhr('GET', url, {retries: 5, entity_name: ''}, {
|
||||||
<h3> \
|
on200: function (response) {
|
||||||
<a href="javascript:void(0)">[ - ]</a> \
|
comments.innerHTML = ' \
|
||||||
{title} \
|
<div> \
|
||||||
</h3> \
|
<h3> \
|
||||||
<p> \
|
<a href="javascript:void(0)">[ − ]</a> \
|
||||||
<b> \
|
{title} \
|
||||||
<a href="javascript:void(0)" data-comments="youtube"> \
|
</h3> \
|
||||||
{youtubeCommentsText} \
|
<p> \
|
||||||
</a> \
|
|
||||||
</b> \
|
|
||||||
</p> \
|
|
||||||
<b> \
|
<b> \
|
||||||
<a rel="noopener" target="_blank" href="https://reddit.com{permalink}">{redditPermalinkText}</a> \
|
<a href="javascript:void(0)" data-comments="youtube"> \
|
||||||
|
{youtubeCommentsText} \
|
||||||
|
</a> \
|
||||||
</b> \
|
</b> \
|
||||||
</div> \
|
</p> \
|
||||||
<div>{contentHtml}</div> \
|
<b> \
|
||||||
<hr>'.supplant({
|
<a rel="noopener" target="_blank" href="https://reddit.com{permalink}">{redditPermalinkText}</a> \
|
||||||
title: xhr.response.title,
|
</b> \
|
||||||
youtubeCommentsText: video_data.youtube_comments_text,
|
</div> \
|
||||||
redditPermalinkText: video_data.reddit_permalink_text,
|
<div>{contentHtml}</div> \
|
||||||
permalink: xhr.response.permalink,
|
<hr>'.supplant({
|
||||||
contentHtml: xhr.response.contentHtml
|
title: response.title,
|
||||||
});
|
youtubeCommentsText: video_data.youtube_comments_text,
|
||||||
|
redditPermalinkText: video_data.reddit_permalink_text,
|
||||||
|
permalink: response.permalink,
|
||||||
|
contentHtml: response.contentHtml
|
||||||
|
});
|
||||||
|
|
||||||
comments.children[0].children[0].children[0].onclick = toggle_comments;
|
comments.children[0].children[0].children[0].onclick = toggle_comments;
|
||||||
comments.children[0].children[1].children[0].onclick = swap_comments;
|
comments.children[0].children[1].children[0].onclick = swap_comments;
|
||||||
} else {
|
},
|
||||||
if (video_data.params.comments[1] === 'youtube') {
|
onNon200: onNon200, // declared above
|
||||||
console.log('Pulling comments failed... ' + retries + '/5');
|
});
|
||||||
setTimeout(function () { get_youtube_comments(retries - 1) }, 1000);
|
|
||||||
} else {
|
|
||||||
comments.innerHTML = fallback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.onerror = function () {
|
|
||||||
console.log('Pulling comments failed... ' + retries + '/5');
|
|
||||||
setInterval(function () { get_reddit_comments(retries - 1) }, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
|
||||||
console.log('Pulling comments failed... ' + retries + '/5');
|
|
||||||
get_reddit_comments(retries - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_youtube_comments(retries) {
|
function get_youtube_comments() {
|
||||||
if (retries == undefined) retries = 5;
|
var comments = document.getElementById('comments');
|
||||||
comments = document.getElementById('comments');
|
|
||||||
|
|
||||||
if (retries <= 0) {
|
|
||||||
console.log('Failed to pull comments');
|
|
||||||
comments.innerHTML = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fallback = comments.innerHTML;
|
var fallback = comments.innerHTML;
|
||||||
comments.innerHTML =
|
comments.innerHTML = spinnerHTML;
|
||||||
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
|
|
||||||
|
|
||||||
var url = '/api/v1/comments/' + video_data.id +
|
var url = '/api/v1/comments/' + video_data.id +
|
||||||
'?format=html' +
|
'?format=html' +
|
||||||
'&hl=' + video_data.preferences.locale +
|
'&hl=' + video_data.preferences.locale +
|
||||||
'&thin_mode=' + video_data.preferences.thin_mode;
|
'&thin_mode=' + video_data.preferences.thin_mode;
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('GET', url, true);
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
var onNon200 = function (xhr) { comments.innerHTML = fallback; };
|
||||||
if (xhr.readyState == 4) {
|
if (video_data.params.comments[1] === 'youtube')
|
||||||
if (xhr.status == 200) {
|
onNon200 = function (xhr) {};
|
||||||
comments.innerHTML = ' \
|
|
||||||
<div> \
|
|
||||||
<h3> \
|
|
||||||
<a href="javascript:void(0)">[ - ]</a> \
|
|
||||||
{commentsText} \
|
|
||||||
</h3> \
|
|
||||||
<b> \
|
|
||||||
<a href="javascript:void(0)" data-comments="reddit"> \
|
|
||||||
{redditComments} \
|
|
||||||
</a> \
|
|
||||||
</b> \
|
|
||||||
</div> \
|
|
||||||
<div>{contentHtml}</div> \
|
|
||||||
<hr>'.supplant({
|
|
||||||
contentHtml: xhr.response.contentHtml,
|
|
||||||
redditComments: video_data.reddit_comments_text,
|
|
||||||
commentsText: video_data.comments_text.supplant(
|
|
||||||
{ commentCount: number_with_separator(xhr.response.commentCount) }
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
comments.children[0].children[0].children[0].onclick = toggle_comments;
|
helpers.xhr('GET', url, {retries: 5, entity_name: 'comments'}, {
|
||||||
comments.children[0].children[1].children[0].onclick = swap_comments;
|
on200: function (response) {
|
||||||
} else {
|
comments.innerHTML = ' \
|
||||||
if (video_data.params.comments[1] === 'youtube') {
|
<div> \
|
||||||
setTimeout(function () { get_youtube_comments(retries - 1) }, 1000);
|
<h3> \
|
||||||
} else {
|
<a href="javascript:void(0)">[ − ]</a> \
|
||||||
comments.innerHTML = '';
|
{commentsText} \
|
||||||
}
|
</h3> \
|
||||||
}
|
<b> \
|
||||||
|
<a href="javascript:void(0)" data-comments="reddit"> \
|
||||||
|
{redditComments} \
|
||||||
|
</a> \
|
||||||
|
</b> \
|
||||||
|
</div> \
|
||||||
|
<div>{contentHtml}</div> \
|
||||||
|
<hr>'.supplant({
|
||||||
|
contentHtml: response.contentHtml,
|
||||||
|
redditComments: video_data.reddit_comments_text,
|
||||||
|
commentsText: video_data.comments_text.supplant({
|
||||||
|
// toLocaleString correctly splits number with local thousands separator. e.g.:
|
||||||
|
// '1,234,567.89' for user with English locale
|
||||||
|
// '1 234 567,89' for user with Russian locale
|
||||||
|
// '1.234.567,89' for user with Portuguese locale
|
||||||
|
commentCount: response.commentCount.toLocaleString()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
comments.children[0].children[0].children[0].onclick = toggle_comments;
|
||||||
|
comments.children[0].children[1].children[0].onclick = swap_comments;
|
||||||
|
},
|
||||||
|
onNon200: onNon200, // declared above
|
||||||
|
onError: function (xhr) {
|
||||||
|
comments.innerHTML = spinnerHTML;
|
||||||
|
},
|
||||||
|
onTimeout: function (xhr) {
|
||||||
|
comments.innerHTML = spinnerHTML;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
xhr.onerror = function () {
|
|
||||||
comments.innerHTML =
|
|
||||||
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
|
|
||||||
console.log('Pulling comments failed... ' + retries + '/5');
|
|
||||||
setInterval(function () { get_youtube_comments(retries - 1) }, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
|
||||||
comments.innerHTML =
|
|
||||||
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
|
|
||||||
console.log('Pulling comments failed... ' + retries + '/5');
|
|
||||||
get_youtube_comments(retries - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_youtube_replies(target, load_more) {
|
function get_youtube_replies(target, load_more, load_replies) {
|
||||||
var continuation = target.getAttribute('data-continuation');
|
var continuation = target.getAttribute('data-continuation');
|
||||||
|
|
||||||
var body = target.parentNode.parentNode;
|
var body = target.parentNode.parentNode;
|
||||||
var fallback = body.innerHTML;
|
var fallback = body.innerHTML;
|
||||||
body.innerHTML =
|
body.innerHTML = spinnerHTML;
|
||||||
'<h3 style="text-align:center"><div class="loading"><i class="icon ion-ios-refresh"></i></div></h3>';
|
|
||||||
|
|
||||||
var url = '/api/v1/comments/' + video_data.id +
|
var url = '/api/v1/comments/' + video_data.id +
|
||||||
'?format=html' +
|
'?format=html' +
|
||||||
'&hl=' + video_data.preferences.locale +
|
'&hl=' + video_data.preferences.locale +
|
||||||
'&thin_mode=' + video_data.preferences.thin_mode +
|
'&thin_mode=' + video_data.preferences.thin_mode +
|
||||||
'&continuation=' + continuation;
|
'&continuation=' + continuation;
|
||||||
var xhr = new XMLHttpRequest();
|
if (load_replies) url += '&action=action_get_comment_replies';
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('GET', url, true);
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
helpers.xhr('GET', url, {}, {
|
||||||
if (xhr.readyState == 4) {
|
on200: function (response) {
|
||||||
if (xhr.status == 200) {
|
if (load_more) {
|
||||||
if (load_more) {
|
body = body.parentNode.parentNode;
|
||||||
body = body.parentNode.parentNode;
|
body.removeChild(body.lastElementChild);
|
||||||
body.removeChild(body.lastElementChild);
|
body.innerHTML += response.contentHtml;
|
||||||
body.innerHTML += xhr.response.contentHtml;
|
|
||||||
} else {
|
|
||||||
body.removeChild(body.lastElementChild);
|
|
||||||
|
|
||||||
var p = document.createElement('p');
|
|
||||||
var a = document.createElement('a');
|
|
||||||
p.appendChild(a);
|
|
||||||
|
|
||||||
a.href = 'javascript:void(0)';
|
|
||||||
a.onclick = hide_youtube_replies;
|
|
||||||
a.setAttribute('data-sub-text', video_data.hide_replies_text);
|
|
||||||
a.setAttribute('data-inner-text', video_data.show_replies_text);
|
|
||||||
a.innerText = video_data.hide_replies_text;
|
|
||||||
|
|
||||||
var div = document.createElement('div');
|
|
||||||
div.innerHTML = xhr.response.contentHtml;
|
|
||||||
|
|
||||||
body.appendChild(p);
|
|
||||||
body.appendChild(div);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
body.innerHTML = fallback;
|
body.removeChild(body.lastElementChild);
|
||||||
|
|
||||||
|
var p = document.createElement('p');
|
||||||
|
var a = document.createElement('a');
|
||||||
|
p.appendChild(a);
|
||||||
|
|
||||||
|
a.href = 'javascript:void(0)';
|
||||||
|
a.onclick = hide_youtube_replies;
|
||||||
|
a.setAttribute('data-sub-text', video_data.hide_replies_text);
|
||||||
|
a.setAttribute('data-inner-text', video_data.show_replies_text);
|
||||||
|
a.textContent = video_data.hide_replies_text;
|
||||||
|
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.innerHTML = response.contentHtml;
|
||||||
|
|
||||||
|
body.appendChild(p);
|
||||||
|
body.appendChild(div);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onNon200: function (xhr) {
|
||||||
|
body.innerHTML = fallback;
|
||||||
|
},
|
||||||
|
onTimeout: function (xhr) {
|
||||||
|
console.warn('Pulling comments failed');
|
||||||
|
body.innerHTML = fallback;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
xhr.ontimeout = function () {
|
|
||||||
console.log('Pulling comments failed.');
|
|
||||||
body.innerHTML = fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video_data.play_next) {
|
if (video_data.play_next) {
|
||||||
player.on('ended', function () {
|
player.on('ended', function () {
|
||||||
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
|
var url = new URL('https://example.com/watch?v=' + video_data.next_video);
|
||||||
|
|
||||||
if (video_data.params.autoplay || video_data.params.continue_autoplay) {
|
if (video_data.params.autoplay || video_data.params.continue_autoplay)
|
||||||
url.searchParams.set('autoplay', '1');
|
url.searchParams.set('autoplay', '1');
|
||||||
}
|
if (video_data.params.listen !== video_data.preferences.listen)
|
||||||
|
|
||||||
if (video_data.params.listen !== video_data.preferences.listen) {
|
|
||||||
url.searchParams.set('listen', video_data.params.listen);
|
url.searchParams.set('listen', video_data.params.listen);
|
||||||
}
|
if (video_data.params.speed !== video_data.preferences.speed)
|
||||||
|
|
||||||
if (video_data.params.speed !== video_data.preferences.speed) {
|
|
||||||
url.searchParams.set('speed', video_data.params.speed);
|
url.searchParams.set('speed', video_data.params.speed);
|
||||||
}
|
if (video_data.params.local !== video_data.preferences.local)
|
||||||
|
|
||||||
if (video_data.params.local !== video_data.preferences.local) {
|
|
||||||
url.searchParams.set('local', video_data.params.local);
|
url.searchParams.set('local', video_data.params.local);
|
||||||
}
|
|
||||||
|
|
||||||
url.searchParams.set('continue', '1');
|
url.searchParams.set('continue', '1');
|
||||||
|
|
||||||
location.assign(url.pathname + url.search);
|
location.assign(url.pathname + url.search);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('load', function (e) {
|
addEventListener('load', function (e) {
|
||||||
if (video_data.plid) {
|
if (video_data.plid)
|
||||||
get_playlist(video_data.plid);
|
get_playlist(video_data.plid);
|
||||||
}
|
|
||||||
|
|
||||||
if (video_data.params.comments[0] === 'youtube') {
|
if (video_data.params.comments[0] === 'youtube') {
|
||||||
get_youtube_comments();
|
get_youtube_comments();
|
||||||
@@ -453,7 +344,7 @@ window.addEventListener('load', function (e) {
|
|||||||
} else if (video_data.params.comments[1] === 'reddit') {
|
} else if (video_data.params.comments[1] === 'reddit') {
|
||||||
get_reddit_comments();
|
get_reddit_comments();
|
||||||
} else {
|
} else {
|
||||||
comments = document.getElementById('comments');
|
var comments = document.getElementById('comments');
|
||||||
comments.innerHTML = '';
|
comments.innerHTML = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,48 +1,34 @@
|
|||||||
|
'use strict';
|
||||||
|
var watched_data = JSON.parse(document.getElementById('watched_data').textContent);
|
||||||
|
var payload = 'csrf_token=' + watched_data.csrf_token;
|
||||||
|
|
||||||
function mark_watched(target) {
|
function mark_watched(target) {
|
||||||
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||||
tile.style.display = 'none';
|
tile.style.display = 'none';
|
||||||
|
|
||||||
var url = '/watch_ajax?action_mark_watched=1&redirect=false' +
|
var url = '/watch_ajax?action_mark_watched=1&redirect=false' +
|
||||||
'&id=' + target.getAttribute('data-id');
|
'&id=' + target.getAttribute('data-id');
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('POST', url, true);
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
helpers.xhr('POST', url, {payload: payload}, {
|
||||||
if (xhr.readyState == 4) {
|
onNon200: function (xhr) {
|
||||||
if (xhr.status != 200) {
|
tile.style.display = '';
|
||||||
tile.style.display = '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
xhr.send('csrf_token=' + watched_data.csrf_token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mark_unwatched(target) {
|
function mark_unwatched(target) {
|
||||||
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||||
tile.style.display = 'none';
|
tile.style.display = 'none';
|
||||||
var count = document.getElementById('count')
|
var count = document.getElementById('count');
|
||||||
count.innerText = count.innerText - 1;
|
count.textContent--;
|
||||||
|
|
||||||
var url = '/watch_ajax?action_mark_unwatched=1&redirect=false' +
|
var url = '/watch_ajax?action_mark_unwatched=1&redirect=false' +
|
||||||
'&id=' + target.getAttribute('data-id');
|
'&id=' + target.getAttribute('data-id');
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.timeout = 10000;
|
|
||||||
xhr.open('POST', url, true);
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
||||||
|
|
||||||
xhr.onreadystatechange = function () {
|
helpers.xhr('POST', url, {payload: payload}, {
|
||||||
if (xhr.readyState == 4) {
|
onNon200: function (xhr) {
|
||||||
if (xhr.status != 200) {
|
count.textContent++;
|
||||||
count.innerText = count.innerText - 1 + 2;
|
tile.style.display = '';
|
||||||
tile.style.display = '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
xhr.send('csrf_token=' + watched_data.csrf_token);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
User-agent: *
|
User-agent: *
|
||||||
Disallow: /search
|
Disallow: /
|
||||||
Disallow: /login
|
|
||||||
|
|||||||
4
assets/videojs/.gitignore
vendored
Normal file
4
assets/videojs/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Ignore everything in this directory
|
||||||
|
*
|
||||||
|
# Except this file
|
||||||
|
!.gitignore
|
||||||
871
config/config.example.yml
Normal file
871
config/config.example.yml
Normal file
@@ -0,0 +1,871 @@
|
|||||||
|
#########################################
|
||||||
|
#
|
||||||
|
# Database configuration
|
||||||
|
#
|
||||||
|
#########################################
|
||||||
|
|
||||||
|
##
|
||||||
|
## Database configuration with separate parameters.
|
||||||
|
## This setting is MANDATORY, unless 'database_url' is used.
|
||||||
|
##
|
||||||
|
db:
|
||||||
|
user: kemal
|
||||||
|
password: kemal
|
||||||
|
host: localhost
|
||||||
|
port: 5432
|
||||||
|
dbname: invidious
|
||||||
|
|
||||||
|
##
|
||||||
|
## Database configuration using a single URI. This is an
|
||||||
|
## alternative to the 'db' parameter above. If both forms
|
||||||
|
## are used, then only database_url is used.
|
||||||
|
## This setting is MANDATORY, unless 'db' is used.
|
||||||
|
##
|
||||||
|
## Note: The 'database_url' setting allows the use of UNIX
|
||||||
|
## sockets. To do so, remove the IP address (or FQDN) and port
|
||||||
|
## and append the 'host' parameter. E.g:
|
||||||
|
## postgres://kemal:kemal@/invidious?host=/var/run/postgresql
|
||||||
|
##
|
||||||
|
## Accepted values: a postgres:// URI
|
||||||
|
## Default: postgres://kemal:kemal@localhost:5432/invidious
|
||||||
|
##
|
||||||
|
#database_url: postgres://kemal:kemal@localhost:5432/invidious
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable automatic table integrity check. This will create
|
||||||
|
## the required tables and columns if anything is missing.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#check_tables: false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
#
|
||||||
|
# Server config
|
||||||
|
#
|
||||||
|
#########################################
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Network (inbound)
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Port to listen on for incoming connections.
|
||||||
|
##
|
||||||
|
## Note: Ports lower than 1024 requires either root privileges
|
||||||
|
## (not recommended) or the "CAP_NET_BIND_SERVICE" capability
|
||||||
|
## (See https://stackoverflow.com/a/414258 and `man capabilities`)
|
||||||
|
##
|
||||||
|
## Accepted values: 1-65535
|
||||||
|
## Default: 3000
|
||||||
|
##
|
||||||
|
#port: 3000
|
||||||
|
|
||||||
|
##
|
||||||
|
## When the invidious instance is behind a proxy, and the proxy
|
||||||
|
## listens on a different port than the instance does, this lets
|
||||||
|
## invidious know about it. This is used to craft absolute URLs
|
||||||
|
## to the instance (e.g in the API).
|
||||||
|
##
|
||||||
|
## Note: This setting is MANDATORY if invidious is behind a
|
||||||
|
## reverse proxy.
|
||||||
|
##
|
||||||
|
## Accepted values: 1-65535
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
#external_port:
|
||||||
|
|
||||||
|
##
|
||||||
|
## Interface address to listen on for incoming connections.
|
||||||
|
##
|
||||||
|
## Accepted values: a valid IPv4 or IPv6 address.
|
||||||
|
## default: 0.0.0.0 (listen on all interfaces)
|
||||||
|
##
|
||||||
|
#host_binding: 0.0.0.0
|
||||||
|
|
||||||
|
##
|
||||||
|
## Domain name under which this instance is hosted. This is
|
||||||
|
## used to craft absolute URLs to the instance (e.g in the API).
|
||||||
|
## The domain MUST be defined if your instance is accessed from
|
||||||
|
## a domain name (like 'example.com').
|
||||||
|
##
|
||||||
|
## Accepted values: a fully qualified domain name (FQDN)
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
domain:
|
||||||
|
|
||||||
|
##
|
||||||
|
## Tell Invidious that it is behind a proxy that provides only
|
||||||
|
## HTTPS, so all links must use the https:// scheme. This
|
||||||
|
## setting MUST be set to true if invidious is behind a
|
||||||
|
## reverse proxy serving HTTPs.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
https_only: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable/Disable 'Strict-Transport-Security'. Make sure that
|
||||||
|
## the domain specified under 'domain' is served securely.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#hsts: true
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Network (outbound)
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Disable proxying server-wide. Can be disable as a whole, or
|
||||||
|
## only for a single function.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false, dash, livestreams, downloads, local
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#disable_proxy: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Size of the HTTP pool used to connect to youtube. Each
|
||||||
|
## domain ('youtube.com', 'ytimg.com', ...) has its own pool.
|
||||||
|
##
|
||||||
|
## Accepted values: a positive integer
|
||||||
|
## Default: 100
|
||||||
|
##
|
||||||
|
#pool_size: 100
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable/Disable the use of QUIC (HTTP/3) when connecting
|
||||||
|
## to the youtube API and websites ('youtube.com', 'ytimg.com').
|
||||||
|
## QUIC's main advantages are its lower latency and lower bandwidth
|
||||||
|
## use, compared to its predecessors. However, the current version
|
||||||
|
## of QUIC used in invidious is still based on the IETF draft 31,
|
||||||
|
## meaning that the underlying library may still not be fully
|
||||||
|
## optimized. You can read more about QUIC at the link below:
|
||||||
|
## https://datatracker.ietf.org/doc/html/draft-ietf-quic-transport-31
|
||||||
|
##
|
||||||
|
## Note: you should try both options and see what is the best for your
|
||||||
|
## instance. In general QUIC is recommended for public instances. Your
|
||||||
|
## mileage may vary.
|
||||||
|
##
|
||||||
|
## Note 2: Using QUIC prevents some captcha challenges from appearing.
|
||||||
|
## See: https://github.com/iv-org/invidious/issues/957#issuecomment-576424042
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#use_quic: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Additional cookies to be sent when requesting the youtube API.
|
||||||
|
##
|
||||||
|
## Accepted values: a string in the format "name1=value1; name2=value2..."
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
#cookies:
|
||||||
|
|
||||||
|
##
|
||||||
|
## Force connection to youtube over a specific IP family.
|
||||||
|
##
|
||||||
|
## Note: This may sometimes resolve issues involving rate-limiting.
|
||||||
|
## See https://github.com/ytdl-org/youtube-dl/issues/21729.
|
||||||
|
##
|
||||||
|
## Accepted values: ipv4, ipv6
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
#force_resolve:
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Logging
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Path to log file. Can be absolute or relative to the invidious
|
||||||
|
## binary. This is overridden if "-o OUTPUT" or "--output=OUTPUT"
|
||||||
|
## are passed on the command line.
|
||||||
|
##
|
||||||
|
## Accepted values: a filesystem path or 'STDOUT'
|
||||||
|
## Default: STDOUT
|
||||||
|
##
|
||||||
|
#output: STDOUT
|
||||||
|
|
||||||
|
##
|
||||||
|
## Logging Verbosity. This is overridden if "-l LEVEL" or
|
||||||
|
## "--log-level=LEVEL" are passed on the command line.
|
||||||
|
##
|
||||||
|
## Accepted values: All, Trace, Debug, Info, Warn, Error, Fatal, Off
|
||||||
|
## Default: Info
|
||||||
|
##
|
||||||
|
#log_level: Info
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Features
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable/Disable the "Popular" tab on the main page.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#popular_enabled: true
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable/Disable statstics (available at /api/v1/stats).
|
||||||
|
## The following data is available:
|
||||||
|
## - Software name ("invidious") and version+branch (same data as
|
||||||
|
## displayed in the footer, e.g: "2021.05.13-75e5b49" / "master")
|
||||||
|
## - The value of the 'registration_enabled' config (true/false)
|
||||||
|
## - Number of currently registered users
|
||||||
|
## - Number of registered users who connected in the last month
|
||||||
|
## - Number of registered users who connected in the last 6 months
|
||||||
|
## - Timestamp of the last server restart
|
||||||
|
## - Timestamp of the last "Channel Refresh" job execution
|
||||||
|
##
|
||||||
|
## Warning: This setting MUST be set to true if you plan to run
|
||||||
|
## a public instance. It is used by api.invidious.io to refresh
|
||||||
|
## your instance's status.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#statistics_enabled: false
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Users and accounts
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Allow/Forbid Invidious (local) account creation. Invidious
|
||||||
|
## accounts allow users to subscribe to channels and to create
|
||||||
|
## playlists without a Google account.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#registration_enabled: true
|
||||||
|
|
||||||
|
##
|
||||||
|
## Allow/Forbid users to log-in. This setting affects the ability
|
||||||
|
## to connect with BOTH Google and Invidious (local) accounts.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#login_enabled: true
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable/Disable the captcha challenge on the login page.
|
||||||
|
##
|
||||||
|
## Note: this is a basic captcha challenge that doesn't
|
||||||
|
## depend on any third parties.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#captcha_enabled: true
|
||||||
|
|
||||||
|
##
|
||||||
|
## List of usernames that will be granted administrator rights.
|
||||||
|
## A user with administrator rights will be able to change the
|
||||||
|
## server configuration options listed below in /preferences,
|
||||||
|
## in addition to the usual user preferences.
|
||||||
|
##
|
||||||
|
## Server-wide settings:
|
||||||
|
## - popular_enabled
|
||||||
|
## - captcha_enabled
|
||||||
|
## - login_enabled
|
||||||
|
## - registration_enabled
|
||||||
|
## - statistics_enabled
|
||||||
|
## Default user preferences:
|
||||||
|
## - default_home
|
||||||
|
## - feed_menu
|
||||||
|
##
|
||||||
|
## Accepted values: an array of strings
|
||||||
|
## Default: [""]
|
||||||
|
##
|
||||||
|
#admins: [""]
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Background jobs
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Number of threads to use when crawling channel videos (during
|
||||||
|
## subscriptions update).
|
||||||
|
##
|
||||||
|
## Notes:
|
||||||
|
## - Setting this to 0 will disable the channel videos crawl job.
|
||||||
|
## - This setting is overridden if "-c THREADS" or
|
||||||
|
## "--channel-threads=THREADS" are passed on the command line.
|
||||||
|
##
|
||||||
|
## Accepted values: a positive integer
|
||||||
|
## Default: 1
|
||||||
|
##
|
||||||
|
channel_threads: 1
|
||||||
|
|
||||||
|
##
|
||||||
|
## Time interval between two executions of the job that crawls
|
||||||
|
## channel videos (subscriptions update).
|
||||||
|
##
|
||||||
|
## Accepted values: a valid time interval (like 1h30m or 90m)
|
||||||
|
## Default: 30m
|
||||||
|
##
|
||||||
|
#channel_refresh_interval: 30m
|
||||||
|
|
||||||
|
##
|
||||||
|
## Forcefully dump and re-download the entire list of uploaded
|
||||||
|
## videos when crawling channel (during subscriptions update).
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
full_refresh: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Number of threads to use when updating RSS feeds.
|
||||||
|
##
|
||||||
|
## Notes:
|
||||||
|
## - Setting this to 0 will disable the channel videos crawl job.
|
||||||
|
## - This setting is overridden if "-f THREADS" or
|
||||||
|
## "--feed-threads=THREADS" are passed on the command line.
|
||||||
|
##
|
||||||
|
## Accepted values: a positive integer
|
||||||
|
## Default: 1
|
||||||
|
##
|
||||||
|
feed_threads: 1
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable/Disable the polling job that keeps the decryption
|
||||||
|
## function (for "secured" videos) up to date.
|
||||||
|
##
|
||||||
|
## Note: This part of the code generate a small amount of data every minute.
|
||||||
|
## This may not be desired if you have bandwidth limits set by your ISP.
|
||||||
|
##
|
||||||
|
## Note 2: This part of the code is currently broken, so changing
|
||||||
|
## this setting has no impact.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#decrypt_polling: false
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Captcha API
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## URL of the captcha solving service.
|
||||||
|
##
|
||||||
|
## Accepted values: any URL
|
||||||
|
## Default: https://api.anti-captcha.com
|
||||||
|
##
|
||||||
|
#captcha_api_url: https://api.anti-captcha.com
|
||||||
|
|
||||||
|
##
|
||||||
|
## API key for the captcha solving service.
|
||||||
|
##
|
||||||
|
## Accepted values: a string
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
#captcha_key:
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Miscellaneous
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## custom banner displayed at the top of every page. This can
|
||||||
|
## used for instance announcements, e.g.
|
||||||
|
##
|
||||||
|
## Accepted values: any string. HTML is accepted.
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
#banner:
|
||||||
|
|
||||||
|
##
|
||||||
|
## Subscribe to channels using PubSubHub (Google PubSubHubbub service).
|
||||||
|
## PubSubHub allows Invidious to be instantly notified when a new video
|
||||||
|
## is published on any subscribed channels. When PubSubHub is not used,
|
||||||
|
## Invidious will check for new videos every minute.
|
||||||
|
##
|
||||||
|
## Note: This setting is recommended for public instances.
|
||||||
|
##
|
||||||
|
## Note 2:
|
||||||
|
## - Requires a public instance (it uses /feed/webhook/v1)
|
||||||
|
## - Requires 'domain' and 'hmac_key' to be set.
|
||||||
|
## - Setting this parameter to any number greater than zero will
|
||||||
|
## enable channel subscriptions via PubSubHub, but will limit the
|
||||||
|
## amount of concurrent subscriptions.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false, a positive integer
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#use_pubsub_feeds: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## HMAC signing key used for CSRF tokens and pubsub
|
||||||
|
## subscriptions verification.
|
||||||
|
##
|
||||||
|
## Accepted values: a string
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
#hmac_key:
|
||||||
|
|
||||||
|
##
|
||||||
|
## List of video IDs where the "download" widget must be
|
||||||
|
## disabled, in order to comply with DMCA requests.
|
||||||
|
##
|
||||||
|
## Accepted values: an array of string
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
#dmca_content:
|
||||||
|
|
||||||
|
##
|
||||||
|
## Cache video annotations in the database.
|
||||||
|
##
|
||||||
|
## Warning: empty annotations or annotations that only contain
|
||||||
|
## cards won't be cached.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#cache_annotations: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Source code URL. If your instance is running a modified source
|
||||||
|
## code, you MUST publish it somewhere and set this option.
|
||||||
|
##
|
||||||
|
## Accepted values: a string
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
#modified_source_code_url: ""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
#
|
||||||
|
# Default user preferences
|
||||||
|
#
|
||||||
|
#########################################
|
||||||
|
|
||||||
|
##
|
||||||
|
## NOTE: All the settings below define the default user
|
||||||
|
## preferences. They will apply to ALL users connecting
|
||||||
|
## without a preferences cookie (so either on the first
|
||||||
|
## connection to the instance or after clearing the
|
||||||
|
## browser's cookies).
|
||||||
|
##
|
||||||
|
|
||||||
|
default_user_preferences:
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Internationalization
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default user interface language (locale).
|
||||||
|
##
|
||||||
|
## Note: When hosting a public instance, overriding the
|
||||||
|
## default (english) is not recommended, as it may
|
||||||
|
## people using other languages.
|
||||||
|
##
|
||||||
|
## Accepted values:
|
||||||
|
## ar (Arabic)
|
||||||
|
## da (Danish)
|
||||||
|
## de (German)
|
||||||
|
## en-US (english, US)
|
||||||
|
## el (Greek)
|
||||||
|
## eo (Esperanto)
|
||||||
|
## es (Spanish)
|
||||||
|
## fa (Persian)
|
||||||
|
## fi (Finnish)
|
||||||
|
## fr (French)
|
||||||
|
## he (Hebrew)
|
||||||
|
## hr (Hungarian)
|
||||||
|
## id (Indonesian)
|
||||||
|
## is (Icelandic)
|
||||||
|
## it (Italian)
|
||||||
|
## ja (Japanese)
|
||||||
|
## nb-NO (Norwegian, Bokmål)
|
||||||
|
## nl (Dutch)
|
||||||
|
## pl (Polish)
|
||||||
|
## pt-BR (Portuguese, Brazil)
|
||||||
|
## pt-PT (Portuguese, Portugal)
|
||||||
|
## ro (Romanian)
|
||||||
|
## ru (Russian)
|
||||||
|
## sv (Swedish)
|
||||||
|
## tr (Turkish)
|
||||||
|
## uk (Ukrainian)
|
||||||
|
## zh-CN (Chinese, China) (a.k.a "Simplified Chinese")
|
||||||
|
## zh-TW (Chinese, Taiwan) (a.k.a "Traditional Chinese")
|
||||||
|
##
|
||||||
|
## Default: en-US
|
||||||
|
##
|
||||||
|
#locale: en-US
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default geographical location for content.
|
||||||
|
##
|
||||||
|
## Accepted values:
|
||||||
|
## AE, AR, AT, AU, AZ, BA, BD, BE, BG, BH, BO, BR, BY, CA, CH, CL, CO, CR,
|
||||||
|
## CY, CZ, DE, DK, DO, DZ, EC, EE, EG, ES, FI, FR, GB, GE, GH, GR, GT, HK,
|
||||||
|
## HN, HR, HU, ID, IE, IL, IN, IQ, IS, IT, JM, JO, JP, KE, KR, KW, KZ, LB,
|
||||||
|
## LI, LK, LT, LU, LV, LY, MA, ME, MK, MT, MX, MY, NG, NI, NL, NO, NP, NZ,
|
||||||
|
## OM, PA, PE, PG, PH, PK, PL, PR, PT, PY, QA, RO, RS, RU, SA, SE, SG, SI,
|
||||||
|
## SK, SN, SV, TH, TN, TR, TW, TZ, UA, UG, US, UY, VE, VN, YE, ZA, ZW
|
||||||
|
##
|
||||||
|
## Default: US
|
||||||
|
##
|
||||||
|
#region: US
|
||||||
|
|
||||||
|
##
|
||||||
|
## Top 3 preferred languages for video captions.
|
||||||
|
##
|
||||||
|
## Note: overriding the default (no preferred
|
||||||
|
## caption language) is not recommended, in order
|
||||||
|
## to not penalize people using other languages.
|
||||||
|
##
|
||||||
|
## Accepted values: a three-entries array.
|
||||||
|
## Each entry can be one of:
|
||||||
|
## "English", "English (auto-generated)",
|
||||||
|
## "Afrikaans", "Albanian", "Amharic", "Arabic",
|
||||||
|
## "Armenian", "Azerbaijani", "Bangla", "Basque",
|
||||||
|
## "Belarusian", "Bosnian", "Bulgarian", "Burmese",
|
||||||
|
## "Catalan", "Cebuano", "Chinese (Simplified)",
|
||||||
|
## "Chinese (Traditional)", "Corsican", "Croatian",
|
||||||
|
## "Czech", "Danish", "Dutch", "Esperanto", "Estonian",
|
||||||
|
## "Filipino", "Finnish", "French", "Galician", "Georgian",
|
||||||
|
## "German", "Greek", "Gujarati", "Haitian Creole", "Hausa",
|
||||||
|
## "Hawaiian", "Hebrew", "Hindi", "Hmong", "Hungarian",
|
||||||
|
## "Icelandic", "Igbo", "Indonesian", "Irish", "Italian",
|
||||||
|
## "Japanese", "Javanese", "Kannada", "Kazakh", "Khmer",
|
||||||
|
## "Korean", "Kurdish", "Kyrgyz", "Lao", "Latin", "Latvian",
|
||||||
|
## "Lithuanian", "Luxembourgish", "Macedonian",
|
||||||
|
## "Malagasy", "Malay", "Malayalam", "Maltese", "Maori",
|
||||||
|
## "Marathi", "Mongolian", "Nepali", "Norwegian Bokmål",
|
||||||
|
## "Nyanja", "Pashto", "Persian", "Polish", "Portuguese",
|
||||||
|
## "Punjabi", "Romanian", "Russian", "Samoan",
|
||||||
|
## "Scottish Gaelic", "Serbian", "Shona", "Sindhi",
|
||||||
|
## "Sinhala", "Slovak", "Slovenian", "Somali",
|
||||||
|
## "Southern Sotho", "Spanish", "Spanish (Latin America)",
|
||||||
|
## "Sundanese", "Swahili", "Swedish", "Tajik", "Tamil",
|
||||||
|
## "Telugu", "Thai", "Turkish", "Ukrainian", "Urdu",
|
||||||
|
## "Uzbek", "Vietnamese", "Welsh", "Western Frisian",
|
||||||
|
## "Xhosa", "Yiddish", "Yoruba", "Zulu"
|
||||||
|
##
|
||||||
|
## Default: ["", "", ""]
|
||||||
|
##
|
||||||
|
#captions: ["", "", ""]
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Interface
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable/Disable dark mode.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: <none>
|
||||||
|
##
|
||||||
|
#dark_mode:
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable/Disable thin mode (no video thumbnails).
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#thin_mode: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## List of feeds available on the home page.
|
||||||
|
##
|
||||||
|
## Note: "Subscriptions" and "Playlists" are only visible
|
||||||
|
## when the user is logged in.
|
||||||
|
##
|
||||||
|
## Accepted values: A list of strings
|
||||||
|
## Each entry can be one of: "Popular", "Trending",
|
||||||
|
## "Subscriptions", "Playlists"
|
||||||
|
##
|
||||||
|
## Default: ["Popular", "Trending", "Subscriptions", "Playlists"] (show all feeds)
|
||||||
|
##
|
||||||
|
#feed_menu: ["Popular", "Trending", "Subscriptions", "Playlists"]
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default feed to display on the home page.
|
||||||
|
##
|
||||||
|
## Note: setting this option to "Popular" has no
|
||||||
|
## effect when 'popular_enabled' is set to false.
|
||||||
|
##
|
||||||
|
## Accepted values: Popular, Trending, Subscriptions, Playlists, <none>
|
||||||
|
## Default: Popular
|
||||||
|
##
|
||||||
|
#default_home: Popular
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default number of results to display per page.
|
||||||
|
##
|
||||||
|
## Note: this affects invidious-generated pages only, such
|
||||||
|
## as watch history and subscription feeds. Playlists, search
|
||||||
|
## results and channel videos depend on the data returned by
|
||||||
|
## the Youtube API.
|
||||||
|
##
|
||||||
|
## Accepted values: any positive integer
|
||||||
|
## Default: 40
|
||||||
|
##
|
||||||
|
#max_results: 40
|
||||||
|
|
||||||
|
##
|
||||||
|
## Show/hide annotations.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#annotations: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Show/hide annotation.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#annotations_subscribed: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Type of comments to display below video.
|
||||||
|
##
|
||||||
|
## Accepted values: a two-entries array.
|
||||||
|
## Each entry can be one of: "youtube", "reddit", ""
|
||||||
|
##
|
||||||
|
## Default: ["youtube", ""]
|
||||||
|
##
|
||||||
|
#comments: ["youtube", ""]
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default player style.
|
||||||
|
##
|
||||||
|
## Accepted values: invidious, youtube
|
||||||
|
## Default: invidious
|
||||||
|
##
|
||||||
|
#player_style: invidious
|
||||||
|
|
||||||
|
##
|
||||||
|
## Show/Hide the "related videos" sidebar when
|
||||||
|
## watching a video.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#related_videos: true
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Video player behavior
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Automatically play videos on page load.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#autoplay: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Automatically load the "next" video (either next in
|
||||||
|
## playlist or proposed) when the current video ends.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#continue: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Autoplay next video by default.
|
||||||
|
##
|
||||||
|
## Note: Only effective if 'continue' is set to true.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#continue_autoplay: true
|
||||||
|
|
||||||
|
##
|
||||||
|
## Play videos in Audio-only mode by default.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#listen: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Loop videos automatically.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#video_loop: false
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Video playback settings
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default video quality.
|
||||||
|
##
|
||||||
|
## Accepted values: dash, hd720, medium, small
|
||||||
|
## Default: hd720
|
||||||
|
##
|
||||||
|
#quality: hd720
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default dash video quality.
|
||||||
|
##
|
||||||
|
## Note: this setting only takes effet if the
|
||||||
|
## 'quality' parameter is set to "dash".
|
||||||
|
##
|
||||||
|
## Accepted values:
|
||||||
|
## auto, best, 4320p, 2160p, 1440p, 1080p,
|
||||||
|
## 720p, 480p, 360p, 240p, 144p, worst
|
||||||
|
## Default: auto
|
||||||
|
##
|
||||||
|
#quality_dash: auto
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default video playback speed.
|
||||||
|
##
|
||||||
|
## Accepted values: 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0
|
||||||
|
## Default: 1.0
|
||||||
|
##
|
||||||
|
#speed: 1.0
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default volume.
|
||||||
|
##
|
||||||
|
## Accepted values: 0-100
|
||||||
|
## Default: 100
|
||||||
|
##
|
||||||
|
#volume: 100
|
||||||
|
|
||||||
|
##
|
||||||
|
## Allow 360° videos to be played.
|
||||||
|
##
|
||||||
|
## Note: This feature requires a WebGL-enabled browser.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#vr_mode: true
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Subscription feed
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## In the "Subscription" feed, only show the latest video
|
||||||
|
## of each channel the user is subscribed to.
|
||||||
|
##
|
||||||
|
## Note: when combined with 'unseen_only', the latest unseen
|
||||||
|
## video of each channel will be displayed instead of the
|
||||||
|
## latest by date.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#latest_only: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Enable/Disable user subscriptions desktop notifications.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#notifications_only: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## In the "Subscription" feed, Only show the videos that the
|
||||||
|
## user haven't watched yet (i.e which are not in their watch
|
||||||
|
## history).
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#unseen_only: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Default sorting parameter for subscription feeds.
|
||||||
|
##
|
||||||
|
## Accepted values:
|
||||||
|
## 'alphabetically'
|
||||||
|
## 'alphabetically - reverse'
|
||||||
|
## 'channel name'
|
||||||
|
## 'channel name - reverse'
|
||||||
|
## 'published'
|
||||||
|
## 'published - reverse'
|
||||||
|
##
|
||||||
|
## Default: published
|
||||||
|
##
|
||||||
|
#sort: published
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Miscellaneous
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
##
|
||||||
|
## Proxy videos through instance by default.
|
||||||
|
##
|
||||||
|
## Warning: As most users won't change this setting in their
|
||||||
|
## preferences, defaulting to true will significantly
|
||||||
|
## increase the instance's network usage, so make sure that
|
||||||
|
## your server's connection can handle it.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#local: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Show the connected user's nick at the top right.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: true
|
||||||
|
##
|
||||||
|
#show_nick: true
|
||||||
|
|
||||||
|
##
|
||||||
|
## Automatically redirect to a random instance when the user uses
|
||||||
|
## any "switch invidious instance" link (For videos, it's the plane
|
||||||
|
## icon, next to "watch on youtube" and "listen"). When set to false,
|
||||||
|
## the user is sent to https://redirect.invidious.io instead, where
|
||||||
|
## they can manually select an instance.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#automatic_instance_redirect: false
|
||||||
|
|
||||||
|
##
|
||||||
|
## Show the entire video description by default (when set to 'false',
|
||||||
|
## only the first few lines of the description are shown and a
|
||||||
|
## "show more" button allows to expand it).
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#extend_desc: false
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
channel_threads: 1
|
|
||||||
feed_threads: 1
|
|
||||||
db:
|
|
||||||
user: kemal
|
|
||||||
password: kemal
|
|
||||||
host: localhost
|
|
||||||
port: 5432
|
|
||||||
dbname: invidious
|
|
||||||
full_refresh: false
|
|
||||||
https_only: false
|
|
||||||
domain:
|
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal -c "ALTER TABLE channels ADD COLUMN subscribed bool;"
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
psql invidious kemal -c "UPDATE channels SET subscribed = false;"
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channels ADD COLUMN subscribed bool;"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "UPDATE channels SET subscribed = false;"
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal -c "ALTER TABLE channel_videos DROP COLUMN live_now CASCADE"
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
psql invidious kemal -c "ALTER TABLE channel_videos DROP COLUMN premiere_timestamp CASCADE"
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
|
|
||||||
psql invidious kemal -c "ALTER TABLE channel_videos ADD COLUMN live_now bool"
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channel_videos DROP COLUMN live_now CASCADE"
|
||||||
psql invidious kemal -c "ALTER TABLE channel_videos ADD COLUMN premiere_timestamp timestamptz"
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channel_videos DROP COLUMN premiere_timestamp CASCADE"
|
||||||
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channel_videos ADD COLUMN live_now bool"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channel_videos ADD COLUMN premiere_timestamp timestamptz"
|
||||||
|
|||||||
22
config/migrate-scripts/migrate-db-1eca969.sh
Executable file
22
config/migrate-scripts/migrate-db-1eca969.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN title CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN views CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN likes CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN dislikes CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN wilson_score CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN published CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN description CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN language CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN author CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN ucid CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN allowed_regions CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN is_family_friendly CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN genre CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN genre_url CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN license CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN sub_count_text CASCADE"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE videos DROP COLUMN author_thumbnail CASCADE"
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal -c "ALTER TABLE channels ADD COLUMN deleted bool;"
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
psql invidious kemal -c "UPDATE channels SET deleted = false;"
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channels ADD COLUMN deleted bool;"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "UPDATE channels SET deleted = false;"
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal < config/sql/session_ids.sql
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
psql invidious kemal -c "INSERT INTO session_ids (SELECT unnest(id), email, CURRENT_TIMESTAMP FROM users) ON CONFLICT (id) DO NOTHING"
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
psql invidious kemal -c "ALTER TABLE users DROP COLUMN id"
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" < config/sql/session_ids.sql
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "INSERT INTO session_ids (SELECT unnest(id), email, CURRENT_TIMESTAMP FROM users) ON CONFLICT (id) DO NOTHING"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE users DROP COLUMN id"
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal < config/sql/annotations.sql
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" < config/sql/annotations.sql
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal -c "ALTER TABLE channel_videos ADD COLUMN views bigint;"
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channel_videos ADD COLUMN views bigint;"
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal -c "ALTER TABLE channel_videos ADD COLUMN live_now bool;"
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
psql invidious kemal -c "UPDATE channel_videos SET live_now = false;"
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channel_videos ADD COLUMN live_now bool;"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "UPDATE channel_videos SET live_now = false;"
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal -c "ALTER TABLE users ADD COLUMN feed_needs_update boolean"
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE users ADD COLUMN feed_needs_update boolean"
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal -c "ALTER TABLE channel_videos ADD COLUMN premiere_timestamp timestamptz;"
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channel_videos ADD COLUMN premiere_timestamp timestamptz;"
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
psql invidious kemal -c "ALTER TABLE channels DROP COLUMN subscribed"
|
[ -z "$POSTGRES_USER" ] && POSTGRES_USER=kemal
|
||||||
psql invidious kemal -c "ALTER TABLE channels ADD COLUMN subscribed timestamptz"
|
[ -z "$POSTGRES_DB" ] && POSTGRES_DB=invidious
|
||||||
psql invidious kemal -c "UPDATE channels SET subscribed = '2019-01-01 00:00:00+00'"
|
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channels DROP COLUMN subscribed"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "ALTER TABLE channels ADD COLUMN subscribed timestamptz"
|
||||||
|
psql "$POSTGRES_DB" "$POSTGRES_USER" -c "UPDATE channels SET subscribed = '2019-01-01 00:00:00+00'"
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
-- DROP TABLE public.annotations;
|
-- DROP TABLE public.annotations;
|
||||||
|
|
||||||
CREATE TABLE public.annotations
|
CREATE TABLE IF NOT EXISTS public.annotations
|
||||||
(
|
(
|
||||||
id text NOT NULL,
|
id text NOT NULL,
|
||||||
annotations xml,
|
annotations xml,
|
||||||
CONSTRAINT annotations_id_key UNIQUE (id)
|
CONSTRAINT annotations_id_key UNIQUE (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
GRANT ALL ON TABLE public.annotations TO kemal;
|
GRANT ALL ON TABLE public.annotations TO current_user;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
-- DROP TABLE public.channel_videos;
|
-- DROP TABLE public.channel_videos;
|
||||||
|
|
||||||
CREATE TABLE public.channel_videos
|
CREATE TABLE IF NOT EXISTS public.channel_videos
|
||||||
(
|
(
|
||||||
id text NOT NULL,
|
id text NOT NULL,
|
||||||
title text,
|
title text,
|
||||||
@@ -17,13 +17,13 @@ CREATE TABLE public.channel_videos
|
|||||||
CONSTRAINT channel_videos_id_key UNIQUE (id)
|
CONSTRAINT channel_videos_id_key UNIQUE (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
GRANT ALL ON TABLE public.channel_videos TO kemal;
|
GRANT ALL ON TABLE public.channel_videos TO current_user;
|
||||||
|
|
||||||
-- Index: public.channel_videos_ucid_idx
|
-- Index: public.channel_videos_ucid_idx
|
||||||
|
|
||||||
-- DROP INDEX public.channel_videos_ucid_idx;
|
-- DROP INDEX public.channel_videos_ucid_idx;
|
||||||
|
|
||||||
CREATE INDEX channel_videos_ucid_idx
|
CREATE INDEX IF NOT EXISTS channel_videos_ucid_idx
|
||||||
ON public.channel_videos
|
ON public.channel_videos
|
||||||
USING btree
|
USING btree
|
||||||
(ucid COLLATE pg_catalog."default");
|
(ucid COLLATE pg_catalog."default");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
-- DROP TABLE public.channels;
|
-- DROP TABLE public.channels;
|
||||||
|
|
||||||
CREATE TABLE public.channels
|
CREATE TABLE IF NOT EXISTS public.channels
|
||||||
(
|
(
|
||||||
id text NOT NULL,
|
id text NOT NULL,
|
||||||
author text,
|
author text,
|
||||||
@@ -12,13 +12,13 @@ CREATE TABLE public.channels
|
|||||||
CONSTRAINT channels_id_key UNIQUE (id)
|
CONSTRAINT channels_id_key UNIQUE (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
GRANT ALL ON TABLE public.channels TO kemal;
|
GRANT ALL ON TABLE public.channels TO current_user;
|
||||||
|
|
||||||
-- Index: public.channels_id_idx
|
-- Index: public.channels_id_idx
|
||||||
|
|
||||||
-- DROP INDEX public.channels_id_idx;
|
-- DROP INDEX public.channels_id_idx;
|
||||||
|
|
||||||
CREATE INDEX channels_id_idx
|
CREATE INDEX IF NOT EXISTS channels_id_idx
|
||||||
ON public.channels
|
ON public.channels
|
||||||
USING btree
|
USING btree
|
||||||
(id COLLATE pg_catalog."default");
|
(id COLLATE pg_catalog."default");
|
||||||
|
|||||||
@@ -2,20 +2,20 @@
|
|||||||
|
|
||||||
-- DROP TABLE public.nonces;
|
-- DROP TABLE public.nonces;
|
||||||
|
|
||||||
CREATE TABLE public.nonces
|
CREATE TABLE IF NOT EXISTS public.nonces
|
||||||
(
|
(
|
||||||
nonce text,
|
nonce text,
|
||||||
expire timestamp with time zone,
|
expire timestamp with time zone,
|
||||||
CONSTRAINT nonces_id_key UNIQUE (nonce)
|
CONSTRAINT nonces_id_key UNIQUE (nonce)
|
||||||
);
|
);
|
||||||
|
|
||||||
GRANT ALL ON TABLE public.nonces TO kemal;
|
GRANT ALL ON TABLE public.nonces TO current_user;
|
||||||
|
|
||||||
-- Index: public.nonces_nonce_idx
|
-- Index: public.nonces_nonce_idx
|
||||||
|
|
||||||
-- DROP INDEX public.nonces_nonce_idx;
|
-- DROP INDEX public.nonces_nonce_idx;
|
||||||
|
|
||||||
CREATE INDEX nonces_nonce_idx
|
CREATE INDEX IF NOT EXISTS nonces_nonce_idx
|
||||||
ON public.nonces
|
ON public.nonces
|
||||||
USING btree
|
USING btree
|
||||||
(nonce COLLATE pg_catalog."default");
|
(nonce COLLATE pg_catalog."default");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
-- DROP TABLE public.playlist_videos;
|
-- DROP TABLE public.playlist_videos;
|
||||||
|
|
||||||
CREATE TABLE playlist_videos
|
CREATE TABLE IF NOT EXISTS public.playlist_videos
|
||||||
(
|
(
|
||||||
title text,
|
title text,
|
||||||
id text,
|
id text,
|
||||||
@@ -16,4 +16,4 @@ CREATE TABLE playlist_videos
|
|||||||
PRIMARY KEY (index,plid)
|
PRIMARY KEY (index,plid)
|
||||||
);
|
);
|
||||||
|
|
||||||
GRANT ALL ON TABLE public.playlist_videos TO kemal;
|
GRANT ALL ON TABLE public.playlist_videos TO current_user;
|
||||||
|
|||||||
@@ -1,8 +1,19 @@
|
|||||||
|
-- Type: public.privacy
|
||||||
|
|
||||||
|
-- DROP TYPE public.privacy;
|
||||||
|
|
||||||
|
CREATE TYPE public.privacy AS ENUM
|
||||||
|
(
|
||||||
|
'Public',
|
||||||
|
'Unlisted',
|
||||||
|
'Private'
|
||||||
|
);
|
||||||
|
|
||||||
-- Table: public.playlists
|
-- Table: public.playlists
|
||||||
|
|
||||||
-- DROP TABLE public.playlists;
|
-- DROP TABLE public.playlists;
|
||||||
|
|
||||||
CREATE TABLE public.playlists
|
CREATE TABLE IF NOT EXISTS public.playlists
|
||||||
(
|
(
|
||||||
title text,
|
title text,
|
||||||
id text primary key,
|
id text primary key,
|
||||||
@@ -15,4 +26,4 @@ CREATE TABLE public.playlists
|
|||||||
index int8[]
|
index int8[]
|
||||||
);
|
);
|
||||||
|
|
||||||
GRANT ALL ON public.playlists TO kemal;
|
GRANT ALL ON public.playlists TO current_user;
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
-- Type: public.privacy
|
|
||||||
|
|
||||||
-- DROP TYPE public.privacy;
|
|
||||||
|
|
||||||
CREATE TYPE public.privacy AS ENUM
|
|
||||||
(
|
|
||||||
'Public',
|
|
||||||
'Unlisted',
|
|
||||||
'Private'
|
|
||||||
);
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
-- DROP TABLE public.session_ids;
|
-- DROP TABLE public.session_ids;
|
||||||
|
|
||||||
CREATE TABLE public.session_ids
|
CREATE TABLE IF NOT EXISTS public.session_ids
|
||||||
(
|
(
|
||||||
id text NOT NULL,
|
id text NOT NULL,
|
||||||
email text,
|
email text,
|
||||||
@@ -10,13 +10,13 @@ CREATE TABLE public.session_ids
|
|||||||
CONSTRAINT session_ids_pkey PRIMARY KEY (id)
|
CONSTRAINT session_ids_pkey PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
GRANT ALL ON TABLE public.session_ids TO kemal;
|
GRANT ALL ON TABLE public.session_ids TO current_user;
|
||||||
|
|
||||||
-- Index: public.session_ids_id_idx
|
-- Index: public.session_ids_id_idx
|
||||||
|
|
||||||
-- DROP INDEX public.session_ids_id_idx;
|
-- DROP INDEX public.session_ids_id_idx;
|
||||||
|
|
||||||
CREATE INDEX session_ids_id_idx
|
CREATE INDEX IF NOT EXISTS session_ids_id_idx
|
||||||
ON public.session_ids
|
ON public.session_ids
|
||||||
USING btree
|
USING btree
|
||||||
(id COLLATE pg_catalog."default");
|
(id COLLATE pg_catalog."default");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
-- DROP TABLE public.users;
|
-- DROP TABLE public.users;
|
||||||
|
|
||||||
CREATE TABLE public.users
|
CREATE TABLE IF NOT EXISTS public.users
|
||||||
(
|
(
|
||||||
updated timestamp with time zone,
|
updated timestamp with time zone,
|
||||||
notifications text[],
|
notifications text[],
|
||||||
@@ -16,13 +16,13 @@ CREATE TABLE public.users
|
|||||||
CONSTRAINT users_email_key UNIQUE (email)
|
CONSTRAINT users_email_key UNIQUE (email)
|
||||||
);
|
);
|
||||||
|
|
||||||
GRANT ALL ON TABLE public.users TO kemal;
|
GRANT ALL ON TABLE public.users TO current_user;
|
||||||
|
|
||||||
-- Index: public.email_unique_idx
|
-- Index: public.email_unique_idx
|
||||||
|
|
||||||
-- DROP INDEX public.email_unique_idx;
|
-- DROP INDEX public.email_unique_idx;
|
||||||
|
|
||||||
CREATE UNIQUE INDEX email_unique_idx
|
CREATE UNIQUE INDEX IF NOT EXISTS email_unique_idx
|
||||||
ON public.users
|
ON public.users
|
||||||
USING btree
|
USING btree
|
||||||
(lower(email) COLLATE pg_catalog."default");
|
(lower(email) COLLATE pg_catalog."default");
|
||||||
|
|||||||
@@ -2,38 +2,21 @@
|
|||||||
|
|
||||||
-- DROP TABLE public.videos;
|
-- DROP TABLE public.videos;
|
||||||
|
|
||||||
CREATE TABLE public.videos
|
CREATE UNLOGGED TABLE IF NOT EXISTS public.videos
|
||||||
(
|
(
|
||||||
id text NOT NULL,
|
id text NOT NULL,
|
||||||
info text,
|
info text,
|
||||||
updated timestamp with time zone,
|
updated timestamp with time zone,
|
||||||
title text,
|
|
||||||
views bigint,
|
|
||||||
likes integer,
|
|
||||||
dislikes integer,
|
|
||||||
wilson_score double precision,
|
|
||||||
published timestamp with time zone,
|
|
||||||
description text,
|
|
||||||
language text,
|
|
||||||
author text,
|
|
||||||
ucid text,
|
|
||||||
allowed_regions text[],
|
|
||||||
is_family_friendly boolean,
|
|
||||||
genre text,
|
|
||||||
genre_url text,
|
|
||||||
license text,
|
|
||||||
sub_count_text text,
|
|
||||||
author_thumbnail text,
|
|
||||||
CONSTRAINT videos_pkey PRIMARY KEY (id)
|
CONSTRAINT videos_pkey PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
GRANT ALL ON TABLE public.videos TO kemal;
|
GRANT ALL ON TABLE public.videos TO current_user;
|
||||||
|
|
||||||
-- Index: public.id_idx
|
-- Index: public.id_idx
|
||||||
|
|
||||||
-- DROP INDEX public.id_idx;
|
-- DROP INDEX public.id_idx;
|
||||||
|
|
||||||
CREATE UNIQUE INDEX id_idx
|
CREATE UNIQUE INDEX IF NOT EXISTS id_idx
|
||||||
ON public.videos
|
ON public.videos
|
||||||
USING btree
|
USING btree
|
||||||
(id COLLATE pg_catalog."default");
|
(id COLLATE pg_catalog."default");
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
version: '3'
|
# Warning: This docker-compose file is made for development purposes.
|
||||||
|
# Using it will build an image from the locally cloned repository.
|
||||||
|
#
|
||||||
|
# If you want to use Invidious in production, see the docker-compose.yml file provided
|
||||||
|
# in the installation documentation: https://docs.invidious.io/installation/
|
||||||
|
|
||||||
|
version: "3"
|
||||||
services:
|
services:
|
||||||
postgres:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: docker/Dockerfile.postgres
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- postgresdata:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "pg_isready", "-U", "postgres"]
|
|
||||||
invidious:
|
invidious:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
@@ -16,8 +14,43 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:3000:3000"
|
- "127.0.0.1:3000:3000"
|
||||||
|
environment:
|
||||||
|
# Please read the following file for a comprehensive list of all available
|
||||||
|
# configuration options and their associated syntax:
|
||||||
|
# https://github.com/iv-org/invidious/blob/master/config/config.example.yml
|
||||||
|
INVIDIOUS_CONFIG: |
|
||||||
|
db:
|
||||||
|
dbname: invidious
|
||||||
|
user: kemal
|
||||||
|
password: kemal
|
||||||
|
host: invidious-db
|
||||||
|
port: 5432
|
||||||
|
check_tables: true
|
||||||
|
# external_port:
|
||||||
|
# domain:
|
||||||
|
# https_only: false
|
||||||
|
# statistics_enabled: false
|
||||||
|
healthcheck:
|
||||||
|
test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/comments/jNQXAC9IVRw || exit 1
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 2
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- invidious-db
|
||||||
|
|
||||||
|
invidious-db:
|
||||||
|
image: docker.io/library/postgres:13
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- postgresdata:/var/lib/postgresql/data
|
||||||
|
- ./config/sql:/config/sql
|
||||||
|
- ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: invidious
|
||||||
|
POSTGRES_USER: kemal
|
||||||
|
POSTGRES_PASSWORD: kemal
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgresdata:
|
postgresdata:
|
||||||
|
|||||||
@@ -1,29 +1,54 @@
|
|||||||
FROM alpine:edge AS builder
|
FROM crystallang/crystal:1.4.1-alpine AS builder
|
||||||
RUN apk add --no-cache crystal shards libc-dev \
|
RUN apk add --no-cache sqlite-static yaml-static
|
||||||
yaml-dev libxml2-dev sqlite-dev zlib-dev openssl-dev \
|
|
||||||
sqlite-static zlib-static openssl-libs-static
|
ARG release
|
||||||
|
|
||||||
WORKDIR /invidious
|
WORKDIR /invidious
|
||||||
COPY ./shard.yml ./shard.yml
|
COPY ./shard.yml ./shard.yml
|
||||||
RUN shards update && shards install
|
COPY ./shard.lock ./shard.lock
|
||||||
|
RUN shards install --production
|
||||||
|
|
||||||
|
COPY --from=quay.io/invidious/lsquic-compiled /root/liblsquic.a ./lib/lsquic/src/lsquic/ext/liblsquic.a
|
||||||
|
|
||||||
COPY ./src/ ./src/
|
COPY ./src/ ./src/
|
||||||
# TODO: .git folder is required for building – this is destructive.
|
# TODO: .git folder is required for building – this is destructive.
|
||||||
# See definition of CURRENT_BRANCH, CURRENT_COMMIT and CURRENT_VERSION.
|
# See definition of CURRENT_BRANCH, CURRENT_COMMIT and CURRENT_VERSION.
|
||||||
COPY ./.git/ ./.git/
|
COPY ./.git/ ./.git/
|
||||||
RUN crystal build --static --release --warnings all --error-on-warnings \
|
|
||||||
# TODO: Remove next line, see https://github.com/crystal-lang/crystal/issues/7946
|
# Required for fetching player dependencies
|
||||||
-Dmusl \
|
COPY ./scripts/ ./scripts/
|
||||||
./src/invidious.cr
|
COPY ./assets/ ./assets/
|
||||||
|
COPY ./videojs-dependencies.yml ./videojs-dependencies.yml
|
||||||
|
|
||||||
|
RUN crystal spec --warnings all \
|
||||||
|
--link-flags "-lxml2 -llzma"
|
||||||
|
|
||||||
|
RUN if [ "${release}" == 1 ] ; then \
|
||||||
|
crystal build ./src/invidious.cr \
|
||||||
|
--release \
|
||||||
|
--static --warnings all \
|
||||||
|
--link-flags "-lxml2 -llzma"; \
|
||||||
|
else \
|
||||||
|
crystal build ./src/invidious.cr \
|
||||||
|
--static --warnings all \
|
||||||
|
--link-flags "-lxml2 -llzma"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
RUN apk add --no-cache librsvg ttf-opensans
|
RUN apk add --no-cache librsvg ttf-opensans
|
||||||
WORKDIR /invidious
|
WORKDIR /invidious
|
||||||
RUN addgroup -g 1000 -S invidious && \
|
RUN addgroup -g 1000 -S invidious && \
|
||||||
adduser -u 1000 -S invidious -G invidious
|
adduser -u 1000 -S invidious -G invidious
|
||||||
COPY ./assets/ ./assets/
|
COPY --chown=invidious ./config/config.* ./config/
|
||||||
COPY ./config/config.yml ./config/config.yml
|
RUN mv -n config/config.example.yml config/config.yml
|
||||||
|
RUN sed -i 's/host: \(127.0.0.1\|localhost\)/host: invidious-db/' config/config.yml
|
||||||
COPY ./config/sql/ ./config/sql/
|
COPY ./config/sql/ ./config/sql/
|
||||||
COPY ./locales/ ./locales/
|
COPY ./locales/ ./locales/
|
||||||
RUN sed -i 's/host: \(127.0.0.1\|localhost\)/host: postgres/' config/config.yml
|
COPY --from=builder /invidious/assets ./assets/
|
||||||
COPY --from=builder /invidious/invidious .
|
COPY --from=builder /invidious/invidious .
|
||||||
|
RUN chmod o+rX -R ./assets ./config ./locales
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
USER invidious
|
USER invidious
|
||||||
CMD [ "/invidious/invidious" ]
|
CMD [ "/invidious/invidious" ]
|
||||||
|
|||||||
53
docker/Dockerfile.arm64
Normal file
53
docker/Dockerfile.arm64
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
FROM alpine:3.16 AS builder
|
||||||
|
RUN apk add --no-cache 'crystal=1.4.1-r0' shards sqlite-static yaml-static yaml-dev libxml2-dev zlib-static openssl-libs-static openssl-dev musl-dev
|
||||||
|
|
||||||
|
ARG release
|
||||||
|
|
||||||
|
WORKDIR /invidious
|
||||||
|
COPY ./shard.yml ./shard.yml
|
||||||
|
COPY ./shard.lock ./shard.lock
|
||||||
|
RUN shards install --production
|
||||||
|
|
||||||
|
COPY --from=quay.io/invidious/lsquic-compiled /root/liblsquic.a ./lib/lsquic/src/lsquic/ext/liblsquic.a
|
||||||
|
|
||||||
|
COPY ./src/ ./src/
|
||||||
|
# TODO: .git folder is required for building – this is destructive.
|
||||||
|
# See definition of CURRENT_BRANCH, CURRENT_COMMIT and CURRENT_VERSION.
|
||||||
|
COPY ./.git/ ./.git/
|
||||||
|
|
||||||
|
# Required for fetching player dependencies
|
||||||
|
COPY ./scripts/ ./scripts/
|
||||||
|
COPY ./assets/ ./assets/
|
||||||
|
COPY ./videojs-dependencies.yml ./videojs-dependencies.yml
|
||||||
|
|
||||||
|
RUN crystal spec --warnings all \
|
||||||
|
--link-flags "-lxml2 -llzma"
|
||||||
|
|
||||||
|
RUN if [ ${release} == 1 ] ; then \
|
||||||
|
crystal build ./src/invidious.cr \
|
||||||
|
--release \
|
||||||
|
--static --warnings all \
|
||||||
|
--link-flags "-lxml2 -llzma"; \
|
||||||
|
else \
|
||||||
|
crystal build ./src/invidious.cr \
|
||||||
|
--static --warnings all \
|
||||||
|
--link-flags "-lxml2 -llzma"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
FROM alpine:3.16
|
||||||
|
RUN apk add --no-cache librsvg ttf-opensans
|
||||||
|
WORKDIR /invidious
|
||||||
|
RUN addgroup -g 1000 -S invidious && \
|
||||||
|
adduser -u 1000 -S invidious -G invidious
|
||||||
|
COPY --chown=invidious ./config/config.* ./config/
|
||||||
|
RUN mv -n config/config.example.yml config/config.yml
|
||||||
|
RUN sed -i 's/host: \(127.0.0.1\|localhost\)/host: invidious-db/' config/config.yml
|
||||||
|
COPY ./config/sql/ ./config/sql/
|
||||||
|
COPY ./locales/ ./locales/
|
||||||
|
COPY --from=builder /invidious/assets ./assets/
|
||||||
|
COPY --from=builder /invidious/invidious .
|
||||||
|
RUN chmod o+rX -R ./assets ./config ./locales
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
USER invidious
|
||||||
|
CMD [ "/invidious/invidious" ]
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
FROM postgres:10
|
|
||||||
|
|
||||||
ENV POSTGRES_USER postgres
|
|
||||||
|
|
||||||
ADD ./config/sql /config/sql
|
|
||||||
ADD ./docker/entrypoint.postgres.sh /entrypoint.sh
|
|
||||||
|
|
||||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
|
||||||
CMD [ "postgres" ]
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CMD="$@"
|
|
||||||
if [ ! -f /var/lib/postgresql/data/setupFinished ]; then
|
|
||||||
echo "### first run - setting up invidious database"
|
|
||||||
/usr/local/bin/docker-entrypoint.sh postgres &
|
|
||||||
sleep 10
|
|
||||||
until runuser -l postgres -c 'pg_isready' 2>/dev/null; do
|
|
||||||
>&2 echo "### Postgres is unavailable - waiting"
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
>&2 echo "### importing table schemas"
|
|
||||||
su postgres -c 'createdb invidious'
|
|
||||||
su postgres -c 'psql -c "CREATE USER kemal WITH PASSWORD '"'kemal'"'"'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/channels.sql'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/videos.sql'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/channel_videos.sql'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/users.sql'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/session_ids.sql'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/nonces.sql'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/annotations.sql'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/playlists.sql'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/playlist_videos.sql'
|
|
||||||
su postgres -c 'psql invidious kemal < config/sql/privacy.sql'
|
|
||||||
touch /var/lib/postgresql/data/setupFinished
|
|
||||||
echo "### invidious database setup finished"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "running postgres /usr/local/bin/docker-entrypoint.sh $CMD"
|
|
||||||
exec /usr/local/bin/docker-entrypoint.sh $CMD
|
|
||||||
12
docker/init-invidious-db.sh
Executable file
12
docker/init-invidious-db.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eou pipefail
|
||||||
|
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/channels.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/videos.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/channel_videos.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/users.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/session_ids.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/nonces.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/annotations.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/playlists.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/playlist_videos.sql
|
||||||
1
kubernetes/.gitignore
vendored
Normal file
1
kubernetes/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/charts/*.tgz
|
||||||
6
kubernetes/Chart.lock
Normal file
6
kubernetes/Chart.lock
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
dependencies:
|
||||||
|
- name: postgresql
|
||||||
|
repository: https://charts.bitnami.com/bitnami/
|
||||||
|
version: 11.1.3
|
||||||
|
digest: sha256:79061645472b6fb342d45e8e5b3aacd018ef5067193e46a060bccdc99fe7f6e1
|
||||||
|
generated: "2022-03-02T05:57:20.081432389+13:00"
|
||||||
22
kubernetes/Chart.yaml
Normal file
22
kubernetes/Chart.yaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: invidious
|
||||||
|
description: Invidious is an alternative front-end to YouTube
|
||||||
|
version: 1.1.1
|
||||||
|
appVersion: 0.20.1
|
||||||
|
keywords:
|
||||||
|
- youtube
|
||||||
|
- proxy
|
||||||
|
- video
|
||||||
|
- privacy
|
||||||
|
home: https://invidio.us/
|
||||||
|
icon: https://raw.githubusercontent.com/iv-org/invidious/05988c1c49851b7d0094fca16aeaf6382a7f64ab/assets/favicon-32x32.png
|
||||||
|
sources:
|
||||||
|
- https://github.com/iv-org/invidious
|
||||||
|
maintainers:
|
||||||
|
- name: Leon Klingele
|
||||||
|
email: mail@leonklingele.de
|
||||||
|
dependencies:
|
||||||
|
- name: postgresql
|
||||||
|
version: ~11.1.3
|
||||||
|
repository: "https://charts.bitnami.com/bitnami/"
|
||||||
|
engine: gotpl
|
||||||
41
kubernetes/README.md
Normal file
41
kubernetes/README.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Invidious Helm chart
|
||||||
|
|
||||||
|
Easily deploy Invidious to Kubernetes.
|
||||||
|
|
||||||
|
## Installing Helm chart
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Build Helm dependencies
|
||||||
|
$ helm dep build
|
||||||
|
|
||||||
|
# Add PostgreSQL init scripts
|
||||||
|
$ kubectl create configmap invidious-postgresql-init \
|
||||||
|
--from-file=../config/sql/channels.sql \
|
||||||
|
--from-file=../config/sql/videos.sql \
|
||||||
|
--from-file=../config/sql/channel_videos.sql \
|
||||||
|
--from-file=../config/sql/users.sql \
|
||||||
|
--from-file=../config/sql/session_ids.sql \
|
||||||
|
--from-file=../config/sql/nonces.sql \
|
||||||
|
--from-file=../config/sql/annotations.sql \
|
||||||
|
--from-file=../config/sql/playlists.sql \
|
||||||
|
--from-file=../config/sql/playlist_videos.sql
|
||||||
|
|
||||||
|
# Install Helm app to your Kubernetes cluster
|
||||||
|
$ helm install invidious ./
|
||||||
|
```
|
||||||
|
|
||||||
|
## Upgrading
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Upgrading is easy, too!
|
||||||
|
$ helm upgrade invidious ./
|
||||||
|
```
|
||||||
|
|
||||||
|
## Uninstall
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Get rid of everything (except database)
|
||||||
|
$ helm delete invidious
|
||||||
|
|
||||||
|
# To also delete the database, remove all invidious-postgresql PVCs
|
||||||
|
```
|
||||||
16
kubernetes/templates/_helpers.tpl
Normal file
16
kubernetes/templates/_helpers.tpl
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{{/* vim: set filetype=mustache: */}}
|
||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "invidious.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
|
*/}}
|
||||||
|
{{- define "invidious.fullname" -}}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end -}}
|
||||||
11
kubernetes/templates/configmap.yaml
Normal file
11
kubernetes/templates/configmap.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ template "invidious.fullname" . }}
|
||||||
|
labels:
|
||||||
|
app: {{ template "invidious.name" . }}
|
||||||
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
data:
|
||||||
|
INVIDIOUS_CONFIG: |
|
||||||
|
{{ toYaml .Values.config | indent 4 }}
|
||||||
61
kubernetes/templates/deployment.yaml
Normal file
61
kubernetes/templates/deployment.yaml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ template "invidious.fullname" . }}
|
||||||
|
labels:
|
||||||
|
app: {{ template "invidious.name" . }}
|
||||||
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ template "invidious.name" . }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: {{ template "invidious.name" . }}
|
||||||
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsUser: {{ .Values.securityContext.runAsUser }}
|
||||||
|
runAsGroup: {{ .Values.securityContext.runAsGroup }}
|
||||||
|
fsGroup: {{ .Values.securityContext.fsGroup }}
|
||||||
|
initContainers:
|
||||||
|
- name: wait-for-postgresql
|
||||||
|
image: postgres
|
||||||
|
args:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- until pg_isready -h {{ .Values.config.db.host }} -p {{ .Values.config.db.port }} -U {{ .Values.config.db.user }}; do echo waiting for database; sleep 2; done;
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
env:
|
||||||
|
- name: INVIDIOUS_CONFIG
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
key: INVIDIOUS_CONFIG
|
||||||
|
name: {{ template "invidious.fullname" . }}
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: {{ .Values.securityContext.allowPrivilegeEscalation }}
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
resources:
|
||||||
|
{{ toYaml .Values.resources | indent 10 }}
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
port: 3000
|
||||||
|
path: /
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
port: 3000
|
||||||
|
path: /
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
restartPolicy: Always
|
||||||
18
kubernetes/templates/hpa.yaml
Normal file
18
kubernetes/templates/hpa.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{{- if .Values.autoscaling.enabled }}
|
||||||
|
apiVersion: autoscaling/v1
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: {{ template "invidious.fullname" . }}
|
||||||
|
labels:
|
||||||
|
app: {{ template "invidious.name" . }}
|
||||||
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: {{ template "invidious.fullname" . }}
|
||||||
|
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||||
|
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||||
|
targetCPUUtilizationPercentage: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
20
kubernetes/templates/service.yaml
Normal file
20
kubernetes/templates/service.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ template "invidious.fullname" . }}
|
||||||
|
labels:
|
||||||
|
app: {{ template "invidious.name" . }}
|
||||||
|
chart: {{ .Chart.Name }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: {{ .Values.service.port }}
|
||||||
|
targetPort: 3000
|
||||||
|
selector:
|
||||||
|
app: {{ template "invidious.name" . }}
|
||||||
|
release: {{ .Release.Name }}
|
||||||
|
{{- if .Values.service.loadBalancerIP }}
|
||||||
|
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
|
||||||
|
{{- end }}
|
||||||
61
kubernetes/values.yaml
Normal file
61
kubernetes/values.yaml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
name: invidious
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: quay.io/invidious/invidious
|
||||||
|
tag: latest
|
||||||
|
pullPolicy: Always
|
||||||
|
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
autoscaling:
|
||||||
|
enabled: false
|
||||||
|
minReplicas: 1
|
||||||
|
maxReplicas: 16
|
||||||
|
targetCPUUtilizationPercentage: 50
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 3000
|
||||||
|
#loadBalancerIP:
|
||||||
|
|
||||||
|
resources: {}
|
||||||
|
#requests:
|
||||||
|
# cpu: 100m
|
||||||
|
# memory: 64Mi
|
||||||
|
#limits:
|
||||||
|
# cpu: 800m
|
||||||
|
# memory: 512Mi
|
||||||
|
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
|
||||||
|
# See https://github.com/bitnami/charts/tree/master/bitnami/postgresql
|
||||||
|
postgresql:
|
||||||
|
image:
|
||||||
|
registry: quay.io
|
||||||
|
auth:
|
||||||
|
username: kemal
|
||||||
|
password: kemal
|
||||||
|
database: invidious
|
||||||
|
primary:
|
||||||
|
initdb:
|
||||||
|
username: kemal
|
||||||
|
password: kemal
|
||||||
|
scriptsConfigMap: invidious-postgresql-init
|
||||||
|
|
||||||
|
# Adapted from ../config/config.yml
|
||||||
|
config:
|
||||||
|
channel_threads: 1
|
||||||
|
feed_threads: 1
|
||||||
|
db:
|
||||||
|
user: kemal
|
||||||
|
password: kemal
|
||||||
|
host: invidious-postgresql
|
||||||
|
port: 5432
|
||||||
|
dbname: invidious
|
||||||
|
full_refresh: false
|
||||||
|
https_only: false
|
||||||
|
domain:
|
||||||
493
locales/ar.json
493
locales/ar.json
@@ -1,128 +1,127 @@
|
|||||||
{
|
{
|
||||||
"`x` subscribers": "`x` المشتركين",
|
"LIVE": "مُباشِر",
|
||||||
"`x` videos": "`x` الفيديوهات",
|
"Shared `x` ago": "تمَّ رفع المقطع المرئيّ مُنذ `x`",
|
||||||
"`x` playlists": "`x` قوائم التشغيل",
|
"Unsubscribe": "إلغاء الاشتراك",
|
||||||
"LIVE": "مباشر",
|
"Subscribe": "الإشتراك",
|
||||||
"Shared `x` ago": "تم رفع الفيديو منذ `x`",
|
|
||||||
"Unsubscribe": "إلغاء الإشتراك",
|
|
||||||
"Subscribe": "إشتراك",
|
|
||||||
"View channel on YouTube": "زيارة القناة على موقع يوتيوب",
|
"View channel on YouTube": "زيارة القناة على موقع يوتيوب",
|
||||||
"View playlist on YouTube": "عرض قائمة التشغيل على اليوتيوب",
|
"View playlist on YouTube": "عرض قائمة التشغيل على اليوتيوب",
|
||||||
"newest": "الأجدد",
|
"newest": "الأجدد",
|
||||||
"oldest": "الأقدم",
|
"oldest": "الأقدم",
|
||||||
"popular": "الأكثر شعبية",
|
"popular": "الأكثر شعبية",
|
||||||
"last": "اخر قوائم التشغيل المعدلة",
|
"last": "الأخيرة",
|
||||||
"Next page": "الصفحة الثانية",
|
"Next page": "الصفحة التالية",
|
||||||
"Previous page": "الصفحة السابقة",
|
"Previous page": "الصفحة السابقة",
|
||||||
"Clear watch history?": "مسح السجل ؟",
|
"Clear watch history?": "هل تريد محو سجل المشاهدة؟",
|
||||||
"New password": "الرقم السرى الجديد",
|
"New password": "كلمة مرور جديدة",
|
||||||
"New passwords must match": "الأرقام السرية يجب ان تكون متطابقة",
|
"New passwords must match": "يَجبُ أن تكون كلمتا المرور متطابقتين",
|
||||||
"Cannot change password for Google accounts": "لا يستطيع تغيير الرقم السرى لحساب جوجل",
|
"Cannot change password for Google accounts": "لا يُمكن تغيير كلمة المرور لِحسابات جوجل",
|
||||||
"Authorize token?": "رمز الإذن ؟",
|
"Authorize token?": "رمز التفويض؟",
|
||||||
"Authorize token for `x`?": "تصريح الرمز لـ `x` ؟",
|
"Authorize token for `x`?": "السماح بالرمز المميز ل 'x'؟",
|
||||||
"Yes": "نعم",
|
"Yes": "نعم",
|
||||||
"No": "لا",
|
"No": "لا",
|
||||||
"Import and Export Data": "استخراج و إضافة البيانات",
|
"Import and Export Data": "اِستيراد البيانات وتصديرها",
|
||||||
"Import": "إضافة",
|
"Import": "استيراد",
|
||||||
"Import Invidious data": "إضافة بيانات Invidious",
|
"Import Invidious data": "استيراد بيانات JSON Invidious",
|
||||||
"Import YouTube subscriptions": "إضافةالإشتراكات من موقع يوتيوب",
|
"Import YouTube subscriptions": "استيراد اشتراكات YouTube/OPML",
|
||||||
"Import FreeTube subscriptions (.db)": "إضافةالمشتركين من FreeTube (.db)",
|
"Import FreeTube subscriptions (.db)": "استيراد اشتراكات فريتيوب (.db)",
|
||||||
"Import NewPipe subscriptions (.json)": "إضافة المشتركين من NewPipe (.json)",
|
"Import NewPipe subscriptions (.json)": "استيراد اشتراكات نيو بايب (.json)",
|
||||||
"Import NewPipe data (.zip)": "إضافة بيانات NewPipe (.zip)",
|
"Import NewPipe data (.zip)": "استيراد بيانات نيو بايب (.zip)",
|
||||||
"Export": "استخراج",
|
"Export": "تصدير",
|
||||||
"Export subscriptions as OPML": "استخراج المشتركين كـ OPML",
|
"Export subscriptions as OPML": "تصدير الاشتراكات كـOPML",
|
||||||
"Export subscriptions as OPML (for NewPipe & FreeTube)": "استخراج المشتركين كـ OPML (لـ NewPipe و FreeTube)",
|
"Export subscriptions as OPML (for NewPipe & FreeTube)": "تصدير الاشتراكات كـOPML (لِنيو بايب و فريتيوب)",
|
||||||
"Export data as JSON": "استخراج البيانات كـ JSON",
|
"Export data as JSON": "تصدير بيانات Invidious كـ JSON",
|
||||||
"Delete account?": "حذف الحساب ؟",
|
"Delete account?": "حذف الحساب؟",
|
||||||
"History": "السجل",
|
"History": "السِّجل",
|
||||||
"An alternative front-end to YouTube": "البديل الكامل لموقع يوتيوب",
|
"An alternative front-end to YouTube": "واجهة أمامية بديلة لموقع يوتيوب",
|
||||||
"JavaScript license information": "معلومات ترخيص JavaScript",
|
"JavaScript license information": "معلومات ترخيص جافا سكربت",
|
||||||
"source": "المصدر",
|
"source": "المصدر",
|
||||||
"Log in": "تسجيل الدخول",
|
"Log in": "تسجيل الدخول",
|
||||||
"Log in/register": "تسجيل الدخول\\إنشاء حساب",
|
"Log in/register": "تسجيل الدخول \\ إنشاء حساب",
|
||||||
"Log in with Google": "تسجيل الدخول بإستخدام جوجل",
|
"Log in with Google": "تسجيل الدخول باستخدام جوجل",
|
||||||
"User ID": "إسم المستخدم",
|
"User ID": "مُعرِّف المُستخدم",
|
||||||
"Password": "الرقم السرى",
|
"Password": "كلمة المرور",
|
||||||
"Time (h:mm:ss):": "(يجب ان يكتب مثل هذا التنسيق) الوقت (h(ساعات):mm(دقائق):ss(ثوانى)):",
|
"Time (h:mm:ss):": "الوقت (h:mm:ss):",
|
||||||
"Text CAPTCHA": "CAPTCHA كلامية",
|
"Text CAPTCHA": "نص الكابتشا",
|
||||||
"Image CAPTCHA": "CAPTCHA صورية",
|
"Image CAPTCHA": "صورة الكابتشا",
|
||||||
"Sign In": "تسجيل الدخول",
|
"Sign In": "تسجيل الدخول",
|
||||||
"Register": "انشاء الحساب",
|
"Register": "التسجيل",
|
||||||
"E-mail": "الإيميل",
|
"E-mail": "البريد الإلكتروني",
|
||||||
"Google verification code": "رمز تحقق جوجل",
|
"Google verification code": "رمز تحقق جوجل",
|
||||||
"Preferences": "التفضيلات",
|
"Preferences": "الإعدادات",
|
||||||
"Player preferences": "التفضيلات المشغل",
|
"preferences_category_player": "إعدادات المُشغِّل",
|
||||||
"Always loop: ": "كرر الفيديو دائما: ",
|
"preferences_video_loop_label": "كرر المقطع المرئيّ دائما: ",
|
||||||
"Autoplay: ": "تشغيل تلقائى: ",
|
"preferences_autoplay_label": "تشغيل تلقائي: ",
|
||||||
"Play next by default: ": "شغل الفيديو التالي تلقائيا: ",
|
"preferences_continue_label": "شغل المقطع التالي تلقائيًا: ",
|
||||||
"Autoplay next video: ": "شغل الفيديو التالي تلقائيا (في قوائم التشغيل) ",
|
"preferences_continue_autoplay_label": "شغل المقطع التالي تلقائيًا: ",
|
||||||
"Listen by default: ": "تشغيل النسخة السمعية تلقائى: ",
|
"preferences_listen_label": "تشغيل النسخة السمعية تلقائيًا: ",
|
||||||
"Proxy videos: ": "عرض الفيديوهات عن طريق البروكسي؟ ",
|
"preferences_local_label": "بروكسي المقاطع المرئيّة؟ ",
|
||||||
"Default speed: ": "السرعة الإفتراضية: ",
|
"preferences_speed_label": "السرعة الافتراضية: ",
|
||||||
"Preferred video quality: ": "الجودة المفضلة للفيديوهات: ",
|
"preferences_quality_label": "الجودة المفضلة للمقاطع: ",
|
||||||
"Player volume: ": "صوت المشغل: ",
|
"preferences_volume_label": "صوت المشغل: ",
|
||||||
"Default comments: ": "إضهار التعليقات الإفتراضية لـ: ",
|
"preferences_comments_label": "التعليقات الافتراضية: ",
|
||||||
"youtube": "يوتيوب",
|
"youtube": "يوتيوب",
|
||||||
"reddit": "Reddit",
|
"reddit": "ريديت",
|
||||||
"Default captions: ": "الترجمات الإفتراضية: ",
|
"preferences_captions_label": "التسميات التوضيحية الإفتراضية: ",
|
||||||
"Fallback captions: ": "الترجمات المصاحبة: ",
|
"Fallback captions: ": "التسميات التوضيحية الاحتياطيَّة: ",
|
||||||
"Show related videos: ": "اعرض الفيديوهات ذات الصلة: ",
|
"preferences_related_videos_label": "اعرض الفيديوهات ذات الصلة: ",
|
||||||
"Show annotations by default: ": "اعرض الملاحظات في الفيديو تلقائيا: ",
|
"preferences_annotations_label": "اعرض الملاحظات في الفيديو تلقائيا: ",
|
||||||
"Visual preferences": "التفضيلات المرئية",
|
"preferences_extend_desc_label": "توسيع وصف الفيديو تلقائيا: ",
|
||||||
"Player style: ": "شكل مشغل الفيديوهات: ",
|
"preferences_vr_mode_label": "مقاطع فيديو تفاعلية بزاوية 360 درجة (تتطلب WebGL): ",
|
||||||
"Dark mode: ": "الوضع الليلى: ",
|
"preferences_category_visual": "التفضيلات المرئية",
|
||||||
"Theme: ": "المظهر: ",
|
"preferences_player_style_label": "شكل مشغل الفيديوهات: ",
|
||||||
|
"Dark mode: ": "الوضع الليلي: ",
|
||||||
|
"preferences_dark_mode_label": "المظهر: ",
|
||||||
"dark": "غامق (اسود)",
|
"dark": "غامق (اسود)",
|
||||||
"light": "فاتح (ابيض)",
|
"light": "فاتح (ابيض)",
|
||||||
"Thin mode: ": "الوضع الخفيف: ",
|
"preferences_thin_mode_label": "الوضع الخفيف: ",
|
||||||
"Subscription preferences": "تفضيلات الإشتراك",
|
"preferences_category_misc": "تفضيلات متنوعة",
|
||||||
"Show annotations by default for subscribed channels: ": "عرض الملاحظات في الفيديوهات تلقائيا في القنوات المشترك بها فقط: ",
|
"preferences_automatic_instance_redirect_label": "إعادة توجيه المثيل التلقائي (إعادة التوجيه إلى redirect.invidious.io): ",
|
||||||
|
"preferences_category_subscription": "تفضيلات الاشتراك",
|
||||||
|
"preferences_annotations_subscribed_label": "عرض الملاحظات في الفيديوهات تلقائيا في القنوات المشترك بها فقط: ",
|
||||||
"Redirect homepage to feed: ": "إعادة التوجية من الصفحة الرئيسية لصفحة المشتركين (لرؤية اخر فيديوهات المشتركين): ",
|
"Redirect homepage to feed: ": "إعادة التوجية من الصفحة الرئيسية لصفحة المشتركين (لرؤية اخر فيديوهات المشتركين): ",
|
||||||
"Number of videos shown in feed: ": "عدد الفيديوهات التى ستظهر فى صفحة المشتركين: ",
|
"preferences_max_results_label": "عدد الفيديوهات التى ستظهر فى صفحة المشتركين: ",
|
||||||
"Sort videos by: ": "ترتيب الفيديو بـ: ",
|
"preferences_sort_label": "ترتيب الفيديوهات بـ: ",
|
||||||
"published": "احدث فيديو",
|
"published": "أحدث فيديو",
|
||||||
"published - reverse": "احدث فيديو - عكسى",
|
"published - reverse": "أحدث فيديو - عكسي",
|
||||||
"alphabetically": "ترتيب ابجدى",
|
"alphabetically": "ترتيب أبجدي",
|
||||||
"alphabetically - reverse": "ابجدى - عكسى",
|
"alphabetically - reverse": "أبجدي - عكسي",
|
||||||
"channel name": "بإسم القناة",
|
"channel name": "باسم القناة",
|
||||||
"channel name - reverse": "بإسم القناة - عكسى",
|
"channel name - reverse": "باسم القناة - عكسى",
|
||||||
"Only show latest video from channel: ": "فقط إظهر اخر فيديو من القناة: ",
|
"Only show latest video from channel: ": "فقط أظهر آخر فيديو من القناة: ",
|
||||||
"Only show latest unwatched video from channel: ": "فقط اظهر اخر فيديو لم يتم رؤيتة من القناة: ",
|
"Only show latest unwatched video from channel: ": "فقط أظهر آخر فيديو لم يتم رؤيته من القناة: ",
|
||||||
"Only show unwatched: ": "فقط اظهر الذى لم يتم رؤيتة: ",
|
"preferences_unseen_only_label": "فقط أظهر الذي لم يتم رؤيته: ",
|
||||||
"Only show notifications (if there are any): ": "إظهار الإشعارات فقط (إذا كان هناك أي): ",
|
"preferences_notifications_only_label": "إظهار الإشعارات فقط (إذا كان هناك أي): ",
|
||||||
"Enable web notifications": "تفعيل إشعارات المتصفح",
|
"Enable web notifications": "تفعيل إشعارات المتصفح",
|
||||||
"`x` uploaded a video": "`x` رفع فيديو",
|
"`x` uploaded a video": "`x` رفع فيديو",
|
||||||
"`x` is live": "`x` فى بث مباشر",
|
"`x` is live": "`x` في بث مباشر",
|
||||||
"Data preferences": "إعدادات التفضيلات",
|
"preferences_category_data": "إعدادات التفضيلات",
|
||||||
"Clear watch history": "حذف سجل المشاهدة",
|
"Clear watch history": "حذف سجل المشاهدة",
|
||||||
"Import/export data": "إضافة\\إستخراج البيانات",
|
"Import/export data": "إضافة\\استخراج البيانات",
|
||||||
"Change password": "غير الرقم السرى",
|
"Change password": "غير كلمة السر",
|
||||||
"Manage subscriptions": "إدارة المشتركين",
|
"Manage subscriptions": "إدارة الاشتراكات",
|
||||||
"Manage tokens": "إدارة الرموز",
|
"Manage tokens": "إدارة الرموز",
|
||||||
"Watch history": "سجل المشاهدة",
|
"Watch history": "سجل المشاهدة",
|
||||||
"Delete account": "حذف الحساب",
|
"Delete account": "حذف الحساب",
|
||||||
"Administrator preferences": "إعدادات المدير",
|
"preferences_category_admin": "إعدادات المدير",
|
||||||
"Default homepage: ": "الصفحة الرئيسية الافتراضية ",
|
"preferences_default_home_label": "الصفحة الرئيسية الافتراضية: ",
|
||||||
"Feed menu: ": "قائمة التدفقات: ",
|
"preferences_feed_menu_label": "قائمة التدفقات: ",
|
||||||
|
"preferences_show_nick_label": "إظهار اللقب في الأعلى: ",
|
||||||
"Top enabled: ": "تفعيل 'الأفضل' ؟ ",
|
"Top enabled: ": "تفعيل 'الأفضل' ؟ ",
|
||||||
"CAPTCHA enabled: ": "تفعيل الكابتشا: ",
|
"CAPTCHA enabled: ": "تفعيل الكابتشا: ",
|
||||||
"Login enabled: ": "تفعيل الولوج: ",
|
"Login enabled: ": "تمكين تسجيل الدخول: ",
|
||||||
"Registration enabled: ": "تفعيل التسجيل: ",
|
"Registration enabled: ": "تفعيل التسجيل: ",
|
||||||
"Report statistics: ": "الإبلاغ عن الإحصائيات: ",
|
"Report statistics: ": "تقرير الإحصائيات: ",
|
||||||
"Save preferences": "حفظ التفضيلات",
|
"Save preferences": "حفظ الإعدادات",
|
||||||
"Subscription manager": "مدير الإشتراكات",
|
"Subscription manager": "مدير الاشتراكات",
|
||||||
"Token manager": "إداره الرمز",
|
"Token manager": "إداره الرمز",
|
||||||
"Token": "الرمز",
|
"Token": "الرمز",
|
||||||
"`x` subscriptions": "`x` مشتركين",
|
"Import/export": "استيراد/تصدير",
|
||||||
"`x` tokens": "`x` رموز",
|
"unsubscribe": "إلغاء الاشتراك",
|
||||||
"Import/export": "إضافة\\إستخراج",
|
|
||||||
"unsubscribe": "إلغاء الإشتراك",
|
|
||||||
"revoke": "مسح",
|
"revoke": "مسح",
|
||||||
"Subscriptions": "الإشتراكات",
|
"Subscriptions": "الاشتراكات",
|
||||||
"`x` unseen notifications": "`x` إشعارات لم تشاهدها بعد",
|
|
||||||
"search": "بحث",
|
"search": "بحث",
|
||||||
"Log out": "تسجيل الخروج",
|
"Log out": "تسجيل الخروج",
|
||||||
"Released under the AGPLv3 by Omar Roth.": "تم الإنشاء تحت AGPLv3 بواسطة عمر روث.",
|
"Released under the AGPLv3 on Github.": "صدر تحت AGPLv3 على GitHub.",
|
||||||
"Source available here.": "الأكواد متوفرة هنا.",
|
"Source available here.": "الأكواد متوفرة هنا.",
|
||||||
"View JavaScript license information.": "مشاهدة معلومات حول تراخيص الجافاسكريبت.",
|
"View JavaScript license information.": "مشاهدة معلومات حول تراخيص الجافاسكريبت.",
|
||||||
"View privacy policy.": "عرض سياسة الخصوصية.",
|
"View privacy policy.": "عرض سياسة الخصوصية.",
|
||||||
@@ -132,79 +131,82 @@
|
|||||||
"Private": "خاص",
|
"Private": "خاص",
|
||||||
"View all playlists": "عرض جميع قوائم التشغيل",
|
"View all playlists": "عرض جميع قوائم التشغيل",
|
||||||
"Updated `x` ago": "تم تحديثه منذ `x`",
|
"Updated `x` ago": "تم تحديثه منذ `x`",
|
||||||
"Delete playlist `x`?": "حذف قائمه التشغيل `x` ?",
|
"Delete playlist `x`?": "حذف قائمة التشغيل `x`؟",
|
||||||
"Delete playlist": "حذف قائمه التغشيل",
|
"Delete playlist": "حذف قائمة التغشيل",
|
||||||
"Create playlist": "إنشاء قائمه تشغيل",
|
"Create playlist": "إنشاء قائمة تشغيل",
|
||||||
"Title": "العنوان",
|
"Title": "العنوان",
|
||||||
"Playlist privacy": "إعدادات الخصوصيه",
|
"Playlist privacy": "إعدادات الخصوصية",
|
||||||
"Editing playlist `x`": "تعديل قائمه التشفيل `x`",
|
"Editing playlist `x`": "تعديل قائمة التشغيل `x`",
|
||||||
|
"Show more": "إظهار المزيد",
|
||||||
|
"Show less": "عرض اقل",
|
||||||
"Watch on YouTube": "مشاهدة الفيديو على اليوتيوب",
|
"Watch on YouTube": "مشاهدة الفيديو على اليوتيوب",
|
||||||
"Hide annotations": "إخفاء الملاحظات فى الفيديو",
|
"Switch Invidious Instance": "تبديل المثيل Invidious",
|
||||||
"Show annotations": "عرض الملاحظات فى الفيديو",
|
"Hide annotations": "إخفاء الملاحظات في الفيديو",
|
||||||
|
"Show annotations": "عرض الملاحظات في الفيديو",
|
||||||
"Genre: ": "النوع: ",
|
"Genre: ": "النوع: ",
|
||||||
"License: ": "التراخيص: ",
|
"License: ": "التراخيص: ",
|
||||||
"Family friendly? ": "محتوى عائلى? ",
|
"Family friendly? ": "محتوى عائلي؟ ",
|
||||||
"Wilson score: ": "درجة ويلسون: ",
|
"Wilson score: ": "درجة ويلسون: ",
|
||||||
"Engagement: ": "نسبة المشاركة (عدد المشاهدات\\عدد الإعجابات): ",
|
"Engagement: ": "نسبة المشاركة: ",
|
||||||
"Whitelisted regions: ": "الدول المسموح فيها هذا الفيديو: ",
|
"Whitelisted regions: ": "الدول المسموح فيها هذا الفيديو: ",
|
||||||
"Blacklisted regions: ": "الدول الحظور فيها هذا الفيديو: ",
|
"Blacklisted regions: ": "الدول المحظور فيها هذا الفيديو: ",
|
||||||
"Shared `x`": "شارك منذ `x`",
|
"Shared `x`": "شارك منذ `x`",
|
||||||
"`x` views": "`x` مشاهدات",
|
|
||||||
"Premieres in `x`": "يعرض فى `x`",
|
"Premieres in `x`": "يعرض فى `x`",
|
||||||
"Premieres `x`": "يعرض `x`",
|
"Premieres `x`": "يعرض `x`",
|
||||||
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "اهلا! يبدو ان الجافاسكريبت معطلة. اضغط هنا لعرض التعليقات, ضع فى إعتبارك انها ستأخذ وقت اطول للعرض.",
|
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "أهلًا! يبدو أن جافاسكريبت معطلٌ لديك. اضغط هنا لعرض التعليقات، وَضَع في اعتبارك أنها ستأخذ وقتًا أطول للتحميل.",
|
||||||
"View YouTube comments": "عرض تعليقات اليوتيوب",
|
"View YouTube comments": "عرض تعليقات اليوتيوب",
|
||||||
"View more comments on Reddit": "عرض المزيد من التعليقات على\\من موقع Reddit",
|
"View more comments on Reddit": "عرض المزيد من التعليقات على\\من موقع Reddit",
|
||||||
"View `x` comments": "عرض `x` تعليقات",
|
"View `x` comments": {
|
||||||
|
"([^.,0-9]|^)1([^.,0-9]|$)": "عرض `x` تعليقات",
|
||||||
|
"": "عرض `x` تعليقات"
|
||||||
|
},
|
||||||
"View Reddit comments": "عرض تعليقات ريدإت Reddit",
|
"View Reddit comments": "عرض تعليقات ريدإت Reddit",
|
||||||
"Hide replies": "إخفاء الردود",
|
"Hide replies": "إخفاء الردود",
|
||||||
"Show replies": "عرض الردود",
|
"Show replies": "عرض الردود",
|
||||||
"Incorrect password": "الرقم السرى غير صحيح",
|
"Incorrect password": "كلمة السر غير صحيحة",
|
||||||
"Quota exceeded, try again in a few hours": "تم تجاوز عدد المرات المسموح بها, حاول مرة اخرى بعد عدة ساعات",
|
"Quota exceeded, try again in a few hours": "تم تجاوز عدد المرات المسموح بها، حاول مجددًا بعد بضع ساعات",
|
||||||
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "غير قادر على تسجيل الدخول, تأكد من تشغيل المصادقة الثنائية 2FA.",
|
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "غير قادر على تسجيل الدخول، تأكد من تشغيل المصادقة الثنائية 2FA.",
|
||||||
"Invalid TFA code": "كود مصادقة ثنائية 2FA غير صحيح",
|
"Invalid TFA code": "كود مصادقة ثنائية 2FA غير صحيح",
|
||||||
"Login failed. This may be because two-factor authentication is not turned on for your account.": "لم يتم تسجيل الدخول. هذا ربما بسبب ان المصادقة الثنائية 2FA معطلة فى حسابك.",
|
"Login failed. This may be because two-factor authentication is not turned on for your account.": "فشل تسجيل الدخول. قد يكون هذا بسبب أن المصادقة الثنائية 2FA معطلة في حسابك.",
|
||||||
"Wrong answer": "إجابة خاطئة",
|
"Wrong answer": "إجابة خاطئة",
|
||||||
"Erroneous CAPTCHA": "الكابتشا CAPTCHA غير صاحلة",
|
"Erroneous CAPTCHA": "الكابتشا CAPTCHA غير صاحلة",
|
||||||
"CAPTCHA is a required field": "مكان الكابتشا CAPTCHA مطلوب",
|
"CAPTCHA is a required field": "مكان الكابتشا CAPTCHA مطلوب",
|
||||||
"User ID is a required field": "مكان إسم المستخدم مطلوب",
|
"User ID is a required field": "مكان اسم المستخدم مطلوب",
|
||||||
"Password is a required field": "مكان الرقم السرى مطلوب",
|
"Password is a required field": "مكان كلمة السر مطلوب",
|
||||||
"Wrong username or password": "إسم المستخدم او الرقم السرى غير صحيح",
|
"Wrong username or password": "اسم المستخدم او كلمة السر غير صحيح",
|
||||||
"Please sign in using 'Log in with Google'": "الرجاء تسجيل الدخول 'تسجيل الدخول بواسطة جوجل'",
|
"Please sign in using 'Log in with Google'": "الرجاء تسجيل الدخول باستخدام \"تسجيل الدخول باستخدام Google\"",
|
||||||
"Password cannot be empty": "الرقم السرى لايمكن ان يكون فارغ",
|
"Password cannot be empty": "لا يمكن أن تكون كلمة السر فارغة",
|
||||||
"Password cannot be longer than 55 characters": "الرقم السرى لا يتعدى 55 حرف",
|
"Password cannot be longer than 55 characters": "يجب أن لا تتعدى كلمة السر 55 حرفًا",
|
||||||
"Please log in": "الرجاء تسجيل الدخول",
|
"Please log in": "الرجاء تسجيل الدخول",
|
||||||
"Invidious Private Feed for `x`": "صفحة Invidious للمشتركين الخاصة\\مخفية لـ `x`",
|
"Invidious Private Feed for `x`": "تغذية Invidious خاصة ل 'x'",
|
||||||
"channel:`x`": "قناة:`x`",
|
"channel:`x`": "قناة:`x`",
|
||||||
"Deleted or invalid channel": "قناة ممسوحة او غير صالحة",
|
"Deleted or invalid channel": "قناة ممسوحة او غير صالحة",
|
||||||
"This channel does not exist.": "القناة غير موجودة.",
|
"This channel does not exist.": "هذه القناة غير موجودة.",
|
||||||
"Could not get channel info.": "لم يستطع الحصول على معلومات القناة.",
|
"Could not get channel info.": "لم يستطع الحصول على معلومات القناة.",
|
||||||
"Could not fetch comments": "لم يتمكن من إحضار التعليقات",
|
"Could not fetch comments": "لم يتمكن من إحضار التعليقات",
|
||||||
"View `x` replies": "عرض `x` ردود",
|
|
||||||
"`x` ago": "`x` منذ",
|
"`x` ago": "`x` منذ",
|
||||||
"Load more": "عرض المزيد",
|
"Load more": "عرض المزيد",
|
||||||
"`x` points": "`x` نقاط",
|
"Could not create mix.": "تعذر إنشاء مزيج.",
|
||||||
"Could not create mix.": "لم يستطع عمل خلط.",
|
|
||||||
"Empty playlist": "قائمة التشغيل فارغة",
|
"Empty playlist": "قائمة التشغيل فارغة",
|
||||||
"Not a playlist.": "قائمة التشغيل غير صالحة.",
|
"Not a playlist.": "قائمة التشغيل غير صالحة.",
|
||||||
"Playlist does not exist.": "قائمة التشغيل غير موجودة.",
|
"Playlist does not exist.": "قائمة التشغيل غير موجودة.",
|
||||||
"Could not pull trending pages.": "لم يستطع عرض الصفحات الراجئة.",
|
"Could not pull trending pages.": "لم يستطع عرض الصفحات الراجئة.",
|
||||||
"Hidden field \"challenge\" is a required field": "مكان مخفى \"تحدى\" مكان مطلوب",
|
"Hidden field \"challenge\" is a required field": "مكان مخفي \"تحدي\" مكان مطلوب",
|
||||||
"Hidden field \"token\" is a required field": "مكان مخفى \"رمز\" مكان مطلوب",
|
"Hidden field \"token\" is a required field": "مكان مخفي \"رمز\" مكان مطلوب",
|
||||||
"Erroneous challenge": "تحدى غير صالح",
|
"Erroneous challenge": "تحدي غير صالح",
|
||||||
"Erroneous token": "روز غير صالح",
|
"Erroneous token": "رمز مميز خاطئ",
|
||||||
"No such user": "مستخدم غير صالح",
|
"No such user": "مستخدم غير صالح",
|
||||||
"Token is expired, please try again": "الرمز منتهى الصلاحية , الرجاء المحاولة مرة اخرى",
|
"Token is expired, please try again": "الرمز منتهى الصلاحية، الرجاء المحاولة مرة اخرى",
|
||||||
"English": "إنجليزى",
|
"English": "إنجليزي",
|
||||||
"English (auto-generated)": "إنجليزى (تم إنشائة تلقائى)",
|
"English (auto-generated)": "إنجليزي (تم إنشائه تلقائيًا)",
|
||||||
"Afrikaans": "الأفريكانية",
|
"Afrikaans": "الأفريكانية",
|
||||||
"Albanian": "الألبانية",
|
"Albanian": "الألبانية",
|
||||||
"Amharic": "الأمهرية",
|
"Amharic": "الأمهرية",
|
||||||
"Arabic": "العربية",
|
"Arabic": "العربية",
|
||||||
"Armenian": "الأرميني",
|
"Armenian": "الأرمينية",
|
||||||
"Azerbaijani": "أذربيجان",
|
"Azerbaijani": "أذربيجانية",
|
||||||
"Bangla": "البنغالية",
|
"Bangla": "البنغالية",
|
||||||
"Basque": "الباسكي",
|
"Basque": "الباسكية",
|
||||||
"Belarusian": "البيلاروسية",
|
"Belarusian": "البيلاروسية",
|
||||||
"Bosnian": "البوسنية",
|
"Bosnian": "البوسنية",
|
||||||
"Bulgarian": "البلغارية",
|
"Bulgarian": "البلغارية",
|
||||||
@@ -301,19 +303,13 @@
|
|||||||
"Yiddish": "اليديشية",
|
"Yiddish": "اليديشية",
|
||||||
"Yoruba": "اليوروبا",
|
"Yoruba": "اليوروبا",
|
||||||
"Zulu": "الزولو",
|
"Zulu": "الزولو",
|
||||||
"`x` years": "`x` سنوات",
|
|
||||||
"`x` months": "`x` شهور",
|
|
||||||
"`x` weeks": "`x` اسابيع",
|
|
||||||
"`x` days": "`x` ايام",
|
|
||||||
"`x` hours": "`x` ساعات",
|
|
||||||
"`x` minutes": "`x` دقائق",
|
|
||||||
"`x` seconds": "`x` ثوانى",
|
|
||||||
"Fallback comments: ": "التعليقات البديلة: ",
|
"Fallback comments: ": "التعليقات البديلة: ",
|
||||||
"Popular": "الأكثر شعبية",
|
"Popular": "الأكثر شعبية",
|
||||||
|
"Search": "بحث",
|
||||||
"Top": "الأفضل",
|
"Top": "الأفضل",
|
||||||
"About": "حول",
|
"About": "حول",
|
||||||
"Rating: ": "التقييم: ",
|
"Rating: ": "التقييم: ",
|
||||||
"Language: ": "اللغة: ",
|
"preferences_locale_label": "اللغة: ",
|
||||||
"View as playlist": "عرض كا قائمة التشغيل",
|
"View as playlist": "عرض كا قائمة التشغيل",
|
||||||
"Default": "الكل",
|
"Default": "الكل",
|
||||||
"Music": "الاغانى",
|
"Music": "الاغانى",
|
||||||
@@ -321,16 +317,223 @@
|
|||||||
"News": "الأخبار",
|
"News": "الأخبار",
|
||||||
"Movies": "الأفلام",
|
"Movies": "الأفلام",
|
||||||
"Download": "نزّل",
|
"Download": "نزّل",
|
||||||
"Download as: ": "نزّله كـ: ",
|
"Download as: ": "نزله كـ: ",
|
||||||
"%A %B %-d, %Y": "%A %-d %B %Y",
|
"%A %B %-d, %Y": "%A %-d %B %Y",
|
||||||
"(edited)": "(تم تعديلة)",
|
"(edited)": "(معدّل)",
|
||||||
"YouTube comment permalink": "رابط التعليق على اليوتيوب",
|
"YouTube comment permalink": "رابط التعليق على اليوتيوب",
|
||||||
"permalink": "الرابط",
|
"permalink": "الرابط",
|
||||||
"`x` marked it with a ❤": "`x` اعجب بهذا",
|
"`x` marked it with a ❤": "`x` أعجب بهذا",
|
||||||
"Audio mode": "الوضع الصوتى",
|
"Audio mode": "الوضع الصوتي",
|
||||||
"Video mode": "وضع الفيديو",
|
"Video mode": "وضع الفيديو",
|
||||||
"Videos": "الفيديوهات",
|
"Videos": "الفيديوهات",
|
||||||
"Playlists": "قوائم التشغيل",
|
"Playlists": "قوائم التشغيل",
|
||||||
"Community": "المجتمع",
|
"Community": "المجتمع",
|
||||||
"Current version: ": "الإصدار الحالي: "
|
"search_filters_sort_option_relevance": "ملاؤم",
|
||||||
|
"search_filters_sort_option_rating": "تقييم",
|
||||||
|
"search_filters_sort_option_date": "التاريخ",
|
||||||
|
"search_filters_sort_option_views": "مشاهدات",
|
||||||
|
"search_filters_type_label": "نوع المحتوى",
|
||||||
|
"search_filters_duration_label": "المدة الزمنية",
|
||||||
|
"search_filters_features_label": "الميزات",
|
||||||
|
"search_filters_sort_label": "فرز",
|
||||||
|
"search_filters_date_option_hour": "آخر ساعة",
|
||||||
|
"search_filters_date_option_today": "اليوم",
|
||||||
|
"search_filters_date_option_week": "هذا الأسبوع",
|
||||||
|
"search_filters_date_option_month": "هذا الشهر",
|
||||||
|
"search_filters_date_option_year": "هذه السنة",
|
||||||
|
"search_filters_type_option_video": "فيديو",
|
||||||
|
"search_filters_type_option_channel": "قناة",
|
||||||
|
"search_filters_type_option_playlist": "قائمة التشغيل",
|
||||||
|
"search_filters_type_option_movie": "فيلم",
|
||||||
|
"search_filters_type_option_show": "عرض",
|
||||||
|
"search_filters_features_option_hd": "عالية الدقة",
|
||||||
|
"search_filters_features_option_subtitles": "ترجمات",
|
||||||
|
"search_filters_features_option_c_commons": "المشاع الإبداعي",
|
||||||
|
"search_filters_features_option_three_d": "ثلاثي الأبعاد",
|
||||||
|
"search_filters_features_option_live": "مباشر",
|
||||||
|
"search_filters_features_option_four_k": "4k",
|
||||||
|
"search_filters_features_option_location": "الأماكن",
|
||||||
|
"search_filters_features_option_hdr": "وضع التباين العالي",
|
||||||
|
"Current version: ": "الإصدار الحالي: ",
|
||||||
|
"next_steps_error_message": "بعد ذلك يجب أن تحاول: ",
|
||||||
|
"next_steps_error_message_refresh": "تحديث",
|
||||||
|
"next_steps_error_message_go_to_youtube": "انتقل إلى يوتيوب",
|
||||||
|
"search_filters_duration_option_short": "قصير (< 4 دقائق)",
|
||||||
|
"search_filters_duration_option_long": "طويل (> 20 دقيقة)",
|
||||||
|
"footer_source_code": "شفرة المصدر",
|
||||||
|
"footer_original_source_code": "كود المصدر الأصلي",
|
||||||
|
"footer_modfied_source_code": "شفرة المصدر المعدلة",
|
||||||
|
"adminprefs_modified_source_code_url_label": "URL إلى مستودع التعليمات البرمجية المصدرية المعدلة",
|
||||||
|
"footer_documentation": "التوثيق",
|
||||||
|
"footer_donate_page": "تبرّع",
|
||||||
|
"preferences_region_label": "بلد المحتوى: ",
|
||||||
|
"preferences_quality_dash_label": "جودة فيديو DASH المفضلة: ",
|
||||||
|
"preferences_quality_option_dash": "DASH (الجودة التلقائية)",
|
||||||
|
"preferences_quality_option_hd720": "HD720",
|
||||||
|
"preferences_quality_option_medium": "متوسطة",
|
||||||
|
"preferences_quality_option_small": "صغيرة",
|
||||||
|
"preferences_quality_dash_option_auto": "تلقائي",
|
||||||
|
"preferences_quality_dash_option_best": "الأفضل",
|
||||||
|
"preferences_quality_dash_option_worst": "أسوأ",
|
||||||
|
"preferences_quality_dash_option_4320p": "4320p",
|
||||||
|
"preferences_quality_dash_option_2160p": "2160p",
|
||||||
|
"preferences_quality_dash_option_1440p": "1440p",
|
||||||
|
"preferences_quality_dash_option_1080p": "1080p",
|
||||||
|
"preferences_quality_dash_option_720p": "720p",
|
||||||
|
"preferences_quality_dash_option_480p": "480p",
|
||||||
|
"preferences_quality_dash_option_360p": "360p",
|
||||||
|
"preferences_quality_dash_option_240p": "240p",
|
||||||
|
"preferences_quality_dash_option_144p": "144p",
|
||||||
|
"search_filters_features_option_purchased": "تم شراؤها",
|
||||||
|
"none": "لاشيء",
|
||||||
|
"videoinfo_started_streaming_x_ago": "بدأ البث منذ `x`",
|
||||||
|
"videoinfo_watch_on_youTube": "مشاهدة على يوتيوب",
|
||||||
|
"videoinfo_youTube_embed_link": "مضمن",
|
||||||
|
"videoinfo_invidious_embed_link": "رابط مضمن",
|
||||||
|
"user_created_playlists": "'x' إنشاء قوائم التشغيل",
|
||||||
|
"user_saved_playlists": "قوائم التشغيل المحفوظة 'x'",
|
||||||
|
"Video unavailable": "الفيديو غير متوفر",
|
||||||
|
"search_filters_features_option_three_sixty": "360°",
|
||||||
|
"download_subtitles": "ترجمات - 'x' (.vtt)",
|
||||||
|
"invidious": "الخيالي",
|
||||||
|
"preferences_save_player_pos_label": "حفظ موضع التشغيل: ",
|
||||||
|
"crash_page_you_found_a_bug": "يبدو أنك قد وجدت خطأً برمجيًّا في Invidious!",
|
||||||
|
"generic_videos_count_0": "لا فيديوهات",
|
||||||
|
"generic_videos_count_1": "فيديو واحد",
|
||||||
|
"generic_videos_count_2": "فيديوهين",
|
||||||
|
"generic_videos_count_3": "{{count}} فيديوهات",
|
||||||
|
"generic_videos_count_4": "{{count}} فيديو",
|
||||||
|
"generic_videos_count_5": "{{count}} فيديو",
|
||||||
|
"generic_subscribers_count_0": "لا مشتركين",
|
||||||
|
"generic_subscribers_count_1": "مشترك واحد",
|
||||||
|
"generic_subscribers_count_2": "مشتركان",
|
||||||
|
"generic_subscribers_count_3": "{{count}} مشتركين",
|
||||||
|
"generic_subscribers_count_4": "{{count}} مشترك",
|
||||||
|
"generic_subscribers_count_5": "{{count}} مشترك",
|
||||||
|
"generic_views_count_0": "لا مشاهدات",
|
||||||
|
"generic_views_count_1": "مشاهدة واحدة",
|
||||||
|
"generic_views_count_2": "مشاهدتان",
|
||||||
|
"generic_views_count_3": "{{count}} مشاهدات",
|
||||||
|
"generic_views_count_4": "{{count}} مشاهدة",
|
||||||
|
"generic_views_count_5": "{{count}} مشاهدة",
|
||||||
|
"generic_subscriptions_count_0": "لا اشتراكات",
|
||||||
|
"generic_subscriptions_count_1": "اشتراك واحد",
|
||||||
|
"generic_subscriptions_count_2": "اشتراكان",
|
||||||
|
"generic_subscriptions_count_3": "{{count}} اشتراكات",
|
||||||
|
"generic_subscriptions_count_4": "{{count}} اشتراك",
|
||||||
|
"generic_subscriptions_count_5": "{{count}} اشتراك",
|
||||||
|
"generic_playlists_count_0": "لا قوائم تشغيل",
|
||||||
|
"generic_playlists_count_1": "قائمة تشغيل واحدة",
|
||||||
|
"generic_playlists_count_2": "قائمتا تشغيل",
|
||||||
|
"generic_playlists_count_3": "{{count}} قوائم تشغيل",
|
||||||
|
"generic_playlists_count_4": "{{count}} قائمة تشغيل",
|
||||||
|
"generic_playlists_count_5": "{{count}} قائمة تشغيل",
|
||||||
|
"English (United States)": "الإنجليزية (الولايات المتحدة)",
|
||||||
|
"Indonesian (auto-generated)": "إندونيسي (مُنشأ تلقائيًا)",
|
||||||
|
"Interlingue": "إنترلينغوي",
|
||||||
|
"Italian (auto-generated)": "الإيطالية (مُنشأة تلقائيًا)",
|
||||||
|
"Spanish (auto-generated)": "الأسبانية (تم إنشاؤه تلقائيًا)",
|
||||||
|
"crash_page_before_reporting": "قبل الإبلاغ عن خطأ، تأكد من وجود:",
|
||||||
|
"French (auto-generated)": "الفرنسية (مُنشأة تلقائيًا)",
|
||||||
|
"Portuguese (auto-generated)": "البرتغالية (تم إنشاؤه تلقائيًا)",
|
||||||
|
"Turkish (auto-generated)": "التركية (تم إنشاؤها تلقائيًا)",
|
||||||
|
"crash_page_refresh": "حاول <a href=\"`x`\"> تحديث الصفحة </a>",
|
||||||
|
"crash_page_switch_instance": "حاول <a href=\"`x`\"> استخدام مثيل آخر </a>",
|
||||||
|
"Korean (auto-generated)": "كوري (تم إنشاؤه تلقائيًا)",
|
||||||
|
"Spanish (Mexico)": "الإسبانية (المكسيك)",
|
||||||
|
"Vietnamese (auto-generated)": "فيتنامي (تم إنشاؤه تلقائيًا)",
|
||||||
|
"crash_page_report_issue": "إذا لم يساعد أي مما سبق، يرجى فتح <a href=\"`x`\"> مشكلة جديدة على GitHub </a> (ويفضل أن يكون باللغة الإنجليزية) وتضمين النص التالي في رسالتك (لا تترجم هذا النص):",
|
||||||
|
"crash_page_read_the_faq": "قراءة <a href=\"`x`\"> الأسئلة المتكررة (الأسئلة الشائعة) </a>",
|
||||||
|
"preferences_watch_history_label": "تمكين سجل المشاهدة: ",
|
||||||
|
"English (United Kingdom)": "الإنجليزية (المملكة المتحدة)",
|
||||||
|
"Cantonese (Hong Kong)": "الكانتونية (هونغ كونغ)",
|
||||||
|
"Chinese": "الصينية",
|
||||||
|
"Chinese (China)": "الصينية (الصين)",
|
||||||
|
"Chinese (Hong Kong)": "الصينية (هونج كونج)",
|
||||||
|
"Chinese (Taiwan)": "الصينية (تايوان)",
|
||||||
|
"Dutch (auto-generated)": "هولندي (تم إنشاؤه تلقائيًا)",
|
||||||
|
"German (auto-generated)": "ألماني (تم إنشاؤه تلقائيًا)",
|
||||||
|
"Japanese (auto-generated)": "اليابانية (مُنشأة تلقائيًا)",
|
||||||
|
"Portuguese (Brazil)": "البرتغالية (البرازيل)",
|
||||||
|
"Russian (auto-generated)": "الروسية (منشأة تلقائيا)",
|
||||||
|
"Spanish (Spain)": "الإسبانية (إسبانيا)",
|
||||||
|
"crash_page_search_issue": "بحثت عن <a href=\"`x`\"> المشكلات الموجودة على GitHub </a>",
|
||||||
|
"search_filters_title": "معامل الفرز",
|
||||||
|
"search_message_no_results": "لا توجد نتائج.",
|
||||||
|
"search_message_change_filters_or_query": "حاول توسيع استعلام البحث و / أو تغيير عوامل التصفية.",
|
||||||
|
"search_filters_date_label": "تاريخ الرفع",
|
||||||
|
"generic_count_weeks_0": "{{count}} أسبوع",
|
||||||
|
"generic_count_weeks_1": "{{count}} أسبوع",
|
||||||
|
"generic_count_weeks_2": "{{count}} أسبوع",
|
||||||
|
"generic_count_weeks_3": "{{count}} أسبوع",
|
||||||
|
"generic_count_weeks_4": "{{count}} أسابيع",
|
||||||
|
"generic_count_weeks_5": "{{count}} أسبوع",
|
||||||
|
"Popular enabled: ": "تم تمكين الشعبية: ",
|
||||||
|
"search_filters_duration_option_medium": "متوسط (4-20 دقيقة)",
|
||||||
|
"search_filters_date_option_none": "أي تاريخ",
|
||||||
|
"search_filters_type_option_all": "أي نوع",
|
||||||
|
"search_filters_features_option_vr180": "VR180",
|
||||||
|
"generic_count_minutes_0": "{{count}} دقيقة",
|
||||||
|
"generic_count_minutes_1": "{{count}} دقيقة",
|
||||||
|
"generic_count_minutes_2": "{{count}} دقيقة",
|
||||||
|
"generic_count_minutes_3": "{{count}} دقيقة",
|
||||||
|
"generic_count_minutes_4": "{{count}} دقائق",
|
||||||
|
"generic_count_minutes_5": "{{count}} دقيقة",
|
||||||
|
"generic_count_hours_0": "{{count}} ساعة",
|
||||||
|
"generic_count_hours_1": "{{count}} ساعة",
|
||||||
|
"generic_count_hours_2": "{{count}} ساعة",
|
||||||
|
"generic_count_hours_3": "{{count}} ساعة",
|
||||||
|
"generic_count_hours_4": "{{count}} ساعات",
|
||||||
|
"generic_count_hours_5": "{{count}} ساعة",
|
||||||
|
"comments_view_x_replies_0": "عرض رد {{count}}",
|
||||||
|
"comments_view_x_replies_1": "عرض رد {{count}}",
|
||||||
|
"comments_view_x_replies_2": "عرض رد {{count}}",
|
||||||
|
"comments_view_x_replies_3": "عرض رد {{count}}",
|
||||||
|
"comments_view_x_replies_4": "عرض الردود {{count}}",
|
||||||
|
"comments_view_x_replies_5": "عرض رد {{count}}",
|
||||||
|
"search_message_use_another_instance": " يمكنك أيضًا البحث عن <a href=\"`x`\"> في مثيل آخر </a>.",
|
||||||
|
"comments_points_count_0": "{{count}} نقطة",
|
||||||
|
"comments_points_count_1": "{{count}} نقطة",
|
||||||
|
"comments_points_count_2": "{{count}} نقطة",
|
||||||
|
"comments_points_count_3": "{{count}} نقطة",
|
||||||
|
"comments_points_count_4": "{{count}} نقاط",
|
||||||
|
"comments_points_count_5": "{{count}} نقطة",
|
||||||
|
"generic_count_years_0": "{{count}} السنة",
|
||||||
|
"generic_count_years_1": "{{count}} السنة",
|
||||||
|
"generic_count_years_2": "{{count}} السنة",
|
||||||
|
"generic_count_years_3": "{{count}} السنة",
|
||||||
|
"generic_count_years_4": "{{count}} سنوات",
|
||||||
|
"generic_count_years_5": "{{count}} السنة",
|
||||||
|
"tokens_count_0": "الرمز المميز {{count}}",
|
||||||
|
"tokens_count_1": "الرمز المميز {{count}}",
|
||||||
|
"tokens_count_2": "الرمز المميز {{count}}",
|
||||||
|
"tokens_count_3": "الرمز المميز {{count}}",
|
||||||
|
"tokens_count_4": "الرموز المميزة {{count}}",
|
||||||
|
"tokens_count_5": "الرمز المميز {{count}}",
|
||||||
|
"search_filters_apply_button": "تطبيق الفلاتر المحددة",
|
||||||
|
"search_filters_duration_option_none": "أي مدة",
|
||||||
|
"subscriptions_unseen_notifs_count_0": "{{count}} إشعار غير مرئي",
|
||||||
|
"subscriptions_unseen_notifs_count_1": "{{count}} إشعار غير مرئي",
|
||||||
|
"subscriptions_unseen_notifs_count_2": "{{count}} إشعار غير مرئي",
|
||||||
|
"subscriptions_unseen_notifs_count_3": "{{count}} إشعار غير مرئي",
|
||||||
|
"subscriptions_unseen_notifs_count_4": "{{count}} إشعارات غير مرئية",
|
||||||
|
"subscriptions_unseen_notifs_count_5": "{{count}} إشعار غير مرئي",
|
||||||
|
"generic_count_days_0": "{{count}} يوم",
|
||||||
|
"generic_count_days_1": "{{count}} يوم",
|
||||||
|
"generic_count_days_2": "{{count}} يوم",
|
||||||
|
"generic_count_days_3": "{{count}} يوم",
|
||||||
|
"generic_count_days_4": "{{count}} أيام",
|
||||||
|
"generic_count_days_5": "{{count}} يوم",
|
||||||
|
"generic_count_months_0": "{{count}} شهر",
|
||||||
|
"generic_count_months_1": "{{count}} شهر",
|
||||||
|
"generic_count_months_2": "{{count}} شهر",
|
||||||
|
"generic_count_months_3": "{{count}} شهر",
|
||||||
|
"generic_count_months_4": "{{count}} شهور",
|
||||||
|
"generic_count_months_5": "{{count}} شهر",
|
||||||
|
"generic_count_seconds_0": "{{count}} ثانية",
|
||||||
|
"generic_count_seconds_1": "{{count}} ثانية",
|
||||||
|
"generic_count_seconds_2": "{{count}} ثانية",
|
||||||
|
"generic_count_seconds_3": "{{count}} ثانية",
|
||||||
|
"generic_count_seconds_4": "{{count}} ثوانٍ",
|
||||||
|
"generic_count_seconds_5": "{{count}} ثانية"
|
||||||
}
|
}
|
||||||
|
|||||||
97
locales/bn.json
Normal file
97
locales/bn.json
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
{
|
||||||
|
"Subscribe": "সাবস্ক্রাইব",
|
||||||
|
"View channel on YouTube": "ইউটিউবে চ্যানেল দেখুন",
|
||||||
|
"View playlist on YouTube": "ইউটিউবে প্লেলিস্ট দেখুন",
|
||||||
|
"newest": "সর্ব-নতুন",
|
||||||
|
"oldest": "পুরানতম",
|
||||||
|
"popular": "জনপ্রিয়",
|
||||||
|
"last": "শেষটা",
|
||||||
|
"Next page": "পরের পৃষ্ঠা",
|
||||||
|
"Previous page": "আগের পৃষ্ঠা",
|
||||||
|
"Clear watch history?": "দেখার ইতিহাস সাফ করবেন?",
|
||||||
|
"New password": "নতুন পাসওয়ার্ড",
|
||||||
|
"New passwords must match": "নতুন পাসওয়ার্ড অবশ্যই মিলতে হবে",
|
||||||
|
"Cannot change password for Google accounts": "গুগল অ্যাকাউন্টগুলোর জন্য পাসওয়ার্ড পরিবর্তন করা যায় না",
|
||||||
|
"Authorize token?": "টোকেন অনুমোদন করবেন?",
|
||||||
|
"Authorize token for `x`?": "`x` -এর জন্য টোকেন অনুমোদন?",
|
||||||
|
"Yes": "হ্যাঁ",
|
||||||
|
"No": "না",
|
||||||
|
"Import and Export Data": "তথ্য আমদানি ও রপ্তানি",
|
||||||
|
"Import": "আমদানি",
|
||||||
|
"Import Invidious data": "ইনভিডিয়াস তথ্য আমদানি",
|
||||||
|
"Import YouTube subscriptions": "ইউটিউব সাবস্ক্রিপশন আনুন",
|
||||||
|
"Import FreeTube subscriptions (.db)": "ফ্রিটিউব সাবস্ক্রিপশন (.db) আনুন",
|
||||||
|
"Import NewPipe subscriptions (.json)": "নতুন পাইপ সাবস্ক্রিপশন আনুন (.json)",
|
||||||
|
"Import NewPipe data (.zip)": "নিউপাইপ তথ্য আনুন (.zip)",
|
||||||
|
"Export": "তথ্য বের করুন",
|
||||||
|
"Export subscriptions as OPML": "সাবস্ক্রিপশন OPML হিসাবে আনুন",
|
||||||
|
"Export subscriptions as OPML (for NewPipe & FreeTube)": "OPML-এ সাবস্ক্রিপশন বের করুন(নিউ পাইপ এবং ফ্রিউটিউব এর জন্য)",
|
||||||
|
"Export data as JSON": "JSON হিসাবে তথ্য বের করুন",
|
||||||
|
"Delete account?": "অ্যাকাউন্ট মুছে ফেলবেন?",
|
||||||
|
"History": "ইতিহাস",
|
||||||
|
"An alternative front-end to YouTube": "ইউটিউবের একটি বিকল্পস্বরূপ সম্মুখ-প্রান্ত",
|
||||||
|
"JavaScript license information": "জাভাস্ক্রিপ্ট লাইসেন্সের তথ্য",
|
||||||
|
"source": "সূত্র",
|
||||||
|
"Log in": "লগ ইন",
|
||||||
|
"Log in/register": "লগ ইন/রেজিস্টার",
|
||||||
|
"Log in with Google": "গুগল দিয়ে লগ ইন করুন",
|
||||||
|
"User ID": "ইউজার আইডি",
|
||||||
|
"Password": "পাসওয়ার্ড",
|
||||||
|
"Time (h:mm:ss):": "সময় (ঘণ্টা:মিনিট:সেকেন্ড):",
|
||||||
|
"Text CAPTCHA": "টেক্সট ক্যাপচা",
|
||||||
|
"Image CAPTCHA": "চিত্র ক্যাপচা",
|
||||||
|
"Sign In": "সাইন ইন",
|
||||||
|
"Register": "নিবন্ধন",
|
||||||
|
"E-mail": "ই-মেইল",
|
||||||
|
"Google verification code": "গুগল যাচাইকরণ কোড",
|
||||||
|
"Preferences": "পছন্দসমূহ",
|
||||||
|
"preferences_category_player": "প্লেয়ারের পছন্দসমূহ",
|
||||||
|
"preferences_video_loop_label": "সর্বদা লুপ: ",
|
||||||
|
"preferences_autoplay_label": "স্বয়ংক্রিয় চালু: ",
|
||||||
|
"preferences_continue_label": "ডিফল্টভাবে পরবর্তী চালাও: ",
|
||||||
|
"preferences_continue_autoplay_label": "পরবর্তী ভিডিও স্বয়ংক্রিয়ভাবে চালাও: ",
|
||||||
|
"preferences_listen_label": "সহজাতভাবে শোনো: ",
|
||||||
|
"preferences_local_label": "ভিডিও প্রক্সি করো: ",
|
||||||
|
"preferences_speed_label": "সহজাত গতি: ",
|
||||||
|
"preferences_quality_label": "পছন্দের ভিডিও মান: ",
|
||||||
|
"preferences_volume_label": "প্লেয়ার শব্দের মাত্রা: ",
|
||||||
|
"LIVE": "লাইভ",
|
||||||
|
"Shared `x` ago": "`x` আগে শেয়ার করা হয়েছে",
|
||||||
|
"Unsubscribe": "আনসাবস্ক্রাইব",
|
||||||
|
"generic_views_count": "{{count}}জন দেখেছে",
|
||||||
|
"generic_views_count_plural": "{{count}}জন দেখেছে",
|
||||||
|
"generic_videos_count": "{{count}}টি ভিডিও",
|
||||||
|
"generic_videos_count_plural": "{{count}}টি ভিডিও",
|
||||||
|
"generic_subscribers_count": "{{count}}জন অনুসরণকারী",
|
||||||
|
"generic_subscribers_count_plural": "{{count}}জন অনুসরণকারী",
|
||||||
|
"preferences_watch_history_label": "দেখার ইতিহাস চালু করো: ",
|
||||||
|
"preferences_quality_option_dash": "ড্যাশ (সময়োপযোগী মান)",
|
||||||
|
"preferences_quality_dash_option_auto": "স্বয়ংক্রিয়",
|
||||||
|
"preferences_quality_dash_option_best": "সেরা",
|
||||||
|
"preferences_quality_dash_option_worst": "মন্দতম",
|
||||||
|
"preferences_quality_dash_option_4320p": "৪৩২০পি",
|
||||||
|
"preferences_quality_dash_option_2160p": "২১৬০পি",
|
||||||
|
"preferences_quality_dash_option_1440p": "১৪৪০পি",
|
||||||
|
"preferences_quality_dash_option_480p": "৪৮০পি",
|
||||||
|
"preferences_quality_dash_option_360p": "৩৬০পি",
|
||||||
|
"preferences_quality_dash_option_240p": "২৪০পি",
|
||||||
|
"preferences_quality_dash_option_144p": "১৪৪পি",
|
||||||
|
"preferences_comments_label": "সহজাত মন্তব্য: ",
|
||||||
|
"youtube": "ইউটিউব",
|
||||||
|
"Fallback captions: ": "বিকল্প উপাখ্যান: ",
|
||||||
|
"preferences_related_videos_label": "সম্পর্কিত ভিডিও দেখাও: ",
|
||||||
|
"preferences_annotations_label": "সহজাতভাবে টীকা দেখাও ",
|
||||||
|
"preferences_quality_option_hd720": "উচ্চ৭২০",
|
||||||
|
"preferences_quality_dash_label": "পছন্দের ড্যাশ ভিডিও মান: ",
|
||||||
|
"preferences_captions_label": "সহজাত উপাখ্যান: ",
|
||||||
|
"generic_playlists_count": "{{count}}টি চালুতালিকা",
|
||||||
|
"generic_playlists_count_plural": "{{count}}টি চালুতালিকা",
|
||||||
|
"reddit": "রেডিট",
|
||||||
|
"invidious": "ইনভিডিয়াস",
|
||||||
|
"generic_subscriptions_count": "{{count}}টি অনুসরণ",
|
||||||
|
"generic_subscriptions_count_plural": "{{count}}টি অনুসরণ",
|
||||||
|
"preferences_quality_option_medium": "মধ্যম",
|
||||||
|
"preferences_quality_option_small": "ছোট",
|
||||||
|
"preferences_quality_dash_option_1080p": "১০৮০পি",
|
||||||
|
"preferences_quality_dash_option_720p": "৭২০পি"
|
||||||
|
}
|
||||||
61
locales/bn_BD.json
Normal file
61
locales/bn_BD.json
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"LIVE": "লাইভ",
|
||||||
|
"Shared `x` ago": "`x` আগে শেয়ার করা হয়েছে",
|
||||||
|
"Unsubscribe": "আনসাবস্ক্রাইব",
|
||||||
|
"Subscribe": "সাবস্ক্রাইব",
|
||||||
|
"View channel on YouTube": "ইউটিউবে চ্যানেল দেখুন",
|
||||||
|
"View playlist on YouTube": "ইউটিউবে প্লেলিস্ট দেখুন",
|
||||||
|
"newest": "সর্ব-নতুন",
|
||||||
|
"oldest": "পুরানতম",
|
||||||
|
"popular": "জনপ্রিয়",
|
||||||
|
"last": "শেষটা",
|
||||||
|
"Next page": "পরের পৃষ্ঠা",
|
||||||
|
"Previous page": "আগের পৃষ্ঠা",
|
||||||
|
"Clear watch history?": "দেখার ইতিহাস সাফ করবেন?",
|
||||||
|
"New password": "নতুন পাসওয়ার্ড",
|
||||||
|
"New passwords must match": "নতুন পাসওয়ার্ড অবশ্যই মিলতে হবে",
|
||||||
|
"Cannot change password for Google accounts": "গুগল অ্যাকাউন্টগুলোর জন্য পাসওয়ার্ড পরিবর্তন করা যায় না",
|
||||||
|
"Authorize token?": "টোকেন অনুমোদন করবেন?",
|
||||||
|
"Authorize token for `x`?": "`x` -এর জন্য টোকেন অনুমোদন?",
|
||||||
|
"Yes": "হ্যাঁ",
|
||||||
|
"No": "না",
|
||||||
|
"Import and Export Data": "তথ্য আমদানি ও রপ্তানি",
|
||||||
|
"Import": "আমদানি",
|
||||||
|
"Import Invidious data": "ইনভিডিয়াস তথ্য আমদানি",
|
||||||
|
"Import YouTube subscriptions": "ইউটিউব সাবস্ক্রিপশন আনুন",
|
||||||
|
"Import FreeTube subscriptions (.db)": "ফ্রিটিউব সাবস্ক্রিপশন (.db) আনুন",
|
||||||
|
"Import NewPipe subscriptions (.json)": "নতুন পাইপ সাবস্ক্রিপশন আনুন (.json)",
|
||||||
|
"Import NewPipe data (.zip)": "নিউপাইপ তথ্য আনুন (.zip)",
|
||||||
|
"Export": "তথ্য বের করুন",
|
||||||
|
"Export subscriptions as OPML": "সাবস্ক্রিপশন OPML হিসাবে আনুন",
|
||||||
|
"Export subscriptions as OPML (for NewPipe & FreeTube)": "OPML-এ সাবস্ক্রিপশন বের করুন(নিউ পাইপ এবং ফ্রিউটিউব এর জন্য)",
|
||||||
|
"Export data as JSON": "JSON হিসাবে তথ্য বের করুন",
|
||||||
|
"Delete account?": "অ্যাকাউন্ট মুছে ফেলবেন?",
|
||||||
|
"History": "ইতিহাস",
|
||||||
|
"An alternative front-end to YouTube": "ইউটিউবের একটি বিকল্পস্বরূপ সম্মুখ-প্রান্ত",
|
||||||
|
"JavaScript license information": "জাভাস্ক্রিপ্ট লাইসেন্সের তথ্য",
|
||||||
|
"source": "সূত্র",
|
||||||
|
"Log in": "লগ ইন",
|
||||||
|
"Log in/register": "লগ ইন/রেজিস্টার",
|
||||||
|
"Log in with Google": "গুগল দিয়ে লগ ইন করুন",
|
||||||
|
"User ID": "ইউজার আইডি",
|
||||||
|
"Password": "পাসওয়ার্ড",
|
||||||
|
"Time (h:mm:ss):": "সময় (ঘণ্টা:মিনিট:সেকেন্ড):",
|
||||||
|
"Text CAPTCHA": "টেক্সট ক্যাপচা",
|
||||||
|
"Image CAPTCHA": "চিত্র ক্যাপচা",
|
||||||
|
"Sign In": "সাইন ইন",
|
||||||
|
"Register": "নিবন্ধন",
|
||||||
|
"E-mail": "ই-মেইল",
|
||||||
|
"Google verification code": "গুগল যাচাইকরণ কোড",
|
||||||
|
"Preferences": "পছন্দসমূহ",
|
||||||
|
"preferences_category_player": "প্লেয়ারের পছন্দসমূহ",
|
||||||
|
"preferences_video_loop_label": "সর্বদা লুপ: ",
|
||||||
|
"preferences_autoplay_label": "স্বয়ংক্রিয় চালু: ",
|
||||||
|
"preferences_continue_label": "ডিফল্টভাবে পরবর্তী চালাও: ",
|
||||||
|
"preferences_continue_autoplay_label": "পরবর্তী ভিডিও স্বয়ংক্রিয়ভাবে চালাও: ",
|
||||||
|
"preferences_listen_label": "সহজাতভাবে শোনো: ",
|
||||||
|
"preferences_local_label": "ভিডিও প্রক্সি করো: ",
|
||||||
|
"preferences_speed_label": "সহজাত গতি: ",
|
||||||
|
"preferences_quality_label": "পছন্দের ভিডিও মান: ",
|
||||||
|
"preferences_volume_label": "প্লেয়ার শব্দের মাত্রা: "
|
||||||
|
}
|
||||||
103
locales/ca.json
Normal file
103
locales/ca.json
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
{
|
||||||
|
"oldest": "més antic",
|
||||||
|
"Yes": "Sí",
|
||||||
|
"preferences_quality_label": "Qualitat de vídeo preferida: ",
|
||||||
|
"newest": "més nou",
|
||||||
|
"No": "No",
|
||||||
|
"Google verification code": "Codi de verificació de Google",
|
||||||
|
"User ID": "ID d'usuari",
|
||||||
|
"Preferences": "Preferències",
|
||||||
|
"Dark mode: ": "Mode fosc: ",
|
||||||
|
"dark": "fosc",
|
||||||
|
"light": "clar",
|
||||||
|
"published": "publicat",
|
||||||
|
"published - reverse": "publicat - invers",
|
||||||
|
"alphabetically": "alfabèticament",
|
||||||
|
"alphabetically - reverse": "alfabèticament - invers",
|
||||||
|
"channel name - reverse": "nom del canal - invers",
|
||||||
|
"preferences_category_data": "Preferències de dades",
|
||||||
|
"Delete account": "Elimina compte",
|
||||||
|
"Save preferences": "Guarda preferències",
|
||||||
|
"Private": "Privat",
|
||||||
|
"Show more": "Mostra'n més",
|
||||||
|
"Show less": "Mostra'n menys",
|
||||||
|
"Hide replies": "Amaga respostes",
|
||||||
|
"Arabic": "Àrab",
|
||||||
|
"Armenian": "Armeni",
|
||||||
|
"Basque": "Basc",
|
||||||
|
"Filipino": "Filipí",
|
||||||
|
"Finnish": "Finès",
|
||||||
|
"German": "Alemany",
|
||||||
|
"Greek": "Grec",
|
||||||
|
"Hungarian": "Hongarès",
|
||||||
|
"Icelandic": "Islandès",
|
||||||
|
"Italian": "Italià",
|
||||||
|
"Japanese": "Japonès",
|
||||||
|
"Korean": "Coreà",
|
||||||
|
"Kurdish": "Kurd",
|
||||||
|
"Lithuanian": "Lituà",
|
||||||
|
"Luxembourgish": "Luxemburguès",
|
||||||
|
"Macedonian": "Macedoni",
|
||||||
|
"Polish": "Polonès",
|
||||||
|
"Portuguese": "Portuguès",
|
||||||
|
"Romanian": "Romanès",
|
||||||
|
"Russian": "Rus",
|
||||||
|
"Serbian": "Serbi",
|
||||||
|
"Spanish (Latin America)": "Castellà (Amèrica llatina)",
|
||||||
|
"Turkish": "Turc",
|
||||||
|
"Ukrainian": "Ucraïnès",
|
||||||
|
"preferences_locale_label": "Idioma: ",
|
||||||
|
"Gaming": "Jocs",
|
||||||
|
"Movies": "Películes",
|
||||||
|
"Download": "Descarrega",
|
||||||
|
"Download as: ": "Descarrega com: ",
|
||||||
|
"Videos": "Vídeos",
|
||||||
|
"search_filters_type_label": "Tipus",
|
||||||
|
"search_filters_duration_label": "Duració",
|
||||||
|
"search_filters_sort_label": "Ordena per",
|
||||||
|
"search_filters_date_option_week": "Aquesta setmana",
|
||||||
|
"search_filters_date_option_month": "Aquest mes",
|
||||||
|
"search_filters_date_option_year": "Aquest any",
|
||||||
|
"search_filters_type_option_video": "Vídeo",
|
||||||
|
"search_filters_type_option_channel": "Canal",
|
||||||
|
"search_filters_duration_option_short": "Curt (< 4 minuts)",
|
||||||
|
"search_filters_duration_option_long": "Llarg (> 20 minuts)",
|
||||||
|
"Current version: ": "Versió actual: ",
|
||||||
|
"Malay": "Malai",
|
||||||
|
"Persian": "Persa",
|
||||||
|
"Slovak": "Eslovac",
|
||||||
|
"Search": "Busca",
|
||||||
|
"Show annotations": "Mostra anotacions",
|
||||||
|
"preferences_region_label": "País del contingut: ",
|
||||||
|
"preferences_sort_label": "Ordena vídeos per: ",
|
||||||
|
"Import/export": "Importa/exporta",
|
||||||
|
"channel name": "nom del canal",
|
||||||
|
"Title": "Títol",
|
||||||
|
"Belarusian": "Bielorús",
|
||||||
|
"Enable web notifications": "Activa notificacions web",
|
||||||
|
"search": "busca",
|
||||||
|
"Catalan": "Català",
|
||||||
|
"Croatian": "Croat",
|
||||||
|
"preferences_category_admin": "Preferències d'administrador",
|
||||||
|
"Hide annotations": "Amaga anotacions",
|
||||||
|
"Show replies": "Mostra respostes",
|
||||||
|
"Bulgarian": "Búlgar",
|
||||||
|
"Albanian": "Albanès",
|
||||||
|
"French": "Francès",
|
||||||
|
"Irish": "Irlandès",
|
||||||
|
"Maltese": "Maltès",
|
||||||
|
"Danish": "Danès",
|
||||||
|
"Galician": "Gallec",
|
||||||
|
"Hebrew": "Hebreu",
|
||||||
|
"Indonesian": "Indonesi",
|
||||||
|
"Spanish": "Castellà",
|
||||||
|
"Vietnamese": "Vietnamita",
|
||||||
|
"News": "Notícies",
|
||||||
|
"search_filters_type_option_show": "Mostra",
|
||||||
|
"footer_documentation": "Documentació",
|
||||||
|
"Thai": "Tailandès",
|
||||||
|
"Music": "Música",
|
||||||
|
"search_filters_sort_option_relevance": "Rellevància",
|
||||||
|
"search_filters_date_option_hour": "Última hora",
|
||||||
|
"search_filters_date_option_today": "Avui"
|
||||||
|
}
|
||||||
491
locales/cs.json
Normal file
491
locales/cs.json
Normal file
@@ -0,0 +1,491 @@
|
|||||||
|
{
|
||||||
|
"LIVE": "ŽIVĚ",
|
||||||
|
"Shared `x` ago": "Zveřejněno před `x`",
|
||||||
|
"Unsubscribe": "Odhlásit odběr",
|
||||||
|
"Subscribe": "Odebírat",
|
||||||
|
"View channel on YouTube": "Otevřít kanál na YouTube",
|
||||||
|
"View playlist on YouTube": "Zobrazit playlist na YouTube",
|
||||||
|
"newest": "nejnovější",
|
||||||
|
"oldest": "nejstarší",
|
||||||
|
"popular": "populární",
|
||||||
|
"last": "poslední",
|
||||||
|
"Next page": "Další strana",
|
||||||
|
"Previous page": "Předchozí strana",
|
||||||
|
"Clear watch history?": "Smazat historii?",
|
||||||
|
"New password": "Nové heslo",
|
||||||
|
"New passwords must match": "Hesla se musí schodovat",
|
||||||
|
"Cannot change password for Google accounts": "Nelze změnit heslo pro účty Google",
|
||||||
|
"Authorize token?": "Autorizovat token?",
|
||||||
|
"Authorize token for `x`?": "Autorizovat token pro `x`?",
|
||||||
|
"Yes": "Ano",
|
||||||
|
"No": "Ne",
|
||||||
|
"Import and Export Data": "Import a export dat",
|
||||||
|
"Import": "Importovat",
|
||||||
|
"Import Invidious data": "Importovat JSON údaje Invidious",
|
||||||
|
"Import YouTube subscriptions": "Importovat odběry z YouTube/OPML",
|
||||||
|
"Import FreeTube subscriptions (.db)": "Importovat odběry z FreeTube (.db)",
|
||||||
|
"Import NewPipe subscriptions (.json)": "Importovat odběry z NewPipe (.json)",
|
||||||
|
"Import NewPipe data (.zip)": "Importovat údeje z NewPipe (.zip)",
|
||||||
|
"Export": "Exportovat",
|
||||||
|
"Export subscriptions as OPML": "Exportovat odběry jako OPML",
|
||||||
|
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Exportovat údaje jako OPML (na NewPipe a FreeTube)",
|
||||||
|
"Export data as JSON": "Exportovat data Invidious jako JSON",
|
||||||
|
"Delete account?": "Smazat účet?",
|
||||||
|
"History": "Historie",
|
||||||
|
"An alternative front-end to YouTube": "Alternativní front-end pro YouTube",
|
||||||
|
"JavaScript license information": "Informace o licenci JavaScript",
|
||||||
|
"source": "zdrojový kód",
|
||||||
|
"Log in": "Přihlásit se",
|
||||||
|
"Log in/register": "Přihlásit se/vytvořit účet",
|
||||||
|
"Log in with Google": "Přihlásit se s Googlem",
|
||||||
|
"User ID": "ID uživatele",
|
||||||
|
"Password": "Heslo",
|
||||||
|
"Time (h:mm:ss):": "Čas (h:mm:ss):",
|
||||||
|
"Text CAPTCHA": "Textové CAPTCHA",
|
||||||
|
"Image CAPTCHA": "Obrázkové CAPTCHA",
|
||||||
|
"Sign In": "Přihlásit se",
|
||||||
|
"Register": "Vytvořit účet",
|
||||||
|
"E-mail": "E-mail",
|
||||||
|
"Google verification code": "Verifikační číslo Google",
|
||||||
|
"Preferences": "Nastavení",
|
||||||
|
"preferences_category_player": "Nastavení přehravače",
|
||||||
|
"preferences_video_loop_label": "Vždy opakovat: ",
|
||||||
|
"preferences_autoplay_label": "Automatické přehrávání: ",
|
||||||
|
"preferences_continue_label": "Automaticky přehrát další: ",
|
||||||
|
"preferences_continue_autoplay_label": "Automaticky přehrát další video: ",
|
||||||
|
"preferences_listen_label": "Poslouchat ve výchozím nastavení: ",
|
||||||
|
"preferences_local_label": "Video přes proxy: ",
|
||||||
|
"preferences_speed_label": "Výchozí rychlost: ",
|
||||||
|
"preferences_quality_label": "Preferovaná kvalita videa: ",
|
||||||
|
"preferences_volume_label": "Hlasitost přehrávače: ",
|
||||||
|
"preferences_comments_label": "Předpřipravené komentáře: ",
|
||||||
|
"youtube": "YouTube",
|
||||||
|
"reddit": "Reddit",
|
||||||
|
"preferences_captions_label": "Výchozí titulky: ",
|
||||||
|
"Fallback captions: ": "Záložní titulky: ",
|
||||||
|
"preferences_related_videos_label": "Zobrazit podobné videa: ",
|
||||||
|
"preferences_annotations_label": "Zobrazovat poznámky ve výchozím nastavení: ",
|
||||||
|
"preferences_extend_desc_label": "Rozšířit automaticky popis u videa: ",
|
||||||
|
"preferences_category_visual": "Nastavení vzhledu",
|
||||||
|
"preferences_player_style_label": "Styl přehrávače ",
|
||||||
|
"Dark mode: ": "Tmavý režim ",
|
||||||
|
"preferences_dark_mode_label": "Vzhled: ",
|
||||||
|
"dark": "tmavý",
|
||||||
|
"light": "světlý",
|
||||||
|
"preferences_thin_mode_label": "Kompaktní režim: ",
|
||||||
|
"preferences_category_subscription": "Nastavení předplatných",
|
||||||
|
"preferences_annotations_subscribed_label": "Ve výchozím nastavení zobrazovat poznámky u odebíraných kanálů: ",
|
||||||
|
"Redirect homepage to feed: ": "Přesměrovávat domovskou stránku na informační kanál: ",
|
||||||
|
"preferences_max_results_label": "Počet videí zobrazovaných v informačním kanále: ",
|
||||||
|
"preferences_sort_label": "Roztřídit videa podle: ",
|
||||||
|
"published": "publikováno",
|
||||||
|
"published - reverse": "podle publikování - obrátit",
|
||||||
|
"alphabetically": "podle abecedy",
|
||||||
|
"alphabetically - reverse": "podle abecedy - převrátit",
|
||||||
|
"channel name": "název kanálu",
|
||||||
|
"channel name - reverse": "podle jména kanálu - převrátit",
|
||||||
|
"Only show latest video from channel: ": "Jenom zobrazit nejnovjejší video z kanálu: ",
|
||||||
|
"Only show latest unwatched video from channel: ": "Zobrazit jen nejnovější nezhlédnuté video z daného kanálu: ",
|
||||||
|
"preferences_unseen_only_label": "Zobrazit jen již nezhlédnuté: ",
|
||||||
|
"preferences_notifications_only_label": "Zobrazit pouze upozornění (pokud nějaká jsou): ",
|
||||||
|
"Enable web notifications": "Povolit webová upozornění",
|
||||||
|
"`x` uploaded a video": "`x` nahrál(a) video",
|
||||||
|
"`x` is live": "`x` je živě",
|
||||||
|
"preferences_category_data": "Nastavení dat",
|
||||||
|
"Clear watch history": "Smazat historii",
|
||||||
|
"Import/export data": "Importovat/exportovat data",
|
||||||
|
"Change password": "Změnit heslo",
|
||||||
|
"Manage subscriptions": "Spravovat odebírané kanály",
|
||||||
|
"Manage tokens": "Spravovat tokeny",
|
||||||
|
"Watch history": "Historie sledování",
|
||||||
|
"Delete account": "Smazat účet",
|
||||||
|
"preferences_category_admin": "Administrátorská nastavení",
|
||||||
|
"preferences_default_home_label": "Základní domovská stránka: ",
|
||||||
|
"preferences_feed_menu_label": "Menu doporučených: ",
|
||||||
|
"CAPTCHA enabled: ": "CAPTCHA povolena: ",
|
||||||
|
"Login enabled: ": "Přihlášení povoleno: ",
|
||||||
|
"Registration enabled: ": "Registrace povolena ",
|
||||||
|
"Report statistics: ": "Oznámit statistiky: ",
|
||||||
|
"Save preferences": "Uložit nastavení",
|
||||||
|
"Subscription manager": "Správa odběrů",
|
||||||
|
"Token manager": "Správa tokenů",
|
||||||
|
"Token": "Token",
|
||||||
|
"Import/export": "Importovat/exportovat",
|
||||||
|
"unsubscribe": "odhlásit odběr",
|
||||||
|
"revoke": "vrátit zpět",
|
||||||
|
"Subscriptions": "Odběry",
|
||||||
|
"search": "hledat",
|
||||||
|
"Log out": "Odhlásit se",
|
||||||
|
"Source available here.": "Zdrojový kód dostupný zde.",
|
||||||
|
"View JavaScript license information.": "Zobrazit informace o licenci JavaScript .",
|
||||||
|
"View privacy policy.": "Zobrazit zásady ochrany osobních údajů.",
|
||||||
|
"Trending": "Trendy",
|
||||||
|
"Public": "Veřejné",
|
||||||
|
"Unlisted": "Neveřejné",
|
||||||
|
"Private": "Soukromé",
|
||||||
|
"View all playlists": "Zobrazit všechny playlisty",
|
||||||
|
"Updated `x` ago": "Aktualizováno před `x`",
|
||||||
|
"Delete playlist `x`?": "Smazat playlist `x`?",
|
||||||
|
"Delete playlist": "Smazat playlist",
|
||||||
|
"Create playlist": "Vytvořit playlist",
|
||||||
|
"Title": "Název",
|
||||||
|
"Editing playlist `x`": "Upravování playlistu `x`",
|
||||||
|
"Show more": "Zobrazit více",
|
||||||
|
"Show less": "Zobrazit méně",
|
||||||
|
"Watch on YouTube": "Sledovat na YouTube",
|
||||||
|
"Hide annotations": "Skrýt poznámky",
|
||||||
|
"Show annotations": "Zobrazit poznámky",
|
||||||
|
"Genre: ": "Žánr: ",
|
||||||
|
"License: ": "Licence: ",
|
||||||
|
"Family friendly? ": "Vhodné pro rodiny? ",
|
||||||
|
"Engagement: ": "Zapojení: ",
|
||||||
|
"English": "Angličtina",
|
||||||
|
"English (auto-generated)": "Angličtina (automaticky generováno)",
|
||||||
|
"Afrikaans": "Afrikánština",
|
||||||
|
"Albanian": "Albánština",
|
||||||
|
"Amharic": "Amharština",
|
||||||
|
"Arabic": "Arabština",
|
||||||
|
"Armenian": "Arménština",
|
||||||
|
"Azerbaijani": "Azerbajdžánština",
|
||||||
|
"Bangla": "Bengálština",
|
||||||
|
"Basque": "Baskičtina",
|
||||||
|
"Belarusian": "Běloruština",
|
||||||
|
"Bosnian": "Bosenština",
|
||||||
|
"Bulgarian": "Bulharština",
|
||||||
|
"Burmese": "Barmština",
|
||||||
|
"Catalan": "Katalánština",
|
||||||
|
"Cebuano": "Cebuánština",
|
||||||
|
"Chinese (Simplified)": "Čínština (zjednodušená)",
|
||||||
|
"Chinese (Traditional)": "Čínština (tradiční)",
|
||||||
|
"Corsican": "Korsičtina",
|
||||||
|
"Croatian": "Chorvatština",
|
||||||
|
"Czech": "Čeština",
|
||||||
|
"Danish": "Dánština",
|
||||||
|
"Dutch": "Nizozemština",
|
||||||
|
"Esperanto": "Esperanto",
|
||||||
|
"Estonian": "Estonština",
|
||||||
|
"Filipino": "Filipínština",
|
||||||
|
"Finnish": "Finština",
|
||||||
|
"French": "Francouzština",
|
||||||
|
"Galician": "Galicijština",
|
||||||
|
"Georgian": "Gruzínština",
|
||||||
|
"German": "Němčina",
|
||||||
|
"Greek": "Řečtina",
|
||||||
|
"Gujarati": "Gudžarátština",
|
||||||
|
"Haitian Creole": "Haitská kreolština",
|
||||||
|
"Hausa": "Hauština",
|
||||||
|
"Hawaiian": "Havajština",
|
||||||
|
"Hebrew": "Hebrejština",
|
||||||
|
"Hindi": "Hindština",
|
||||||
|
"Hmong": "Hmongština",
|
||||||
|
"Hungarian": "Maďarština",
|
||||||
|
"Icelandic": "Islandština",
|
||||||
|
"Igbo": "Igboština",
|
||||||
|
"Indonesian": "Indonéština",
|
||||||
|
"Irish": "Irština",
|
||||||
|
"Italian": "Italština",
|
||||||
|
"Japanese": "Japonština",
|
||||||
|
"Javanese": "Javánština",
|
||||||
|
"Kannada": "Kannadština",
|
||||||
|
"Kazakh": "Kazaština",
|
||||||
|
"Khmer": "Khmerština",
|
||||||
|
"Korean": "Korejština",
|
||||||
|
"Kurdish": "Kurdština",
|
||||||
|
"Kyrgyz": "Kyrgyzština",
|
||||||
|
"Lao": "Laoština",
|
||||||
|
"Latin": "Latina",
|
||||||
|
"Latvian": "Lotyština",
|
||||||
|
"Lithuanian": "Litevština",
|
||||||
|
"Luxembourgish": "Lucemburština",
|
||||||
|
"Macedonian": "Makedonština",
|
||||||
|
"Malagasy": "Malgaština",
|
||||||
|
"Malay": "Malajština",
|
||||||
|
"Malayalam": "Malajálamština",
|
||||||
|
"Maltese": "Maltština",
|
||||||
|
"Maori": "Maorština",
|
||||||
|
"Marathi": "Maráthština",
|
||||||
|
"Mongolian": "Mongolština",
|
||||||
|
"Nepali": "Nepálština",
|
||||||
|
"Norwegian Bokmål": "Norština Bokmål",
|
||||||
|
"Nyanja": "Čičevština",
|
||||||
|
"Pashto": "Paštština",
|
||||||
|
"Persian": "Perština",
|
||||||
|
"Polish": "Polština",
|
||||||
|
"Portuguese": "Portugalština",
|
||||||
|
"Punjabi": "Paňdžábština",
|
||||||
|
"Romanian": "Rumunština",
|
||||||
|
"Russian": "Ruština",
|
||||||
|
"Samoan": "Samojština",
|
||||||
|
"Scottish Gaelic": "Skotská gaelština",
|
||||||
|
"Serbian": "Srbština",
|
||||||
|
"Shona": "Shona",
|
||||||
|
"Sindhi": "Sindhština",
|
||||||
|
"Sinhala": "Sinhálština",
|
||||||
|
"Slovak": "Slovenština",
|
||||||
|
"Slovenian": "Slovinština",
|
||||||
|
"Somali": "Somálština",
|
||||||
|
"Southern Sotho": "Sesothština",
|
||||||
|
"Spanish": "Španělština",
|
||||||
|
"Spanish (Latin America)": "Španělština (Latinská Amerika)",
|
||||||
|
"Sundanese": "Sundština",
|
||||||
|
"Swahili": "Svahilština",
|
||||||
|
"Swedish": "Švédština",
|
||||||
|
"Tajik": "Tádžičtina",
|
||||||
|
"Tamil": "Tamilština",
|
||||||
|
"Telugu": "Telugština",
|
||||||
|
"Thai": "Thajština",
|
||||||
|
"Turkish": "Turečtina",
|
||||||
|
"Ukrainian": "Ukrajinština",
|
||||||
|
"Urdu": "Urdština",
|
||||||
|
"Uzbek": "Uzbečtina",
|
||||||
|
"Vietnamese": "Vietnamština",
|
||||||
|
"Welsh": "Velština",
|
||||||
|
"Western Frisian": "Západofríština",
|
||||||
|
"Xhosa": "Xhoština",
|
||||||
|
"Yiddish": "Jidiš",
|
||||||
|
"Yoruba": "Jorubština",
|
||||||
|
"Zulu": "Zuluština",
|
||||||
|
"Popular": "Populární",
|
||||||
|
"About": "Informace",
|
||||||
|
"Rating: ": "Hodnocení: ",
|
||||||
|
"preferences_locale_label": "Jazyk: ",
|
||||||
|
"Default": "Výchozí",
|
||||||
|
"Music": "Hudba",
|
||||||
|
"Gaming": "Hry",
|
||||||
|
"News": "Zprávy",
|
||||||
|
"Movies": "Filmy",
|
||||||
|
"Download": "Stáhnout",
|
||||||
|
"Download as: ": "Stáhnout jako: ",
|
||||||
|
"(edited)": "(upraveno)",
|
||||||
|
"`x` marked it with a ❤": "`x` to označil(a) se ❤",
|
||||||
|
"Audio mode": "Audiový režim",
|
||||||
|
"Video mode": "Videový režim",
|
||||||
|
"Videos": "Videa",
|
||||||
|
"Community": "Komunita",
|
||||||
|
"search_filters_sort_option_rating": "Hodnocení",
|
||||||
|
"search_filters_sort_option_date": "Datum nahrání",
|
||||||
|
"search_filters_sort_option_views": "Počet zhlédnutí",
|
||||||
|
"search_filters_duration_label": "Délka",
|
||||||
|
"search_filters_date_option_hour": "Poslední hodina",
|
||||||
|
"search_filters_date_option_today": "Dnes",
|
||||||
|
"search_filters_date_option_week": "Tento týden",
|
||||||
|
"search_filters_date_option_month": "Tento měsíc",
|
||||||
|
"search_filters_date_option_year": "Tento rok",
|
||||||
|
"search_filters_type_option_video": "Video",
|
||||||
|
"search_filters_type_option_channel": "Kanál",
|
||||||
|
"search_filters_type_option_playlist": "Playlist",
|
||||||
|
"search_filters_type_option_movie": "Film",
|
||||||
|
"search_filters_type_option_show": "Seriál",
|
||||||
|
"search_filters_features_option_hd": "HD",
|
||||||
|
"search_filters_features_option_subtitles": "Titulky",
|
||||||
|
"search_filters_features_option_c_commons": "Creative Commons",
|
||||||
|
"search_filters_features_option_three_d": "3D",
|
||||||
|
"search_filters_features_option_live": "Živě",
|
||||||
|
"search_filters_features_option_four_k": "4K",
|
||||||
|
"search_filters_features_option_location": "Umístění",
|
||||||
|
"search_filters_features_option_hdr": "HDR",
|
||||||
|
"generic_count_days_0": "{{count}} dnem",
|
||||||
|
"generic_count_days_1": "{{count}} dny",
|
||||||
|
"generic_count_days_2": "{{count}} dny",
|
||||||
|
"generic_count_hours_0": "{{count}} hodinou",
|
||||||
|
"generic_count_hours_1": "{{count}} hodinami",
|
||||||
|
"generic_count_hours_2": "{{count}} hodinami",
|
||||||
|
"crash_page_refresh": "zkusili <a href=\"`x`\">obnovit stránku</a>",
|
||||||
|
"crash_page_switch_instance": "zkusili <a href=\"`x`\">použít jinou instanci</a>",
|
||||||
|
"preferences_vr_mode_label": "Interaktivní 360-stupňová videa (vyžaduje WebGL): ",
|
||||||
|
"English (United Kingdom)": "Angličtina (Spojené království)",
|
||||||
|
"Chinese (China)": "Čínština (Čína)",
|
||||||
|
"Chinese (Hong Kong)": "Čínština (Hong Kong)",
|
||||||
|
"Chinese (Taiwan)": "Čínština (Taiwan)",
|
||||||
|
"Portuguese (auto-generated)": "Portugalština (automaticky generováno)",
|
||||||
|
"Spanish (auto-generated)": "Španělština (automaticky generováno)",
|
||||||
|
"Spanish (Mexico)": "Španělština (Mexiko)",
|
||||||
|
"Spanish (Spain)": "Španělština (Španělsko)",
|
||||||
|
"generic_count_years_0": "{{count}} rokem",
|
||||||
|
"generic_count_years_1": "{{count}} lety",
|
||||||
|
"generic_count_years_2": "{{count}} lety",
|
||||||
|
"Fallback comments: ": "Záložní komentáře: ",
|
||||||
|
"Search": "Hledat",
|
||||||
|
"Top": "Nejlepší",
|
||||||
|
"Playlists": "Playlisty",
|
||||||
|
"videoinfo_started_streaming_x_ago": "Stream spuštěn před `x`",
|
||||||
|
"videoinfo_watch_on_youTube": "Sledovat na YouTube",
|
||||||
|
"videoinfo_youTube_embed_link": "Vložení",
|
||||||
|
"crash_page_read_the_faq": "si přečetli <a href=\"`x`\">často kladené otázky (FAQ)</a>",
|
||||||
|
"crash_page_before_reporting": "Před nahlášením chyby se ujistěte, že jste:",
|
||||||
|
"preferences_quality_option_hd720": "HD720",
|
||||||
|
"preferences_quality_option_dash": "DASH (adaptivní kvalita)",
|
||||||
|
"generic_views_count_0": "{{count}} zhlédnutí",
|
||||||
|
"generic_views_count_1": "{{count}} zhlédnutí",
|
||||||
|
"generic_views_count_2": "{{count}} zhlédnutí",
|
||||||
|
"generic_subscriptions_count_0": "{{count}} odběr",
|
||||||
|
"generic_subscriptions_count_1": "{{count}} odběry",
|
||||||
|
"generic_subscriptions_count_2": "{{count}} odběrů",
|
||||||
|
"preferences_quality_dash_option_4320p": "4320p",
|
||||||
|
"generic_videos_count_0": "{{count}} video",
|
||||||
|
"generic_videos_count_1": "{{count}} videa",
|
||||||
|
"generic_videos_count_2": "{{count}} videí",
|
||||||
|
"preferences_quality_option_small": "Nízká",
|
||||||
|
"preferences_quality_dash_option_2160p": "2160p",
|
||||||
|
"preferences_quality_dash_option_1080p": "1080p",
|
||||||
|
"preferences_quality_dash_option_720p": "720p",
|
||||||
|
"preferences_quality_dash_option_360p": "360p",
|
||||||
|
"preferences_quality_dash_option_144p": "144p",
|
||||||
|
"preferences_quality_option_medium": "Střední",
|
||||||
|
"preferences_quality_dash_option_1440p": "1440p",
|
||||||
|
"invidious": "Invidious",
|
||||||
|
"View more comments on Reddit": "Zobrazit více komentářů na Redditu",
|
||||||
|
"Invalid TFA code": "Nesprávný TFA kód",
|
||||||
|
"generic_playlists_count_0": "{{count}} playlist",
|
||||||
|
"generic_playlists_count_1": "{{count}} playlisty",
|
||||||
|
"generic_playlists_count_2": "{{count}} playlistů",
|
||||||
|
"generic_subscribers_count_0": "{{count}} odběratel",
|
||||||
|
"generic_subscribers_count_1": "{{count}} odběratelé",
|
||||||
|
"generic_subscribers_count_2": "{{count}} odběratelů",
|
||||||
|
"preferences_watch_history_label": "Povolit historii sledování: ",
|
||||||
|
"preferences_quality_dash_option_240p": "240p",
|
||||||
|
"preferences_region_label": "Země obsahu: ",
|
||||||
|
"subscriptions_unseen_notifs_count_0": "{{count}} nezobrazené oznámení",
|
||||||
|
"subscriptions_unseen_notifs_count_1": "{{count}} nezobrazená oznámení",
|
||||||
|
"subscriptions_unseen_notifs_count_2": "{{count}} nezobrazených oznámení",
|
||||||
|
"Show replies": "Zobrazit odpovědi",
|
||||||
|
"Quota exceeded, try again in a few hours": "Kvóta překročena, zkuste to znovu za pár hodin",
|
||||||
|
"Password cannot be longer than 55 characters": "Heslo nesmí být delší než 55 znaků",
|
||||||
|
"comments_view_x_replies_0": "Zobrazit {{count}} odpověď",
|
||||||
|
"comments_view_x_replies_1": "Zobrazit {{count}} odpovědi",
|
||||||
|
"comments_view_x_replies_2": "Zobrazit {{count}} odpovědí",
|
||||||
|
"comments_points_count_0": "{{count}} bod",
|
||||||
|
"comments_points_count_1": "{{count}} body",
|
||||||
|
"comments_points_count_2": "{{count}} bodů",
|
||||||
|
"German (auto-generated)": "Němčina (automaticky generováno)",
|
||||||
|
"Indonesian (auto-generated)": "Indonéština (automaticky generováno)",
|
||||||
|
"Interlingue": "Interlingue",
|
||||||
|
"Italian (auto-generated)": "Italština (automaticky generováno)",
|
||||||
|
"Japanese (auto-generated)": "Japonština (automaticky generováno)",
|
||||||
|
"Korean (auto-generated)": "Korejština (automaticky generováno)",
|
||||||
|
"Russian (auto-generated)": "Ruština (automaticky generováno)",
|
||||||
|
"generic_count_months_0": "{{count}} měsícem",
|
||||||
|
"generic_count_months_1": "{{count}} měsíci",
|
||||||
|
"generic_count_months_2": "{{count}} měsíci",
|
||||||
|
"generic_count_weeks_0": "{{count}} týdnem",
|
||||||
|
"generic_count_weeks_1": "{{count}} týdny",
|
||||||
|
"generic_count_weeks_2": "{{count}} týdny",
|
||||||
|
"generic_count_minutes_0": "{{count}} minutou",
|
||||||
|
"generic_count_minutes_1": "{{count}} minutami",
|
||||||
|
"generic_count_minutes_2": "{{count}} minutami",
|
||||||
|
"footer_documentation": "Dokumentace",
|
||||||
|
"next_steps_error_message_refresh": "Obnovit stránku",
|
||||||
|
"Chinese": "Čínština",
|
||||||
|
"Dutch (auto-generated)": "Nizozemština (automaticky generováno)",
|
||||||
|
"Erroneous token": "Chybný token",
|
||||||
|
"tokens_count_0": "{{count}} token",
|
||||||
|
"tokens_count_1": "{{count}} tokeny",
|
||||||
|
"tokens_count_2": "{{count}} tokenů",
|
||||||
|
"Portuguese (Brazil)": "Portugalština (Brazílie)",
|
||||||
|
"Token is expired, please try again": "Token vypršel, zkuste to prosím znovu",
|
||||||
|
"English (United States)": "Angličtina (Spojené státy)",
|
||||||
|
"Cantonese (Hong Kong)": "Kantonština (Hong Kong)",
|
||||||
|
"French (auto-generated)": "Francouzština (automaticky generováno)",
|
||||||
|
"Turkish (auto-generated)": "Turečtina (automaticky generováno)",
|
||||||
|
"Vietnamese (auto-generated)": "Vietnamština (automaticky generováno)",
|
||||||
|
"Current version: ": "Aktuální verze: ",
|
||||||
|
"next_steps_error_message": "Měli byste zkusit: ",
|
||||||
|
"footer_donate_page": "Přispět",
|
||||||
|
"download_subtitles": "Titulky - `x` (.vtt)",
|
||||||
|
"%A %B %-d, %Y": "%A %B %-d, %Y",
|
||||||
|
"YouTube comment permalink": "Permanentní odkaz YouTube komentáře",
|
||||||
|
"permalink": "permalink",
|
||||||
|
"footer_original_source_code": "Původní zdrojový kód",
|
||||||
|
"adminprefs_modified_source_code_url_label": "URL repozitáře s upraveným zdrojovým kódem",
|
||||||
|
"Video unavailable": "Video není dostupné",
|
||||||
|
"next_steps_error_message_go_to_youtube": "Jít na YouTube",
|
||||||
|
"footer_modfied_source_code": "Upravený zdrojový kód",
|
||||||
|
"none": "žádné",
|
||||||
|
"videoinfo_invidious_embed_link": "Odkaz na vložení",
|
||||||
|
"user_saved_playlists": "`x` uložených playlistů",
|
||||||
|
"crash_page_you_found_a_bug": "Vypadá to, že jste našli chybu v Invidious!",
|
||||||
|
"user_created_playlists": "`x` vytvořených playlistů",
|
||||||
|
"crash_page_search_issue": "vyhledali <a href=\"`x`\">existující problémy na GitHubu</a>",
|
||||||
|
"crash_page_report_issue": "Pokud nepomohlo nic z výše uvedeného, <a href=\"`x`\">otevřete prosím nový problém na GitHubu</a> (pokud možno v angličtině) a zahrňte do zprávy následující text (NEpřekládejte jej):",
|
||||||
|
"preferences_quality_dash_label": "Preferovaná kvalita videí DASH: ",
|
||||||
|
"preferences_quality_dash_option_auto": "Automatická",
|
||||||
|
"preferences_quality_dash_option_best": "Nejlepší",
|
||||||
|
"preferences_quality_dash_option_worst": "Nejhorší",
|
||||||
|
"preferences_quality_dash_option_480p": "480p",
|
||||||
|
"Top enabled: ": "Povoleny nejlepší: ",
|
||||||
|
"generic_count_seconds_0": "{{count}} sekundou",
|
||||||
|
"generic_count_seconds_1": "{{count}} sekundami",
|
||||||
|
"generic_count_seconds_2": "{{count}} sekundami",
|
||||||
|
"preferences_save_player_pos_label": "Uložit pozici přehrávání: ",
|
||||||
|
"Incorrect password": "Nesprávné heslo",
|
||||||
|
"View as playlist": "Zobrazit jako playlist",
|
||||||
|
"View Reddit comments": "Zobrazit komentáře z Redditu",
|
||||||
|
"No such user": "Uživatel nenalezen",
|
||||||
|
"Playlist privacy": "Soukromí playlistu",
|
||||||
|
"Wrong answer": "Špatná odpověď",
|
||||||
|
"Could not pull trending pages.": "Nepodařilo se získat trendy stránky.",
|
||||||
|
"Erroneous CAPTCHA": "Chybná CAPTCHA",
|
||||||
|
"Password is a required field": "Heslo je vyžadované pole",
|
||||||
|
"preferences_automatic_instance_redirect_label": "Automatické přesměrování instance (fallback na redirect.invidious.io): ",
|
||||||
|
"Switch Invidious Instance": "Přepnout instanci Invidious",
|
||||||
|
"Empty playlist": "Prázdný playlist",
|
||||||
|
"footer_source_code": "Zdrojový kód",
|
||||||
|
"View YouTube comments": "Zobrazit YouTube komentáře",
|
||||||
|
"Blacklisted regions: ": "Oblasti na černé listině: ",
|
||||||
|
"Wrong username or password": "Nesprávné uživatelské jméno nebo heslo",
|
||||||
|
"Please sign in using 'Log in with Google'": "Přihlaste se prosím pomocí Googlu",
|
||||||
|
"Password cannot be empty": "Heslo nemůže být prázné",
|
||||||
|
"preferences_category_misc": "Různá nastavení",
|
||||||
|
"preferences_show_nick_label": "Zobrazit přezdívku na vrchu: ",
|
||||||
|
"Whitelisted regions: ": "Oblasti na bílé listině: ",
|
||||||
|
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Zdravíme! Zdá se, že máte vypnutý JavaScript. Klikněte sem pro zobrazení komentářů - nezapomeňte, že se mohou načítat trochu déle.",
|
||||||
|
"User ID is a required field": "ID uživatele je vyžadované pole",
|
||||||
|
"Please log in": "Přihlaste se prosím",
|
||||||
|
"Invidious Private Feed for `x`": "Soukromý kanál Invidious pro `x`",
|
||||||
|
"Deleted or invalid channel": "Smazaný nebo neplatný kanál",
|
||||||
|
"This channel does not exist.": "Tento kanál neexistuje.",
|
||||||
|
"Hidden field \"token\" is a required field": "Skryté pole \"token\" je vyžadované",
|
||||||
|
"Wilson score: ": "Skóre Wilson: ",
|
||||||
|
"Shared `x`": "Zveřejněno `x`",
|
||||||
|
"Premieres in `x`": "Premiéra za `x`",
|
||||||
|
"View `x` comments": {
|
||||||
|
"([^.,0-9]|^)1([^.,0-9]|$)": "Zobrazit `x` komentář",
|
||||||
|
"": "Zobrazit `x` komentářů"
|
||||||
|
},
|
||||||
|
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Nepodařilo se přihlásit, ujistěte se, že je povoleno dvoufázové ověřování (autentifikátor nebo SMS).",
|
||||||
|
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Přihlášení selhalo. Toto se může stát, když není na vašem účtu povolené dvoufázové ověřování.",
|
||||||
|
"Could not get channel info.": "Nepodařilo se získat informace o kanálu.",
|
||||||
|
"Could not fetch comments": "Nepodařilo se získat komentáře",
|
||||||
|
"Could not create mix.": "Nepodařilo se vytvořit mix.",
|
||||||
|
"Hidden field \"challenge\" is a required field": "Skryté pole \"challenge\" je vyžadované",
|
||||||
|
"Released under the AGPLv3 on Github.": "Vydáno pod licencí AGPLv3 na GitHubu.",
|
||||||
|
"Hide replies": "Skrýt odpovědi",
|
||||||
|
"channel:`x`": "kanál: `x`",
|
||||||
|
"Load more": "Načíst další",
|
||||||
|
"Not a playlist.": "Není playlist.",
|
||||||
|
"Playlist does not exist.": "Playlist neexistuje.",
|
||||||
|
"Erroneous challenge": "Chybná výzva",
|
||||||
|
"Premieres `x`": "Premiéra `x`",
|
||||||
|
"CAPTCHA is a required field": "CAPTCHA je vyžadované pole",
|
||||||
|
"`x` ago": "Před `x`",
|
||||||
|
"search_message_change_filters_or_query": "Zkuste rozšířit vyhledávaný dotaz a/nebo změnit filtry.",
|
||||||
|
"search_filters_date_option_none": "Jakékoli datum",
|
||||||
|
"search_filters_date_label": "Datum nahrání",
|
||||||
|
"search_filters_type_option_all": "Jakýkoli typ",
|
||||||
|
"search_filters_duration_option_none": "Jakákoli délka",
|
||||||
|
"search_filters_type_label": "Typ",
|
||||||
|
"search_filters_duration_option_short": "Krátká (< 4 minuty)",
|
||||||
|
"search_message_no_results": "Nenalezeny žádné výsledky.",
|
||||||
|
"search_filters_title": "Filtry",
|
||||||
|
"search_filters_duration_option_medium": "Střední (4 - 20 minut)",
|
||||||
|
"search_filters_duration_option_long": "Dlouhá (> 20 minut)",
|
||||||
|
"search_message_use_another_instance": " Můžete také <a href=\"`x`\">hledat na jiné instanci</a>.",
|
||||||
|
"search_filters_features_label": "Vlastnosti",
|
||||||
|
"search_filters_features_option_three_sixty": "360°",
|
||||||
|
"search_filters_features_option_vr180": "VR180",
|
||||||
|
"search_filters_features_option_purchased": "Zakoupeno",
|
||||||
|
"search_filters_sort_label": "Řadit dle",
|
||||||
|
"search_filters_sort_option_relevance": "Relevantnost",
|
||||||
|
"search_filters_apply_button": "Použít vybrané filtry",
|
||||||
|
"Popular enabled: ": "Populární povoleno: "
|
||||||
|
}
|
||||||
464
locales/da.json
Normal file
464
locales/da.json
Normal file
@@ -0,0 +1,464 @@
|
|||||||
|
{
|
||||||
|
"LIVE": "LIVE",
|
||||||
|
"Shared `x` ago": "Delt for `x` siden",
|
||||||
|
"Unsubscribe": "Opsig abonnement",
|
||||||
|
"Subscribe": "Abonner",
|
||||||
|
"View channel on YouTube": "Vis kanal på YouTube",
|
||||||
|
"View playlist on YouTube": "Vis afspilningsliste på YouTube",
|
||||||
|
"newest": "nyeste",
|
||||||
|
"oldest": "ældste",
|
||||||
|
"popular": "populært",
|
||||||
|
"last": "sidste",
|
||||||
|
"Next page": "Næste side",
|
||||||
|
"Previous page": "Forrige side",
|
||||||
|
"Clear watch history?": "Ryd afspilningshistorik?",
|
||||||
|
"New password": "Nyt kodeord",
|
||||||
|
"New passwords must match": "Nye kodeord skal matche",
|
||||||
|
"Cannot change password for Google accounts": "Kan ikke skifte kodeord til Google-konti",
|
||||||
|
"Authorize token?": "Godkend token?",
|
||||||
|
"Authorize token for `x`?": "Godkend token til `x`?",
|
||||||
|
"Yes": "Ja",
|
||||||
|
"No": "Nej",
|
||||||
|
"Import and Export Data": "Importer og Eksporter Data",
|
||||||
|
"Import": "Importer",
|
||||||
|
"Import Invidious data": "Importer Invidious JSON-data",
|
||||||
|
"Import YouTube subscriptions": "Importer YouTube/OPML-abonnementer",
|
||||||
|
"Import FreeTube subscriptions (.db)": "Importer FreeTube abonnementer (.db)",
|
||||||
|
"Import NewPipe subscriptions (.json)": "Importer NewPipe abonnementer (.json)",
|
||||||
|
"Import NewPipe data (.zip)": "Importer NewPipe data (.zip)",
|
||||||
|
"Export": "Exporter",
|
||||||
|
"Export subscriptions as OPML": "Exporter abonnementer som OPML",
|
||||||
|
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Exporter abonnementer som OPML (til NewPipe & FreeTube)",
|
||||||
|
"Export data as JSON": "Eksporter Invidious-data som JSON",
|
||||||
|
"Delete account?": "Slet konto?",
|
||||||
|
"History": "Historik",
|
||||||
|
"An alternative front-end to YouTube": "Et alternativt front-end til YouTube",
|
||||||
|
"JavaScript license information": "JavaScript licens information",
|
||||||
|
"source": "kilde",
|
||||||
|
"Log in": "Log på",
|
||||||
|
"Log in/register": "Log på/registrer",
|
||||||
|
"Log in with Google": "Log på med Google",
|
||||||
|
"User ID": "Bruger ID",
|
||||||
|
"Password": "Kodeord",
|
||||||
|
"Time (h:mm:ss):": "Tid (t:mm:ss):",
|
||||||
|
"Text CAPTCHA": "Tekst CAPTCHA",
|
||||||
|
"Image CAPTCHA": "Billede CAPTCHA",
|
||||||
|
"Sign In": "Log ind",
|
||||||
|
"Register": "Registrer",
|
||||||
|
"E-mail": "E-mail",
|
||||||
|
"Google verification code": "Google-verifikationskode",
|
||||||
|
"Preferences": "Præferencer",
|
||||||
|
"preferences_category_player": "Afspillerindstillinger",
|
||||||
|
"preferences_video_loop_label": "Altid gentag: ",
|
||||||
|
"preferences_autoplay_label": "Auto afspil: ",
|
||||||
|
"preferences_continue_label": "Afspil næste som standard: ",
|
||||||
|
"preferences_continue_autoplay_label": "Auto afspil næste video: ",
|
||||||
|
"preferences_listen_label": "Lyt som standard: ",
|
||||||
|
"preferences_local_label": "Proxy videoer: ",
|
||||||
|
"preferences_speed_label": "Standard hastighed: ",
|
||||||
|
"preferences_quality_label": "Foretrukken video kvalitet: ",
|
||||||
|
"preferences_volume_label": "Lydstyrke: ",
|
||||||
|
"preferences_comments_label": "Standard kommentarer: ",
|
||||||
|
"youtube": "YouTube",
|
||||||
|
"reddit": "Reddit",
|
||||||
|
"preferences_captions_label": "Standard undertekster: ",
|
||||||
|
"Fallback captions: ": "Alternative undertekster: ",
|
||||||
|
"preferences_related_videos_label": "Vis relaterede videoer: ",
|
||||||
|
"preferences_annotations_label": "Vis annotationer som standard: ",
|
||||||
|
"preferences_extend_desc_label": "Automatisk udvid videoens beskrivelse: ",
|
||||||
|
"preferences_vr_mode_label": "Interaktive 360 graders videoer (kræver WebGL): ",
|
||||||
|
"preferences_category_visual": "Visuelle præferencer",
|
||||||
|
"preferences_player_style_label": "Afspiller stil: ",
|
||||||
|
"Dark mode: ": "Mørk tilstand: ",
|
||||||
|
"preferences_dark_mode_label": "Tema: ",
|
||||||
|
"dark": "mørk",
|
||||||
|
"light": "lys",
|
||||||
|
"preferences_thin_mode_label": "Tynd tilstand: ",
|
||||||
|
"preferences_category_subscription": "Abonnements præferencer",
|
||||||
|
"preferences_annotations_subscribed_label": "Vis annotationer som standard for abonnerede kanaler: ",
|
||||||
|
"Redirect homepage to feed: ": "Omdiriger startside til feed: ",
|
||||||
|
"preferences_max_results_label": "Antal videoer vist i feed: ",
|
||||||
|
"preferences_sort_label": "Sorter videoer efter: ",
|
||||||
|
"published": "offentliggjort",
|
||||||
|
"published - reverse": "offentliggjort - omvendt",
|
||||||
|
"alphabetically": "alfabetisk",
|
||||||
|
"alphabetically - reverse": "alfabetisk - omvendt",
|
||||||
|
"channel name": "kanalnavn",
|
||||||
|
"channel name - reverse": "kanalnavn - omvendt",
|
||||||
|
"Only show latest video from channel: ": "Vis kun seneste video fra kanal: ",
|
||||||
|
"Only show latest unwatched video from channel: ": "Vis kun seneste usete video fra kanal: ",
|
||||||
|
"preferences_unseen_only_label": "Vis kun usete: ",
|
||||||
|
"preferences_notifications_only_label": "Vis kun notifikationer (hvis der er nogle): ",
|
||||||
|
"Enable web notifications": "Aktiver webnotifikationer",
|
||||||
|
"`x` uploaded a video": "`x` uploadede en video",
|
||||||
|
"`x` is live": "`x` er live",
|
||||||
|
"preferences_category_data": "Data præferencer",
|
||||||
|
"Clear watch history": "Ryd afspilningshistorik",
|
||||||
|
"Import/export data": "Importer/exporter data",
|
||||||
|
"Change password": "Skift adgangskode",
|
||||||
|
"Manage subscriptions": "Administrer abonnementer",
|
||||||
|
"Manage tokens": "Administrer tokens",
|
||||||
|
"Watch history": "Afspilningshistorik",
|
||||||
|
"Delete account": "Slet konto",
|
||||||
|
"preferences_category_admin": "Administrator præferencer",
|
||||||
|
"preferences_default_home_label": "Standard startside: ",
|
||||||
|
"preferences_feed_menu_label": "Feed menu: ",
|
||||||
|
"Top enabled: ": "Top aktiveret: ",
|
||||||
|
"CAPTCHA enabled: ": "CAPTCHA aktiveret: ",
|
||||||
|
"Login enabled: ": "Login aktiveret: ",
|
||||||
|
"Registration enabled: ": "Registrering aktiveret: ",
|
||||||
|
"Report statistics: ": "Indsend statistik: ",
|
||||||
|
"Save preferences": "Gem præferencer",
|
||||||
|
"Subscription manager": "Abonnementsmanager",
|
||||||
|
"Token manager": "Tokenmanager",
|
||||||
|
"Token": "Token",
|
||||||
|
"Import/export": "Importer/eksporter",
|
||||||
|
"unsubscribe": "opsig abonnement",
|
||||||
|
"revoke": "tilbagekald",
|
||||||
|
"Subscriptions": "Abonnementer",
|
||||||
|
"search": "søg",
|
||||||
|
"Log out": "Log ud",
|
||||||
|
"Source available here.": "Kilde tilgængelig her.",
|
||||||
|
"View JavaScript license information.": "Vis JavaScriptlicensinformation.",
|
||||||
|
"View privacy policy.": "Vis privatpolitik.",
|
||||||
|
"Trending": "Trending",
|
||||||
|
"Public": "Offentlig",
|
||||||
|
"Unlisted": "Skjult",
|
||||||
|
"Private": "Privat",
|
||||||
|
"View all playlists": "Vis alle afspilningslister",
|
||||||
|
"Updated `x` ago": "Opdateret for `x` siden",
|
||||||
|
"Delete playlist `x`?": "Fjern spilleliste `x`?",
|
||||||
|
"Delete playlist": "Slet afspilningsliste",
|
||||||
|
"Create playlist": "Opret afspilningsliste",
|
||||||
|
"Title": "Titel",
|
||||||
|
"Playlist privacy": "Privatlivsindstillinger for afspilningsliste",
|
||||||
|
"Editing playlist `x`": "Redigerer afspilningsliste `x`",
|
||||||
|
"Show more": "Vis mere",
|
||||||
|
"Show less": "Vis mindre",
|
||||||
|
"Watch on YouTube": "Se på YouTube",
|
||||||
|
"Hide annotations": "Skjul annotationer",
|
||||||
|
"Show annotations": "Vis annotationer",
|
||||||
|
"Genre: ": "Genre: ",
|
||||||
|
"License: ": "Licens: ",
|
||||||
|
"Family friendly? ": "Familievenlig? ",
|
||||||
|
"Wilson score: ": "Wilson score: ",
|
||||||
|
"Engagement: ": "Engagement: ",
|
||||||
|
"Whitelisted regions: ": "Whitelistede regioner: ",
|
||||||
|
"Blacklisted regions: ": "Blacklistede regioner: ",
|
||||||
|
"Shared `x`": "Delt `x`",
|
||||||
|
"Premieres in `x`": "Har premiere om `x`",
|
||||||
|
"Premieres `x`": "Har premiere om `x`",
|
||||||
|
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hej! Det ser ud til at du har JavaScript slået fra. Klik her for at se kommentarer, vær opmærksom på at de kan tage længere om at indlæse.",
|
||||||
|
"View YouTube comments": "Vis YouTube kommentarer",
|
||||||
|
"View more comments on Reddit": "Se flere kommentarer på Reddit",
|
||||||
|
"View `x` comments": {
|
||||||
|
"([^.,0-9]|^)1([^.,0-9]|$)": "Vis `x` kommentarer.([^.,0-9]|^)1([^.,0-9]|$)",
|
||||||
|
"": "Vis `x` kommentarer"
|
||||||
|
},
|
||||||
|
"View Reddit comments": "Vis Reddit kommentarer",
|
||||||
|
"Hide replies": "Skjul svar",
|
||||||
|
"Show replies": "Vis svar",
|
||||||
|
"Incorrect password": "Forkert adgangskode",
|
||||||
|
"Quota exceeded, try again in a few hours": "Kvota overskredet, prøv igen om et par timer",
|
||||||
|
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Login fejlet, tjek at totrinsbekræftelse (Authenticator eller SMS) er slået til.",
|
||||||
|
"Invalid TFA code": "Ugyldig TFA kode",
|
||||||
|
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Login fejlede. Dette kan skyldes, at to-faktor autentificering ikke er aktiveret for din konto.",
|
||||||
|
"Wrong answer": "Forkert svar",
|
||||||
|
"Erroneous CAPTCHA": "Fejlagtig CAPTCHA",
|
||||||
|
"CAPTCHA is a required field": "CAPTCHA er et obligatorisk felt",
|
||||||
|
"User ID is a required field": "Bruger ID er et krævet felt",
|
||||||
|
"Password is a required field": "Adgangskode er et obligatorisk felt",
|
||||||
|
"Wrong username or password": "Forkert brugernavn eller adgangskode",
|
||||||
|
"Please sign in using 'Log in with Google'": "Log ind via 'Log ind med Google'",
|
||||||
|
"Password cannot be empty": "Adgangskoden må ikke være tom",
|
||||||
|
"Password cannot be longer than 55 characters": "Adgangskoden må ikke være længere end 55 tegn",
|
||||||
|
"Please log in": "Venligst log ind",
|
||||||
|
"channel:`x`": "kanal: 'x'",
|
||||||
|
"Deleted or invalid channel": "Slettet eller invalid kanal",
|
||||||
|
"This channel does not exist.": "Denne kanal eksisterer ikke.",
|
||||||
|
"Could not get channel info.": "Kunne ikke hente kanal info.",
|
||||||
|
"Could not fetch comments": "Kunne ikke hente kommentarer",
|
||||||
|
"`x` ago": "'x' siden",
|
||||||
|
"Load more": "Hent flere",
|
||||||
|
"Could not create mix.": "Kunne ikke skabe blanding.",
|
||||||
|
"Empty playlist": "Tom playliste",
|
||||||
|
"Not a playlist.": "Ikke en playliste.",
|
||||||
|
"Playlist does not exist.": "Playlist eksisterer ikke.",
|
||||||
|
"Esperanto": "Esperanto",
|
||||||
|
"Czech": "Tjekkisk",
|
||||||
|
"Danish": "Dansk",
|
||||||
|
"Community": "Samfund",
|
||||||
|
"Afrikaans": "Afrikansk",
|
||||||
|
"Portuguese": "Portugisisk",
|
||||||
|
"Ukrainian": "Ukrainsk",
|
||||||
|
"Fallback comments: ": "Fallback kommentarer: ",
|
||||||
|
"Popular": "Populær",
|
||||||
|
"footer_donate_page": "Doner",
|
||||||
|
"Gujarati": "Gujarati",
|
||||||
|
"Punjabi": "Punjabi",
|
||||||
|
"Sundanese": "Sundanesisk",
|
||||||
|
"Urdu": "Urdu",
|
||||||
|
"preferences_region_label": "Indhold land: ",
|
||||||
|
"Hidden field \"challenge\" is a required field": "Det skjulte felt \"challenge\" er et påkrævet felt",
|
||||||
|
"Albanian": "Albansk",
|
||||||
|
"preferences_quality_dash_label": "Fortrukket DASH video kvalitet: ",
|
||||||
|
"search_filters_features_option_live": "Direkte",
|
||||||
|
"Lao": "Lao-tse",
|
||||||
|
"Filipino": "Filippinsk",
|
||||||
|
"Greek": "Græsk",
|
||||||
|
"Kurdish": "Kurdisk",
|
||||||
|
"Malay": "Malaysisk",
|
||||||
|
"Romanian": "Rumænsk",
|
||||||
|
"Somali": "Somalisk",
|
||||||
|
"preferences_locale_label": "Sprog: ",
|
||||||
|
"News": "Nyheder",
|
||||||
|
"permalink": "permalink",
|
||||||
|
"search_filters_sort_option_date": "Upload dato",
|
||||||
|
"search_filters_features_label": "Funktioner",
|
||||||
|
"Khmer": "Khmer",
|
||||||
|
"Finnish": "Finsk",
|
||||||
|
"search_filters_date_option_week": "Denne uge",
|
||||||
|
"Korean": "Koreansk",
|
||||||
|
"Telugu": "Telugu",
|
||||||
|
"Malayalam": "Malayalam",
|
||||||
|
"View as playlist": "Se som spilleliste",
|
||||||
|
"Hungarian": "Ungarsk",
|
||||||
|
"Welsh": "Walisisk",
|
||||||
|
"search_filters_features_option_subtitles": "Undertekster/CC",
|
||||||
|
"Bosnian": "Bosnisk",
|
||||||
|
"Yiddish": "Jiddisch",
|
||||||
|
"Belarusian": "Belarussisk",
|
||||||
|
"search_filters_date_option_today": "I dag",
|
||||||
|
"Shona": "Shona",
|
||||||
|
"Slovenian": "Slovensk",
|
||||||
|
"Gaming": "Gaming",
|
||||||
|
"Bangla": "Bengali",
|
||||||
|
"Swahili": "Swahili",
|
||||||
|
"`x` marked it with a ❤": "`x`markeret med et ❤",
|
||||||
|
"Kyrgyz": "Kirgisisk",
|
||||||
|
"Turkish": "Tyrkisk",
|
||||||
|
"adminprefs_modified_source_code_url_label": "URL-adresse til modificeret kildekodelager",
|
||||||
|
"Switch Invidious Instance": "Skift Invidious instans",
|
||||||
|
"Samoan": "Samoansk",
|
||||||
|
"Spanish": "Spansk",
|
||||||
|
"%A %B %-d, %Y": "%A %B %-d, %Y",
|
||||||
|
"footer_documentation": "Dokumentation",
|
||||||
|
"Pashto": "Pashto",
|
||||||
|
"footer_modfied_source_code": "Modificeret Kildekode",
|
||||||
|
"Released under the AGPLv3 on Github.": "Udgivet under AGPLv3 på GitHub.",
|
||||||
|
"Tajik": "Tadsjikisk",
|
||||||
|
"search_filters_date_option_month": "Denne måned",
|
||||||
|
"Hebrew": "Hebraisk",
|
||||||
|
"Kannada": "Kannada",
|
||||||
|
"Current version: ": "Nuværende version: ",
|
||||||
|
"Amharic": "Amharisk",
|
||||||
|
"Swedish": "Svensk",
|
||||||
|
"Corsican": "Korsikansk",
|
||||||
|
"search_filters_type_option_movie": "Film",
|
||||||
|
"Could not pull trending pages.": "Kunne ikke hente trending sider.",
|
||||||
|
"English": "Engelsk",
|
||||||
|
"search_filters_features_option_hd": "HD",
|
||||||
|
"Hausa": "Islandsk",
|
||||||
|
"search_filters_date_option_year": "Dette år",
|
||||||
|
"Japanese": "Japansk",
|
||||||
|
"search_filters_type_label": "Type",
|
||||||
|
"Icelandic": "Islandsk",
|
||||||
|
"Basque": "Baskisk",
|
||||||
|
"search_filters_sort_option_rating": "Bedømmelse",
|
||||||
|
"Yoruba": "Yoruba",
|
||||||
|
"Erroneous token": "Fejlagtig token",
|
||||||
|
"Videos": "Videoer",
|
||||||
|
"search_filters_type_option_show": "Vis",
|
||||||
|
"Luxembourgish": "Luxemboursk",
|
||||||
|
"Vietnamese": "Vietnamesisk",
|
||||||
|
"Latvian": "Lettisk",
|
||||||
|
"Indonesian": "Indonesisk",
|
||||||
|
"search_filters_duration_label": "Varighed",
|
||||||
|
"footer_original_source_code": "Original kildekode",
|
||||||
|
"Search": "Søg",
|
||||||
|
"Serbian": "Serbisk",
|
||||||
|
"Armenian": "Armensk",
|
||||||
|
"Bulgarian": "Bulgarsk",
|
||||||
|
"French": "Fransk",
|
||||||
|
"Burmese": "Burmesisk",
|
||||||
|
"Macedonian": "Makedonsk",
|
||||||
|
"Southern Sotho": "Sydlige Sotho",
|
||||||
|
"About": "Omkring",
|
||||||
|
"Malagasy": "Madagaskiske",
|
||||||
|
"Rating: ": "Bedømmelse: ",
|
||||||
|
"Movies": "Film",
|
||||||
|
"YouTube comment permalink": "Youtube kommentarer permalink",
|
||||||
|
"search_filters_features_option_location": "Lokation",
|
||||||
|
"search_filters_features_option_hdr": "HDR",
|
||||||
|
"Cebuano": "Cebuano (Sugbuanon)",
|
||||||
|
"Nyanja": "Nyanja",
|
||||||
|
"Chinese (Simplified)": "Kinesisk (forenklet)",
|
||||||
|
"Chinese (Traditional)": "Kinesisk (traditionelt)",
|
||||||
|
"Dutch": "Hollandsk",
|
||||||
|
"Estonian": "Estisk",
|
||||||
|
"preferences_automatic_instance_redirect_label": "Automatisk eksempel omdirigering (Fallback til redirect.invidious.io): ",
|
||||||
|
"Nepali": "Nepalesisk",
|
||||||
|
"Norwegian Bokmål": "Norsk Bokmål",
|
||||||
|
"(edited)": "(ændret)",
|
||||||
|
"preferences_show_nick_label": "Vis kælenavn på toppen: ",
|
||||||
|
"Galician": "Galisisk",
|
||||||
|
"German": "Tysk",
|
||||||
|
"Maori": "Maori",
|
||||||
|
"Slovak": "Slovakisk",
|
||||||
|
"search_filters_sort_option_relevance": "Relevans",
|
||||||
|
"search_filters_date_option_hour": "Sidste time",
|
||||||
|
"search_filters_type_option_playlist": "Spilleliste",
|
||||||
|
"search_filters_duration_option_long": "Lang (> 20 minutter)",
|
||||||
|
"search_filters_features_option_c_commons": "Creative Commons",
|
||||||
|
"Marathi": "Marathi",
|
||||||
|
"Sindhi": "Sindhi",
|
||||||
|
"preferences_category_misc": "Diverse indstillinger",
|
||||||
|
"Erroneous challenge": "Fejlagtig udfordring",
|
||||||
|
"Hindi": "Hindi",
|
||||||
|
"Igbo": "Igbo",
|
||||||
|
"Javanese": "Javanesisk",
|
||||||
|
"Kazakh": "Kasabhisk",
|
||||||
|
"Latin": "Latinsk",
|
||||||
|
"Lithuanian": "Lituaisk",
|
||||||
|
"Mongolian": "Mongolsk",
|
||||||
|
"Spanish (Latin America)": "Spansk (Latinamerika)",
|
||||||
|
"Uzbek": "Usbekisk",
|
||||||
|
"Western Frisian": "Vestfrisisk",
|
||||||
|
"Top": "Top",
|
||||||
|
"Music": "Musik",
|
||||||
|
"search_filters_sort_option_views": "Antal visninger",
|
||||||
|
"search_filters_sort_label": "Sorter efter",
|
||||||
|
"Zulu": "Zulu",
|
||||||
|
"Invidious Private Feed for `x`": "Invidious Privat Feed til `x`",
|
||||||
|
"English (auto-generated)": "Engelsk (autogenereret)",
|
||||||
|
"Arabic": "Arabisk",
|
||||||
|
"Croatian": "Kroatisk",
|
||||||
|
"Hawaiian": "Hawaiiansk",
|
||||||
|
"Maltese": "Maltesisk",
|
||||||
|
"Polish": "Polsk",
|
||||||
|
"Russian": "Russisk",
|
||||||
|
"Download": "Hent",
|
||||||
|
"Download as: ": "Hent som: ",
|
||||||
|
"Playlists": "Spillelister",
|
||||||
|
"next_steps_error_message_refresh": "Opdater",
|
||||||
|
"next_steps_error_message_go_to_youtube": "Gå til Youtube",
|
||||||
|
"footer_source_code": "Kildekode",
|
||||||
|
"Tamil": "Tamil",
|
||||||
|
"Xhosa": "Xhosa",
|
||||||
|
"next_steps_error_message": "Efter det burde du prøve at: ",
|
||||||
|
"Sinhala": "Singalesisk (Sinhala)",
|
||||||
|
"Thai": "Thai",
|
||||||
|
"No such user": "Brugeren findes ikke",
|
||||||
|
"Token is expired, please try again": "Token er udløbet, prøv igen",
|
||||||
|
"Catalan": "Catalansk",
|
||||||
|
"Haitian Creole": "Haitiansk",
|
||||||
|
"Irish": "Irsk",
|
||||||
|
"Persian": "Persisk",
|
||||||
|
"Scottish Gaelic": "Skotsk Gælisk",
|
||||||
|
"Default": "Standard",
|
||||||
|
"Video mode": "Videotilstand",
|
||||||
|
"search_filters_duration_option_short": "Kort (< 4 minutter)",
|
||||||
|
"Hidden field \"token\" is a required field": "Det skjulte felt \"token\" er et påkrævet felt",
|
||||||
|
"Azerbaijani": "Aserbajdsjansk",
|
||||||
|
"Georgian": "Georgisk",
|
||||||
|
"Italian": "Italiensk",
|
||||||
|
"Audio mode": "Lydtilstand",
|
||||||
|
"search_filters_type_option_video": "Video",
|
||||||
|
"search_filters_type_option_channel": "Kanal",
|
||||||
|
"search_filters_features_option_three_d": "3D",
|
||||||
|
"search_filters_features_option_four_k": "4K",
|
||||||
|
"Hmong": "Hmong",
|
||||||
|
"preferences_quality_option_medium": "Medium",
|
||||||
|
"preferences_quality_option_small": "Lille",
|
||||||
|
"preferences_quality_dash_option_best": "Bedste",
|
||||||
|
"preferences_quality_dash_option_worst": "Værste",
|
||||||
|
"preferences_quality_dash_option_4320p": "4320p",
|
||||||
|
"preferences_quality_dash_option_1080p": "1080p",
|
||||||
|
"preferences_quality_dash_option_720p": "720p",
|
||||||
|
"preferences_quality_dash_option_480p": "480p",
|
||||||
|
"preferences_quality_dash_option_360p": "360p",
|
||||||
|
"preferences_quality_dash_option_144p": "144p",
|
||||||
|
"invidious": "Invidious",
|
||||||
|
"search_filters_features_option_purchased": "Købt",
|
||||||
|
"search_filters_features_option_three_sixty": "360°",
|
||||||
|
"none": "ingen",
|
||||||
|
"videoinfo_started_streaming_x_ago": "Streamen blev startet for `x`siden",
|
||||||
|
"videoinfo_watch_on_youTube": "Se på YouTube",
|
||||||
|
"videoinfo_youTube_embed_link": "Integrer",
|
||||||
|
"videoinfo_invidious_embed_link": "Integrer Link",
|
||||||
|
"download_subtitles": "Undertekster - `x`(.vtt)",
|
||||||
|
"user_created_playlists": "`x`opretede spillelister",
|
||||||
|
"user_saved_playlists": "´x`gemte spillelister",
|
||||||
|
"Video unavailable": "Video ikke tilgængelig",
|
||||||
|
"preferences_save_player_pos_label": "Gem afspilningsposition: ",
|
||||||
|
"preferences_quality_dash_option_auto": "Auto",
|
||||||
|
"preferences_quality_option_hd720": "HD720",
|
||||||
|
"preferences_quality_dash_option_2160p": "2160p",
|
||||||
|
"preferences_quality_option_dash": "DASH (adaptiv kvalitet)",
|
||||||
|
"preferences_quality_dash_option_1440p": "1440p",
|
||||||
|
"preferences_quality_dash_option_240p": "240p",
|
||||||
|
"subscriptions_unseen_notifs_count": "{{count}} uset notifikation",
|
||||||
|
"subscriptions_unseen_notifs_count_plural": "{{count}} usete notifikationer",
|
||||||
|
"comments_view_x_replies": "Vis {{count}} svar",
|
||||||
|
"comments_view_x_replies_plural": "Vis {{count}} svar",
|
||||||
|
"comments_points_count": "{{count}} point",
|
||||||
|
"comments_points_count_plural": "{{count}} point",
|
||||||
|
"generic_count_years": "{{count}} år",
|
||||||
|
"generic_count_years_plural": "{{count}} år",
|
||||||
|
"generic_count_months": "{{count}} måned",
|
||||||
|
"generic_count_months_plural": "{{count}} måneder",
|
||||||
|
"generic_count_days": "{{count}} dag",
|
||||||
|
"generic_count_days_plural": "{{count}} dage",
|
||||||
|
"generic_count_minutes": "{{count}} minut",
|
||||||
|
"generic_count_minutes_plural": "{{count}} minutter",
|
||||||
|
"generic_count_seconds": "{{count}} sekund",
|
||||||
|
"generic_count_seconds_plural": "{{count}} sekunder",
|
||||||
|
"generic_subscribers_count": "{{count}} abonnent",
|
||||||
|
"generic_subscribers_count_plural": "{{count}} abonnenter",
|
||||||
|
"generic_subscriptions_count": "{{count}} abonnement",
|
||||||
|
"generic_subscriptions_count_plural": "{{count}} abonnementer",
|
||||||
|
"generic_videos_count": "{{count}} video",
|
||||||
|
"generic_videos_count_plural": "{{count}} videoer",
|
||||||
|
"English (United States)": "Engelsk (USA)",
|
||||||
|
"French (auto-generated)": "Fransk (autogenereret)",
|
||||||
|
"Spanish (auto-generated)": "Spansk (autogenereret)",
|
||||||
|
"crash_page_before_reporting": "Før du rapporterer en fejl, skal du sikre dig, at du har:",
|
||||||
|
"crash_page_refresh": "forsøgte at <a href=\"`x`\">opdatere siden</a>",
|
||||||
|
"generic_playlists_count": "{{count}} spilleliste",
|
||||||
|
"generic_playlists_count_plural": "{{count}} spillelister",
|
||||||
|
"preferences_watch_history_label": "Aktiver afspilningshistorik: ",
|
||||||
|
"tokens_count": "{{count}} token",
|
||||||
|
"tokens_count_plural": "{{count}} tokens",
|
||||||
|
"Cantonese (Hong Kong)": "Kantonesisk (Hongkong)",
|
||||||
|
"Chinese": "Kinesisk",
|
||||||
|
"Chinese (China)": "Kinesisk (Kina)",
|
||||||
|
"Chinese (Hong Kong)": "Kinesisk (Hongkong)",
|
||||||
|
"Chinese (Taiwan)": "Kinesisk (Taiwan)",
|
||||||
|
"Dutch (auto-generated)": "Hollandsk (autogenereret)",
|
||||||
|
"Indonesian (auto-generated)": "Indonesisk (autogenereret)",
|
||||||
|
"Interlingue": "Interlingue",
|
||||||
|
"Japanese (auto-generated)": "Japansk (autogenereret)",
|
||||||
|
"Korean (auto-generated)": "Koreansk (autogenereret)",
|
||||||
|
"Russian (auto-generated)": "Russisk (autogenereret)",
|
||||||
|
"Turkish (auto-generated)": "Tyrkisk (autogenereret)",
|
||||||
|
"Vietnamese (auto-generated)": "Vietnamesisk (autogenereret)",
|
||||||
|
"crash_page_report_issue": "Hvis intet af ovenstående hjalp, bedes du <a href=\"`x`\">åbne et nyt problem på GitHub</a> (helst på engelsk) og inkludere følgende tekst i din besked (oversæt IKKE denne tekst):",
|
||||||
|
"English (United Kingdom)": "Engelsk (Storbritannien)",
|
||||||
|
"Italian (auto-generated)": "Italiensk (autogenereret)",
|
||||||
|
"Portuguese (auto-generated)": "Portugisisk (autogenereret)",
|
||||||
|
"Portuguese (Brazil)": "Portugisisk (Brasilien)",
|
||||||
|
"generic_views_count": "{{count}} visning",
|
||||||
|
"generic_views_count_plural": "{{count}} visninger",
|
||||||
|
"generic_count_hours": "{{count}} time",
|
||||||
|
"generic_count_hours_plural": "{{count}} timer",
|
||||||
|
"Spanish (Spain)": "Spansk (Spanien)",
|
||||||
|
"crash_page_switch_instance": "forsøgte at <a href=\"`x`\">bruge en anden instans</a>",
|
||||||
|
"German (auto-generated)": "Tysk (autogenereret)",
|
||||||
|
"Spanish (Mexico)": "Spansk (Mexico)",
|
||||||
|
"generic_count_weeks": "{{count}} uge",
|
||||||
|
"generic_count_weeks_plural": "{{count}} uger",
|
||||||
|
"crash_page_you_found_a_bug": "Det ser ud til, at du har fundet en fejl i Invidious!",
|
||||||
|
"crash_page_read_the_faq": "læs <a href=\"`x`\">Ofte stillede spørgsmål (FAQ)</a>",
|
||||||
|
"crash_page_search_issue": "søgte efter <a href=\"`x`\">eksisterende problemer på GitHub</a>",
|
||||||
|
"search_filters_title": "Filter"
|
||||||
|
}
|
||||||
313
locales/de.json
313
locales/de.json
@@ -1,22 +1,19 @@
|
|||||||
{
|
{
|
||||||
"`x` subscribers": "`x` Abonnenten",
|
|
||||||
"`x` videos": "`x` Videos",
|
|
||||||
"`x` playlists": "",
|
|
||||||
"LIVE": "LIVE",
|
"LIVE": "LIVE",
|
||||||
"Shared `x` ago": "Vor `x` geteilt",
|
"Shared `x` ago": "Vor `x` geteilt",
|
||||||
"Unsubscribe": "Abbestellen",
|
"Unsubscribe": "Abo beenden",
|
||||||
"Subscribe": "Abonnieren",
|
"Subscribe": "Abonnieren",
|
||||||
"View channel on YouTube": "Kanal auf YouTube anzeigen",
|
"View channel on YouTube": "Kanal auf YouTube anzeigen",
|
||||||
"View playlist on YouTube": "Wiedergabeliste auf YouTube anzeigen",
|
"View playlist on YouTube": "Wiedergabeliste auf YouTube anzeigen",
|
||||||
"newest": "neueste",
|
"newest": "neueste",
|
||||||
"oldest": "älteste",
|
"oldest": "älteste",
|
||||||
"popular": "beliebt",
|
"popular": "beliebteste",
|
||||||
"last": "letzte",
|
"last": "neueste",
|
||||||
"Next page": "Nächste Seite",
|
"Next page": "Nächste Seite",
|
||||||
"Previous page": "Vorherige Seite",
|
"Previous page": "Vorherige Seite",
|
||||||
"Clear watch history?": "Verlauf löschen?",
|
"Clear watch history?": "Verlauf löschen?",
|
||||||
"New password": "Neues Passwort",
|
"New password": "Neues Passwort",
|
||||||
"New passwords must match": "Neue Passwörter müssen gleich sein",
|
"New passwords must match": "Neue Passwörter müssen übereinstimmen",
|
||||||
"Cannot change password for Google accounts": "Ich kann das Passwort deines Google Kontos nicht ändern",
|
"Cannot change password for Google accounts": "Ich kann das Passwort deines Google Kontos nicht ändern",
|
||||||
"Authorize token?": "Token autorisieren?",
|
"Authorize token?": "Token autorisieren?",
|
||||||
"Authorize token for `x`?": "Token für `x` autorisieren?",
|
"Authorize token for `x`?": "Token für `x` autorisieren?",
|
||||||
@@ -24,24 +21,24 @@
|
|||||||
"No": "Nein",
|
"No": "Nein",
|
||||||
"Import and Export Data": "Daten importieren und exportieren",
|
"Import and Export Data": "Daten importieren und exportieren",
|
||||||
"Import": "Importieren",
|
"Import": "Importieren",
|
||||||
"Import Invidious data": "Invidious Daten importieren",
|
"Import Invidious data": "Invidious-JSON-Daten importieren",
|
||||||
"Import YouTube subscriptions": "YouTube Abonnements importieren",
|
"Import YouTube subscriptions": "YouTube-/OPML-Abonnements importieren",
|
||||||
"Import FreeTube subscriptions (.db)": "FreeTube Abonnements importieren (.db)",
|
"Import FreeTube subscriptions (.db)": "FreeTube Abonnements importieren (.db)",
|
||||||
"Import NewPipe subscriptions (.json)": "NewPipe Abonnements importieren (.json)",
|
"Import NewPipe subscriptions (.json)": "NewPipe Abonnements importieren (.json)",
|
||||||
"Import NewPipe data (.zip)": "NewPipe Daten importieren (.zip)",
|
"Import NewPipe data (.zip)": "NewPipe Daten importieren (.zip)",
|
||||||
"Export": "Exportieren",
|
"Export": "Exportieren",
|
||||||
"Export subscriptions as OPML": "Abonnements als OPML exportieren",
|
"Export subscriptions as OPML": "Abonnements als OPML exportieren",
|
||||||
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Abonnements als OPML exportieren (für NewPipe & FreeTube)",
|
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Abonnements als OPML exportieren (für NewPipe & FreeTube)",
|
||||||
"Export data as JSON": "Daten als JSON exportieren",
|
"Export data as JSON": "Invidious-Daten als JSON exportieren",
|
||||||
"Delete account?": "Account löschen?",
|
"Delete account?": "Konto löschen?",
|
||||||
"History": "Verlauf",
|
"History": "Verlauf",
|
||||||
"An alternative front-end to YouTube": "Eine alternative Oberfläche für YouTube",
|
"An alternative front-end to YouTube": "Eine alternative Oberfläche für YouTube",
|
||||||
"JavaScript license information": "JavaScript Lizenzinformationen",
|
"JavaScript license information": "JavaScript Lizenzinformationen",
|
||||||
"source": "Quelle",
|
"source": "Quelle",
|
||||||
"Log in": "Einloggen",
|
"Log in": "Anmelden",
|
||||||
"Log in/register": "Einloggen/Registrieren",
|
"Log in/register": "Anmelden/registrieren",
|
||||||
"Log in with Google": "Mit Google einloggen",
|
"Log in with Google": "Mit Google anmelden",
|
||||||
"User ID": "Benutzer ID",
|
"User ID": "Benutzer-ID",
|
||||||
"Password": "Passwort",
|
"Password": "Passwort",
|
||||||
"Time (h:mm:ss):": "Zeit (h:mm:ss):",
|
"Time (h:mm:ss):": "Zeit (h:mm:ss):",
|
||||||
"Text CAPTCHA": "Text CAPTCHA",
|
"Text CAPTCHA": "Text CAPTCHA",
|
||||||
@@ -51,35 +48,39 @@
|
|||||||
"E-mail": "E-Mail",
|
"E-mail": "E-Mail",
|
||||||
"Google verification code": "Google-Bestätigungscode",
|
"Google verification code": "Google-Bestätigungscode",
|
||||||
"Preferences": "Einstellungen",
|
"Preferences": "Einstellungen",
|
||||||
"Player preferences": "Wiedergabeeinstellungen",
|
"preferences_category_player": "Wiedergabeeinstellungen",
|
||||||
"Always loop: ": "Immer wiederholen: ",
|
"preferences_video_loop_label": "Immer wiederholen: ",
|
||||||
"Autoplay: ": "Automatisch abspielen: ",
|
"preferences_autoplay_label": "Automatisch abspielen: ",
|
||||||
"Play next by default: ": "Immer automatisch nächstes Video spielen: ",
|
"preferences_continue_label": "Immer automatisch nächstes Video abspielen: ",
|
||||||
"Autoplay next video: ": "nächstes Video automatisch abspielen: ",
|
"preferences_continue_autoplay_label": "Nächstes Video automatisch abspielen: ",
|
||||||
"Listen by default: ": "Nur Ton als Standard: ",
|
"preferences_listen_label": "Nur Ton als Standard: ",
|
||||||
"Proxy videos: ": "Proxy-Videos: ",
|
"preferences_local_label": "Videos durch Proxy leiten: ",
|
||||||
"Default speed: ": "Standardgeschwindigkeit: ",
|
"preferences_speed_label": "Standardgeschwindigkeit: ",
|
||||||
"Preferred video quality: ": "Bevorzugte Videoqualität: ",
|
"preferences_quality_label": "Bevorzugte Videoqualität: ",
|
||||||
"Player volume: ": "Wiedergabelautstärke: ",
|
"preferences_volume_label": "Wiedergabelautstärke: ",
|
||||||
"Default comments: ": "Standardkommentare: ",
|
"preferences_comments_label": "Standardkommentare: ",
|
||||||
"youtube": "youtube",
|
"youtube": "YouTube",
|
||||||
"reddit": "reddit",
|
"reddit": "Reddit",
|
||||||
"Default captions: ": "Standarduntertitel: ",
|
"preferences_captions_label": "Standarduntertitel: ",
|
||||||
"Fallback captions: ": "Ersatzuntertitel: ",
|
"Fallback captions: ": "Ersatzuntertitel: ",
|
||||||
"Show related videos: ": "Ähnliche Videos anzeigen? ",
|
"preferences_related_videos_label": "Ähnliche Videos anzeigen: ",
|
||||||
"Show annotations by default: ": "Standardmäßig Anmerkungen anzeigen? ",
|
"preferences_annotations_label": "Anmerkungen standardmäßig anzeigen: ",
|
||||||
"Visual preferences": "Anzeigeeinstellungen",
|
"preferences_extend_desc_label": "Videobeschreibung automatisch erweitern: ",
|
||||||
"Player style: ": "Abspielgeräterstil: ",
|
"preferences_vr_mode_label": "Interaktive 360-Grad-Videos (erfordert WebGL): ",
|
||||||
|
"preferences_category_visual": "Anzeigeeinstellungen",
|
||||||
|
"preferences_player_style_label": "Player-Stil: ",
|
||||||
"Dark mode: ": "Nachtmodus: ",
|
"Dark mode: ": "Nachtmodus: ",
|
||||||
"Theme: ": "Modus: ",
|
"preferences_dark_mode_label": "Modus: ",
|
||||||
"dark": "Nachtmodus",
|
"dark": "Nachtmodus",
|
||||||
"light": "klarer Modus",
|
"light": "hell",
|
||||||
"Thin mode: ": "Schlanker Modus: ",
|
"preferences_thin_mode_label": "Schlanker Modus: ",
|
||||||
"Subscription preferences": "Abonnementeinstellungen",
|
"preferences_category_misc": "Sonstige Einstellungen",
|
||||||
"Show annotations by default for subscribed channels: ": "Anmerkungen für abonnierte Kanäle standardmäßig anzeigen? ",
|
"preferences_automatic_instance_redirect_label": "Automatische Instanzweiterleitung (über redirect.invidious.io): ",
|
||||||
|
"preferences_category_subscription": "Abonnementeinstellungen",
|
||||||
|
"preferences_annotations_subscribed_label": "Anmerkungen für abonnierte Kanäle standardmäßig anzeigen? ",
|
||||||
"Redirect homepage to feed: ": "Startseite zu Feed umleiten: ",
|
"Redirect homepage to feed: ": "Startseite zu Feed umleiten: ",
|
||||||
"Number of videos shown in feed: ": "Anzahl von Videos die im Feed angezeigt werden: ",
|
"preferences_max_results_label": "Anzahl von Videos die im Feed angezeigt werden: ",
|
||||||
"Sort videos by: ": "Videos sortieren nach: ",
|
"preferences_sort_label": "Videos sortieren nach: ",
|
||||||
"published": "veröffentlicht",
|
"published": "veröffentlicht",
|
||||||
"published - reverse": "veröffentlicht - invertiert",
|
"published - reverse": "veröffentlicht - invertiert",
|
||||||
"alphabetically": "alphabetisch",
|
"alphabetically": "alphabetisch",
|
||||||
@@ -88,57 +89,58 @@
|
|||||||
"channel name - reverse": "Kanalname - invertiert",
|
"channel name - reverse": "Kanalname - invertiert",
|
||||||
"Only show latest video from channel: ": "Nur neueste Videos des Kanals anzeigen: ",
|
"Only show latest video from channel: ": "Nur neueste Videos des Kanals anzeigen: ",
|
||||||
"Only show latest unwatched video from channel: ": "Nur neueste ungesehene Videos des Kanals anzeigen: ",
|
"Only show latest unwatched video from channel: ": "Nur neueste ungesehene Videos des Kanals anzeigen: ",
|
||||||
"Only show unwatched: ": "Nur ungesehene anzeigen: ",
|
"preferences_unseen_only_label": "Nur ungesehene anzeigen: ",
|
||||||
"Only show notifications (if there are any): ": "Nur Benachrichtigungen anzeigen (wenn es welche gibt): ",
|
"preferences_notifications_only_label": "Nur Benachrichtigungen anzeigen (wenn es welche gibt): ",
|
||||||
"Enable web notifications": "Webbenachrichtigungen aktivieren",
|
"Enable web notifications": "Webbenachrichtigungen aktivieren",
|
||||||
"`x` uploaded a video": "`x` hat ein Video hochgeladen",
|
"`x` uploaded a video": "`x` hat ein Video hochgeladen",
|
||||||
"`x` is live": "`x` ist live",
|
"`x` is live": "`x` ist live",
|
||||||
"Data preferences": "Dateneinstellungen",
|
"preferences_category_data": "Dateneinstellungen",
|
||||||
"Clear watch history": "Verlauf löschen",
|
"Clear watch history": "Verlauf löschen",
|
||||||
"Import/export data": "Daten im-/exportieren",
|
"Import/export data": "Daten importieren/exportieren",
|
||||||
"Change password": "Passwort ändern",
|
"Change password": "Passwort ändern",
|
||||||
"Manage subscriptions": "Abonnements verwalten",
|
"Manage subscriptions": "Abonnements verwalten",
|
||||||
"Manage tokens": "Tokens verwalten",
|
"Manage tokens": "Tokens verwalten",
|
||||||
"Watch history": "Verlauf",
|
"Watch history": "Verlauf",
|
||||||
"Delete account": "Account löschen",
|
"Delete account": "Account löschen",
|
||||||
"Administrator preferences": "Administrator-Einstellungen",
|
"preferences_category_admin": "Administrator-Einstellungen",
|
||||||
"Default homepage: ": "Standard-Startseite: ",
|
"preferences_default_home_label": "Standard-Startseite: ",
|
||||||
"Feed menu: ": "Feed-Menü: ",
|
"preferences_feed_menu_label": "Feed-Menü: ",
|
||||||
|
"preferences_show_nick_label": "Nutzernamen oben anzeigen: ",
|
||||||
"Top enabled: ": "Top aktiviert? ",
|
"Top enabled: ": "Top aktiviert? ",
|
||||||
"CAPTCHA enabled: ": "CAPTCHA aktiviert? ",
|
"CAPTCHA enabled: ": "CAPTCHA aktiviert? ",
|
||||||
"Login enabled: ": "Login aktiviert? ",
|
"Login enabled: ": "Anmeldung aktiviert: ",
|
||||||
"Registration enabled: ": "Registrierung aktiviert? ",
|
"Registration enabled: ": "Registrierung aktiviert? ",
|
||||||
"Report statistics: ": "Statistiken berichten? ",
|
"Report statistics: ": "Statistiken berichten? ",
|
||||||
"Save preferences": "Einstellungen speichern",
|
"Save preferences": "Einstellungen speichern",
|
||||||
"Subscription manager": "Abonnementverwaltung",
|
"Subscription manager": "Abonnementverwaltung",
|
||||||
"Token manager": "Tokenverwalter",
|
"Token manager": "Tokenverwalter",
|
||||||
"Token": "Token",
|
"Token": "Token",
|
||||||
"`x` subscriptions": "`x` Abonnements",
|
|
||||||
"`x` tokens": "`x` Tokens",
|
|
||||||
"Import/export": "Importieren/Exportieren",
|
"Import/export": "Importieren/Exportieren",
|
||||||
"unsubscribe": "abbestellen",
|
"unsubscribe": "abbestellen",
|
||||||
"revoke": "widerrufen",
|
"revoke": "widerrufen",
|
||||||
"Subscriptions": "Abonnements",
|
"Subscriptions": "Abonnements",
|
||||||
"`x` unseen notifications": "`x` ungesehene Benachrichtigungen",
|
|
||||||
"search": "Suchen",
|
"search": "Suchen",
|
||||||
"Log out": "Abmelden",
|
"Log out": "Abmelden",
|
||||||
"Released under the AGPLv3 by Omar Roth.": "Veröffentlicht unter AGPLv3 von Omar Roth.",
|
"Released under the AGPLv3 on Github.": "Auf GitHub unter der AGPLv3 Lizenz veröffentlicht.",
|
||||||
"Source available here.": "Quellcode verfügbar hier.",
|
"Source available here.": "Quellcode verfügbar hier.",
|
||||||
"View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.",
|
"View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.",
|
||||||
"View privacy policy.": "Datenschutzerklärung einsehen.",
|
"View privacy policy.": "Datenschutzerklärung einsehen.",
|
||||||
"Trending": "Trending",
|
"Trending": "Angesagt",
|
||||||
"Public": "",
|
"Public": "Öffentlich",
|
||||||
"Unlisted": "Nicht aufgeführt",
|
"Unlisted": "Nicht aufgeführt",
|
||||||
"Private": "",
|
"Private": "Privat",
|
||||||
"View all playlists": "",
|
"View all playlists": "Alle Wiedergabelisten anzeigen",
|
||||||
"Updated `x` ago": "",
|
"Updated `x` ago": "Aktualisiert `x` vor",
|
||||||
"Delete playlist `x`?": "",
|
"Delete playlist `x`?": "Wiedergabeliste löschen `x`?",
|
||||||
"Delete playlist": "",
|
"Delete playlist": "Wiedergabeliste löschen",
|
||||||
"Create playlist": "",
|
"Create playlist": "Wiedergabeliste erstellen",
|
||||||
"Title": "",
|
"Title": "Titel",
|
||||||
"Playlist privacy": "",
|
"Playlist privacy": "Vertrauliche Wiedergabeliste",
|
||||||
"Editing playlist `x`": "",
|
"Editing playlist `x`": "Wiedergabeliste bearbeiten `x`",
|
||||||
|
"Show more": "Mehr anzeigen",
|
||||||
|
"Show less": "Weniger anzeigen",
|
||||||
"Watch on YouTube": "Video auf YouTube ansehen",
|
"Watch on YouTube": "Video auf YouTube ansehen",
|
||||||
|
"Switch Invidious Instance": "Invidious Instanz wechseln",
|
||||||
"Hide annotations": "Anmerkungen ausblenden",
|
"Hide annotations": "Anmerkungen ausblenden",
|
||||||
"Show annotations": "Anmerkungen anzeigen",
|
"Show annotations": "Anmerkungen anzeigen",
|
||||||
"Genre: ": "Genre: ",
|
"Genre: ": "Genre: ",
|
||||||
@@ -149,28 +151,30 @@
|
|||||||
"Whitelisted regions: ": "Erlaubte Regionen: ",
|
"Whitelisted regions: ": "Erlaubte Regionen: ",
|
||||||
"Blacklisted regions: ": "Unerlaubte Regionen: ",
|
"Blacklisted regions: ": "Unerlaubte Regionen: ",
|
||||||
"Shared `x`": "Geteilt `x`",
|
"Shared `x`": "Geteilt `x`",
|
||||||
"`x` views": "`x` Aufrufe",
|
|
||||||
"Premieres in `x`": "Zuerst gesehen in `x`",
|
"Premieres in `x`": "Zuerst gesehen in `x`",
|
||||||
"Premieres `x`": "Erster Start `x`",
|
"Premieres `x`": "Erster Start `x`",
|
||||||
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.",
|
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.",
|
||||||
"View YouTube comments": "YouTube Kommentare anzeigen",
|
"View YouTube comments": "YouTube Kommentare anzeigen",
|
||||||
"View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen",
|
"View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen",
|
||||||
"View `x` comments": "`x` Kommentare anzeigen",
|
"View `x` comments": {
|
||||||
|
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` Kommentare anzeigen",
|
||||||
|
"": "`x` Kommentare anzeigen"
|
||||||
|
},
|
||||||
"View Reddit comments": "Reddit Kommentare anzeigen",
|
"View Reddit comments": "Reddit Kommentare anzeigen",
|
||||||
"Hide replies": "Antworten verstecken",
|
"Hide replies": "Antworten verstecken",
|
||||||
"Show replies": "Antworten anzeigen",
|
"Show replies": "Antworten anzeigen",
|
||||||
"Incorrect password": "Falsches Passwort",
|
"Incorrect password": "Falsches Passwort",
|
||||||
"Quota exceeded, try again in a few hours": "Kontingent überschritten, versuche es in ein paar Stunden erneut",
|
"Quota exceeded, try again in a few hours": "Kontingent überschritten, versuche es in ein paar Stunden erneut",
|
||||||
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Login nicht möglich, stellen Sie sicher dass two-factor Authentifikation (Authentifizierung oder SMS) aktiviert ist.",
|
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Anmeldung nicht möglich, stellen Sie sicher, dass die Zwei-Faktor-Authentisierung (Authenticator oder SMS) aktiviert ist.",
|
||||||
"Invalid TFA code": "Ungültiger TFA Code",
|
"Invalid TFA code": "Ungültiger TFA Code",
|
||||||
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Login fehlgeschlagen. Das kann daran liegen dass two-factor Authentifizierung in ihrem Account nicht aktiviert ist.",
|
"Login failed. This may be because two-factor authentication is not turned on for your account.": "Die Anmeldung ist fehlgeschlagen. Dies kann daran liegen, dass die Zwei-Faktor-Authentisierung für Ihr Konto nicht aktiviert ist.",
|
||||||
"Wrong answer": "Ungültige Antwort",
|
"Wrong answer": "Ungültige Antwort",
|
||||||
"Erroneous CAPTCHA": "Ungültiges CAPTCHA",
|
"Erroneous CAPTCHA": "Ungültiges CAPTCHA",
|
||||||
"CAPTCHA is a required field": "CAPTCHA ist eine erforderliche Eingabe",
|
"CAPTCHA is a required field": "CAPTCHA ist eine erforderliche Eingabe",
|
||||||
"User ID is a required field": "Benutzer ID ist eine erforderliche Eingabe",
|
"User ID is a required field": "Benutzer ID ist eine erforderliche Eingabe",
|
||||||
"Password is a required field": "Passwort ist eine erforderliche Eingabe",
|
"Password is a required field": "Passwort ist eine erforderliche Eingabe",
|
||||||
"Wrong username or password": "Ungültiger Benutzername oder Passwort",
|
"Wrong username or password": "Ungültiger Benutzername oder Passwort",
|
||||||
"Please sign in using 'Log in with Google'": "Bitte melden sie sich mit 'Mit Google anmelden' an",
|
"Please sign in using 'Log in with Google'": "Bitte melden Sie sich mit „Mit Google anmelden“ an",
|
||||||
"Password cannot be empty": "Passwort darf nicht leer sein",
|
"Password cannot be empty": "Passwort darf nicht leer sein",
|
||||||
"Password cannot be longer than 55 characters": "Passwort darf nicht länger als 55 Zeichen sein",
|
"Password cannot be longer than 55 characters": "Passwort darf nicht länger als 55 Zeichen sein",
|
||||||
"Please log in": "Bitte anmelden",
|
"Please log in": "Bitte anmelden",
|
||||||
@@ -180,17 +184,15 @@
|
|||||||
"This channel does not exist.": "Dieser Kanal existiert nicht.",
|
"This channel does not exist.": "Dieser Kanal existiert nicht.",
|
||||||
"Could not get channel info.": "Kanalinformationen konnten nicht geladen werden.",
|
"Could not get channel info.": "Kanalinformationen konnten nicht geladen werden.",
|
||||||
"Could not fetch comments": "Kommentare konnten nicht geladen werden",
|
"Could not fetch comments": "Kommentare konnten nicht geladen werden",
|
||||||
"View `x` replies": "Zeige `x` Antworten",
|
|
||||||
"`x` ago": "vor `x`",
|
"`x` ago": "vor `x`",
|
||||||
"Load more": "Mehr laden",
|
"Load more": "Mehr laden",
|
||||||
"`x` points": "`x` Punkte",
|
|
||||||
"Could not create mix.": "Mix konnte nicht erstellt werden.",
|
"Could not create mix.": "Mix konnte nicht erstellt werden.",
|
||||||
"Empty playlist": "Playlist ist leer",
|
"Empty playlist": "Wiedergabeliste ist leer",
|
||||||
"Not a playlist.": "Ungültige Playlist.",
|
"Not a playlist.": "Ungültige Wiedergabeliste.",
|
||||||
"Playlist does not exist.": "Playlist existiert nicht.",
|
"Playlist does not exist.": "Wiedergabeliste existiert nicht.",
|
||||||
"Could not pull trending pages.": "Trending Seiten konnten nicht geladen werden.",
|
"Could not pull trending pages.": "Trendenz-Seiten konnten nicht geladen werden.",
|
||||||
"Hidden field \"challenge\" is a required field": "Verstecktes Feld \"challenge\" ist eine erforderliche Eingabe",
|
"Hidden field \"challenge\" is a required field": "Verstecktes Feld „challenge“ ist eine erforderliche Eingabe",
|
||||||
"Hidden field \"token\" is a required field": "Verstecktes Feld \"token\" ist eine erforderliche Eingabe",
|
"Hidden field \"token\" is a required field": "Verstecktes Feld „token“ ist eine erforderliche Eingabe",
|
||||||
"Erroneous challenge": "Ungültiger Test",
|
"Erroneous challenge": "Ungültiger Test",
|
||||||
"Erroneous token": "Ungültiger Token",
|
"Erroneous token": "Ungültiger Token",
|
||||||
"No such user": "Ungültiger Benutzer",
|
"No such user": "Ungültiger Benutzer",
|
||||||
@@ -301,19 +303,13 @@
|
|||||||
"Yiddish": "Jiddisch",
|
"Yiddish": "Jiddisch",
|
||||||
"Yoruba": "Joruba",
|
"Yoruba": "Joruba",
|
||||||
"Zulu": "Zulu",
|
"Zulu": "Zulu",
|
||||||
"`x` years": "`x` Jahre",
|
|
||||||
"`x` months": "`x` Monate",
|
|
||||||
"`x` weeks": "`x` Wochen",
|
|
||||||
"`x` days": "`x` Tage",
|
|
||||||
"`x` hours": "`x` Stunden",
|
|
||||||
"`x` minutes": "`x` Minuten",
|
|
||||||
"`x` seconds": "`x` Sekunden",
|
|
||||||
"Fallback comments: ": "Alternative Kommentare: ",
|
"Fallback comments: ": "Alternative Kommentare: ",
|
||||||
"Popular": "Populär",
|
"Popular": "Populär",
|
||||||
|
"Search": "Suchen",
|
||||||
"Top": "Top",
|
"Top": "Top",
|
||||||
"About": "Über",
|
"About": "Über",
|
||||||
"Rating: ": "Bewertung: ",
|
"Rating: ": "Bewertung: ",
|
||||||
"Language: ": "Sprache: ",
|
"preferences_locale_label": "Sprache: ",
|
||||||
"View as playlist": "Als Wiedergabeliste anzeigen",
|
"View as playlist": "Als Wiedergabeliste anzeigen",
|
||||||
"Default": "Standard",
|
"Default": "Standard",
|
||||||
"Music": "Musik",
|
"Music": "Musik",
|
||||||
@@ -322,7 +318,7 @@
|
|||||||
"Movies": "Filme",
|
"Movies": "Filme",
|
||||||
"Download": "Herunterladen",
|
"Download": "Herunterladen",
|
||||||
"Download as: ": "Herunterladen als: ",
|
"Download as: ": "Herunterladen als: ",
|
||||||
"%A %B %-d, %Y": "%A %B %-d, %Y",
|
"%A %B %-d, %Y": "%A %-d %B %Y",
|
||||||
"(edited)": "(editiert)",
|
"(edited)": "(editiert)",
|
||||||
"YouTube comment permalink": "YouTube-Kommentar Permalink",
|
"YouTube comment permalink": "YouTube-Kommentar Permalink",
|
||||||
"permalink": "Permalink",
|
"permalink": "Permalink",
|
||||||
@@ -332,5 +328,148 @@
|
|||||||
"Videos": "Videos",
|
"Videos": "Videos",
|
||||||
"Playlists": "Wiedergabelisten",
|
"Playlists": "Wiedergabelisten",
|
||||||
"Community": "Gemeinschaft",
|
"Community": "Gemeinschaft",
|
||||||
"Current version: ": "Aktuelle Version: "
|
"search_filters_sort_option_relevance": "Relevanz",
|
||||||
}
|
"search_filters_sort_option_rating": "Bewertung",
|
||||||
|
"search_filters_sort_option_date": "Datum",
|
||||||
|
"search_filters_sort_option_views": "Aufrufe",
|
||||||
|
"search_filters_type_label": "Inhaltstyp",
|
||||||
|
"search_filters_duration_label": "Dauer",
|
||||||
|
"search_filters_features_label": "Eigenschaften",
|
||||||
|
"search_filters_sort_label": "sortieren",
|
||||||
|
"search_filters_date_option_hour": "Letzte Stunde",
|
||||||
|
"search_filters_date_option_today": "Heute",
|
||||||
|
"search_filters_date_option_week": "Diese Woche",
|
||||||
|
"search_filters_date_option_month": "Diesen Monat",
|
||||||
|
"search_filters_date_option_year": "Dieses Jahr",
|
||||||
|
"search_filters_type_option_video": "Video",
|
||||||
|
"search_filters_type_option_channel": "Kanal",
|
||||||
|
"search_filters_type_option_playlist": "Wiedergabeliste",
|
||||||
|
"search_filters_type_option_movie": "Film",
|
||||||
|
"search_filters_type_option_show": "Anzeigen",
|
||||||
|
"search_filters_features_option_hd": "HD",
|
||||||
|
"search_filters_features_option_subtitles": "Untertitel / CC",
|
||||||
|
"search_filters_features_option_c_commons": "Creative Commons",
|
||||||
|
"search_filters_features_option_three_d": "3D",
|
||||||
|
"search_filters_features_option_live": "Live",
|
||||||
|
"search_filters_features_option_four_k": "4K",
|
||||||
|
"search_filters_features_option_location": "Standort",
|
||||||
|
"search_filters_features_option_hdr": "HDR",
|
||||||
|
"Current version: ": "Aktuelle Version: ",
|
||||||
|
"next_steps_error_message": "Danach folgendes versuchen: ",
|
||||||
|
"next_steps_error_message_refresh": "Aktualisieren",
|
||||||
|
"next_steps_error_message_go_to_youtube": "Zu YouTube gehen",
|
||||||
|
"footer_donate_page": "Spende",
|
||||||
|
"search_filters_duration_option_long": "Lang (> 20 Minuten)",
|
||||||
|
"footer_original_source_code": "Original Quellcode",
|
||||||
|
"footer_modfied_source_code": "Modifizierter Quellcode",
|
||||||
|
"footer_documentation": "Dokumentation",
|
||||||
|
"footer_source_code": "Quellcode",
|
||||||
|
"adminprefs_modified_source_code_url_label": "URL zum Repositorie des modifizierten Quellcodes",
|
||||||
|
"search_filters_duration_option_short": "Kurz (< 4 Minuten)",
|
||||||
|
"preferences_region_label": "Land der Inhalte: ",
|
||||||
|
"preferences_quality_option_dash": "DASH (adaptive Qualität)",
|
||||||
|
"preferences_quality_option_hd720": "HD720",
|
||||||
|
"preferences_quality_option_medium": "Mittel",
|
||||||
|
"preferences_quality_option_small": "Niedrig",
|
||||||
|
"preferences_quality_dash_option_auto": "Auto",
|
||||||
|
"preferences_quality_dash_option_4320p": "4320p",
|
||||||
|
"preferences_quality_dash_option_2160p": "2160p",
|
||||||
|
"preferences_quality_dash_option_1080p": "1080p",
|
||||||
|
"preferences_quality_dash_option_720p": "720p",
|
||||||
|
"preferences_quality_dash_option_480p": "480p",
|
||||||
|
"preferences_quality_dash_option_360p": "360p",
|
||||||
|
"preferences_quality_dash_option_240p": "240p",
|
||||||
|
"preferences_quality_dash_option_144p": "144p",
|
||||||
|
"invidious": "Invidious",
|
||||||
|
"videoinfo_invidious_embed_link": "Link zum Einbetten",
|
||||||
|
"download_subtitles": "Untertitel - `x` (.vtt)",
|
||||||
|
"Video unavailable": "Video nicht verfügbar",
|
||||||
|
"user_created_playlists": "`x` Wiedergabelisten erstellt",
|
||||||
|
"user_saved_playlists": "`x` Wiedergabelisten gespeichert",
|
||||||
|
"preferences_save_player_pos_label": "Wiedergabeposition speichern: ",
|
||||||
|
"search_filters_features_option_three_sixty": "360°",
|
||||||
|
"preferences_quality_dash_option_best": "Höchste",
|
||||||
|
"preferences_quality_dash_option_worst": "Niedrigste",
|
||||||
|
"preferences_quality_dash_option_1440p": "1440p",
|
||||||
|
"videoinfo_youTube_embed_link": "Eingebettet",
|
||||||
|
"search_filters_features_option_purchased": "Gekauft",
|
||||||
|
"none": "keine",
|
||||||
|
"videoinfo_started_streaming_x_ago": "Stream begann vor `x`",
|
||||||
|
"videoinfo_watch_on_youTube": "Auf YouTube ansehen",
|
||||||
|
"preferences_quality_dash_label": "Bevorzugte DASH-Videoqualität: ",
|
||||||
|
"generic_subscribers_count": "{{count}} Abonnent",
|
||||||
|
"generic_subscribers_count_plural": "{{count}} Abonnenten",
|
||||||
|
"generic_videos_count": "{{count}} Video",
|
||||||
|
"generic_videos_count_plural": "{{count}} Videos",
|
||||||
|
"subscriptions_unseen_notifs_count": "{{count}} ungesehene Benachrichtung",
|
||||||
|
"subscriptions_unseen_notifs_count_plural": "{{count}} ungesehene Benachrichtungen",
|
||||||
|
"crash_page_refresh": "Versucht haben, <a href=\"`x`\">die Seite neu zu laden</a>",
|
||||||
|
"comments_view_x_replies": "{{count}} Antwort anzeigen",
|
||||||
|
"comments_view_x_replies_plural": "{{count}} Antworten anzeigen",
|
||||||
|
"generic_count_years": "{{count}} Jahr",
|
||||||
|
"generic_count_years_plural": "{{count}} Jahre",
|
||||||
|
"generic_count_weeks": "{{count}} Woche",
|
||||||
|
"generic_count_weeks_plural": "{{count}} Wochen",
|
||||||
|
"generic_count_days": "{{count}} Tag",
|
||||||
|
"generic_count_days_plural": "{{count}} Tage",
|
||||||
|
"crash_page_before_reporting": "Bevor Sie einen Bug melden, stellen Sie sicher, dass Sie:",
|
||||||
|
"crash_page_switch_instance": "Eine <a href=\"`x`\">andere Instanz</a> versucht haben",
|
||||||
|
"generic_count_hours": "{{count}} Stunde",
|
||||||
|
"generic_count_hours_plural": "{{count}} Stunden",
|
||||||
|
"generic_count_minutes": "{{count}} Minute",
|
||||||
|
"generic_count_minutes_plural": "{{count}} Minuten",
|
||||||
|
"crash_page_read_the_faq": "Das <a href=\"`x`\">FAQ</a> gelesen haben",
|
||||||
|
"crash_page_search_issue": "Nach <a href=\"`x`\">bereits gemeldeten Bugs auf GitHub</a> gesucht haben",
|
||||||
|
"crash_page_report_issue": "Wenn all dies nicht geholfen hat, <a href=\"`x`\">öffnen Sie bitte ein neues Problem (issue) auf Github</a> (vorzugsweise auf Englisch) und fügen Sie den folgenden Text in Ihre Nachricht ein (bitte übersetzen Sie diesen Text NICHT):",
|
||||||
|
"generic_views_count": "{{count}} Aufruf",
|
||||||
|
"generic_views_count_plural": "{{count}} Aufrufe",
|
||||||
|
"generic_count_seconds": "{{count}} Sekunde",
|
||||||
|
"generic_count_seconds_plural": "{{count}} Sekunden",
|
||||||
|
"generic_subscriptions_count": "{{count}} Abo",
|
||||||
|
"generic_subscriptions_count_plural": "{{count}} Abos",
|
||||||
|
"tokens_count": "{{count}} Token",
|
||||||
|
"tokens_count_plural": "{{count}} Tokens",
|
||||||
|
"comments_points_count": "{{count}} Punkt",
|
||||||
|
"comments_points_count_plural": "{{count}} Punkte",
|
||||||
|
"crash_page_you_found_a_bug": "Anscheinend haben Sie einen Fehler in Invidious gefunden!",
|
||||||
|
"generic_count_months": "{{count}} Monat",
|
||||||
|
"generic_count_months_plural": "{{count}} Monate",
|
||||||
|
"Cantonese (Hong Kong)": "Kantonesisch (Hong Kong)",
|
||||||
|
"Chinese (Hong Kong)": "Chinesisch (Hong Kong)",
|
||||||
|
"generic_playlists_count": "{{count}} Wiedergabeliste",
|
||||||
|
"generic_playlists_count_plural": "{{count}} Wiedergabelisten",
|
||||||
|
"preferences_watch_history_label": "Wiedergabeverlauf aktivieren: ",
|
||||||
|
"English (United Kingdom)": "Englisch (Vereinigtes Königreich)",
|
||||||
|
"English (United States)": "Englisch (Vereinigte Staaten)",
|
||||||
|
"Dutch (auto-generated)": "Niederländisch (automatisch generiert)",
|
||||||
|
"French (auto-generated)": "Französisch (automatisch generiert)",
|
||||||
|
"German (auto-generated)": "Deutsch (automatisch generiert)",
|
||||||
|
"Indonesian (auto-generated)": "Indonesisch (automatisch generiert)",
|
||||||
|
"Interlingue": "Interlingue",
|
||||||
|
"Italian (auto-generated)": "Italienisch (automatisch generiert)",
|
||||||
|
"Japanese (auto-generated)": "Japanisch (automatisch generiert)",
|
||||||
|
"Spanish (Mexico)": "Spanisch (Mexiko)",
|
||||||
|
"Spanish (Spain)": "Spanisch (Spanien)",
|
||||||
|
"Vietnamese (auto-generated)": "Vietnamesisch (automatisch generiert)",
|
||||||
|
"Russian (auto-generated)": "Russisch (automatisch generiert)",
|
||||||
|
"Chinese": "Chinesisch",
|
||||||
|
"Portuguese (Brazil)": "Portugiesisch (Brasilien)",
|
||||||
|
"Spanish (auto-generated)": "Spanisch (automatisch generiert)",
|
||||||
|
"Turkish (auto-generated)": "Türkisch (automatisch generiert)",
|
||||||
|
"Chinese (China)": "Chinesisch (China)",
|
||||||
|
"Chinese (Taiwan)": "Chinesisch (Taiwan)",
|
||||||
|
"Korean (auto-generated)": "Koreanisch (automatisch generiert)",
|
||||||
|
"Portuguese (auto-generated)": "Portugiesisch (automatisch generiert)",
|
||||||
|
"search_filters_title": "Filtern",
|
||||||
|
"search_message_change_filters_or_query": "Versuchen Sie, Ihre Suchanfrage zu erweitern und/oder die Filter zu ändern.",
|
||||||
|
"search_message_use_another_instance": " Sie können auch <a href=\"`x`\">auf einer anderen Instanz suchen</a>.",
|
||||||
|
"Popular enabled: ": "„Beliebt“-Seite aktiviert: ",
|
||||||
|
"search_message_no_results": "Keine Ergebnisse gefunden.",
|
||||||
|
"search_filters_duration_option_medium": "Mittel (4 - 20 Minuten)",
|
||||||
|
"search_filters_features_option_vr180": "VR180",
|
||||||
|
"search_filters_type_option_all": "Beliebiger Typ",
|
||||||
|
"search_filters_apply_button": "Ausgewählte Filter anwenden",
|
||||||
|
"search_filters_duration_option_none": "Beliebige Länge",
|
||||||
|
"search_filters_date_label": "Upload-Datum",
|
||||||
|
"search_filters_date_option_none": "Beliebiges Datum"
|
||||||
|
}
|
||||||
|
|||||||
319
locales/el.json
319
locales/el.json
@@ -1,19 +1,10 @@
|
|||||||
{
|
{
|
||||||
"`x` subscribers": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` συνδρομητής",
|
|
||||||
"": "`x` συνδρομητές"
|
|
||||||
},
|
|
||||||
"`x` videos": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` βίντεο",
|
|
||||||
"": "`x` βίντεο"
|
|
||||||
},
|
|
||||||
"`x` playlists": "",
|
|
||||||
"LIVE": "ΖΩΝΤΑΝΑ",
|
"LIVE": "ΖΩΝΤΑΝΑ",
|
||||||
"Shared `x` ago": "Μοιράστηκε πριν `x`",
|
"Shared `x` ago": "Μοιράστηκε πριν από `x`",
|
||||||
"Unsubscribe": "Απεγγραφή",
|
"Unsubscribe": "Απεγγραφή",
|
||||||
"Subscribe": "Εγγραφή",
|
"Subscribe": "Εγγραφή",
|
||||||
"View channel on YouTube": "Προβολή καναλιού στο YouTube",
|
"View channel on YouTube": "Προβολή καναλιού στο YouTube",
|
||||||
"View playlist on YouTube": "",
|
"View playlist on YouTube": "Προβολή καταλόγου αναπαραγωγής στο YouTube",
|
||||||
"newest": "νεότερα",
|
"newest": "νεότερα",
|
||||||
"oldest": "παλιότερα",
|
"oldest": "παλιότερα",
|
||||||
"popular": "δημοφιλή",
|
"popular": "δημοφιλή",
|
||||||
@@ -30,15 +21,15 @@
|
|||||||
"No": "Όχι",
|
"No": "Όχι",
|
||||||
"Import and Export Data": "Εισαγωγή και Εξαγωγή Δεδομένων",
|
"Import and Export Data": "Εισαγωγή και Εξαγωγή Δεδομένων",
|
||||||
"Import": "Εισαγωγή",
|
"Import": "Εισαγωγή",
|
||||||
"Import Invidious data": "Εισαγωγή δεδομένων Invidious",
|
"Import Invidious data": "Εsαγωγή δεδομένων Invidious JSON",
|
||||||
"Import YouTube subscriptions": "Εισαγωγή συνδρομών YouTube",
|
"Import YouTube subscriptions": "Εισαγωγή συνδρομών YouTube/OPML",
|
||||||
"Import FreeTube subscriptions (.db)": "Εισαγωγή συνδρομών FreeTube (.db)",
|
"Import FreeTube subscriptions (.db)": "Εισαγωγή συνδρομών FreeTube (.db)",
|
||||||
"Import NewPipe subscriptions (.json)": "Εισαγωγή συνδρομών NewPipe (.json)",
|
"Import NewPipe subscriptions (.json)": "Εισαγωγή συνδρομών NewPipe (.json)",
|
||||||
"Import NewPipe data (.zip)": "Εισαγωγή δεδομένων NewPipe (.zip)",
|
"Import NewPipe data (.zip)": "Εισαγωγή δεδομένων NewPipe (.zip)",
|
||||||
"Export": "Εξαγωγή",
|
"Export": "Εξαγωγή",
|
||||||
"Export subscriptions as OPML": "Εξαγωγή συνδρομών ως OPML",
|
"Export subscriptions as OPML": "Εξαγωγή συνδρομών ως OPML",
|
||||||
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Εξαγωγή συνδρομών ως OPML (για NewPipe & FreeTube)",
|
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Εξαγωγή συνδρομών ως OPML (για NewPipe & FreeTube)",
|
||||||
"Export data as JSON": "Εξαγωγή δεδομένων ως JSON",
|
"Export data as JSON": "Εξαγωγή δεδομένων Invidious ως JSON",
|
||||||
"Delete account?": "Διαγραφή λογαριασμού;",
|
"Delete account?": "Διαγραφή λογαριασμού;",
|
||||||
"History": "Ιστορικό",
|
"History": "Ιστορικό",
|
||||||
"An alternative front-end to YouTube": "Μία εναλλακτική πλατφόρμα για το YouTube",
|
"An alternative front-end to YouTube": "Μία εναλλακτική πλατφόρμα για το YouTube",
|
||||||
@@ -54,38 +45,38 @@
|
|||||||
"Image CAPTCHA": "Εικόνα CAPTCHA",
|
"Image CAPTCHA": "Εικόνα CAPTCHA",
|
||||||
"Sign In": "Σύνδεση",
|
"Sign In": "Σύνδεση",
|
||||||
"Register": "Εγγραφή",
|
"Register": "Εγγραφή",
|
||||||
"E-mail": "E-mail",
|
"E-mail": "Ηλεκτρονικό ταχυδρομείο",
|
||||||
"Google verification code": "Κωδικός επαλήθευσης Google",
|
"Google verification code": "Κωδικός επαλήθευσης Google",
|
||||||
"Preferences": "Προτιμήσεις",
|
"Preferences": "Προτιμήσεις",
|
||||||
"Player preferences": "Προτιμήσεις αναπαραγωγής",
|
"preferences_category_player": "Προτιμήσεις αναπαραγωγής",
|
||||||
"Always loop: ": "Αυτόματη επανάληψη: ",
|
"preferences_video_loop_label": "Αυτόματη επανάληψη: ",
|
||||||
"Autoplay: ": "Αυτόματη αναπαραγωγή: ",
|
"preferences_autoplay_label": "Αυτόματη αναπαραγωγή: ",
|
||||||
"Play next by default: ": "Αναπαραγωγή επόμενου: ",
|
"preferences_continue_label": "Αναπαραγωγή επόμενου: ",
|
||||||
"Autoplay next video: ": "Αυτόματη αναπαραγωγή επόμενου: ",
|
"preferences_continue_autoplay_label": "Αυτόματη αναπαραγωγή επόμενου: ",
|
||||||
"Listen by default: ": "Φόρτωση μόνο ήχου: ",
|
"preferences_listen_label": "Φόρτωση μόνο ήχου: ",
|
||||||
"Proxy videos: ": "Αναπαραγωγή με διακομιστή μεσολάβησης (proxy): ",
|
"preferences_local_label": "Αναπαραγωγή με διακομιστή μεσολάβησης (proxy): ",
|
||||||
"Default speed: ": "Προεπιλεγμένη ταχύτητα: ",
|
"preferences_speed_label": "Προεπιλεγμένη ταχύτητα: ",
|
||||||
"Preferred video quality: ": "Προτιμώμενη ανάλυση: ",
|
"preferences_quality_label": "Προτιμώμενη ανάλυση: ",
|
||||||
"Player volume: ": "Ένταση αναπαραγωγής: ",
|
"preferences_volume_label": "Ένταση αναπαραγωγής: ",
|
||||||
"Default comments: ": "Προεπιλεγμένα σχόλια: ",
|
"preferences_comments_label": "Προεπιλεγμένα σχόλια: ",
|
||||||
"youtube": "youtube",
|
"youtube": "YouTube",
|
||||||
"reddit": "reddit",
|
"reddit": "Reddit",
|
||||||
"Default captions: ": "Προεπιλεγμένοι υπότιτλοι: ",
|
"preferences_captions_label": "Προεπιλεγμένοι υπότιτλοι: ",
|
||||||
"Fallback captions: ": "Εναλλακτικοί υπότιτλοι: ",
|
"Fallback captions: ": "Εναλλακτικοί υπότιτλοι: ",
|
||||||
"Show related videos: ": "Προβολή σχετικών βίντεο; ",
|
"preferences_related_videos_label": "Προβολή σχετικών βίντεο; ",
|
||||||
"Show annotations by default: ": "Αυτόματη προβολή σημειώσεων; :",
|
"preferences_annotations_label": "Αυτόματη προβολή σημειώσεων: ",
|
||||||
"Visual preferences": "Προτιμήσεις εμφάνισης",
|
"preferences_category_visual": "Προτιμήσεις εμφάνισης",
|
||||||
"Player style: ": "",
|
"preferences_player_style_label": "Τεχνοτροπία της συσκευής αναπαραγωγης: ",
|
||||||
"Dark mode: ": "Σκοτεινή λειτουργία: ",
|
"Dark mode: ": "Σκοτεινή λειτουργία: ",
|
||||||
"Theme: ": "",
|
"preferences_dark_mode_label": "Θέμα: ",
|
||||||
"dark": "",
|
"dark": "σκοτεινό",
|
||||||
"light": "",
|
"light": "φωτεινό",
|
||||||
"Thin mode: ": "Ελαφριά λειτουργία: ",
|
"preferences_thin_mode_label": "Ελαφριά λειτουργία: ",
|
||||||
"Subscription preferences": "Προτιμήσεις συνδρομών",
|
"preferences_category_subscription": "Προτιμήσεις συνδρομών",
|
||||||
"Show annotations by default for subscribed channels: ": "Προβολή σημειώσεων μόνο για κανάλια στα οποία είστε συνδρομητής; ",
|
"preferences_annotations_subscribed_label": "Προβολή σημειώσεων μόνο για κανάλια στα οποία είστε συνδρομητής; ",
|
||||||
"Redirect homepage to feed: ": "Ανακατεύθυνση αρχικής στη ροή συνδρομών: ",
|
"Redirect homepage to feed: ": "Ανακατεύθυνση αρχικής στη ροή συνδρομών: ",
|
||||||
"Number of videos shown in feed: ": "Αριθμός βίντεο ανά σελίδα ροής συνδρομών: ",
|
"preferences_max_results_label": "Αριθμός βίντεο ανά σελίδα ροής συνδρομών: ",
|
||||||
"Sort videos by: ": "Ταξινόμηση ανά: ",
|
"preferences_sort_label": "Ταξινόμηση ανά: ",
|
||||||
"published": "ημερομηνία δημοσίευσης",
|
"published": "ημερομηνία δημοσίευσης",
|
||||||
"published - reverse": "ημερομηνία δημοσίευσης - ανάποδα",
|
"published - reverse": "ημερομηνία δημοσίευσης - ανάποδα",
|
||||||
"alphabetically": "αλφαβητικά",
|
"alphabetically": "αλφαβητικά",
|
||||||
@@ -94,12 +85,12 @@
|
|||||||
"channel name - reverse": "όνομα καναλιού - ανάποδα",
|
"channel name - reverse": "όνομα καναλιού - ανάποδα",
|
||||||
"Only show latest video from channel: ": "Προβολή μόνο του τελευταίου βίντεο του καναλιού: ",
|
"Only show latest video from channel: ": "Προβολή μόνο του τελευταίου βίντεο του καναλιού: ",
|
||||||
"Only show latest unwatched video from channel: ": "Προβολή μόνο του τελευταίου μη-προβεβλημένου βίντεο του καναλιού: ",
|
"Only show latest unwatched video from channel: ": "Προβολή μόνο του τελευταίου μη-προβεβλημένου βίντεο του καναλιού: ",
|
||||||
"Only show unwatched: ": "Προβολή μόνο μη-προβεβλημένων: ",
|
"preferences_unseen_only_label": "Προβολή μόνο μη-προβεβλημένων: ",
|
||||||
"Only show notifications (if there are any): ": "Προβολή μόνο ειδοποιήσεων (αν υπάρχουν): ",
|
"preferences_notifications_only_label": "Προβολή μόνο ειδοποιήσεων (αν υπάρχουν): ",
|
||||||
"Enable web notifications": "",
|
"Enable web notifications": "Ενεργοποίηση ειδοποιήσεων δικτύου",
|
||||||
"`x` uploaded a video": "",
|
"`x` uploaded a video": "`x` κοινοποίησε ένα βίντεο",
|
||||||
"`x` is live": "",
|
"`x` is live": "`x` κάνει live",
|
||||||
"Data preferences": "Προτιμήσεις δεδομένων",
|
"preferences_category_data": "Προτιμήσεις δεδομένων",
|
||||||
"Clear watch history": "Εκκαθάριση ιστορικού προβολής",
|
"Clear watch history": "Εκκαθάριση ιστορικού προβολής",
|
||||||
"Import/export data": "Εισαγωγή/εξαγωγή δεδομένων",
|
"Import/export data": "Εισαγωγή/εξαγωγή δεδομένων",
|
||||||
"Change password": "Αλλαγή κωδικού πρόσβασης",
|
"Change password": "Αλλαγή κωδικού πρόσβασης",
|
||||||
@@ -107,9 +98,9 @@
|
|||||||
"Manage tokens": "Διαχείριση διασυνδέσεων",
|
"Manage tokens": "Διαχείριση διασυνδέσεων",
|
||||||
"Watch history": "Ιστορικό προβολής",
|
"Watch history": "Ιστορικό προβολής",
|
||||||
"Delete account": "Διαγραφή λογαριασμού",
|
"Delete account": "Διαγραφή λογαριασμού",
|
||||||
"Administrator preferences": "Προτιμήσεις διαχειριστή",
|
"preferences_category_admin": "Προτιμήσεις διαχειριστή",
|
||||||
"Default homepage: ": "Προεπιλεγμένη αρχική: ",
|
"preferences_default_home_label": "Προεπιλεγμένη αρχική: ",
|
||||||
"Feed menu: ": "Μενού ροής συνδρομών: ",
|
"preferences_feed_menu_label": "Μενού ροής συνδρομών: ",
|
||||||
"Top enabled: ": "Ενεργοποίηση κορυφαίων; ",
|
"Top enabled: ": "Ενεργοποίηση κορυφαίων; ",
|
||||||
"CAPTCHA enabled: ": "Ενεργοποίηση CAPTCHA; ",
|
"CAPTCHA enabled: ": "Ενεργοποίηση CAPTCHA; ",
|
||||||
"Login enabled: ": "Ενεργοποίηση σύνδεσης; ",
|
"Login enabled: ": "Ενεργοποίηση σύνδεσης; ",
|
||||||
@@ -119,61 +110,47 @@
|
|||||||
"Subscription manager": "Διαχειριστής συνδρομών",
|
"Subscription manager": "Διαχειριστής συνδρομών",
|
||||||
"Token manager": "Διαχειριστής διασυνδέσεων",
|
"Token manager": "Διαχειριστής διασυνδέσεων",
|
||||||
"Token": "Διασύνδεση",
|
"Token": "Διασύνδεση",
|
||||||
"`x` subscriptions": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` συνδρομή",
|
|
||||||
"": "`x` συνδρομές"
|
|
||||||
},
|
|
||||||
"`x` tokens": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` διασύνδεση",
|
|
||||||
"": "`x` διασυνδέσεις"
|
|
||||||
},
|
|
||||||
"Import/export": "Εισαγωγή/εξαγωγή",
|
"Import/export": "Εισαγωγή/εξαγωγή",
|
||||||
"unsubscribe": "κατάργηση συνδρομής",
|
"unsubscribe": "κατάργηση συνδρομής",
|
||||||
"revoke": "ανάκληση",
|
"revoke": "ανάκληση",
|
||||||
"Subscriptions": "Συνδρομές",
|
"Subscriptions": "Συνδρομές",
|
||||||
"`x` unseen notifications": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` καινούρια ειδοποίηση",
|
|
||||||
"": "`x` καινούριες ειδοποιήσεις"
|
|
||||||
},
|
|
||||||
"search": "αναζήτηση",
|
"search": "αναζήτηση",
|
||||||
"Log out": "Αποσύνδεση",
|
"Log out": "Αποσύνδεση",
|
||||||
"Released under the AGPLv3 by Omar Roth.": "Κυκλοφορεί υπό την άδεια AGPLv3 από τον Omar Roth.",
|
|
||||||
"Source available here.": "Προβολή πηγαίου κώδικα εδώ.",
|
"Source available here.": "Προβολή πηγαίου κώδικα εδώ.",
|
||||||
"View JavaScript license information.": "Προβολή πληροφοριών άδειας JavaScript.",
|
"View JavaScript license information.": "Προβολή πληροφοριών άδειας JavaScript.",
|
||||||
"View privacy policy.": "Προβολή πολιτικής απορρήτου.",
|
"View privacy policy.": "Προβολή πολιτικής απορρήτου.",
|
||||||
"Trending": "Τάσεις",
|
"Trending": "Τάσεις",
|
||||||
"Public": "",
|
"Public": "Δημόσιο",
|
||||||
"Unlisted": "Κρυφό",
|
"Unlisted": "Κρυφό",
|
||||||
"Private": "",
|
"Private": "Ιδιωτικό",
|
||||||
"View all playlists": "",
|
"View all playlists": "Προβολή όλων των καταλόγων αναπαραγωγής",
|
||||||
"Updated `x` ago": "",
|
"Updated `x` ago": "Ενημερώθηκε πριν από `x`",
|
||||||
"Delete playlist `x`?": "",
|
"Delete playlist `x`?": "Διαγραφή `x` καταλόγου αναπαραγωγής;",
|
||||||
"Delete playlist": "",
|
"Delete playlist": "Διαγραφή καταλόγου αναπαραγωγής",
|
||||||
"Create playlist": "",
|
"Create playlist": "Δημιουργία καταλόγου αναπαραγωγής",
|
||||||
"Title": "",
|
"Title": "Τίτλος",
|
||||||
"Playlist privacy": "",
|
"Playlist privacy": "Ιδιωτικότητα καταλόγων αναπαραγωγής",
|
||||||
"Editing playlist `x`": "",
|
"Editing playlist `x`": "Επεξεργασία `x` καταλόγου αναπαραγωγής",
|
||||||
"Watch on YouTube": "Προβολή στο YouTube",
|
"Watch on YouTube": "Προβολή στο YouTube",
|
||||||
"Hide annotations": "Απόκρυψη σημειώσεων",
|
"Hide annotations": "Απόκρυψη σημειώσεων",
|
||||||
"Show annotations": "Προβολή σημειώσεων",
|
"Show annotations": "Προβολή σημειώσεων",
|
||||||
"Genre: ": "Είδος: ",
|
"Genre: ": "Είδος: ",
|
||||||
"License: ": "Άδεια: ",
|
"License: ": "Άδεια: ",
|
||||||
"Family friendly? ": "Φιλικό προς την οικογένεια; ",
|
"Family friendly? ": "Φιλικό προς την οικογένεια; ",
|
||||||
"Wilson score: ": "Wilson score: ",
|
"Wilson score: ": "Αποτελέσματα Wilson: ",
|
||||||
"Engagement: ": "Ενδιαφέρον: ",
|
"Engagement: ": "Ενδιαφέρον: ",
|
||||||
"Whitelisted regions: ": "Επιτρεπτές περιοχές: ",
|
"Whitelisted regions: ": "Επιτρεπτές περιοχές: ",
|
||||||
"Blacklisted regions: ": "Μη-επιτρεπτές περιοχές: ",
|
"Blacklisted regions: ": "Μη-επιτρεπτές περιοχές: ",
|
||||||
"Shared `x`": "Μοιράστηκε το `x`",
|
"Shared `x`": "Μοιράστηκε το `x`",
|
||||||
"`x` views": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` προβολή",
|
|
||||||
"": "`x` προβολές"
|
|
||||||
},
|
|
||||||
"Premieres in `x`": "Πρώτη προβολή σε `x`",
|
"Premieres in `x`": "Πρώτη προβολή σε `x`",
|
||||||
"Premieres `x`": "",
|
"Premieres `x`": "Επίσημη πρώτη παράσταση του `x`",
|
||||||
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Γεια! Φαίνεται πως έχετε απενεργοποιήσει το JavaScript. Πατήστε εδώ για προβολή σχολίων, αλλά έχετε υπ'όψιν σας πως ίσως φορτώσουν πιο αργά. ",
|
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Γεια! Φαίνεται πως έχετε απενεργοποιήσει το JavaScript. Πατήστε εδώ για προβολή σχολίων, αλλά έχετε υπ'όψιν σας πως ίσως φορτώσουν πιο αργά.",
|
||||||
"View YouTube comments": "Προβολή σχολίων από το YouTube",
|
"View YouTube comments": "Προβολή σχολίων από το YouTube",
|
||||||
"View more comments on Reddit": "Προβολή περισσότερων σχολίων στο Reddit",
|
"View more comments on Reddit": "Προβολή περισσότερων σχολίων στο Reddit",
|
||||||
"View `x` comments": "Προβολή `x` σχολίων",
|
"View `x` comments": {
|
||||||
|
"([^.,0-9]|^)1([^.,0-9]|$)": "Προβολή `x` σχολίων",
|
||||||
|
"": "Προβολή `x` σχολίων"
|
||||||
|
},
|
||||||
"View Reddit comments": "Προβολή σχολίων από το Reddit",
|
"View Reddit comments": "Προβολή σχολίων από το Reddit",
|
||||||
"Hide replies": "Απόκρυψη απαντήσεων",
|
"Hide replies": "Απόκρυψη απαντήσεων",
|
||||||
"Show replies": "Προβολή απαντήσεων",
|
"Show replies": "Προβολή απαντήσεων",
|
||||||
@@ -198,19 +175,11 @@
|
|||||||
"This channel does not exist.": "Αυτό το κανάλι δεν υπάρχει.",
|
"This channel does not exist.": "Αυτό το κανάλι δεν υπάρχει.",
|
||||||
"Could not get channel info.": "Αδύναμια εύρεσης πληροφοριών καναλιού.",
|
"Could not get channel info.": "Αδύναμια εύρεσης πληροφοριών καναλιού.",
|
||||||
"Could not fetch comments": "Αδυναμία λήψης σχολίων",
|
"Could not fetch comments": "Αδυναμία λήψης σχολίων",
|
||||||
"View `x` replies": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "Προβολή `x` απάντησης",
|
|
||||||
"": "Προβολή `x` απαντήσεων"
|
|
||||||
},
|
|
||||||
"`x` ago": "Πριν `x`",
|
"`x` ago": "Πριν `x`",
|
||||||
"Load more": "Φόρτωση περισσότερων",
|
"Load more": "Φόρτωση περισσότερων",
|
||||||
"`x` points": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` βαθμός",
|
|
||||||
"": "`x` βαθμοί"
|
|
||||||
},
|
|
||||||
"Could not create mix.": "Αδυναμία δημιουργίας μίξης.",
|
"Could not create mix.": "Αδυναμία δημιουργίας μίξης.",
|
||||||
"Empty playlist": "Κενή λίστα αναπαραγωγής",
|
"Empty playlist": "Κενή λίστα αναπαραγωγής",
|
||||||
"Not a playlist.": "Μη έγκυρη λίστα αναπαραγωγής",
|
"Not a playlist.": "Μη έγκυρη λίστα αναπαραγωγής.",
|
||||||
"Playlist does not exist.": "Μη υπαρκτή λίστα αναπαραγωγής.",
|
"Playlist does not exist.": "Μη υπαρκτή λίστα αναπαραγωγής.",
|
||||||
"Could not pull trending pages.": "Αδυναμία λήψης σελίδας τάσεων.",
|
"Could not pull trending pages.": "Αδυναμία λήψης σελίδας τάσεων.",
|
||||||
"Hidden field \"challenge\" is a required field": "Το Κρυφό πεδίο \"δοκιμασία\" είναι απαραίτητο",
|
"Hidden field \"challenge\" is a required field": "Το Κρυφό πεδίο \"δοκιμασία\" είναι απαραίτητο",
|
||||||
@@ -325,40 +294,12 @@
|
|||||||
"Yiddish": "Γίντις",
|
"Yiddish": "Γίντις",
|
||||||
"Yoruba": "Γιορούμπα",
|
"Yoruba": "Γιορούμπα",
|
||||||
"Zulu": "Ζουλού",
|
"Zulu": "Ζουλού",
|
||||||
"`x` years": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` χρόνο",
|
|
||||||
"": "`x` χρόνια"
|
|
||||||
},
|
|
||||||
"`x` months": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` μήνα",
|
|
||||||
"": "`x` μήνες"
|
|
||||||
},
|
|
||||||
"`x` weeks": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` εβδομάδα",
|
|
||||||
"": "`x` εβδομάδες"
|
|
||||||
},
|
|
||||||
"`x` days": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ημέρα",
|
|
||||||
"": "`x` ημέρες"
|
|
||||||
},
|
|
||||||
"`x` hours": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` ώρα",
|
|
||||||
"": "`x` ώρες"
|
|
||||||
},
|
|
||||||
"`x` minutes": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` λεπτό",
|
|
||||||
"": "`x` λεπτά"
|
|
||||||
},
|
|
||||||
"`x` seconds": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` δευτερόλεπτο",
|
|
||||||
"": "`x` δευτερόλεπτα"
|
|
||||||
},
|
|
||||||
"Fallback comments: ": "Εναλλακτικά σχόλια: ",
|
"Fallback comments: ": "Εναλλακτικά σχόλια: ",
|
||||||
"Popular": "Δημοφιλή",
|
"Popular": "Δημοφιλή",
|
||||||
"Top": "Κορυφαία",
|
"Top": "Κορυφαία",
|
||||||
"About": "Σχετικά",
|
"About": "Σχετικά",
|
||||||
"Rating: ": "Aξιολόγηση: ",
|
"Rating: ": "Aξιολόγηση: ",
|
||||||
"Language: ": "Γλώσσα: ",
|
"preferences_locale_label": "Γλώσσα: ",
|
||||||
"View as playlist": "Προβολή ως λίστα αναπαραγωγής",
|
"View as playlist": "Προβολή ως λίστα αναπαραγωγής",
|
||||||
"Default": "Προεπιλογή",
|
"Default": "Προεπιλογή",
|
||||||
"Music": "Μουσική",
|
"Music": "Μουσική",
|
||||||
@@ -370,12 +311,144 @@
|
|||||||
"%A %B %-d, %Y": "%A %B %-d, %Y",
|
"%A %B %-d, %Y": "%A %B %-d, %Y",
|
||||||
"(edited)": "(τροποποιημένο)",
|
"(edited)": "(τροποποιημένο)",
|
||||||
"YouTube comment permalink": "Σύνδεσμος YouTube σχολίου",
|
"YouTube comment permalink": "Σύνδεσμος YouTube σχολίου",
|
||||||
"permalink": "",
|
"permalink": "μόνιμος σύνδεσμος",
|
||||||
"`x` marked it with a ❤": "Ο χρηστης `x` έβαλε ❤",
|
"`x` marked it with a ❤": "Ο χρηστης `x` έβαλε ❤",
|
||||||
"Audio mode": "Λειτουργία ήχου",
|
"Audio mode": "Λειτουργία ήχου",
|
||||||
"Video mode": "Λειτουργία βίντεο",
|
"Video mode": "Λειτουργία βίντεο",
|
||||||
"Videos": "Βίντεο",
|
"Videos": "Βίντεο",
|
||||||
"Playlists": "Λίστες Αναπαραγωγής",
|
"Playlists": "Λίστες Αναπαραγωγής",
|
||||||
"Community": "",
|
"Community": "Κοινότητα",
|
||||||
"Current version: ": "Τρέχουσα έκδοση: "
|
"Current version: ": "Τρέχουσα έκδοση: ",
|
||||||
}
|
"generic_playlists_count": "{{count}} λίστα αναπαραγωγής",
|
||||||
|
"generic_playlists_count_plural": "{{count}} λίστες αναπαραγωγής",
|
||||||
|
"preferences_quality_dash_option_worst": "Χειρότερη",
|
||||||
|
"preferences_quality_dash_option_2160p": "2160 p",
|
||||||
|
"Video unavailable": "Το βίντεο δεν είναι διαθέσιμο",
|
||||||
|
"preferences_quality_dash_option_auto": "Αυτόματη",
|
||||||
|
"preferences_quality_dash_option_1440p": "1440p",
|
||||||
|
"preferences_quality_dash_option_1080p": "1080p",
|
||||||
|
"comments_view_x_replies": "Προβολή {{count}} απάντησης",
|
||||||
|
"comments_view_x_replies_plural": "Προβολή {{count}} απαντήσεων",
|
||||||
|
"crash_page_report_issue": "Εάν κανένα από τα παραπάνω δεν βοήθησε, παρακαλούμε <a href=\"`x`\">ανοίξτε ένα νέο θέμα στο GitHub</a> (κατά προτίμηση στα αγγλικά) και συμπεριλάβετε το ακόλουθο κείμενο στο μήνυμά σας (ΜΗΝ μεταφράζετε αυτό το κείμενο):",
|
||||||
|
"generic_count_hours": "{{count}} ώρα",
|
||||||
|
"generic_count_hours_plural": "{{count}} ώρες",
|
||||||
|
"generic_count_minutes": "{{count}} λεπτό",
|
||||||
|
"generic_count_minutes_plural": "{{count}} λεπτά",
|
||||||
|
"generic_count_seconds": "{{count}} δευτερόλεπτο",
|
||||||
|
"generic_count_seconds_plural": "{{count}} δευτερόλεπτα",
|
||||||
|
"preferences_quality_dash_label": "Προτιμώμενη ποιότητα βίντεο DASH: ",
|
||||||
|
"preferences_quality_dash_option_best": "Καλύτερη",
|
||||||
|
"preferences_quality_dash_option_480p": "480p",
|
||||||
|
"preferences_quality_dash_option_360p": "360p",
|
||||||
|
"preferences_quality_dash_option_240p": "240p",
|
||||||
|
"preferences_quality_dash_option_144p": "144p",
|
||||||
|
"generic_subscribers_count": "{{count}} συνδρομητής",
|
||||||
|
"generic_subscribers_count_plural": "{{count}} συνδρομητές",
|
||||||
|
"generic_subscriptions_count": "{{count}} συνδρομή",
|
||||||
|
"generic_subscriptions_count_plural": "{{count}} συνδρομές",
|
||||||
|
"generic_count_years": "{{count}} έτος",
|
||||||
|
"generic_count_years_plural": "{{count}} έτη",
|
||||||
|
"generic_count_months": "{{count}} μήνας",
|
||||||
|
"generic_count_months_plural": "{{count}} μήνες",
|
||||||
|
"generic_count_weeks": "{{count}} εβδομάδα",
|
||||||
|
"generic_count_weeks_plural": "{{count}} εβδομάδες",
|
||||||
|
"generic_count_days": "{{count}} ημέρα",
|
||||||
|
"generic_count_days_plural": "{{count}} ημέρες",
|
||||||
|
"crash_page_you_found_a_bug": "Φαίνεται ότι βρήκατε ένα σφάλμα στο Invidious!",
|
||||||
|
"crash_page_before_reporting": "Πριν αναφέρετε ένα σφάλμα, βεβαιωθείτε ότι έχετε:",
|
||||||
|
"crash_page_refresh": "προσπαθήσει να <a href=\"`x`\">ανανεώσετε τη σελίδα</a>",
|
||||||
|
"crash_page_read_the_faq": "διαβάσει τις <a href=\"`x`\">Συχνές Ερωτήσεις (ΣΕ)</a>",
|
||||||
|
"crash_page_search_issue": "αναζητήσει για <a href=\"`x`\">υπάρχοντα θέματα στο GitHub</a>",
|
||||||
|
"generic_views_count": "{{count}} προβολή",
|
||||||
|
"generic_views_count_plural": "{{count}} προβολές",
|
||||||
|
"generic_videos_count": "{{count}} βίντεο",
|
||||||
|
"generic_videos_count_plural": "{{count}} βίντεο",
|
||||||
|
"preferences_quality_option_hd720": "HD720",
|
||||||
|
"preferences_quality_option_medium": "Μεσαία",
|
||||||
|
"preferences_quality_option_small": "Μικρό",
|
||||||
|
"preferences_quality_option_dash": "DASH (προσαρμοστική ποιότητα)",
|
||||||
|
"preferences_quality_dash_option_4320p": "4320p",
|
||||||
|
"preferences_quality_dash_option_720p": "720p",
|
||||||
|
"invidious": "Invidious",
|
||||||
|
"preferences_region_label": "Χώρα περιεχομένου: ",
|
||||||
|
"preferences_category_misc": "Διάφορες προτιμήσεις",
|
||||||
|
"Show more": "Εμφάνιση περισσότερων",
|
||||||
|
"search_filters_date_option_today": "Σήμερα",
|
||||||
|
"search_filters_features_option_three_sixty": "360°",
|
||||||
|
"videoinfo_started_streaming_x_ago": "Ξεκίνησε η ροή `x` πριν από",
|
||||||
|
"videoinfo_watch_on_youTube": "Παρακολουθήστε στο YouTube",
|
||||||
|
"download_subtitles": "Υπότιτλοι - `x` (.vtt)",
|
||||||
|
"user_created_playlists": "`x` δημιουργημένες λίστες αναπαραγωγής",
|
||||||
|
"user_saved_playlists": "`x` αποθηκευμένες λίστες αναπαραγωγής",
|
||||||
|
"search_filters_sort_option_rating": "Αξιολόγηση",
|
||||||
|
"search_filters_sort_option_relevance": "Συνάφεια",
|
||||||
|
"search_filters_features_option_purchased": "Αγορασμένο",
|
||||||
|
"search_filters_sort_option_date": "Ημερομηνία μεταφόρτωσης",
|
||||||
|
"search_filters_type_label": "Τύπος",
|
||||||
|
"search_filters_duration_label": "Διάρκεια",
|
||||||
|
"search_filters_date_option_week": "Αυτή την εβδομάδα",
|
||||||
|
"search_filters_date_option_year": "Φέτος",
|
||||||
|
"search_filters_type_option_channel": "Κανάλι",
|
||||||
|
"search_filters_type_option_playlist": "Λίστα αναπαραγωγής",
|
||||||
|
"search_filters_duration_option_long": "Μεγάλο (> 20 λεπτά)",
|
||||||
|
"search_filters_features_option_hd": "HD",
|
||||||
|
"search_filters_features_option_location": "Τοποθεσία",
|
||||||
|
"search_filters_features_option_three_d": "3D",
|
||||||
|
"next_steps_error_message": "Μετά από αυτό θα πρέπει να προσπαθήσετε να: ",
|
||||||
|
"next_steps_error_message_go_to_youtube": "Μεταβείτε στο YouTube",
|
||||||
|
"footer_donate_page": "Δωρεά",
|
||||||
|
"footer_original_source_code": "Πρωτότυπος πηγαίος κώδικας",
|
||||||
|
"preferences_show_nick_label": "Εμφάνιση ψευδώνυμου στην κορυφή: ",
|
||||||
|
"search_filters_date_option_hour": "Τελευταία ώρα",
|
||||||
|
"adminprefs_modified_source_code_url_label": "URL σε αποθετήριο τροποποιημένου πηγαίου κώδικα",
|
||||||
|
"search_filters_features_option_subtitles": "Υπότιτλοι/CC",
|
||||||
|
"search_filters_date_option_month": "Αυτόν τον μήνα",
|
||||||
|
"Released under the AGPLv3 on Github.": "Κυκλοφορεί υπό την AGPLv3 στο GitHub.",
|
||||||
|
"search_filters_sort_label": "Ταξινόμηση κατά",
|
||||||
|
"search_filters_type_option_movie": "Ταινία",
|
||||||
|
"footer_modfied_source_code": "Τροποποιημένος πηγαίος κώδικας",
|
||||||
|
"search_filters_features_label": "Χαρακτηριστικά",
|
||||||
|
"search_filters_features_option_four_k": "4K",
|
||||||
|
"footer_documentation": "Τεκμηρίωση",
|
||||||
|
"search_filters_duration_option_short": "Σύντομο (< 4 λεπτά)",
|
||||||
|
"next_steps_error_message_refresh": "Ανανέωση",
|
||||||
|
"search_filters_type_option_video": "Βίντεο",
|
||||||
|
"search_filters_features_option_live": "Ζωντανά",
|
||||||
|
"search_filters_features_option_c_commons": "Creative Commons",
|
||||||
|
"Search": "Αναζήτηση",
|
||||||
|
"search_filters_features_option_hdr": "HDR",
|
||||||
|
"preferences_extend_desc_label": "Αυτόματη επέκταση της περιγραφής του βίντεο: ",
|
||||||
|
"preferences_vr_mode_label": "Διαδραστικά βίντεο 360 μοιρών (απαιτεί WebGL): ",
|
||||||
|
"Show less": "Εμφάνιση λιγότερων",
|
||||||
|
"footer_source_code": "Πηγαίος κώδικας",
|
||||||
|
"Chinese (Taiwan)": "Κινέζικα (Ταϊβάν)",
|
||||||
|
"Portuguese (Brazil)": "Πορτογαλικά (Βραζιλία)",
|
||||||
|
"German (auto-generated)": "Γερμανικά (αυτόματη παραγωγή)",
|
||||||
|
"Korean (auto-generated)": "Κορεάτικα (αυτόματη παραγωγή)",
|
||||||
|
"Russian (auto-generated)": "Ρωσικά (αυτόματη παραγωγή)",
|
||||||
|
"Spanish (auto-generated)": "Ισπανικά (αυτόματη παραγωγή)",
|
||||||
|
"Vietnamese (auto-generated)": "Βιετναμέζικα (αυτόματη παραγωγή)",
|
||||||
|
"English (United Kingdom)": "Αγγλικά (Ηνωμένο Βασίλειο)",
|
||||||
|
"English (United States)": "Αγγλικά (Ηνωμένων Πολιτειών)",
|
||||||
|
"Cantonese (Hong Kong)": "Καντονέζικα (Χονγκ Κονγκ)",
|
||||||
|
"Chinese": "Κινεζικά",
|
||||||
|
"Chinese (China)": "Κινέζικα (Κίνα)",
|
||||||
|
"Chinese (Hong Kong)": "Κινεζικά (Χονγκ Κονγκ)",
|
||||||
|
"Dutch (auto-generated)": "Ολαμδικά (αυτόματη παραγωγή)",
|
||||||
|
"French (auto-generated)": "Γαλλικά (αυτόματη παραγωγή)",
|
||||||
|
"Interlingue": "Ιντερλίνγκουα",
|
||||||
|
"Indonesian (auto-generated)": "Ινδονησιακά (αυτόματη παραγωγή)",
|
||||||
|
"Italian (auto-generated)": "Ιταλικά (αυτόματη παραγωγή)",
|
||||||
|
"Japanese (auto-generated)": "Ιαπωνικά (αυτόματη παραγωγή)",
|
||||||
|
"Portuguese (auto-generated)": "Πορτογαλικά (αυτόματη παραγωγή)",
|
||||||
|
"Spanish (Mexico)": "Ισπανικά (Μεξικό)",
|
||||||
|
"Spanish (Spain)": "Ισπανικά (Ισπανία)",
|
||||||
|
"Turkish (auto-generated)": "Τούρκικα (αυτόματη παραγωγή)",
|
||||||
|
"none": "κανένα",
|
||||||
|
"videoinfo_youTube_embed_link": "Ενσωμάτωση",
|
||||||
|
"videoinfo_invidious_embed_link": "Σύνδεσμος Ενσωμάτωσης",
|
||||||
|
"search_filters_type_option_show": "Μπάρα προόδου διαβάσματος",
|
||||||
|
"preferences_watch_history_label": "Ενεργοποίηση ιστορικού παρακολούθησης: ",
|
||||||
|
"search_filters_title": "Φίλτρο",
|
||||||
|
"search_message_no_results": "Δεν"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
{
|
{
|
||||||
"`x` subscribers": {
|
"generic_views_count": "{{count}} view",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` subscriber",
|
"generic_views_count_plural": "{{count}} views",
|
||||||
"": "`x` subscribers"
|
"generic_videos_count": "{{count}} video",
|
||||||
},
|
"generic_videos_count_plural": "{{count}} videos",
|
||||||
"`x` videos": {
|
"generic_playlists_count": "{{count}} playlist",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` video",
|
"generic_playlists_count_plural": "{{count}} playlists",
|
||||||
"": "`x` videos"
|
"generic_subscribers_count": "{{count}} subscriber",
|
||||||
},
|
"generic_subscribers_count_plural": "{{count}} subscribers",
|
||||||
"`x` playlists": {
|
"generic_subscriptions_count": "{{count}} subscription",
|
||||||
"(\\D|^)1(\\D|$)": "`x` playlist",
|
"generic_subscriptions_count_plural": "{{count}} subscriptions",
|
||||||
"": "`x` playlists"
|
|
||||||
},
|
|
||||||
"LIVE": "LIVE",
|
"LIVE": "LIVE",
|
||||||
"Shared `x` ago": "Shared `x` ago",
|
"Shared `x` ago": "Shared `x` ago",
|
||||||
"Unsubscribe": "Unsubscribe",
|
"Unsubscribe": "Unsubscribe",
|
||||||
@@ -33,15 +31,15 @@
|
|||||||
"No": "No",
|
"No": "No",
|
||||||
"Import and Export Data": "Import and Export Data",
|
"Import and Export Data": "Import and Export Data",
|
||||||
"Import": "Import",
|
"Import": "Import",
|
||||||
"Import Invidious data": "Import Invidious data",
|
"Import Invidious data": "Import Invidious JSON data",
|
||||||
"Import YouTube subscriptions": "Import YouTube subscriptions",
|
"Import YouTube subscriptions": "Import YouTube/OPML subscriptions",
|
||||||
"Import FreeTube subscriptions (.db)": "Import FreeTube subscriptions (.db)",
|
"Import FreeTube subscriptions (.db)": "Import FreeTube subscriptions (.db)",
|
||||||
"Import NewPipe subscriptions (.json)": "Import NewPipe subscriptions (.json)",
|
"Import NewPipe subscriptions (.json)": "Import NewPipe subscriptions (.json)",
|
||||||
"Import NewPipe data (.zip)": "Import NewPipe data (.zip)",
|
"Import NewPipe data (.zip)": "Import NewPipe data (.zip)",
|
||||||
"Export": "Export",
|
"Export": "Export",
|
||||||
"Export subscriptions as OPML": "Export subscriptions as OPML",
|
"Export subscriptions as OPML": "Export subscriptions as OPML",
|
||||||
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Export subscriptions as OPML (for NewPipe & FreeTube)",
|
"Export subscriptions as OPML (for NewPipe & FreeTube)": "Export subscriptions as OPML (for NewPipe & FreeTube)",
|
||||||
"Export data as JSON": "Export data as JSON",
|
"Export data as JSON": "Export Invidious data as JSON",
|
||||||
"Delete account?": "Delete account?",
|
"Delete account?": "Delete account?",
|
||||||
"History": "History",
|
"History": "History",
|
||||||
"An alternative front-end to YouTube": "An alternative front-end to YouTube",
|
"An alternative front-end to YouTube": "An alternative front-end to YouTube",
|
||||||
@@ -60,35 +58,59 @@
|
|||||||
"E-mail": "E-mail",
|
"E-mail": "E-mail",
|
||||||
"Google verification code": "Google verification code",
|
"Google verification code": "Google verification code",
|
||||||
"Preferences": "Preferences",
|
"Preferences": "Preferences",
|
||||||
"Player preferences": "Player preferences",
|
"preferences_category_player": "Player preferences",
|
||||||
"Always loop: ": "Always loop: ",
|
"preferences_video_loop_label": "Always loop: ",
|
||||||
"Autoplay: ": "Autoplay: ",
|
"preferences_autoplay_label": "Autoplay: ",
|
||||||
"Play next by default: ": "Play next by default: ",
|
"preferences_continue_label": "Play next by default: ",
|
||||||
"Autoplay next video: ": "Autoplay next video: ",
|
"preferences_continue_autoplay_label": "Autoplay next video: ",
|
||||||
"Listen by default: ": "Listen by default: ",
|
"preferences_listen_label": "Listen by default: ",
|
||||||
"Proxy videos: ": "Proxy videos: ",
|
"preferences_local_label": "Proxy videos: ",
|
||||||
"Default speed: ": "Default speed: ",
|
"preferences_watch_history_label": "Enable watch history: ",
|
||||||
"Preferred video quality: ": "Preferred video quality: ",
|
"preferences_speed_label": "Default speed: ",
|
||||||
"Player volume: ": "Player volume: ",
|
"preferences_quality_label": "Preferred video quality: ",
|
||||||
"Default comments: ": "Default comments: ",
|
"preferences_quality_option_dash": "DASH (adaptive quality)",
|
||||||
"youtube": "youtube",
|
"preferences_quality_option_hd720": "HD720",
|
||||||
"reddit": "reddit",
|
"preferences_quality_option_medium": "Medium",
|
||||||
"Default captions: ": "Default captions: ",
|
"preferences_quality_option_small": "Small",
|
||||||
|
"preferences_quality_dash_label": "Preferred DASH video quality: ",
|
||||||
|
"preferences_quality_dash_option_auto": "Auto",
|
||||||
|
"preferences_quality_dash_option_best": "Best",
|
||||||
|
"preferences_quality_dash_option_worst": "Worst",
|
||||||
|
"preferences_quality_dash_option_4320p": "4320p",
|
||||||
|
"preferences_quality_dash_option_2160p": "2160p",
|
||||||
|
"preferences_quality_dash_option_1440p": "1440p",
|
||||||
|
"preferences_quality_dash_option_1080p": "1080p",
|
||||||
|
"preferences_quality_dash_option_720p": "720p",
|
||||||
|
"preferences_quality_dash_option_480p": "480p",
|
||||||
|
"preferences_quality_dash_option_360p": "360p",
|
||||||
|
"preferences_quality_dash_option_240p": "240p",
|
||||||
|
"preferences_quality_dash_option_144p": "144p",
|
||||||
|
"preferences_volume_label": "Player volume: ",
|
||||||
|
"preferences_comments_label": "Default comments: ",
|
||||||
|
"youtube": "YouTube",
|
||||||
|
"reddit": "Reddit",
|
||||||
|
"invidious": "Invidious",
|
||||||
|
"preferences_captions_label": "Default captions: ",
|
||||||
"Fallback captions: ": "Fallback captions: ",
|
"Fallback captions: ": "Fallback captions: ",
|
||||||
"Show related videos: ": "Show related videos: ",
|
"preferences_related_videos_label": "Show related videos: ",
|
||||||
"Show annotations by default: ": "Show annotations by default: ",
|
"preferences_annotations_label": "Show annotations by default: ",
|
||||||
"Visual preferences": "Visual preferences",
|
"preferences_extend_desc_label": "Automatically extend video description: ",
|
||||||
"Player style: ": "Player style: ",
|
"preferences_vr_mode_label": "Interactive 360 degree videos (requires WebGL): ",
|
||||||
|
"preferences_category_visual": "Visual preferences",
|
||||||
|
"preferences_region_label": "Content country: ",
|
||||||
|
"preferences_player_style_label": "Player style: ",
|
||||||
"Dark mode: ": "Dark mode: ",
|
"Dark mode: ": "Dark mode: ",
|
||||||
"Theme: ": "Theme: ",
|
"preferences_dark_mode_label": "Theme: ",
|
||||||
"dark": "dark",
|
"dark": "dark",
|
||||||
"light": "light",
|
"light": "light",
|
||||||
"Thin mode: ": "Thin mode: ",
|
"preferences_thin_mode_label": "Thin mode: ",
|
||||||
"Subscription preferences": "Subscription preferences",
|
"preferences_category_misc": "Miscellaneous preferences",
|
||||||
"Show annotations by default for subscribed channels: ": "Show annotations by default for subscribed channels? ",
|
"preferences_automatic_instance_redirect_label": "Automatic instance redirection (fallback to redirect.invidious.io): ",
|
||||||
|
"preferences_category_subscription": "Subscription preferences",
|
||||||
|
"preferences_annotations_subscribed_label": "Show annotations by default for subscribed channels? ",
|
||||||
"Redirect homepage to feed: ": "Redirect homepage to feed: ",
|
"Redirect homepage to feed: ": "Redirect homepage to feed: ",
|
||||||
"Number of videos shown in feed: ": "Number of videos shown in feed: ",
|
"preferences_max_results_label": "Number of videos shown in feed: ",
|
||||||
"Sort videos by: ": "Sort videos by: ",
|
"preferences_sort_label": "Sort videos by: ",
|
||||||
"published": "published",
|
"published": "published",
|
||||||
"published - reverse": "published - reverse",
|
"published - reverse": "published - reverse",
|
||||||
"alphabetically": "alphabetically",
|
"alphabetically": "alphabetically",
|
||||||
@@ -97,12 +119,12 @@
|
|||||||
"channel name - reverse": "channel name - reverse",
|
"channel name - reverse": "channel name - reverse",
|
||||||
"Only show latest video from channel: ": "Only show latest video from channel: ",
|
"Only show latest video from channel: ": "Only show latest video from channel: ",
|
||||||
"Only show latest unwatched video from channel: ": "Only show latest unwatched video from channel: ",
|
"Only show latest unwatched video from channel: ": "Only show latest unwatched video from channel: ",
|
||||||
"Only show unwatched: ": "Only show unwatched: ",
|
"preferences_unseen_only_label": "Only show unwatched: ",
|
||||||
"Only show notifications (if there are any): ": "Only show notifications (if there are any): ",
|
"preferences_notifications_only_label": "Only show notifications (if there are any): ",
|
||||||
"Enable web notifications": "Enable web notifications",
|
"Enable web notifications": "Enable web notifications",
|
||||||
"`x` uploaded a video": "`x` uploaded a video",
|
"`x` uploaded a video": "`x` uploaded a video",
|
||||||
"`x` is live": "`x` is live",
|
"`x` is live": "`x` is live",
|
||||||
"Data preferences": "Data preferences",
|
"preferences_category_data": "Data preferences",
|
||||||
"Clear watch history": "Clear watch history",
|
"Clear watch history": "Clear watch history",
|
||||||
"Import/export data": "Import/export data",
|
"Import/export data": "Import/export data",
|
||||||
"Change password": "Change password",
|
"Change password": "Change password",
|
||||||
@@ -110,9 +132,11 @@
|
|||||||
"Manage tokens": "Manage tokens",
|
"Manage tokens": "Manage tokens",
|
||||||
"Watch history": "Watch history",
|
"Watch history": "Watch history",
|
||||||
"Delete account": "Delete account",
|
"Delete account": "Delete account",
|
||||||
"Administrator preferences": "Administrator preferences",
|
"preferences_category_admin": "Administrator preferences",
|
||||||
"Default homepage: ": "Default homepage: ",
|
"preferences_default_home_label": "Default homepage: ",
|
||||||
"Feed menu: ": "Feed menu: ",
|
"preferences_feed_menu_label": "Feed menu: ",
|
||||||
|
"preferences_show_nick_label": "Show nickname on top: ",
|
||||||
|
"Popular enabled: ": "Popular enabled: ",
|
||||||
"Top enabled: ": "Top enabled: ",
|
"Top enabled: ": "Top enabled: ",
|
||||||
"CAPTCHA enabled: ": "CAPTCHA enabled: ",
|
"CAPTCHA enabled: ": "CAPTCHA enabled: ",
|
||||||
"Login enabled: ": "Login enabled: ",
|
"Login enabled: ": "Login enabled: ",
|
||||||
@@ -122,25 +146,17 @@
|
|||||||
"Subscription manager": "Subscription manager",
|
"Subscription manager": "Subscription manager",
|
||||||
"Token manager": "Token manager",
|
"Token manager": "Token manager",
|
||||||
"Token": "Token",
|
"Token": "Token",
|
||||||
"`x` subscriptions": {
|
"tokens_count": "{{count}} token",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` subscription",
|
"tokens_count_plural": "{{count}} tokens",
|
||||||
"": "`x` subscriptions"
|
|
||||||
},
|
|
||||||
"`x` tokens": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` token",
|
|
||||||
"": "`x` tokens"
|
|
||||||
},
|
|
||||||
"Import/export": "Import/export",
|
"Import/export": "Import/export",
|
||||||
"unsubscribe": "unsubscribe",
|
"unsubscribe": "unsubscribe",
|
||||||
"revoke": "revoke",
|
"revoke": "revoke",
|
||||||
"Subscriptions": "Subscriptions",
|
"Subscriptions": "Subscriptions",
|
||||||
"`x` unseen notifications": {
|
"subscriptions_unseen_notifs_count": "{{count}} unseen notification",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` unseen notification",
|
"subscriptions_unseen_notifs_count_plural": "{{count}} unseen notifications",
|
||||||
"": "`x` unseen notifications"
|
|
||||||
},
|
|
||||||
"search": "search",
|
"search": "search",
|
||||||
"Log out": "Log out",
|
"Log out": "Log out",
|
||||||
"Released under the AGPLv3 by Omar Roth.": "Released under the AGPLv3 by Omar Roth.",
|
"Released under the AGPLv3 on Github.": "Released under the AGPLv3 on GitHub.",
|
||||||
"Source available here.": "Source available here.",
|
"Source available here.": "Source available here.",
|
||||||
"View JavaScript license information.": "View JavaScript license information.",
|
"View JavaScript license information.": "View JavaScript license information.",
|
||||||
"View privacy policy.": "View privacy policy.",
|
"View privacy policy.": "View privacy policy.",
|
||||||
@@ -156,7 +172,13 @@
|
|||||||
"Title": "Title",
|
"Title": "Title",
|
||||||
"Playlist privacy": "Playlist privacy",
|
"Playlist privacy": "Playlist privacy",
|
||||||
"Editing playlist `x`": "Editing playlist `x`",
|
"Editing playlist `x`": "Editing playlist `x`",
|
||||||
|
"Show more": "Show more",
|
||||||
|
"Show less": "Show less",
|
||||||
"Watch on YouTube": "Watch on YouTube",
|
"Watch on YouTube": "Watch on YouTube",
|
||||||
|
"Switch Invidious Instance": "Switch Invidious Instance",
|
||||||
|
"search_message_no_results": "No results found.",
|
||||||
|
"search_message_change_filters_or_query": "Try widening your search query and/or changing the filters.",
|
||||||
|
"search_message_use_another_instance": " You can also <a href=\"`x`\">search on another instance</a>.",
|
||||||
"Hide annotations": "Hide annotations",
|
"Hide annotations": "Hide annotations",
|
||||||
"Show annotations": "Show annotations",
|
"Show annotations": "Show annotations",
|
||||||
"Genre: ": "Genre: ",
|
"Genre: ": "Genre: ",
|
||||||
@@ -167,17 +189,13 @@
|
|||||||
"Whitelisted regions: ": "Whitelisted regions: ",
|
"Whitelisted regions: ": "Whitelisted regions: ",
|
||||||
"Blacklisted regions: ": "Blacklisted regions: ",
|
"Blacklisted regions: ": "Blacklisted regions: ",
|
||||||
"Shared `x`": "Shared `x`",
|
"Shared `x`": "Shared `x`",
|
||||||
"`x` views": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` view",
|
|
||||||
"": "`x` views"
|
|
||||||
},
|
|
||||||
"Premieres in `x`": "Premieres in `x`",
|
"Premieres in `x`": "Premieres in `x`",
|
||||||
"Premieres `x`": "Premieres `x`",
|
"Premieres `x`": "Premieres `x`",
|
||||||
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.",
|
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.",
|
||||||
"View YouTube comments": "View YouTube comments",
|
"View YouTube comments": "View YouTube comments",
|
||||||
"View more comments on Reddit": "View more comments on Reddit",
|
"View more comments on Reddit": "View more comments on Reddit",
|
||||||
"View `x` comments": {
|
"View `x` comments": {
|
||||||
"(\\D|^)1(\\D|$)": "View `x` comment",
|
"([^.,0-9]|^)1([^.,0-9]|$)": "View `x` comment",
|
||||||
"": "View `x` comments"
|
"": "View `x` comments"
|
||||||
},
|
},
|
||||||
"View Reddit comments": "View Reddit comments",
|
"View Reddit comments": "View Reddit comments",
|
||||||
@@ -204,16 +222,12 @@
|
|||||||
"This channel does not exist.": "This channel does not exist.",
|
"This channel does not exist.": "This channel does not exist.",
|
||||||
"Could not get channel info.": "Could not get channel info.",
|
"Could not get channel info.": "Could not get channel info.",
|
||||||
"Could not fetch comments": "Could not fetch comments",
|
"Could not fetch comments": "Could not fetch comments",
|
||||||
"View `x` replies": {
|
"comments_view_x_replies": "View {{count}} reply",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "View `x` reply",
|
"comments_view_x_replies_plural": "View {{count}} replies",
|
||||||
"": "View `x` replies"
|
|
||||||
},
|
|
||||||
"`x` ago": "`x` ago",
|
"`x` ago": "`x` ago",
|
||||||
"Load more": "Load more",
|
"Load more": "Load more",
|
||||||
"`x` points": {
|
"comments_points_count": "{{count}} point",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` point",
|
"comments_points_count_plural": "{{count}} points",
|
||||||
"": "`x` points"
|
|
||||||
},
|
|
||||||
"Could not create mix.": "Could not create mix.",
|
"Could not create mix.": "Could not create mix.",
|
||||||
"Empty playlist": "Empty playlist",
|
"Empty playlist": "Empty playlist",
|
||||||
"Not a playlist.": "Not a playlist.",
|
"Not a playlist.": "Not a playlist.",
|
||||||
@@ -226,6 +240,8 @@
|
|||||||
"No such user": "No such user",
|
"No such user": "No such user",
|
||||||
"Token is expired, please try again": "Token is expired, please try again",
|
"Token is expired, please try again": "Token is expired, please try again",
|
||||||
"English": "English",
|
"English": "English",
|
||||||
|
"English (United Kingdom)": "English (United Kingdom)",
|
||||||
|
"English (United States)": "English (United States)",
|
||||||
"English (auto-generated)": "English (auto-generated)",
|
"English (auto-generated)": "English (auto-generated)",
|
||||||
"Afrikaans": "Afrikaans",
|
"Afrikaans": "Afrikaans",
|
||||||
"Albanian": "Albanian",
|
"Albanian": "Albanian",
|
||||||
@@ -239,23 +255,31 @@
|
|||||||
"Bosnian": "Bosnian",
|
"Bosnian": "Bosnian",
|
||||||
"Bulgarian": "Bulgarian",
|
"Bulgarian": "Bulgarian",
|
||||||
"Burmese": "Burmese",
|
"Burmese": "Burmese",
|
||||||
|
"Cantonese (Hong Kong)": "Cantonese (Hong Kong)",
|
||||||
"Catalan": "Catalan",
|
"Catalan": "Catalan",
|
||||||
"Cebuano": "Cebuano",
|
"Cebuano": "Cebuano",
|
||||||
|
"Chinese": "Chinese",
|
||||||
|
"Chinese (China)": "Chinese (China)",
|
||||||
|
"Chinese (Hong Kong)": "Chinese (Hong Kong)",
|
||||||
"Chinese (Simplified)": "Chinese (Simplified)",
|
"Chinese (Simplified)": "Chinese (Simplified)",
|
||||||
|
"Chinese (Taiwan)": "Chinese (Taiwan)",
|
||||||
"Chinese (Traditional)": "Chinese (Traditional)",
|
"Chinese (Traditional)": "Chinese (Traditional)",
|
||||||
"Corsican": "Corsican",
|
"Corsican": "Corsican",
|
||||||
"Croatian": "Croatian",
|
"Croatian": "Croatian",
|
||||||
"Czech": "Czech",
|
"Czech": "Czech",
|
||||||
"Danish": "Danish",
|
"Danish": "Danish",
|
||||||
"Dutch": "Dutch",
|
"Dutch": "Dutch",
|
||||||
|
"Dutch (auto-generated)": "Dutch (auto-generated)",
|
||||||
"Esperanto": "Esperanto",
|
"Esperanto": "Esperanto",
|
||||||
"Estonian": "Estonian",
|
"Estonian": "Estonian",
|
||||||
"Filipino": "Filipino",
|
"Filipino": "Filipino",
|
||||||
"Finnish": "Finnish",
|
"Finnish": "Finnish",
|
||||||
"French": "French",
|
"French": "French",
|
||||||
|
"French (auto-generated)": "French (auto-generated)",
|
||||||
"Galician": "Galician",
|
"Galician": "Galician",
|
||||||
"Georgian": "Georgian",
|
"Georgian": "Georgian",
|
||||||
"German": "German",
|
"German": "German",
|
||||||
|
"German (auto-generated)": "German (auto-generated)",
|
||||||
"Greek": "Greek",
|
"Greek": "Greek",
|
||||||
"Gujarati": "Gujarati",
|
"Gujarati": "Gujarati",
|
||||||
"Haitian Creole": "Haitian Creole",
|
"Haitian Creole": "Haitian Creole",
|
||||||
@@ -268,14 +292,19 @@
|
|||||||
"Icelandic": "Icelandic",
|
"Icelandic": "Icelandic",
|
||||||
"Igbo": "Igbo",
|
"Igbo": "Igbo",
|
||||||
"Indonesian": "Indonesian",
|
"Indonesian": "Indonesian",
|
||||||
|
"Indonesian (auto-generated)": "Indonesian (auto-generated)",
|
||||||
|
"Interlingue": "Interlingue",
|
||||||
"Irish": "Irish",
|
"Irish": "Irish",
|
||||||
"Italian": "Italian",
|
"Italian": "Italian",
|
||||||
|
"Italian (auto-generated)": "Italian (auto-generated)",
|
||||||
"Japanese": "Japanese",
|
"Japanese": "Japanese",
|
||||||
|
"Japanese (auto-generated)": "Japanese (auto-generated)",
|
||||||
"Javanese": "Javanese",
|
"Javanese": "Javanese",
|
||||||
"Kannada": "Kannada",
|
"Kannada": "Kannada",
|
||||||
"Kazakh": "Kazakh",
|
"Kazakh": "Kazakh",
|
||||||
"Khmer": "Khmer",
|
"Khmer": "Khmer",
|
||||||
"Korean": "Korean",
|
"Korean": "Korean",
|
||||||
|
"Korean (auto-generated)": "Korean (auto-generated)",
|
||||||
"Kurdish": "Kurdish",
|
"Kurdish": "Kurdish",
|
||||||
"Kyrgyz": "Kyrgyz",
|
"Kyrgyz": "Kyrgyz",
|
||||||
"Lao": "Lao",
|
"Lao": "Lao",
|
||||||
@@ -298,9 +327,12 @@
|
|||||||
"Persian": "Persian",
|
"Persian": "Persian",
|
||||||
"Polish": "Polish",
|
"Polish": "Polish",
|
||||||
"Portuguese": "Portuguese",
|
"Portuguese": "Portuguese",
|
||||||
|
"Portuguese (auto-generated)": "Portuguese (auto-generated)",
|
||||||
|
"Portuguese (Brazil)": "Portuguese (Brazil)",
|
||||||
"Punjabi": "Punjabi",
|
"Punjabi": "Punjabi",
|
||||||
"Romanian": "Romanian",
|
"Romanian": "Romanian",
|
||||||
"Russian": "Russian",
|
"Russian": "Russian",
|
||||||
|
"Russian (auto-generated)": "Russian (auto-generated)",
|
||||||
"Samoan": "Samoan",
|
"Samoan": "Samoan",
|
||||||
"Scottish Gaelic": "Scottish Gaelic",
|
"Scottish Gaelic": "Scottish Gaelic",
|
||||||
"Serbian": "Serbian",
|
"Serbian": "Serbian",
|
||||||
@@ -312,7 +344,10 @@
|
|||||||
"Somali": "Somali",
|
"Somali": "Somali",
|
||||||
"Southern Sotho": "Southern Sotho",
|
"Southern Sotho": "Southern Sotho",
|
||||||
"Spanish": "Spanish",
|
"Spanish": "Spanish",
|
||||||
|
"Spanish (auto-generated)": "Spanish (auto-generated)",
|
||||||
"Spanish (Latin America)": "Spanish (Latin America)",
|
"Spanish (Latin America)": "Spanish (Latin America)",
|
||||||
|
"Spanish (Mexico)": "Spanish (Mexico)",
|
||||||
|
"Spanish (Spain)": "Spanish (Spain)",
|
||||||
"Sundanese": "Sundanese",
|
"Sundanese": "Sundanese",
|
||||||
"Swahili": "Swahili",
|
"Swahili": "Swahili",
|
||||||
"Swedish": "Swedish",
|
"Swedish": "Swedish",
|
||||||
@@ -321,50 +356,39 @@
|
|||||||
"Telugu": "Telugu",
|
"Telugu": "Telugu",
|
||||||
"Thai": "Thai",
|
"Thai": "Thai",
|
||||||
"Turkish": "Turkish",
|
"Turkish": "Turkish",
|
||||||
|
"Turkish (auto-generated)": "Turkish (auto-generated)",
|
||||||
"Ukrainian": "Ukrainian",
|
"Ukrainian": "Ukrainian",
|
||||||
"Urdu": "Urdu",
|
"Urdu": "Urdu",
|
||||||
"Uzbek": "Uzbek",
|
"Uzbek": "Uzbek",
|
||||||
"Vietnamese": "Vietnamese",
|
"Vietnamese": "Vietnamese",
|
||||||
|
"Vietnamese (auto-generated)": "Vietnamese (auto-generated)",
|
||||||
"Welsh": "Welsh",
|
"Welsh": "Welsh",
|
||||||
"Western Frisian": "Western Frisian",
|
"Western Frisian": "Western Frisian",
|
||||||
"Xhosa": "Xhosa",
|
"Xhosa": "Xhosa",
|
||||||
"Yiddish": "Yiddish",
|
"Yiddish": "Yiddish",
|
||||||
"Yoruba": "Yoruba",
|
"Yoruba": "Yoruba",
|
||||||
"Zulu": "Zulu",
|
"Zulu": "Zulu",
|
||||||
"`x` years": {
|
"generic_count_years": "{{count}} year",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` year",
|
"generic_count_years_plural": "{{count}} years",
|
||||||
"": "`x` years"
|
"generic_count_months": "{{count}} month",
|
||||||
},
|
"generic_count_months_plural": "{{count}} months",
|
||||||
"`x` months": {
|
"generic_count_weeks": "{{count}} week",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` month",
|
"generic_count_weeks_plural": "{{count}} weeks",
|
||||||
"": "`x` months"
|
"generic_count_days": "{{count}} day",
|
||||||
},
|
"generic_count_days_plural": "{{count}} days",
|
||||||
"`x` weeks": {
|
"generic_count_hours": "{{count}} hour",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` week",
|
"generic_count_hours_plural": "{{count}} hours",
|
||||||
"": "`x` weeks"
|
"generic_count_minutes": "{{count}} minute",
|
||||||
},
|
"generic_count_minutes_plural": "{{count}} minutes",
|
||||||
"`x` days": {
|
"generic_count_seconds": "{{count}} second",
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` day",
|
"generic_count_seconds_plural": "{{count}} seconds",
|
||||||
"": "`x` days"
|
|
||||||
},
|
|
||||||
"`x` hours": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` hour",
|
|
||||||
"": "`x` hours"
|
|
||||||
},
|
|
||||||
"`x` minutes": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` minute",
|
|
||||||
"": "`x` minutes"
|
|
||||||
},
|
|
||||||
"`x` seconds": {
|
|
||||||
"([^.,0-9]|^)1([^.,0-9]|$)": "`x` second",
|
|
||||||
"": "`x` seconds"
|
|
||||||
},
|
|
||||||
"Fallback comments: ": "Fallback comments: ",
|
"Fallback comments: ": "Fallback comments: ",
|
||||||
"Popular": "Popular",
|
"Popular": "Popular",
|
||||||
|
"Search": "Search",
|
||||||
"Top": "Top",
|
"Top": "Top",
|
||||||
"About": "About",
|
"About": "About",
|
||||||
"Rating: ": "Rating: ",
|
"Rating: ": "Rating: ",
|
||||||
"Language: ": "Language: ",
|
"preferences_locale_label": "Language: ",
|
||||||
"View as playlist": "View as playlist",
|
"View as playlist": "View as playlist",
|
||||||
"Default": "Default",
|
"Default": "Default",
|
||||||
"Music": "Music",
|
"Music": "Music",
|
||||||
@@ -383,5 +407,69 @@
|
|||||||
"Videos": "Videos",
|
"Videos": "Videos",
|
||||||
"Playlists": "Playlists",
|
"Playlists": "Playlists",
|
||||||
"Community": "Community",
|
"Community": "Community",
|
||||||
"Current version: ": "Current version: "
|
"search_filters_title": "Filters",
|
||||||
}
|
"search_filters_date_label": "Upload date",
|
||||||
|
"search_filters_date_option_none": "Any date",
|
||||||
|
"search_filters_date_option_hour": "Last Hour",
|
||||||
|
"search_filters_date_option_today": "Today",
|
||||||
|
"search_filters_date_option_week": "This week",
|
||||||
|
"search_filters_date_option_month": "This month",
|
||||||
|
"search_filters_date_option_year": "This year",
|
||||||
|
"search_filters_type_label": "Type",
|
||||||
|
"search_filters_type_option_all": "Any type",
|
||||||
|
"search_filters_type_option_video": "Video",
|
||||||
|
"search_filters_type_option_channel": "Channel",
|
||||||
|
"search_filters_type_option_playlist": "Playlist",
|
||||||
|
"search_filters_type_option_movie": "Movie",
|
||||||
|
"search_filters_type_option_show": "Show",
|
||||||
|
"search_filters_duration_label": "Duration",
|
||||||
|
"search_filters_duration_option_none": "Any duration",
|
||||||
|
"search_filters_duration_option_short": "Short (< 4 minutes)",
|
||||||
|
"search_filters_duration_option_medium": "Medium (4 - 20 minutes)",
|
||||||
|
"search_filters_duration_option_long": "Long (> 20 minutes)",
|
||||||
|
"search_filters_features_label": "Features",
|
||||||
|
"search_filters_features_option_live": "Live",
|
||||||
|
"search_filters_features_option_four_k": "4K",
|
||||||
|
"search_filters_features_option_hd": "HD",
|
||||||
|
"search_filters_features_option_subtitles": "Subtitles/CC",
|
||||||
|
"search_filters_features_option_c_commons": "Creative Commons",
|
||||||
|
"search_filters_features_option_three_sixty": "360°",
|
||||||
|
"search_filters_features_option_vr180": "VR180",
|
||||||
|
"search_filters_features_option_three_d": "3D",
|
||||||
|
"search_filters_features_option_hdr": "HDR",
|
||||||
|
"search_filters_features_option_location": "Location",
|
||||||
|
"search_filters_features_option_purchased": "Purchased",
|
||||||
|
"search_filters_sort_label": "Sort By",
|
||||||
|
"search_filters_sort_option_relevance": "Relevance",
|
||||||
|
"search_filters_sort_option_rating": "Rating",
|
||||||
|
"search_filters_sort_option_date": "Upload Date",
|
||||||
|
"search_filters_sort_option_views": "View count",
|
||||||
|
"search_filters_apply_button": "Apply selected filters",
|
||||||
|
"Current version: ": "Current version: ",
|
||||||
|
"next_steps_error_message": "After which you should try to: ",
|
||||||
|
"next_steps_error_message_refresh": "Refresh",
|
||||||
|
"next_steps_error_message_go_to_youtube": "Go to YouTube",
|
||||||
|
"footer_donate_page": "Donate",
|
||||||
|
"footer_documentation": "Documentation",
|
||||||
|
"footer_source_code": "Source code",
|
||||||
|
"footer_original_source_code": "Original source code",
|
||||||
|
"footer_modfied_source_code": "Modified Source code",
|
||||||
|
"adminprefs_modified_source_code_url_label": "URL to modified source code repository",
|
||||||
|
"none": "none",
|
||||||
|
"videoinfo_started_streaming_x_ago": "Started streaming `x` ago",
|
||||||
|
"videoinfo_watch_on_youTube": "Watch on YouTube",
|
||||||
|
"videoinfo_youTube_embed_link": "Embed",
|
||||||
|
"videoinfo_invidious_embed_link": "Embed Link",
|
||||||
|
"download_subtitles": "Subtitles - `x` (.vtt)",
|
||||||
|
"user_created_playlists": "`x` created playlists",
|
||||||
|
"user_saved_playlists": "`x` saved playlists",
|
||||||
|
"Video unavailable": "Video unavailable",
|
||||||
|
"preferences_save_player_pos_label": "Save playback position: ",
|
||||||
|
"crash_page_you_found_a_bug": "It looks like you found a bug in Invidious!",
|
||||||
|
"crash_page_before_reporting": "Before reporting a bug, make sure that you have:",
|
||||||
|
"crash_page_refresh": "tried to <a href=\"`x`\">refresh the page</a>",
|
||||||
|
"crash_page_switch_instance": "tried to <a href=\"`x`\">use another instance</a>",
|
||||||
|
"crash_page_read_the_faq": "read the <a href=\"`x`\">Frequently Asked Questions (FAQ)</a>",
|
||||||
|
"crash_page_search_issue": "searched for <a href=\"`x`\">existing issues on GitHub</a>",
|
||||||
|
"crash_page_report_issue": "If none of the above helped, please <a href=\"`x`\">open a new issue on GitHub</a> (preferably in English) and include the following text in your message (do NOT translate that text):"
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user