mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2024-05-14 19:02:40 +00:00
Compare commits
618 commits
Author | SHA1 | Date | |
---|---|---|---|
2177995056 | |||
46b45dc51d | |||
9436a18e95 | |||
8d22b9100b | |||
1642c5b9e7 | |||
d72ef2a2b9 | |||
afb28272f5 | |||
b8635c2606 | |||
712f7d18e6 | |||
47ae6e880d | |||
9244620f37 | |||
4e09837aa0 | |||
fde6b32ca5 | |||
63654cb475 | |||
dcd3a0ee46 | |||
db32f70799 | |||
f2895d29e1 | |||
b824480af7 | |||
aa1ea0b6c8 | |||
bce0f2f11b | |||
da949376db | |||
d43dc97767 | |||
92c1ecabf9 | |||
da89fb73b2 | |||
6631facaf6 | |||
07226826ba | |||
d1647652b9 | |||
12d7fdb2f4 | |||
f75dbd5e73 | |||
dbcee9acd9 | |||
a50c542363 | |||
6dc2cf0d42 | |||
8e30e1f5fd | |||
4f12515cc7 | |||
91139b634d | |||
df7008ddad | |||
ddfed6aedf | |||
43373e777b | |||
1208269dcb | |||
8cb1a8f9ff | |||
409ad373ac | |||
382d760bd8 | |||
ca7a869105 | |||
54c0c411f1 | |||
8e87c84f7a | |||
c783356a69 | |||
3fcd0b4153 | |||
0add86337b | |||
1e6edcf060 | |||
4c5d6306b2 | |||
965c592e89 | |||
db05e6cebb | |||
c67dfb979b | |||
f2b4f409a3 | |||
6f3deaee2e | |||
2ccd64b03b | |||
b2dada8974 | |||
b89f37a751 | |||
b0ebb77197 | |||
7163a1a044 | |||
f84ac3ba41 | |||
abc6c2b7f4 | |||
47731d85c4 | |||
f84243fc53 | |||
3bfecf4890 | |||
93b09bf891 | |||
d1e634acff | |||
67ae543604 | |||
7402e6947b | |||
08cce23535 | |||
5cb3e6a0b8 | |||
db69b78f1b | |||
ff5a32ff3e | |||
1c33c6a388 | |||
a93217d2da | |||
6f6abcabfb | |||
cd42491cf0 | |||
9f92c8c426 | |||
4b18b0880d | |||
77d4aa19d2 | |||
4e86c38bc9 | |||
d627ccf2d1 | |||
57610f306c | |||
dca3fc6e47 | |||
bb04450ab7 | |||
e888a248e3 | |||
635d8b49b4 | |||
f30fce8d02 | |||
7eb8f2b102 | |||
44600a6be0 | |||
e90d140bba | |||
7cf7836738 | |||
87e950a91d | |||
8d33f30051 | |||
ea4009bbc5 | |||
3a4e05648f | |||
a88433cdf0 | |||
c1501620c4 | |||
e953f78bac | |||
68ee493c08 | |||
7816fa4d48 | |||
e43326ed5b | |||
f8b8dc674e | |||
61fec4e4ef | |||
9b70c8e7e8 | |||
faabe996ba | |||
17fb4fd6d0 | |||
0794fe2ac1 | |||
1b323f4f65 | |||
107e6e73a6 | |||
1d52f1f138 | |||
121efedde2 | |||
33607e3268 | |||
7eb0189b73 | |||
81963e0c6e | |||
817f754c22 | |||
5ef0430dfb | |||
3f8454ce63 | |||
11521f231f | |||
aaa5acbb0c | |||
bfa7e364bf | |||
ca889dbbb8 | |||
4a35e6587a | |||
26de1467e2 | |||
855def80f6 | |||
51656abe54 | |||
a9cb4bcd41 | |||
08a8114c9b | |||
5ec9a64806 | |||
8b3df5acd7 | |||
a246c44504 | |||
320327eb47 | |||
f956500d92 | |||
959ebe88db | |||
65f600c776 | |||
70dde4daa5 | |||
2fa474450d | |||
357d502d53 | |||
f6def3b17b | |||
87ec87d9d0 | |||
5610fae234 | |||
c501556d1c | |||
635c2ecad9 | |||
6e11da1c89 | |||
497773c78d | |||
f47a6bfda1 | |||
21f30dfd41 | |||
60d8e54d11 | |||
ff7d7d635b | |||
a113c2e0ab | |||
b95450c417 | |||
98ea109807 | |||
677944c5cf | |||
86ea646e85 | |||
2f7884bd89 | |||
d7046c50dd | |||
756b77d8b8 | |||
a8053326a2 | |||
f3d07f3f8a | |||
2b87e1325a | |||
f5e197d23f | |||
bd59a169ee | |||
942846c46b | |||
fcd8ffd6fe | |||
44e82d7072 | |||
c639af5fb3 | |||
05b39efaf7 | |||
8a76018392 | |||
46ef110507 | |||
9f41897455 | |||
f457a21191 | |||
74cfc88759 | |||
3fd62fdec5 | |||
6d32ad4d03 | |||
a159b8b517 | |||
058ef6912c | |||
5b8da4e051 | |||
d4a09f9ce2 | |||
be19d9be34 | |||
b4169fe0a4 | |||
0c0ea5dbf7 | |||
33101bc5b3 | |||
8da3e2e9b8 | |||
85cc3b2af6 | |||
da63a030f3 | |||
78e4cc30c5 | |||
302fd93c49 | |||
41fd9435a6 | |||
55e3de1cdd | |||
167d36df63 | |||
128748e6e4 | |||
c09e27d77a | |||
4e98d843da | |||
0e718cb7b2 | |||
0301d77254 | |||
c727a34cb6 | |||
3b429f2104 | |||
e6dc5318ca | |||
ae8a0de711 | |||
4aec2ccab1 | |||
ac2386d1a2 | |||
92c1dc5700 | |||
a6712fce06 | |||
41af8c9944 | |||
cb00c76f18 | |||
be2b0b622a | |||
442d71b8c7 | |||
713076c46d | |||
060397dd2d | |||
305070fbab | |||
b0eaa8250e | |||
4e5786ce91 | |||
9fdde1ab0a | |||
c1747f901a | |||
135b8555f1 | |||
89183676c5 | |||
83c272f333 | |||
e04de60d94 | |||
60fbf50b24 | |||
4844d22f50 | |||
6ac028e36a | |||
d9e96c2c62 | |||
18519e2bb3 | |||
f68d7f8a9b | |||
5cc827c79f | |||
16084d12df | |||
766c25c1f8 | |||
6b51caecf2 | |||
5bfaf6b9c4 | |||
cd186a862b | |||
0cda8c70d1 | |||
0f7224b0d1 | |||
798d8d37ee | |||
1a8b20ba30 | |||
c10c3c5e79 | |||
01af40a55f | |||
1048d1054b | |||
e57c3024f4 | |||
ae31e90c30 | |||
486b4a329f | |||
0f67adf98a | |||
46950fbcc8 | |||
fb50a233f4 | |||
52b6d97250 | |||
3eba4fca2a | |||
4e29a6f7ba | |||
888b142e2e | |||
23aafafd1e | |||
6250e4ab1d | |||
cb77bfcd0f | |||
29873257e7 | |||
4596ec2a9f | |||
b080ccc3ee | |||
3a53d44246 | |||
752190f253 | |||
3a4d09a150 | |||
2d20781966 | |||
5c447283a5 | |||
7e573616d9 | |||
10e78bb778 | |||
54a7183b11 | |||
36710e5c24 | |||
eb2ee34c57 | |||
e8955ac8ca | |||
371f08cbaf | |||
29fc2db3a2 | |||
2fc3b90cb7 | |||
15b8f96b75 | |||
0fe016f0ea | |||
f4e79548f3 | |||
a2052bf074 | |||
18b86fad00 | |||
f326b726e7 | |||
2a69a02527 | |||
fa7a022e01 | |||
b6ee2ec689 | |||
2cdb94c885 | |||
11d5cc3be5 | |||
ca0efdc276 | |||
cc4bbad451 | |||
7bd16e512e | |||
7ce853933b | |||
c50e2ddd00 | |||
0870929b75 | |||
c2122f77c4 | |||
2afc4f5dd6 | |||
f92939bd85 | |||
cf6219d5de | |||
f23326b774 | |||
a7142be2f0 | |||
44be6cca1b | |||
de1a3c3795 | |||
a6b732df4d | |||
862c72972b | |||
ee7020685d | |||
bd7f1fed2a | |||
a5613aa8a8 | |||
cef5abbdbb | |||
57268f87ac | |||
6802da3616 | |||
96f8bcae8e | |||
2b8ec2c6da | |||
165449a7a9 | |||
df89e212f2 | |||
db3827d227 | |||
3fe03ee73a | |||
a5c4e271f8 | |||
607ac9be3b | |||
36e88a41da | |||
5d8fa623fb | |||
50152904a5 | |||
5b7a207dad | |||
338633ce72 | |||
5e041ff7c2 | |||
62cc9b1752 | |||
bfdf82c490 | |||
275ba643eb | |||
c8d1f0d9c5 | |||
287ab812d3 | |||
4b857f50c8 | |||
4af8f5a581 | |||
b00180744c | |||
98781f353d | |||
7be401ac76 | |||
aff87c12ff | |||
f6fb7cd3e9 | |||
cd9b8c2cc8 | |||
109bff4bf7 | |||
568726e48d | |||
4434e78c56 | |||
cf60f7af03 | |||
9808b179a5 | |||
dee2e66e02 | |||
bb21e0b3c8 | |||
91d7a3928f | |||
dfe98695d6 | |||
9953825499 | |||
206fe1de0e | |||
a4b497c2a9 | |||
2e760485c1 | |||
b6b1aaa56f | |||
c75381208f | |||
a172cadee4 | |||
466acae1e5 | |||
5f3009d8e9 | |||
878ea1499d | |||
68d006b6fc | |||
c2c2cd4121 | |||
f978e52edc | |||
109e93c139 | |||
fb2dc40858 | |||
1abf74e464 | |||
e2b2c46339 | |||
0eff76f800 | |||
3f133cb2e6 | |||
ac3e1df8d5 | |||
91243020b5 | |||
0fe0b1421d | |||
65cb19c253 | |||
2f455f3004 | |||
ca4cc21739 | |||
d92b47dccf | |||
ebf557110e | |||
8cad6a3e6f | |||
0b53d8ae08 | |||
1a8aee7368 | |||
52d15325ae | |||
5b7f477c0c | |||
473840e890 | |||
0db27b44f3 | |||
ed77d65699 | |||
1e17dece73 | |||
c4a062109d | |||
094accd873 | |||
0165786f65 | |||
bb7cb0d2fd | |||
db06d13c67 | |||
007b845cab | |||
9e2700b89d | |||
780f17f116 | |||
971077bccd | |||
d7edb2f8fe | |||
6eda5c36f4 | |||
8349c20c08 | |||
27f2dc51dd | |||
7130b738aa | |||
1a6419668d | |||
1ea6b40a66 | |||
90c36a07c8 | |||
d6fb498573 | |||
69257086ce | |||
e58df247cf | |||
410cd6161f | |||
b0b94df5ae | |||
eb285bc84c | |||
1d871ade86 | |||
f697ebc3c4 | |||
37b2942136 | |||
de4aeee2a6 | |||
a1018488e9 | |||
a77d2e45ef | |||
0225419b24 | |||
02848ab04a | |||
b4e33b91f4 | |||
90a8602c37 | |||
5321fee555 | |||
f29ca82157 | |||
38b16b65c5 | |||
c7ccd9b85a | |||
f2d4da685e | |||
2a0a452984 | |||
f108ef1c24 | |||
5d345167e6 | |||
4506c54c18 | |||
ed0f6dac27 | |||
1890823ec1 | |||
3b0a2988a6 | |||
0af1cb0254 | |||
1166fe1ef8 | |||
76fc3da608 | |||
54ce688c11 | |||
1ad8f40fed | |||
c19c5d7011 | |||
1ca3787c64 | |||
a6ac6ecc55 | |||
c7a9dd3f31 | |||
d1bac9fff4 | |||
b22c846dca | |||
e2c54724c1 | |||
bd8a31c1a2 | |||
3c27cea450 | |||
0335f1c5eb | |||
6add950866 | |||
5a00113c15 | |||
09b6bf1306 | |||
51483237b4 | |||
f6766e6c57 | |||
22d2574cc0 | |||
b89a1654fc | |||
0648d57870 | |||
db69d9491e | |||
fbe47a9f8e | |||
00ee54329a | |||
f7e4f62870 | |||
e286db3a39 | |||
8c3cb7e083 | |||
7986ab8452 | |||
967702d6c7 | |||
009d7b39ac | |||
02596be702 | |||
3cac8a756f | |||
f9c89b98f7 | |||
35f0bb14be | |||
b18127d91b | |||
f6af3f701c | |||
8573e5a80a | |||
4d63e6f577 | |||
93f9677463 | |||
cbfe10a43e | |||
7ee0efb57a | |||
1c0270ca8a | |||
c97b8fd2ea | |||
7b86b9b458 | |||
ebe828ec75 | |||
a40981fc30 | |||
cb23087ff5 | |||
48f1d4b186 | |||
22ab711501 | |||
1387e0a3bb | |||
65e7ffba15 | |||
a53834bdff | |||
f49896f44e | |||
098c25ece6 | |||
b13e81e43f | |||
64128512b2 | |||
ef4e7651c1 | |||
26fb3ee660 | |||
c4b039886e | |||
ba3820965f | |||
5f09fde24e | |||
331e7cb3c5 | |||
a012d6c2a9 | |||
4300cc1ee1 | |||
acd9eaeb1d | |||
bfdd4d10f3 | |||
8758d8ed8f | |||
11458a747c | |||
ca90b8f651 | |||
d7e496d3a3 | |||
9489b536a2 | |||
88006beeb3 | |||
0d89f639f6 | |||
4d8018de68 | |||
91f975f959 | |||
6e3b929518 | |||
53ffe6e4dd | |||
7a6d950c5c | |||
37648b4b06 | |||
025b29d68f | |||
aeb0cb15de | |||
49a64e80c9 | |||
51c88251b5 | |||
6fcbf9dbd0 | |||
a0ff5adfa3 | |||
0c0c7c05ad | |||
365f2363fb | |||
29cd853727 | |||
c366b9aa23 | |||
24d17812d2 | |||
a7e9fe9454 | |||
d30fbaf297 | |||
e18c5c2ba3 | |||
bfe5125b50 | |||
b9f2911814 | |||
1d39df8fb8 | |||
faaad4db67 | |||
2de74bff48 | |||
226f4c9dc5 | |||
b49fd600f8 | |||
10f6af0d96 | |||
ac2a74463e | |||
e349611e49 | |||
86cfb52cf3 | |||
f99d77e1ad | |||
9bcf0ecc48 | |||
72e896ea49 | |||
ffd9bf1c8b | |||
1cb3afb2c2 | |||
0cbe9a471f | |||
9e9a00d7f8 | |||
0461ce8d24 | |||
b9e11ea213 | |||
b68d2b0698 | |||
d1adcfadfd | |||
7f8979e544 | |||
2230b1571f | |||
0a53a54ed7 | |||
4cbea51255 | |||
4437ae0fd3 | |||
4f3fb47884 | |||
b9077c83fc | |||
482223cc23 | |||
374820f2c0 | |||
00e0d15611 | |||
ef39bc9069 | |||
640bc1a0cd | |||
c6a963511f | |||
05bb85c480 | |||
b2f90f761c | |||
2164843f22 | |||
c457a7bd65 | |||
a9b70daf5f | |||
979f240436 | |||
e7a7d5b7bd | |||
7f0f8430de | |||
44a0530175 | |||
b384a9b2c8 | |||
0604db09e8 | |||
861f988667 | |||
22c88842a0 | |||
4cc64bd6ef | |||
3f8b7f7f7f | |||
4b1095ccb4 | |||
2c9047d57a | |||
3a5fe8aba3 | |||
7f771a443c | |||
fd81e20493 | |||
2b397d798c | |||
e1c8e95705 | |||
101c86275b | |||
190f95d405 | |||
7e44bdd59f | |||
885b17be1b | |||
5aafc1ec4e | |||
6e6aba9542 | |||
d21f5c0137 | |||
94adf5adee | |||
8157e37000 | |||
9d401ea8e3 | |||
b0295ea938 | |||
3391bdd66c | |||
9acf470eea | |||
a6dc865d30 | |||
a14fcf3e41 | |||
74005fb55f | |||
721f726cd9 | |||
5f965a34af | |||
e9a7660275 | |||
d7a7f4f869 | |||
db364e32cb | |||
c78afeeadb | |||
0907e7761a | |||
9d128e35e8 | |||
334744a25c | |||
abbd309b5c | |||
60fe81bab3 | |||
1786c82e7d | |||
b85c1865e4 | |||
070624a422 | |||
1d934040d7 | |||
3b60d8e14b | |||
9855f7d7c6 | |||
bb1a75cfe9 | |||
1c697fa24c | |||
f0b8938a80 | |||
83f8ea5c14 | |||
cbe57fa266 | |||
66776b6a25 | |||
c37b19ffa9 | |||
8d1f0853cc | |||
b6b50bf0b4 | |||
fe37e5232b | |||
49a4b8cb7d | |||
bca6d58676 | |||
b4f4432459 | |||
a73f476c8a | |||
dbdc20e673 | |||
eba9528391 |
|
@ -40,6 +40,9 @@
|
|||
}
|
||||
],
|
||||
"quotes": "off",
|
||||
|
||||
"no-constant-binary-expression": "error",
|
||||
|
||||
"@typescript-eslint/indent": [
|
||||
"error",
|
||||
2,
|
||||
|
@ -115,6 +118,8 @@
|
|||
"@typescript-eslint/consistent-type-exports": "off",
|
||||
"@typescript-eslint/key-spacing": "off",
|
||||
|
||||
"@typescript-eslint/no-unsafe-argument": "off",
|
||||
|
||||
"@typescript-eslint/ban-types": [
|
||||
"error",
|
||||
{
|
||||
|
|
|
@ -12,12 +12,12 @@ runs:
|
|||
|
||||
steps:
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ inputs.node-version }}
|
||||
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
|
|
2
.github/workflows/benchmark.yml
vendored
2
.github/workflows/benchmark.yml
vendored
|
@ -31,7 +31,7 @@ jobs:
|
|||
PGHOST: localhost
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: './.github/actions/reusable-prepare-peertube-build'
|
||||
with:
|
||||
|
|
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
|
@ -35,7 +35,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
|
4
.github/workflows/docker.yml
vendored
4
.github/workflows/docker.yml
vendored
|
@ -15,7 +15,7 @@ jobs:
|
|||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set matrix for build
|
||||
|
@ -58,7 +58,7 @@ jobs:
|
|||
|
||||
-
|
||||
name: Checkout develop
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ matrix.ref }}
|
||||
-
|
||||
|
|
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout develop
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: develop
|
||||
|
||||
|
|
2
.github/workflows/stats.yml
vendored
2
.github/workflows/stats.yml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
|||
CI_BRANCH_BASE: develop
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: './.github/actions/reusable-prepare-peertube-build'
|
||||
with:
|
||||
|
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
|
@ -52,7 +52,7 @@ jobs:
|
|||
YOUTUBE_DL_DOWNLOAD_BEARER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: './.github/actions/reusable-prepare-peertube-build'
|
||||
with:
|
||||
|
@ -61,7 +61,7 @@ jobs:
|
|||
- uses: './.github/actions/reusable-prepare-peertube-run'
|
||||
|
||||
- name: Cache fixtures
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
fixtures
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
process.env.ESBK_TSCONFIG_PATH = './packages/tests/tsconfig.json'
|
||||
process.env.TSX_TSCONFIG_PATH = './packages/tests/tsconfig.json'
|
||||
|
||||
module.exports = {
|
||||
"node-option": [
|
||||
"loader=tsx",
|
||||
"import=tsx",
|
||||
"no-warnings",
|
||||
"conditions=peertube:tsx"
|
||||
],
|
||||
|
|
153
CHANGELOG.md
153
CHANGELOG.md
|
@ -1,5 +1,154 @@
|
|||
# Changelog
|
||||
|
||||
## v6.1.0
|
||||
|
||||
### IMPORTANT NOTES
|
||||
|
||||
* You must update nginx configuration: https://github.com/Chocobozzz/PeerTube/blob/develop/support/nginx/peertube
|
||||
* Add `location ~ ^/api/v1/users/[^/]+/imports/import-resumable$ {` block
|
||||
* This release changes the way how PeerTube counts a video view:
|
||||
* Views are taken into account after 10 seconds instead of 30 seconds (can be changed in YAML config)
|
||||
* Views use a *Session ID* generated by the web browser instead of using the request IP (former behavior can be restored in YAML config)
|
||||
* The goal of this change is to get closer to how other video platforms like Mux, Vimeo, or Instagram work
|
||||
|
||||
### SECURITY
|
||||
|
||||
* Compact ActivityPub JSON-LD objects before using them to prevent incorrect access control @tesaguri
|
||||
* Protect ActivityPub information related to private/internal/blocked videos
|
||||
|
||||
### Admin config (non-exhaustive)
|
||||
|
||||
* **Breaking changes**:
|
||||
* Rename `views.videos.ip_view_expiration` to `views.videos.view_expiration`
|
||||
* YAML & web admin configs:
|
||||
* Add `storyboards.enabled` config to disable storyboard generation
|
||||
* Remove `services.twitter.whitelisted`: Twitter/X doesn't seem to need this anymore. This means that PeerTube will try to inject the video player in Twitter/X by default instead of using a classic image/description
|
||||
* YAML config only:
|
||||
* Add `open_telemetry.metrics.playback_stats_interval` config to customize how often viewers send playback stats to server
|
||||
* Add `views.videos.watching_interval.{anonymous,users}` configs to change how often the web browser sends "is watching" information to the server
|
||||
* Add `stats.registration_requests.enabled` and `stats.abuses.enabled` configs to hide instance registration/abuse requests public stats (average response time, total registration/abuse requests etc.)
|
||||
* Add `stats.total_moderators.enabled` and `stats.total_admins.enabled`configs to hide total admins/moderators public stats
|
||||
* Add `object_storage.streaming_playlists.store_live_streams` config to not store live stream chunks into object storage (when enabled for streaming playlists)
|
||||
* Set `open_telemetry.metrics.http_request_duration.enabled` to `false` by default to avoid performance issues on the Prometheus backend due to high metric cardinality
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Also generate `600x600` and `1500x1500` avatar sizes
|
||||
* Also generate `600x100` banner size
|
||||
|
||||
### Plugins/Themes/Embed API
|
||||
|
||||
* Add ability for plugins to create a client custom sub-page in `/my-account` page [#6218](https://github.com/Chocobozzz/PeerTube/pull/6218)
|
||||
* Add access to `req.rawBody` for [plugin routes](https://docs.joinpeertube.org/contribute/plugins#add-custom-routes) [#6300](https://github.com/Chocobozzz/PeerTube/pull/6300)
|
||||
* Add server plugin hooks (https://docs.joinpeertube.org/api/plugins):
|
||||
* `filter:api.user.me.get.result` [#6219](https://github.com/Chocobozzz/PeerTube/issues/6219)
|
||||
* Add `peertubeHelpers.videos.loadByIdOrUUIDWithFiles` helper [#6302](https://github.com/Chocobozzz/PeerTube/pull/6302)
|
||||
|
||||
### Features
|
||||
|
||||
* :tada: Implement user import/export :tada: [#6215](https://github.com/Chocobozzz/PeerTube/pull/6215)
|
||||
* This is not a migration tool: data (like channels or videos) is duplicated and not moved from the previous PeerTube instance
|
||||
* Export:
|
||||
* A ZIP is generated by PeerTube and an email is sent to the user when the archive is ready
|
||||
* The archive file contains ActivityPub data for federation compatibility and custom JSON files used by PeerTube import. It also contains video/playlist thumbnail and channel/account avatar/banner files
|
||||
* User can include video files in the archive
|
||||
* Archive files can be stored in object storage
|
||||
* Export can be disabled by the admin. They can also set an expiration time to automatically delete archive files and limit the export file size depending on the user's video quota
|
||||
* Import:
|
||||
* Update account metadata (display name, description...)
|
||||
* Update user settings (video autoplay policy, notification settings...)
|
||||
* Create entries in the mute list
|
||||
* Add watched videos in user's videos history
|
||||
Add likes/dislikes
|
||||
* Send a follow request to imported subscriptions
|
||||
* Create channels, playlists and videos (if the video files are included in the archive)
|
||||
* Admins can disable user import
|
||||
* :tada: Add ability to keep the original video file :tada: [#6157](https://github.com/Chocobozzz/PeerTube/pull/6157)
|
||||
* Can be stored in object storage
|
||||
* Uploader can download the original file
|
||||
* The original file is used in the user export archive (instead of the max quality file)
|
||||
* Add Turkish language support in client
|
||||
* Add ability for admins to set a banner and an avatar to the instance. The banner is used in *About instance*/*Login*/*Register an account* pages. Both the banner and the avatar can be used on the instance homepage using `<peertube-instance-banner>`/`<peertube-instance-avatar>` tag or on external websites/applications like the [JoinPeerTube website](https://joinpeertube.org/instances)
|
||||
* Add ability for uploaders to download and add a video to a playlist on the *My videos* page using the dropdown button [#6008](https://github.com/Chocobozzz/PeerTube/pull/6008)
|
||||
* Video views statistics:
|
||||
* Count a *view* after 10 seconds and use a web browser session id to identify a viewer (see IMPORTANT CHANGES section)
|
||||
* Add information about the location of the viewer subdivision/region
|
||||
* More accurate retention stats where PeerTube doesn't take into account empty views anymore
|
||||
* UI/UX:
|
||||
* Automatically filter on *Local videos* in admin
|
||||
* Add ability to sort videos by file size
|
||||
* Add total video file size column in admin users list
|
||||
* Improve admin runner jobs list by using badges with same colors for type/runner and add *processed/finished* columns
|
||||
* Add *Recommended* tags to recommended PeerTube plugins/themes
|
||||
* Improve plugins/themes default trending sort
|
||||
* Trim username on login
|
||||
* Warn if "Forgot password" email contains uppercase
|
||||
* Use more precise buttons label to save changes in *My account* settings
|
||||
* Add icon to owners/moderators only options
|
||||
* Always use short UUIDs instead of full UUIDs in client to prevent URL confusion
|
||||
* Add average admins/moderators response time in *Request an account* page
|
||||
* Add color to registration/abuse state icon
|
||||
* Player:
|
||||
* Add an enable/disable subtitle button to the control bar
|
||||
* Faster auto-resizing of the player when the video has a custom aspect ratio (only for videos uploaded on PeerTube >= 6.1)
|
||||
* Use video aspect ratio for responsive embeds (only for videos uploaded on PeerTube >= 6.1)
|
||||
* Performance:
|
||||
* Optimize *watching* (`/api/v1/videos/:videoId/views`) endpoint
|
||||
* Reduce `ffprobe` calls when not needed resulting in faster live stream transcoding startup and CPU/IO reduction during video upload/import
|
||||
* Federation
|
||||
* Introduce a new way to federate `Views` events in the federation. See [the commit details](https://github.com/Chocobozzz/PeerTube/commit/b4f4432459f22994cb8fa667c862a0edd7af0ebc) for more information
|
||||
* Implements [FEP-2677](https://codeberg.org/fediverse/fep/src/branch/main/fep/2677/fep-2677.md) to identify the `Application` `Actor`
|
||||
* Add Lemmy `postingRestrictedToMods` information to channels AP objects
|
||||
* Improve generated video thumbnail quality
|
||||
* Add notification when a subscribed video channel is live streaming
|
||||
* Support `itunes:owner` in podcast feed
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Add stripes to square video thumbnails too (like we do for portrait videos)
|
||||
* Prevent channels from being displayed multiple times on the *My channels* page
|
||||
* Stricter video timestamp "linkification"
|
||||
* Correctly fix downloading video files from object storage with some video names
|
||||
* Fix broken RSS feed in some (rare) cases
|
||||
* Fix local jobs count/pagination with *Waiting* jobs
|
||||
* Banned users cannot live stream anymore
|
||||
* Correctly escape HTML entities in meta tags [#6206](https://github.com/Chocobozzz/PeerTube/pull/6206)
|
||||
* Fix broken account channels page with high `video_channels.max_per_user` config
|
||||
* Add ability for moderators to approve/reject user registrations
|
||||
* Do not display empty notification settings group
|
||||
* Correctly fix WebTorrent video import crash
|
||||
* Fix video channel synchronization crash on remote channels/playlists that contain hidden videos (unavailable, deleted etc.)
|
||||
* Ensure the filename doesn't contain `/` character when downloading a video
|
||||
* Fix Google Search SEO (with `Video is not the main content of the page` error)
|
||||
* Remove password autocomplete in embed which causes issues when the parent page has a password input and the user uses the web browser's password autofill feature
|
||||
* Don't submit the login form on forgot my password keyboard click
|
||||
* Fix storyboard generation with some videos
|
||||
* Fix ffmpeg encoder after custom plugin transcoding profile deletion
|
||||
* Fix navigating from one channel related page (playlist, videos...) to another one
|
||||
* More robust live stream transcoded by a remote runner
|
||||
* Fix first video in playlist that doesn't start at "starts at"
|
||||
* Fix embed HTML code for videos/playlists that have passwords
|
||||
* Display external account/channel playlists if user is allowed to escape the federation
|
||||
* Fix view endpoint crash on geoip update failure
|
||||
* Fix setting video subtitle from URL query
|
||||
* Fix selecting "Display all languages/categories/licences" in videos search resulting in an empty search
|
||||
* Fix followers/following counter of local ActivityPub actors
|
||||
* Fix notification button link on mobile
|
||||
* Fix player subtitles on iOS
|
||||
|
||||
|
||||
## v6.0.4
|
||||
|
||||
### IMPORTANT NOTES
|
||||
|
||||
* If you upgrade from PeerTube **< v6.0.0**, please follow v6.0.0 IMPORTANT NOTES
|
||||
* If you upgrade from PeerTube **v6.0.0**, please follow v6.0.1 IMPORTANT NOTES
|
||||
|
||||
### SECURITY
|
||||
|
||||
* **Important:** Prevent XSS injection in embed. Thanks [Syst3m0ver](https://www.linkedin.com/in/ahmed-hasnaoui-790618180) and [aramido GmbH](https://aramido.de/sicherheitspruefung/penetrationstest)!
|
||||
|
||||
|
||||
## v6.0.3
|
||||
|
||||
### IMPORTANT NOTES
|
||||
|
@ -363,7 +512,7 @@ We have many important notes in this release. We know it's a pain for sysadmin,
|
|||
|
||||
* :tada: Implement user registration approval (https://docs.joinpeertube.org/admin/managing-users#registration-approval) [#5544](https://github.com/Chocobozzz/PeerTube/pull/5544)
|
||||
* If enabled, the user has to fill a *Registration reason* input
|
||||
* Moderators have to to accept/reject the registration with a *Moderation response* that will be sent by email to the user
|
||||
* Moderators have to accept/reject the registration with a *Moderation response* that will be sent by email to the user
|
||||
* If the registration is accepted, the user and its channel are automatically created
|
||||
* Add "back to live" button in player
|
||||
* The *Live* button is red when the player is synced with the live
|
||||
|
@ -1915,7 +2064,7 @@ A new endpoint to report videos will be created in PeerTube 2.4 and will also al
|
|||
|
||||
### Features
|
||||
|
||||
* :tada: Add global search support (has to be explicitely enabled by admins)
|
||||
* :tada: Add global search support (has to be explicitly enabled by admins)
|
||||
* :tada: Add ability for admins to display a banner on their instance
|
||||
* :tada: Support Vietnamese and Kabyle languages. Also re-establish Occitan language locale despite lack of support in Angular
|
||||
* Federation:
|
||||
|
|
111
CREDITS.md
111
CREDITS.md
|
@ -7,49 +7,54 @@
|
|||
* T.S
|
||||
* Hồ Nhất Duy
|
||||
* josé m
|
||||
* Berto Te
|
||||
* Filip Bengtsson
|
||||
* Ihor Hordiichuk
|
||||
* Jeff Huang
|
||||
* Ihor Hordiichuk
|
||||
* Filip Bengtsson
|
||||
* Payman Moghadam
|
||||
* Berto Te
|
||||
* Simon Brosdetzko
|
||||
* kontrollanten
|
||||
* Jiri Podhorecky
|
||||
* Phongpanot
|
||||
* hecko
|
||||
* Milo Ivir
|
||||
* kontrollanten
|
||||
* Phongpanot
|
||||
* GunChleoc
|
||||
* hecko
|
||||
* Laurent Ettouati
|
||||
* kimsible
|
||||
* Zet
|
||||
* GunChleoc
|
||||
* Sveinn í Felli
|
||||
* Aitor Salaberria
|
||||
* Clemens Schielicke
|
||||
* Racida S
|
||||
* Sveinn í Felli
|
||||
* Ewout van Mansom
|
||||
* Marcin Mikołajczak
|
||||
* Eivind Ødegård
|
||||
* Balázs Meskó
|
||||
* Tirifto
|
||||
* Kim
|
||||
* Wicklow
|
||||
* Armin
|
||||
* Hannes Ylä-Jääski
|
||||
* Kim
|
||||
* Armin
|
||||
* Fontan 030
|
||||
* John Livingston
|
||||
* Vodoyo Kamal
|
||||
* Mohamad Reza
|
||||
* John Livingston
|
||||
* Kimsible
|
||||
* Besnik Bleta
|
||||
* Kimsible
|
||||
* Felix Ableitner
|
||||
* Frank Sträter
|
||||
* Free coss
|
||||
* Quentin PAGÈS
|
||||
* Gérald Niel
|
||||
* Luca Calcaterra
|
||||
* ButterflyOfFire
|
||||
* Duy
|
||||
* Slimane Selyan AMIRI
|
||||
* ButterflyOfFire
|
||||
* Dingzhong Chen
|
||||
* Eric Guichaoua
|
||||
* Julien Maulny
|
||||
* Mark Van den Borre
|
||||
* x
|
||||
* Balázs Meskó
|
||||
* Julien Maulny
|
||||
* Jorropo
|
||||
* Josh Morel
|
||||
* Manuel Viens
|
||||
|
@ -58,28 +63,30 @@
|
|||
* Elegant Codes
|
||||
* Florian CUNY
|
||||
* Francesc
|
||||
* Luca Calcaterra
|
||||
* Renne Rocha
|
||||
* mando laress
|
||||
* Артём Котлубай
|
||||
* Ettore Atalan
|
||||
* Ricardo Biloti
|
||||
* Blood Axe
|
||||
* Cedric F
|
||||
* Florent
|
||||
* Marc Strange
|
||||
* Renne Rocha
|
||||
* Ch
|
||||
* J. Lavoie
|
||||
* barzofarev2
|
||||
* jan Seli
|
||||
* lutangar
|
||||
* 李奕寯
|
||||
* Blood Axe
|
||||
* 0que
|
||||
* Martin Hoefler
|
||||
* Porrumentzio
|
||||
* Poslovitch
|
||||
* Xabi
|
||||
* buoyantair
|
||||
* Alexander Ivanov
|
||||
* Balázs Úr
|
||||
* Echo Kilo
|
||||
* Eric Guichaoua
|
||||
* Jan Keromnes
|
||||
* Luc Didry
|
||||
* Siourdakis Thanos
|
||||
|
@ -93,14 +100,17 @@
|
|||
* Jason Zhou
|
||||
* Loukas Stamellos
|
||||
* Ms Kimsible
|
||||
* NorbiPeti
|
||||
* Sergey Zigachev
|
||||
* Thomas Citharel
|
||||
* Txopi
|
||||
* Benjamin Bouvier
|
||||
* Filip Hanes
|
||||
* Joe Bill
|
||||
* Kemal Oktay Aktoğan
|
||||
* Lucas Declercq
|
||||
* Sirxy
|
||||
* matograine
|
||||
* Alexander Ivanov
|
||||
* Daniel Santos
|
||||
* David Libeau
|
||||
* Ewald Arnold
|
||||
|
@ -108,35 +118,39 @@
|
|||
* Jayme Soares Almeida Cruz
|
||||
* Kempelen
|
||||
* Nassim Bounouas
|
||||
* NorbiPeti
|
||||
* Rafael Fontenelle
|
||||
* Sergey Zigachev
|
||||
* Thomas Kuntz
|
||||
* Tzafrir Cohen
|
||||
* Viorel-Cătălin Răpițeanu
|
||||
* Vri
|
||||
* miro
|
||||
* nexi
|
||||
* owiox8+1viroxeaziaxw@sharklasers.com
|
||||
* Adrià Martín
|
||||
* Ahmed ABERWAG
|
||||
* Anne-Gaelle Moulun
|
||||
* Arman
|
||||
* Asier Iturralde Sarasola
|
||||
* BRAINS YUM
|
||||
* Belkacem Mohammed
|
||||
* Côme 744
|
||||
* Dimitri Gilbert
|
||||
* Flavio F. M
|
||||
* Florent Poinsaut
|
||||
* Frank Chang
|
||||
* Green-Star
|
||||
* I_Automne
|
||||
* Ilia
|
||||
* Micah Elizabeth Scott
|
||||
* Pierre-Jean
|
||||
* Ret Samys
|
||||
* SVNET Libre
|
||||
* Tomasz
|
||||
* Tony Simoes
|
||||
* Vri
|
||||
* William Lahti
|
||||
* Wirebrass
|
||||
* Yury Bulka
|
||||
* alex gabilondo
|
||||
* boris joeson
|
||||
* frankstrater
|
||||
* mater
|
||||
|
@ -146,14 +160,14 @@
|
|||
* Ajeje Brazorf
|
||||
* Andrey
|
||||
* Angristan
|
||||
* Asier Iturralde Sarasola
|
||||
* Benjamin Seitz
|
||||
* Bob Oob
|
||||
* Booteille
|
||||
* Cokelat8
|
||||
* DontUseGithub
|
||||
* Farooq Karimi Zadeh
|
||||
* I_Automne
|
||||
* Iñigo
|
||||
* Jim Kats
|
||||
* Joan Montané
|
||||
* Kristoffer Grundström
|
||||
* LecygneNoir
|
||||
|
@ -166,7 +180,6 @@
|
|||
* Nikolay
|
||||
* Okhin
|
||||
* Pierre-Alain TORET
|
||||
* Pierre-Jean
|
||||
* Serge Victor
|
||||
* Théo Le Calvar
|
||||
* Ugaitz
|
||||
|
@ -179,6 +192,7 @@
|
|||
* roberto marcolin
|
||||
* Ahsan Haris Ahmed
|
||||
* Alberto Teira
|
||||
* Alejandro
|
||||
* Alex
|
||||
* Aliaksandr Hrankin
|
||||
* Anael González Paz
|
||||
|
@ -217,9 +231,11 @@
|
|||
* Pedro
|
||||
* Petr Balíček
|
||||
* Piotr Sikora
|
||||
* Ryan He
|
||||
* Stefan Keks
|
||||
* Tom Wellington
|
||||
* Urtzi Odriozola
|
||||
* Victor Hampel
|
||||
* Waazdakka
|
||||
* Winfried Hyronimus
|
||||
* Yohan Boniface
|
||||
|
@ -244,6 +260,7 @@
|
|||
* Arne Uplegger
|
||||
* Aurélien Béranger
|
||||
* Average Dude
|
||||
* BGR2
|
||||
* BitTube
|
||||
* Boo Teille
|
||||
* Branislav Pavelka
|
||||
|
@ -251,7 +268,6 @@
|
|||
* David Luís Pereira Pires
|
||||
* David Marzal
|
||||
* EndoGai
|
||||
* Ettore Atalan
|
||||
* Fatih Özsoy
|
||||
* FediverseTV
|
||||
* Florent Fayolle
|
||||
|
@ -260,22 +276,27 @@
|
|||
* G4dter
|
||||
* Gaëtan Rizio
|
||||
* Gopherslol
|
||||
* Goudarz Jafari
|
||||
* HHY
|
||||
* Hange
|
||||
* Hjalte
|
||||
* Hugo Peixoto
|
||||
* HybridGlucose
|
||||
* J C Worm
|
||||
* Jan Ainali
|
||||
* Jan Marsalek
|
||||
* José M
|
||||
* Joël Galeran
|
||||
* Julien Lemaire
|
||||
* Julien Rabier
|
||||
* Lucas Teixeira
|
||||
* Mamiako Pavel
|
||||
* Masood Masaeli
|
||||
* Millicent Billette
|
||||
* Mondo Xíbaro
|
||||
* Moritz Warning
|
||||
* Mostafa Ahangarha
|
||||
* Neko Nekowazarashi
|
||||
* Nicolai Larsen
|
||||
* Nojus
|
||||
* Pierre Jaury
|
||||
|
@ -287,8 +308,11 @@
|
|||
* Takeshi Umeda
|
||||
* Thai Localization
|
||||
* The Cashew Trader
|
||||
* Thijs Kinkhorst
|
||||
* Timur Seber
|
||||
* Toso Malero
|
||||
* Valvin
|
||||
* Yaron Shahrabani
|
||||
* YiDai
|
||||
* Yogesh K S
|
||||
* ahmadsharifian
|
||||
|
@ -296,6 +320,7 @@
|
|||
* brucekomike
|
||||
* dingycle
|
||||
* framail
|
||||
* h3n3
|
||||
* imgradeone Yan
|
||||
* kafbatur kafbatarsson
|
||||
* les
|
||||
|
@ -327,6 +352,8 @@
|
|||
* Alperen Abak
|
||||
* Alvar C.H. Freude
|
||||
* Aman Sharma
|
||||
* Anatoly
|
||||
* Anatoly Bogomolov
|
||||
* Andrews Góes Santos
|
||||
* Antoine Millet
|
||||
* Anton Latukha
|
||||
|
@ -344,7 +371,9 @@
|
|||
* Brad Johnson
|
||||
* Cadence Ember
|
||||
* Cale
|
||||
* Carlos García Gutiérrez
|
||||
* Charles de Lacombe
|
||||
* Charlie Lambda
|
||||
* Christoph Geschwind
|
||||
* Chronos
|
||||
* Claude
|
||||
|
@ -367,17 +396,20 @@
|
|||
* Esmail_Hazem
|
||||
* Ethan Corgatelli
|
||||
* Fabio Agreles Bezerra
|
||||
* FediThing
|
||||
* Fernandez, ReK2
|
||||
* Flavio F. M
|
||||
* Framasoft
|
||||
* Gabriel Scherer
|
||||
* Glandos
|
||||
* Grzesiek11
|
||||
* Guillaume Pérution-Kihli
|
||||
* Gérald CHATAGNON
|
||||
* Haelwenn (lanodan) Monnier
|
||||
* Henri BAUDESSON
|
||||
* HesioZ
|
||||
* Hozan Şahin
|
||||
* ICabaleiro
|
||||
* Ignacio Carrera González
|
||||
* Iker Garaialde
|
||||
* Ismaël Bouya
|
||||
* Ivan Ip
|
||||
|
@ -391,10 +423,13 @@
|
|||
* Jan Prunk
|
||||
* Janey Muñoz
|
||||
* Jarosław Maciejewski
|
||||
* Jaz Dina
|
||||
* Jeena
|
||||
* Jessica Fairchild
|
||||
* Jeston Tan
|
||||
* Jinn Koriech
|
||||
* Jlll1
|
||||
* Johnny Jazeix
|
||||
* Jonas Sulzer
|
||||
* Jonatan Nyberg
|
||||
* Jorge Silva
|
||||
|
@ -409,6 +444,7 @@
|
|||
* Kyâne Pichou
|
||||
* Leo Mouyna
|
||||
* Lesterpig
|
||||
* Lety Does Stuff
|
||||
* Levi Bard
|
||||
* LiPeK
|
||||
* Lint
|
||||
|
@ -417,10 +453,13 @@
|
|||
* Lupinard
|
||||
* Léo Andrès
|
||||
* ManMade-cube42
|
||||
* Marcel Fuhrmann
|
||||
* Marco Zehe
|
||||
* Marian Steinbach
|
||||
* Mario Pepe
|
||||
* Markus Richter
|
||||
* Martin Trigaux
|
||||
* Matej Šujan
|
||||
* Mateusz Piotrowski
|
||||
* Mathieu Agopian
|
||||
* Mathieu Brunot
|
||||
|
@ -430,8 +469,10 @@
|
|||
* Michael Williams
|
||||
* Miguel Mayol Tur
|
||||
* Mike
|
||||
* Mikel Gartzia Santamaria
|
||||
* Milo van der Linden
|
||||
* MrGiga
|
||||
* Murat Özalp
|
||||
* Mélanie Pin
|
||||
* Nataly Rocha
|
||||
* Nathanaël J
|
||||
|
@ -441,6 +482,7 @@
|
|||
* Nitesh Sawant
|
||||
* Novel Martin Harianto
|
||||
* Nuño Sempere
|
||||
* Olivier Bouillet
|
||||
* Olivier Jolly
|
||||
* Pablo Joubert
|
||||
* Paul FLORENCE
|
||||
|
@ -466,10 +508,14 @@
|
|||
* Roberto Resoli
|
||||
* Robin
|
||||
* Rostyslav Haitkulov
|
||||
* Salif Mehmed
|
||||
* Sankar
|
||||
* SansPseudoFix
|
||||
* Sarah Lewis
|
||||
* Sebastian Paweł Wolski
|
||||
* Seth Falco
|
||||
* Showfom
|
||||
* Shun Sakai
|
||||
* Simon Gilliot
|
||||
* Simounet
|
||||
* Stefan Schüller
|
||||
|
@ -489,19 +535,17 @@
|
|||
* TrashMacNugget
|
||||
* Treacle
|
||||
* Tsuki
|
||||
* Txopi
|
||||
* Unetelle Inconnue
|
||||
* Vagelis F
|
||||
* Varik Valefor
|
||||
* Vegard Fjeldberg
|
||||
* Victor Hampel
|
||||
* Vik
|
||||
* Vincent Stakenburg
|
||||
* WhiredPlanck
|
||||
* William Cliff
|
||||
* WingsLikeEagles
|
||||
* Yann Sionneau
|
||||
* Yaron Shahrabani
|
||||
* Yehuda Deutsch
|
||||
* Yorwba
|
||||
* Yun
|
||||
* Zekovski
|
||||
|
@ -519,8 +563,10 @@
|
|||
* decentral1se
|
||||
* eduard pintilie
|
||||
* framabr
|
||||
* fuomag9
|
||||
* gillux
|
||||
* jameskimmel
|
||||
* jinubook
|
||||
* jomo
|
||||
* kukhariev
|
||||
* lambdacastix
|
||||
|
@ -535,11 +581,14 @@
|
|||
* mahdi
|
||||
* memorybox
|
||||
* mike stedman
|
||||
* mira.bat
|
||||
* mj-saunders
|
||||
* morteza
|
||||
* no
|
||||
* norrist
|
||||
* nxjoseph
|
||||
* osauzet
|
||||
* paring
|
||||
* paulienm
|
||||
* philippe lhardy
|
||||
* pitchum
|
||||
|
|
|
@ -186,7 +186,7 @@ See our [ActivityPub documentation](https://docs.joinpeertube.org/api/activitypu
|
|||
|
||||
### Code
|
||||
|
||||
Copyright (C) 2015-2023 PeerTube Contributors (see [CREDITS.md](/CREDITS.md))
|
||||
Copyright (C) 2015-2024 PeerTube Contributors (see [CREDITS.md](/CREDITS.md))
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@peertube/peertube-cli",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"type": "module",
|
||||
"main": "dist/peertube.js",
|
||||
"bin": "dist/peertube.js",
|
||||
|
@ -11,7 +11,7 @@
|
|||
"license": "AGPL-3.0",
|
||||
"private": false,
|
||||
"devDependencies": {
|
||||
"application-config": "^2.0.0",
|
||||
"application-config": "^3.0.0",
|
||||
"cli-table3": "^0.6.0",
|
||||
"netrc-parser": "^3.1.6"
|
||||
},
|
||||
|
|
|
@ -38,7 +38,7 @@ export function defineUploadProgram () {
|
|||
.option('-U, --username <username>', 'Username')
|
||||
.option('-p, --password <token>', 'Password')
|
||||
.option('-b, --thumbnail <thumbnailPath>', 'Thumbnail path')
|
||||
.option('-v, --preview <previewPath>', 'Preview path')
|
||||
.option('--preview <previewPath>', 'Preview path')
|
||||
.option('-f, --file <file>', 'Video absolute file path')
|
||||
.option('-n, --video-name <name>', 'Video name')
|
||||
.option('-c, --category <category_number>', 'Category number')
|
||||
|
|
|
@ -2,28 +2,6 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/code-frame@^7.0.0":
|
||||
version "7.22.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.10.tgz#1c20e612b768fefa75f6e90d6ecb86329247f0a3"
|
||||
integrity sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.22.10"
|
||||
chalk "^2.4.2"
|
||||
|
||||
"@babel/helper-validator-identifier@^7.22.5":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193"
|
||||
integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==
|
||||
|
||||
"@babel/highlight@^7.22.10":
|
||||
version "7.22.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7"
|
||||
integrity sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.22.5"
|
||||
chalk "^2.4.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@colors/colors@1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
||||
|
@ -34,35 +12,19 @@ ansi-regex@^5.0.1:
|
|||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||
|
||||
ansi-styles@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
|
||||
dependencies:
|
||||
color-convert "^1.9.0"
|
||||
application-config-path@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/application-config-path/-/application-config-path-1.0.0.tgz#9c25b8c00ac9a342db27275abd3f38c67bbe5a05"
|
||||
integrity sha512-6ZDlLTlfqrTybVzZJDpX2K2ZufqyMyiTbOG06GpxmkmczFgTN+YYRGcTcMCXv/F5P5SrZijVjzzpPUE9BvheLg==
|
||||
|
||||
application-config-path@^0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/application-config-path/-/application-config-path-0.1.1.tgz#8b5ac64ff6afdd9bd70ce69f6f64b6998f5f756e"
|
||||
integrity sha512-zy9cHePtMP0YhwG+CfHm0bgwdnga2X3gZexpdCwEj//dpb+TKajtiC8REEUJUSq6Ab4f9cgNy2l8ObXzCXFkEw==
|
||||
|
||||
application-config@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/application-config/-/application-config-2.0.0.tgz#15b4d54d61c0c082f9802227e3e85de876b47747"
|
||||
integrity sha512-NC5/0guSZK3/UgUDfCk/riByXzqz0owL1L3r63JPSBzYk5QALrp3bLxbsR7qeSfvYfFmAhnp3dbqYsW3U9MpZQ==
|
||||
application-config@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/application-config/-/application-config-3.0.0.tgz#9adec84dd2d81e97dd78ea0dffcbf97381a1f55c"
|
||||
integrity sha512-7ViR4soQJDx2O9iLf1vGxvekkPqvwqV/AZ2OL3DNcAQrg03UjJE1VeBk7oYNoN9AKB0eNyVrcM7kPD30NKeLLw==
|
||||
dependencies:
|
||||
application-config-path "^0.1.0"
|
||||
load-json-file "^6.2.0"
|
||||
write-json-file "^4.2.0"
|
||||
|
||||
chalk@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
dependencies:
|
||||
ansi-styles "^3.2.1"
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
application-config-path "^1.0.0"
|
||||
load-json-file "^7.0.1"
|
||||
write-json-file "^5.0.0"
|
||||
|
||||
cli-table3@^0.6.0:
|
||||
version "0.6.3"
|
||||
|
@ -73,18 +35,6 @@ cli-table3@^0.6.0:
|
|||
optionalDependencies:
|
||||
"@colors/colors" "1.5.0"
|
||||
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
|
||||
dependencies:
|
||||
color-name "1.1.3"
|
||||
|
||||
color-name@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
||||
|
||||
cross-spawn@^6.0.0:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
|
@ -103,28 +53,16 @@ debug@^3.1.0:
|
|||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
detect-indent@^6.0.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6"
|
||||
integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==
|
||||
detect-indent@^7.0.0:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.1.tgz#cbb060a12842b9c4d333f1cac4aa4da1bb66bc25"
|
||||
integrity sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
error-ex@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
escape-string-regexp@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
|
||||
|
||||
execa@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
|
||||
|
@ -143,35 +81,20 @@ get-stream@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||
integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==
|
||||
|
||||
graceful-fs@^4.1.15:
|
||||
version "4.2.11"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
|
||||
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
|
||||
|
||||
is-arrayish@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
is-plain-obj@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
|
||||
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
|
||||
is-plain-obj@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0"
|
||||
integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==
|
||||
|
||||
is-stream@^1.1.0:
|
||||
version "1.1.0"
|
||||
|
@ -188,37 +111,10 @@ isexe@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
json-parse-even-better-errors@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||
|
||||
lines-and-columns@^1.1.6:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
load-json-file@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1"
|
||||
integrity sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.1.15"
|
||||
parse-json "^5.0.0"
|
||||
strip-bom "^4.0.0"
|
||||
type-fest "^0.6.0"
|
||||
|
||||
make-dir@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||
integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
|
||||
dependencies:
|
||||
semver "^6.0.0"
|
||||
load-json-file@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-7.0.1.tgz#a3c9fde6beffb6bedb5acf104fad6bb1604e1b00"
|
||||
integrity sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==
|
||||
|
||||
ms@^2.1.1:
|
||||
version "2.1.3"
|
||||
|
@ -250,16 +146,6 @@ p-finally@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
|
||||
integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
|
||||
|
||||
parse-json@^5.0.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
|
||||
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
error-ex "^1.3.1"
|
||||
json-parse-even-better-errors "^2.3.0"
|
||||
lines-and-columns "^1.1.6"
|
||||
|
||||
path-key@^2.0.0, path-key@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
|
||||
|
@ -270,11 +156,6 @@ semver@^5.5.0:
|
|||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||
|
||||
semver@^6.0.0:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
shebang-command@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||
|
@ -292,12 +173,12 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
|||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
||||
sort-keys@^4.0.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-4.2.0.tgz#6b7638cee42c506fff8c1cecde7376d21315be18"
|
||||
integrity sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==
|
||||
sort-keys@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-5.0.0.tgz#5d775f8ae93ecc29bc7312bbf3acac4e36e3c446"
|
||||
integrity sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==
|
||||
dependencies:
|
||||
is-plain-obj "^2.0.0"
|
||||
is-plain-obj "^4.0.0"
|
||||
|
||||
string-width@^4.2.0:
|
||||
version "4.2.3"
|
||||
|
@ -315,28 +196,11 @@ strip-ansi@^6.0.1:
|
|||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-bom@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
|
||||
integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
|
||||
|
||||
strip-eof@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
||||
integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==
|
||||
|
||||
supports-color@^5.3.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
type-fest@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
|
||||
integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
|
||||
|
||||
typedarray-to-buffer@^3.1.5:
|
||||
version "3.1.5"
|
||||
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
|
||||
|
@ -351,7 +215,7 @@ which@^1.2.9:
|
|||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
write-file-atomic@^3.0.0:
|
||||
write-file-atomic@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
|
||||
integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
|
||||
|
@ -361,14 +225,12 @@ write-file-atomic@^3.0.0:
|
|||
signal-exit "^3.0.2"
|
||||
typedarray-to-buffer "^3.1.5"
|
||||
|
||||
write-json-file@^4.2.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-4.3.0.tgz#908493d6fd23225344af324016e4ca8f702dd12d"
|
||||
integrity sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==
|
||||
write-json-file@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-5.0.0.tgz#11c329a8ea9e8e23fb92a87cc27412a15f87708b"
|
||||
integrity sha512-ddSsCLa4aQ3kI21BthINo4q905/wfhvQ3JL3774AcRjBaiQmfn5v4rw77jQ7T6CmAit9VOQO+FsLyPkwxoB1fw==
|
||||
dependencies:
|
||||
detect-indent "^6.0.0"
|
||||
graceful-fs "^4.1.15"
|
||||
is-plain-obj "^2.0.0"
|
||||
make-dir "^3.0.0"
|
||||
sort-keys "^4.0.0"
|
||||
write-file-atomic "^3.0.0"
|
||||
detect-indent "^7.0.0"
|
||||
is-plain-obj "^4.0.0"
|
||||
sort-keys "^5.0.0"
|
||||
write-file-atomic "^3.0.3"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@peertube/peertube-runner",
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.16",
|
||||
"type": "module",
|
||||
"main": "dist/peertube-runner.js",
|
||||
"bin": "dist/peertube-runner.js",
|
||||
|
@ -10,10 +10,11 @@
|
|||
"license": "AGPL-3.0",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@commander-js/extra-typings": "^10.0.3",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"@peertube/net-ipc": "^2.2.0",
|
||||
"@types/follow-redirects": "1.14.4",
|
||||
"env-paths": "^3.0.0",
|
||||
"net-ipc": "^2.0.1",
|
||||
"follow-redirects": "^1.15.5",
|
||||
"pino": "^8.11.0",
|
||||
"pino-pretty": "^10.0.0"
|
||||
}
|
||||
|
|
7
apps/peertube-runner/scripts/watch.js
Normal file
7
apps/peertube-runner/scripts/watch.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import * as esbuild from 'esbuild'
|
||||
import { esbuildOptions } from './build.js'
|
||||
|
||||
const context = await esbuild.context(esbuildOptions)
|
||||
|
||||
// Enable watch mode
|
||||
await context.watch()
|
|
@ -107,7 +107,8 @@ export class ProcessLiveRTMPHLSTranscoding {
|
|||
bitrate,
|
||||
ratio,
|
||||
|
||||
hasAudio
|
||||
hasAudio,
|
||||
probe
|
||||
})
|
||||
|
||||
logger.info(`Running live transcoding for ${payload.input.rtmpUrl}`)
|
||||
|
@ -150,7 +151,10 @@ export class ProcessLiveRTMPHLSTranscoding {
|
|||
|
||||
const type = ((err as any).res?.body as PeerTubeProblemDocument)?.code
|
||||
if (type === ServerErrorCode.RUNNER_JOB_NOT_IN_PROCESSING_STATE) {
|
||||
logger.info({ err }, 'Stopping transcoding as the job is not in processing state anymore')
|
||||
logger.info('Stopping transcoding as the job is not in processing state anymore')
|
||||
|
||||
this.sendSuccess()
|
||||
.catch(err => logger.error({ err }, 'Cannot send success'))
|
||||
|
||||
res()
|
||||
} else {
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
import { LogFn } from 'pino'
|
||||
import { logger } from '../../../shared/index.js'
|
||||
|
||||
export function getTranscodingLogger () {
|
||||
return {
|
||||
info: logger.info.bind(logger),
|
||||
debug: logger.debug.bind(logger),
|
||||
warn: logger.warn.bind(logger),
|
||||
error: logger.error.bind(logger)
|
||||
info: buildWinstonLogger(logger.info.bind(logger)),
|
||||
debug: buildWinstonLogger(logger.debug.bind(logger)),
|
||||
warn: buildWinstonLogger(logger.warn.bind(logger)),
|
||||
error: buildWinstonLogger(logger.error.bind(logger))
|
||||
}
|
||||
}
|
||||
|
||||
function buildWinstonLogger (log: LogFn) {
|
||||
return (arg1: string, arg2?: object) => {
|
||||
if (arg2) return log(arg2, arg1)
|
||||
|
||||
return log(arg1)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ export class RunnerServer {
|
|||
private checkingAvailableJobs = false
|
||||
|
||||
private cleaningUp = false
|
||||
private initialized = false
|
||||
|
||||
private readonly sockets = new Map<PeerTubeServer, Socket>()
|
||||
|
||||
|
@ -70,6 +71,7 @@ export class RunnerServer {
|
|||
|
||||
logger.info(`Using ${ConfigManager.Instance.getTranscodingDirectory()} for transcoding directory`)
|
||||
|
||||
this.initialized = true
|
||||
await this.checkAvailableJobs()
|
||||
}
|
||||
|
||||
|
@ -98,8 +100,6 @@ export class RunnerServer {
|
|||
await this.saveRegisteredInstancesInConf()
|
||||
|
||||
logger.info(`Registered runner ${runnerName} on ${url}`)
|
||||
|
||||
await this.checkAvailableJobs()
|
||||
}
|
||||
|
||||
private loadServer (server: PeerTubeServer) {
|
||||
|
@ -114,8 +114,15 @@ export class RunnerServer {
|
|||
})
|
||||
|
||||
socket.on('connect_error', err => logger.warn({ err }, `Cannot connect to ${url} socket`))
|
||||
socket.on('connect', () => logger.info(`Connected to ${url} socket`))
|
||||
socket.on('available-jobs', () => this.checkAvailableJobs())
|
||||
socket.on('available-jobs', () => this.safeAsyncCheckAvailableJobs())
|
||||
|
||||
socket.on('connect', () => {
|
||||
logger.info(`Connected to ${url} socket`)
|
||||
|
||||
this.safeAsyncCheckAvailableJobs()
|
||||
})
|
||||
socket.on('disconnect', () => logger.warn(`Disconnected from ${url} socket`))
|
||||
socket.io.on('ping', () => logger.debug(`Received a "ping" for ${url}`))
|
||||
|
||||
this.sockets.set(server, socket)
|
||||
}
|
||||
|
@ -169,7 +176,13 @@ export class RunnerServer {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
private safeAsyncCheckAvailableJobs () {
|
||||
this.checkAvailableJobs()
|
||||
.catch(err => logger.error({ err }, `Cannot check available jobs`))
|
||||
}
|
||||
|
||||
private async checkAvailableJobs () {
|
||||
if (!this.initialized) return
|
||||
if (this.checkingAvailableJobs) return
|
||||
|
||||
this.checkingAvailableJobs = true
|
||||
|
@ -187,18 +200,20 @@ export class RunnerServer {
|
|||
|
||||
await this.tryToExecuteJobAsync(server, job)
|
||||
} catch (err) {
|
||||
hadAvailableJob = false
|
||||
|
||||
const code = (err.res?.body as PeerTubeProblemDocument)?.code
|
||||
|
||||
if (code === ServerErrorCode.RUNNER_JOB_NOT_IN_PROCESSING_STATE) {
|
||||
logger.debug({ err }, 'Runner job is not in processing state anymore, retry later')
|
||||
return
|
||||
if (code === ServerErrorCode.RUNNER_JOB_NOT_IN_PENDING_STATE) {
|
||||
logger.debug({ err }, 'Runner job is not in pending state anymore, retry later')
|
||||
continue
|
||||
}
|
||||
|
||||
if (code === ServerErrorCode.UNKNOWN_RUNNER_TOKEN) {
|
||||
logger.error({ err }, `Unregistering ${server.url} as the runner token ${server.runnerToken} is invalid`)
|
||||
|
||||
await this.unregisterRunner({ url: server.url, runnerName: server.runnerName })
|
||||
return
|
||||
continue
|
||||
}
|
||||
|
||||
logger.error({ err }, `Cannot request/accept job on ${server.url} for runner ${server.runnerName}`)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { createWriteStream } from 'fs'
|
||||
import { remove } from 'fs-extra/esm'
|
||||
import { request as requestHTTP } from 'http'
|
||||
import { request as requestHTTPS, RequestOptions } from 'https'
|
||||
import { RequestOptions } from 'https'
|
||||
import { http, https } from 'follow-redirects'
|
||||
import { logger } from './logger.js'
|
||||
|
||||
export function downloadFile (options: {
|
||||
|
@ -61,7 +61,7 @@ export function downloadFile (options: {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
function getRequest (url: string) {
|
||||
if (url.startsWith('https://')) return requestHTTPS
|
||||
if (url.startsWith('https://')) return https.request.bind(https)
|
||||
|
||||
return requestHTTP
|
||||
return http.request.bind(http)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import CliTable3 from 'cli-table3'
|
||||
import { ensureDir } from 'fs-extra/esm'
|
||||
import { Client as NetIPC } from 'net-ipc'
|
||||
import { Client as NetIPC } from '@peertube/net-ipc'
|
||||
import { ConfigManager } from '../config-manager.js'
|
||||
import { IPCReponse, IPCReponseData, IPCRequest } from './shared/index.js'
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ensureDir } from 'fs-extra/esm'
|
||||
import { Server as NetIPC } from 'net-ipc'
|
||||
import { Server as NetIPC } from '@peertube/net-ipc'
|
||||
import { pick } from '@peertube/peertube-core-utils'
|
||||
import { RunnerServer } from '../../server/index.js'
|
||||
import { ConfigManager } from '../config-manager.js'
|
||||
|
|
|
@ -2,121 +2,6 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@commander-js/extra-typings@^10.0.3":
|
||||
version "10.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@commander-js/extra-typings/-/extra-typings-10.0.3.tgz#8b6c64897231ed9c00461db82018b5131b653aae"
|
||||
integrity sha512-OIw28QV/GlP8k0B5CJTRsl8IyNvd0R8C8rfo54Yz9P388vCNDgdNrFlKxZTGqps+5j6lSw3Ss9JTQwcur1w1oA==
|
||||
|
||||
"@esbuild/android-arm64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.15.tgz#893ad71f3920ccb919e1757c387756a9bca2ef42"
|
||||
integrity sha512-0kOB6Y7Br3KDVgHeg8PRcvfLkq+AccreK///B4Z6fNZGr/tNHX0z2VywCc7PTeWp+bPvjA5WMvNXltHw5QjAIA==
|
||||
|
||||
"@esbuild/android-arm@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.15.tgz#143e0d4e4c08c786ea410b9a7739779a9a1315d8"
|
||||
integrity sha512-sRSOVlLawAktpMvDyJIkdLI/c/kdRTOqo8t6ImVxg8yT7LQDUYV5Rp2FKeEosLr6ZCja9UjYAzyRSxGteSJPYg==
|
||||
|
||||
"@esbuild/android-x64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.15.tgz#d2d12a7676b2589864281b2274355200916540bc"
|
||||
integrity sha512-MzDqnNajQZ63YkaUWVl9uuhcWyEyh69HGpMIrf+acR4otMkfLJ4sUCxqwbCyPGicE9dVlrysI3lMcDBjGiBBcQ==
|
||||
|
||||
"@esbuild/darwin-arm64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.15.tgz#2e88e79f1d327a2a7d9d06397e5232eb0a473d61"
|
||||
integrity sha512-7siLjBc88Z4+6qkMDxPT2juf2e8SJxmsbNVKFY2ifWCDT72v5YJz9arlvBw5oB4W/e61H1+HDB/jnu8nNg0rLA==
|
||||
|
||||
"@esbuild/darwin-x64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.15.tgz#9384e64c0be91388c57be6d3a5eaf1c32a99c91d"
|
||||
integrity sha512-NbImBas2rXwYI52BOKTW342Tm3LTeVlaOQ4QPZ7XuWNKiO226DisFk/RyPk3T0CKZkKMuU69yOvlapJEmax7cg==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.15.tgz#2ad5a35bc52ebd9ca6b845dbc59ba39647a93c1a"
|
||||
integrity sha512-Xk9xMDjBVG6CfgoqlVczHAdJnCs0/oeFOspFap5NkYAmRCT2qTn1vJWA2f419iMtsHSLm+O8B6SLV/HlY5cYKg==
|
||||
|
||||
"@esbuild/freebsd-x64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.15.tgz#b513a48446f96c75fda5bef470e64d342d4379cd"
|
||||
integrity sha512-3TWAnnEOdclvb2pnfsTWtdwthPfOz7qAfcwDLcfZyGJwm1SRZIMOeB5FODVhnM93mFSPsHB9b/PmxNNbSnd0RQ==
|
||||
|
||||
"@esbuild/linux-arm64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.15.tgz#9697b168175bfd41fa9cc4a72dd0d48f24715f31"
|
||||
integrity sha512-T0MVnYw9KT6b83/SqyznTs/3Jg2ODWrZfNccg11XjDehIved2oQfrX/wVuev9N936BpMRaTR9I1J0tdGgUgpJA==
|
||||
|
||||
"@esbuild/linux-arm@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.15.tgz#5b22062c54f48cd92fab9ffd993732a52db70cd3"
|
||||
integrity sha512-MLTgiXWEMAMr8nmS9Gigx43zPRmEfeBfGCwxFQEMgJ5MC53QKajaclW6XDPjwJvhbebv+RzK05TQjvH3/aM4Xw==
|
||||
|
||||
"@esbuild/linux-ia32@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.15.tgz#eb28a13f9b60b5189fcc9e98e1024f6b657ba54c"
|
||||
integrity sha512-wp02sHs015T23zsQtU4Cj57WiteiuASHlD7rXjKUyAGYzlOKDAjqK6bk5dMi2QEl/KVOcsjwL36kD+WW7vJt8Q==
|
||||
|
||||
"@esbuild/linux-loong64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.15.tgz#32454bdfe144cf74b77895a8ad21a15cb81cfbe5"
|
||||
integrity sha512-k7FsUJjGGSxwnBmMh8d7IbObWu+sF/qbwc+xKZkBe/lTAF16RqxRCnNHA7QTd3oS2AfGBAnHlXL67shV5bBThQ==
|
||||
|
||||
"@esbuild/linux-mips64el@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.15.tgz#af12bde0d775a318fad90eb13a0455229a63987c"
|
||||
integrity sha512-ZLWk6czDdog+Q9kE/Jfbilu24vEe/iW/Sj2d8EVsmiixQ1rM2RKH2n36qfxK4e8tVcaXkvuV3mU5zTZviE+NVQ==
|
||||
|
||||
"@esbuild/linux-ppc64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.15.tgz#34c5ed145b2dfc493d3e652abac8bd3baa3865a5"
|
||||
integrity sha512-mY6dPkIRAiFHRsGfOYZC8Q9rmr8vOBZBme0/j15zFUKM99d4ILY4WpOC7i/LqoY+RE7KaMaSfvY8CqjJtuO4xg==
|
||||
|
||||
"@esbuild/linux-riscv64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.15.tgz#87bd515e837f2eb004b45f9e6a94dc5b93f22b92"
|
||||
integrity sha512-EcyUtxffdDtWjjwIH8sKzpDRLcVtqANooMNASO59y+xmqqRYBBM7xVLQhqF7nksIbm2yHABptoioS9RAbVMWVA==
|
||||
|
||||
"@esbuild/linux-s390x@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.15.tgz#20bf7947197f199ddac2ec412029a414ceae3aa3"
|
||||
integrity sha512-BuS6Jx/ezxFuHxgsfvz7T4g4YlVrmCmg7UAwboeyNNg0OzNzKsIZXpr3Sb/ZREDXWgt48RO4UQRDBxJN3B9Rbg==
|
||||
|
||||
"@esbuild/linux-x64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.15.tgz#31b93f9c94c195e852c20cd3d1914a68aa619124"
|
||||
integrity sha512-JsdS0EgEViwuKsw5tiJQo9UdQdUJYuB+Mf6HxtJSPN35vez1hlrNb1KajvKWF5Sa35j17+rW1ECEO9iNrIXbNg==
|
||||
|
||||
"@esbuild/netbsd-x64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.15.tgz#8da299b3ac6875836ca8cdc1925826498069ac65"
|
||||
integrity sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA==
|
||||
|
||||
"@esbuild/openbsd-x64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.15.tgz#04a1ec3d4e919714dba68dcf09eeb1228ad0d20c"
|
||||
integrity sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w==
|
||||
|
||||
"@esbuild/sunos-x64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.15.tgz#6694ebe4e16e5cd7dab6505ff7c28f9c1c695ce5"
|
||||
integrity sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ==
|
||||
|
||||
"@esbuild/win32-arm64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.15.tgz#1f95b2564193c8d1fee8f8129a0609728171d500"
|
||||
integrity sha512-W+Z5F++wgKAleDABemiyXVnzXgvRFs+GVKThSI+mGgleLWluv0D7Diz4oQpgdpNzh4i2nNDzQtWbjJiqutRp6Q==
|
||||
|
||||
"@esbuild/win32-ia32@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.15.tgz#c362b88b3df21916ed7bcf75c6d09c6bf3ae354a"
|
||||
integrity sha512-Muz/+uGgheShKGqSVS1KsHtCyEzcdOn/W/Xbh6H91Etm+wiIfwZaBn1W58MeGtfI8WA961YMHFYTthBdQs4t+w==
|
||||
|
||||
"@esbuild/win32-x64@0.17.15":
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.15.tgz#c2e737f3a201ebff8e2ac2b8e9f246b397ad19b8"
|
||||
integrity sha512-DjDa9ywLUUmjhV2Y9wUTIF+1XsmuFGvZoCmOWkli1XcNAh5t25cc7fgsCx4Zi/Uurep3TTLyDiKATgGEg61pkA==
|
||||
|
||||
"@iarna/toml@^2.2.5":
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c"
|
||||
|
@ -152,6 +37,28 @@
|
|||
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz#0f164b726869f71da3c594171df5ebc1c4b0a407"
|
||||
integrity sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==
|
||||
|
||||
"@peertube/net-ipc@^2.2.0":
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@peertube/net-ipc/-/net-ipc-2.2.1.tgz#3d1c154a08b57cfea31ed760ec76fe2f69e35a19"
|
||||
integrity sha512-RyKIGC3EeQ+xnSccf592qqsaXWrGp4wGfGl4W+wxDoZkwsThZJuiSbX8aCC1qZBHaDo3EuRH3ZrwsKpNjnyDAQ==
|
||||
optionalDependencies:
|
||||
fast-zlib "^2.0.1"
|
||||
msgpackr "^1.3.2"
|
||||
|
||||
"@types/follow-redirects@1.14.4":
|
||||
version "1.14.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/follow-redirects/-/follow-redirects-1.14.4.tgz#ca054d72ef574c77949fc5fff278b430fcd508ec"
|
||||
integrity sha512-GWXfsD0Jc1RWiFmMuMFCpXMzi9L7oPDVwxUnZdg89kDNnqsRfUKXEtUYtA98A6lig1WXH/CYY/fvPW9HuN5fTA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*":
|
||||
version "20.11.20"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.20.tgz#f0a2aee575215149a62784210ad88b3a34843659"
|
||||
integrity sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
abort-controller@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
|
||||
|
@ -164,23 +71,11 @@ atomic-sleep@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b"
|
||||
integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
base64-js@^1.3.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
brace-expansion@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
|
||||
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
|
||||
buffer@^6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
|
||||
|
@ -190,9 +85,9 @@ buffer@^6.0.3:
|
|||
ieee754 "^1.2.1"
|
||||
|
||||
colorette@^2.0.7:
|
||||
version "2.0.19"
|
||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798"
|
||||
integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==
|
||||
version "2.0.20"
|
||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
|
||||
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
|
||||
|
||||
dateformat@^4.6.3:
|
||||
version "4.6.3"
|
||||
|
@ -211,34 +106,6 @@ env-paths@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-3.0.0.tgz#2f1e89c2f6dbd3408e1b1711dd82d62e317f58da"
|
||||
integrity sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==
|
||||
|
||||
esbuild@^0.17.15:
|
||||
version "0.17.15"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.15.tgz#209ebc87cb671ffb79574db93494b10ffaf43cbc"
|
||||
integrity sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==
|
||||
optionalDependencies:
|
||||
"@esbuild/android-arm" "0.17.15"
|
||||
"@esbuild/android-arm64" "0.17.15"
|
||||
"@esbuild/android-x64" "0.17.15"
|
||||
"@esbuild/darwin-arm64" "0.17.15"
|
||||
"@esbuild/darwin-x64" "0.17.15"
|
||||
"@esbuild/freebsd-arm64" "0.17.15"
|
||||
"@esbuild/freebsd-x64" "0.17.15"
|
||||
"@esbuild/linux-arm" "0.17.15"
|
||||
"@esbuild/linux-arm64" "0.17.15"
|
||||
"@esbuild/linux-ia32" "0.17.15"
|
||||
"@esbuild/linux-loong64" "0.17.15"
|
||||
"@esbuild/linux-mips64el" "0.17.15"
|
||||
"@esbuild/linux-ppc64" "0.17.15"
|
||||
"@esbuild/linux-riscv64" "0.17.15"
|
||||
"@esbuild/linux-s390x" "0.17.15"
|
||||
"@esbuild/linux-x64" "0.17.15"
|
||||
"@esbuild/netbsd-x64" "0.17.15"
|
||||
"@esbuild/openbsd-x64" "0.17.15"
|
||||
"@esbuild/sunos-x64" "0.17.15"
|
||||
"@esbuild/win32-arm64" "0.17.15"
|
||||
"@esbuild/win32-ia32" "0.17.15"
|
||||
"@esbuild/win32-x64" "0.17.15"
|
||||
|
||||
event-target-shim@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
|
||||
|
@ -255,9 +122,9 @@ fast-copy@^3.0.0:
|
|||
integrity sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==
|
||||
|
||||
fast-redact@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa"
|
||||
integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.3.0.tgz#7c83ce3a7be4898241a46560d51de10f653f7634"
|
||||
integrity sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==
|
||||
|
||||
fast-safe-stringify@^2.1.1:
|
||||
version "2.1.1"
|
||||
|
@ -269,66 +136,32 @@ fast-zlib@^2.0.1:
|
|||
resolved "https://registry.yarnpkg.com/fast-zlib/-/fast-zlib-2.0.1.tgz#be624f592fc80ad8019ee2025d16a367a4e9b024"
|
||||
integrity sha512-DCoYgNagM2Bt1VIpXpdGnRx4LzqJeYG0oh6Nf/7cWo6elTXkFGMw9CrRCYYUIapYNrozYMoyDRflx9mgT3Awyw==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
follow-redirects@^1.15.5:
|
||||
version "1.15.5"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020"
|
||||
integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==
|
||||
|
||||
glob@^8.0.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
|
||||
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^5.0.1"
|
||||
once "^1.3.0"
|
||||
|
||||
help-me@^4.0.1:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/help-me/-/help-me-4.2.0.tgz#50712bfd799ff1854ae1d312c36eafcea85b0563"
|
||||
integrity sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==
|
||||
dependencies:
|
||||
glob "^8.0.0"
|
||||
readable-stream "^3.6.0"
|
||||
help-me@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6"
|
||||
integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==
|
||||
|
||||
ieee754@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
joycon@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
|
||||
integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==
|
||||
|
||||
minimatch@^5.0.1:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
|
||||
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist@^1.2.6:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||
|
||||
msgpackr-extract@^3.0.1:
|
||||
msgpackr-extract@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz#e05ec1bb4453ddf020551bcd5daaf0092a2c279d"
|
||||
integrity sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==
|
||||
|
@ -343,19 +176,11 @@ msgpackr-extract@^3.0.1:
|
|||
"@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2"
|
||||
|
||||
msgpackr@^1.3.2:
|
||||
version "1.8.5"
|
||||
resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.8.5.tgz#8cadfb935357680648f33699d0e833c9179dbfeb"
|
||||
integrity sha512-mpPs3qqTug6ahbblkThoUY2DQdNXcm4IapwOS3Vm/87vmpzLVelvp9h3It1y9l1VPpiFLV11vfOXnmeEwiIXwg==
|
||||
version "1.10.1"
|
||||
resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555"
|
||||
integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==
|
||||
optionalDependencies:
|
||||
msgpackr-extract "^3.0.1"
|
||||
|
||||
net-ipc@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/net-ipc/-/net-ipc-2.0.1.tgz#1da79ca16f1624f2ed1099a124cb065912c595a5"
|
||||
integrity sha512-4HLjZ/Xorj4kxA7WUajF2EAXlS+OR+XliDLkqQA53Wm7eIr/hWLjdXt4zzB6q4Ii8BB+HbuRbM9yLov3+ttRUw==
|
||||
optionalDependencies:
|
||||
fast-zlib "^2.0.1"
|
||||
msgpackr "^1.3.2"
|
||||
msgpackr-extract "^3.0.2"
|
||||
|
||||
node-gyp-build-optional-packages@5.0.7:
|
||||
version "5.0.7"
|
||||
|
@ -363,35 +188,35 @@ node-gyp-build-optional-packages@5.0.7:
|
|||
integrity sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==
|
||||
|
||||
on-exit-leak-free@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4"
|
||||
integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8"
|
||||
integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==
|
||||
|
||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
once@^1.3.1, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3"
|
||||
integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==
|
||||
pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz#083d98f966262164504afb989bccd05f665937a8"
|
||||
integrity sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==
|
||||
dependencies:
|
||||
readable-stream "^4.0.0"
|
||||
split2 "^4.0.0"
|
||||
|
||||
pino-pretty@^10.0.0:
|
||||
version "10.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-10.0.0.tgz#fd2f307ee897289f63d09b0b804ac2ecc9a18516"
|
||||
integrity sha512-zKFjYXBzLaLTEAN1ayKpHXtL5UeRQC7R3lvhKe7fWs7hIVEjKGG/qIXwQt9HmeUp71ogUd/YcW+LmMwRp4KT6Q==
|
||||
version "10.3.1"
|
||||
resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-10.3.1.tgz#e3285a5265211ac6c7cd5988f9e65bf3371a0ca9"
|
||||
integrity sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==
|
||||
dependencies:
|
||||
colorette "^2.0.7"
|
||||
dateformat "^4.6.3"
|
||||
fast-copy "^3.0.0"
|
||||
fast-safe-stringify "^2.1.1"
|
||||
help-me "^4.0.1"
|
||||
help-me "^5.0.0"
|
||||
joycon "^3.1.1"
|
||||
minimist "^1.2.6"
|
||||
on-exit-leak-free "^2.1.0"
|
||||
|
@ -403,31 +228,31 @@ pino-pretty@^10.0.0:
|
|||
strip-json-comments "^3.1.1"
|
||||
|
||||
pino-std-serializers@^6.0.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.2.0.tgz#169048c0df3f61352fce56aeb7fb962f1b66ab43"
|
||||
integrity sha512-IWgSzUL8X1w4BIWTwErRgtV8PyOGOOi60uqv0oKuS/fOA8Nco/OeI6lBuc4dyP8MMfdFwyHqTMcBIA7nDiqEqA==
|
||||
version "6.2.2"
|
||||
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz#d9a9b5f2b9a402486a5fc4db0a737570a860aab3"
|
||||
integrity sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==
|
||||
|
||||
pino@^8.11.0:
|
||||
version "8.11.0"
|
||||
resolved "https://registry.yarnpkg.com/pino/-/pino-8.11.0.tgz#2a91f454106b13e708a66c74ebc1c2ab7ab38498"
|
||||
integrity sha512-Z2eKSvlrl2rH8p5eveNUnTdd4AjJk8tAsLkHYZQKGHP4WTh2Gi1cOSOs3eWPqaj+niS3gj4UkoreoaWgF3ZWYg==
|
||||
version "8.19.0"
|
||||
resolved "https://registry.yarnpkg.com/pino/-/pino-8.19.0.tgz#ccc15ef736f103ec02cfbead0912bc436dc92ce4"
|
||||
integrity sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA==
|
||||
dependencies:
|
||||
atomic-sleep "^1.0.0"
|
||||
fast-redact "^3.1.1"
|
||||
on-exit-leak-free "^2.1.0"
|
||||
pino-abstract-transport v1.0.0
|
||||
pino-abstract-transport v1.1.0
|
||||
pino-std-serializers "^6.0.0"
|
||||
process-warning "^2.0.0"
|
||||
process-warning "^3.0.0"
|
||||
quick-format-unescaped "^4.0.3"
|
||||
real-require "^0.2.0"
|
||||
safe-stable-stringify "^2.3.1"
|
||||
sonic-boom "^3.1.0"
|
||||
sonic-boom "^3.7.0"
|
||||
thread-stream "^2.0.0"
|
||||
|
||||
process-warning@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.2.0.tgz#008ec76b579820a8e5c35d81960525ca64feb626"
|
||||
integrity sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==
|
||||
process-warning@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-3.0.0.tgz#96e5b88884187a1dce6f5c3166d611132058710b"
|
||||
integrity sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==
|
||||
|
||||
process@^0.11.10:
|
||||
version "0.11.10"
|
||||
|
@ -447,24 +272,16 @@ quick-format-unescaped@^4.0.3:
|
|||
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7"
|
||||
integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==
|
||||
|
||||
readable-stream@^3.6.0:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
|
||||
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readable-stream@^4.0.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.3.0.tgz#0914d0c72db03b316c9733bb3461d64a3cc50cba"
|
||||
integrity sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==
|
||||
version "4.5.2"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09"
|
||||
integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==
|
||||
dependencies:
|
||||
abort-controller "^3.0.0"
|
||||
buffer "^6.0.3"
|
||||
events "^3.3.0"
|
||||
process "^0.11.10"
|
||||
string_decoder "^1.3.0"
|
||||
|
||||
real-require@^0.2.0:
|
||||
version "0.2.0"
|
||||
|
@ -486,10 +303,10 @@ secure-json-parse@^2.4.0:
|
|||
resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862"
|
||||
integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==
|
||||
|
||||
sonic-boom@^3.0.0, sonic-boom@^3.1.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.3.0.tgz#cffab6dafee3b2bcb88d08d589394198bee1838c"
|
||||
integrity sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==
|
||||
sonic-boom@^3.0.0, sonic-boom@^3.7.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.8.0.tgz#e442c5c23165df897d77c3c14ef3ca40dec66a66"
|
||||
integrity sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==
|
||||
dependencies:
|
||||
atomic-sleep "^1.0.0"
|
||||
|
||||
|
@ -498,7 +315,7 @@ split2@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
|
||||
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
|
||||
|
||||
string_decoder@^1.1.1:
|
||||
string_decoder@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||
|
@ -511,16 +328,16 @@ strip-json-comments@^3.1.1:
|
|||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||
|
||||
thread-stream@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33"
|
||||
integrity sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.4.1.tgz#6d588b14f0546e59d3f306614f044bc01ce43351"
|
||||
integrity sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==
|
||||
dependencies:
|
||||
real-require "^0.2.0"
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
undici-types@~5.26.4:
|
||||
version "5.26.5"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
|
|
|
@ -159,6 +159,11 @@
|
|||
"quote-props": [
|
||||
"error",
|
||||
"consistent-as-needed"
|
||||
],
|
||||
"no-constant-binary-expression": "error",
|
||||
"@typescript-eslint/unbound-method": [
|
||||
"error",
|
||||
{ "ignoreStatic": true }
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
"extends": "stylelint-config-sass-guidelines",
|
||||
"rules": {
|
||||
"scss/at-import-no-partial-leading-underscore": null,
|
||||
"color-hex-case": null,
|
||||
"color-hex-length": null,
|
||||
"selector-pseudo-element-no-unknown": [
|
||||
true,
|
||||
|
@ -19,10 +18,10 @@
|
|||
"selector-max-compound-selectors": 9,
|
||||
"selector-no-qualifying-type": null,
|
||||
"scss/at-extend-no-missing-placeholder": null,
|
||||
"number-leading-zero": null,
|
||||
"rule-empty-line-before": null,
|
||||
"selector-max-id": null,
|
||||
"scss/at-function-pattern": null,
|
||||
"scss/load-no-partial-leading-underscore": null,
|
||||
"property-no-vendor-prefix": [
|
||||
true,
|
||||
{
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
"translation": "src/locale/angular.th-TH.xlf",
|
||||
"baseHref": "/client/th-TH/"
|
||||
},
|
||||
"tr": {
|
||||
"translation": "src/locale/angular.tr-TR.xlf",
|
||||
"baseHref": "/client/tr-TR/"
|
||||
},
|
||||
"fi": {
|
||||
"translation": "src/locale/angular.fi-FI.xlf",
|
||||
"baseHref": "/client/fi-FI/"
|
||||
|
@ -279,25 +283,25 @@
|
|||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "PeerTube:build",
|
||||
"proxyConfig": "proxy.config.json"
|
||||
"proxyConfig": "proxy.config.json",
|
||||
"buildTarget": "PeerTube:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "PeerTube:build:production"
|
||||
"buildTarget": "PeerTube:build:production"
|
||||
},
|
||||
"hmr": {
|
||||
"browserTarget": "PeerTube:build:hmr"
|
||||
"buildTarget": "PeerTube:build:hmr"
|
||||
},
|
||||
"ar-locale": {
|
||||
"browserTarget": "PeerTube:build:ar-locale"
|
||||
"buildTarget": "PeerTube:build:ar-locale"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "PeerTube:build"
|
||||
"buildTarget": "PeerTube:build"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
|
|
|
@ -10,7 +10,7 @@ export class AdminConfigPage {
|
|||
}
|
||||
await go('/admin/config/edit-custom#' + tab)
|
||||
|
||||
await $('.inner-form-title=' + waitTitles[tab]).waitForDisplayed()
|
||||
await $('h2=' + waitTitles[tab]).waitForDisplayed()
|
||||
}
|
||||
|
||||
async updateNSFWSetting (newValue: 'do_not_list' | 'blur' | 'display') {
|
||||
|
|
|
@ -56,7 +56,7 @@ export class MyAccountPage {
|
|||
async removeVideo (name: string) {
|
||||
const container = await this.getVideoElement(name)
|
||||
|
||||
await container.$('.dropdown-toggle').click()
|
||||
await container.$('my-action-dropdown .dropdown-toggle').click()
|
||||
|
||||
const deleteItem = () => {
|
||||
return $$('.dropdown-menu .dropdown-item').find<WebdriverIO.Element>(async v => {
|
||||
|
@ -120,9 +120,7 @@ export class MyAccountPage {
|
|||
async updatePlaylistPrivacy (playlistUUID: string, privacy: 'Public' | 'Private' | 'Unlisted') {
|
||||
go('/my-library/video-playlists/update/' + playlistUUID)
|
||||
|
||||
await browser.waitUntil(async () => {
|
||||
return (await $('form .video-playlist-title').getText() === 'PLAYLIST')
|
||||
})
|
||||
await $('a[href*="/my-library/video-playlists/update/"]').waitForDisplayed()
|
||||
|
||||
await selectCustomSelect('videoChannelId', 'Main root channel')
|
||||
await selectCustomSelect('privacy', privacy)
|
||||
|
|
|
@ -49,7 +49,13 @@ export class PlayerPage {
|
|||
async playVideo () {
|
||||
await $('div.video-js.vjs-paused, div.video-js.vjs-playing').waitForExist()
|
||||
|
||||
if (await $('div.video-js.vjs-playing').isExisting()) return
|
||||
if (await $('div.video-js.vjs-playing').isExisting()) {
|
||||
if (!isIOS()) return
|
||||
|
||||
// On iOS, the web browser may have aborted player autoplay, so check the video is still autoplayed
|
||||
await browserSleep(5000)
|
||||
if (await $('div.video-js.vjs-playing').isExisting()) return
|
||||
}
|
||||
|
||||
// Autoplay is disabled on iOS and Safari
|
||||
if (isIOS() || isSafari() || isMobileDevice()) {
|
||||
|
|
|
@ -67,7 +67,7 @@ export class VideoListPage {
|
|||
|
||||
async getVideosListName () {
|
||||
const elems = await $$('.videos .video-miniature .video-miniature-name')
|
||||
const texts = await Promise.all(elems.map(e => e.getText()))
|
||||
const texts = await elems.map(e => e.getText())
|
||||
|
||||
return texts.map(t => t.trim())
|
||||
}
|
||||
|
|
|
@ -13,8 +13,11 @@ export class VideoWatchPage {
|
|||
const index = this.isMobileDevice ? 0 : 1
|
||||
|
||||
return browser.waitUntil(async () => {
|
||||
return await $('.video-info .video-info-name').isExisting() &&
|
||||
(await $$('.video-info .video-info-name')[index].getText()).includes(videoName)
|
||||
if (!await $('.video-info .video-info-name').isExisting()) return false
|
||||
|
||||
const elem = await $$('.video-info .video-info-name')[index]
|
||||
|
||||
return (await elem.getText()).includes(videoName) && elem.isDisplayed()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -31,9 +34,13 @@ export class VideoWatchPage {
|
|||
}
|
||||
|
||||
async isDownloadEnabled () {
|
||||
await this.clickOnMoreDropdownIcon()
|
||||
try {
|
||||
await this.clickOnMoreDropdownIcon()
|
||||
|
||||
return $('.dropdown-item .icon-download').isExisting()
|
||||
return await $('.dropdown-item .icon-download').isExisting()
|
||||
} catch {
|
||||
return $('.action-button-download').isDisplayed()
|
||||
}
|
||||
}
|
||||
|
||||
areCommentsEnabled () {
|
||||
|
|
|
@ -176,7 +176,7 @@ describe('Videos all workflow', () => {
|
|||
await videoWatchPage.waitUntilVideoName(video2Name, 40 * 1000)
|
||||
})
|
||||
|
||||
it('Should watch the WEB VIDEO playlist in the embed', async () => {
|
||||
it('Should watch the Web Video playlist in the embed', async () => {
|
||||
if (isUploadUnsupported()) return
|
||||
|
||||
const accessToken = await browser.execute(`return window.localStorage.getItem('access_token');`)
|
||||
|
|
|
@ -30,14 +30,21 @@ describe('Custom server defaults', () => {
|
|||
|
||||
await videoWatchPage.waitWatchVideoName('video')
|
||||
|
||||
expect(await videoWatchPage.getPrivacy()).toBe('Internal')
|
||||
expect(await videoWatchPage.getLicence()).toBe('Attribution - Non Commercial')
|
||||
expect(await videoWatchPage.isDownloadEnabled()).toBeFalsy()
|
||||
expect(await videoWatchPage.areCommentsEnabled()).toBeFalsy()
|
||||
})
|
||||
const videoUrl = await browser.getUrl()
|
||||
|
||||
after(async function () {
|
||||
expect(await videoWatchPage.getPrivacy()).toBe('Unlisted')
|
||||
expect(await videoWatchPage.getLicence()).toBe('Attribution - Non Commercial')
|
||||
expect(await videoWatchPage.areCommentsEnabled()).toBeFalsy()
|
||||
|
||||
// Owners can download their videos
|
||||
expect(await videoWatchPage.isDownloadEnabled()).toBeTruthy()
|
||||
|
||||
// Logout to see if the download enabled is correct for anonymous users
|
||||
await loginPage.logout()
|
||||
await browser.url(videoUrl)
|
||||
await videoWatchPage.waitWatchVideoName('video')
|
||||
|
||||
expect(await videoWatchPage.isDownloadEnabled()).toBeFalsy()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -130,10 +130,12 @@ describe('Password protected videos', () => {
|
|||
|
||||
it('Should update the playlist to public', async () => {
|
||||
const url = await browser.getUrl()
|
||||
const regex = /\/([a-f0-9-]+)$/i
|
||||
const regex = /\/my-library\/video-playlists\/([^/]+)/i
|
||||
const match = url.match(regex)
|
||||
const uuid = match ? match[1] : null
|
||||
|
||||
expect(uuid).not.toBeNull()
|
||||
|
||||
await myAccountPage.updatePlaylistPrivacy(uuid, 'Public')
|
||||
})
|
||||
|
||||
|
|
|
@ -51,15 +51,15 @@ describe('Videos list', () => {
|
|||
|
||||
async function checkCommonVideoListPages (policy: NSFWPolicy) {
|
||||
const promisesWithFilters = [
|
||||
videoListPage.goOnRootAccount,
|
||||
videoListPage.goOnLocal,
|
||||
videoListPage.goOnRecentlyAdded,
|
||||
videoListPage.goOnTrending,
|
||||
videoListPage.goOnRootChannel
|
||||
videoListPage.goOnRootAccount.bind(videoListPage),
|
||||
videoListPage.goOnLocal.bind(videoListPage),
|
||||
videoListPage.goOnRecentlyAdded.bind(videoListPage),
|
||||
videoListPage.goOnTrending.bind(videoListPage),
|
||||
videoListPage.goOnRootChannel.bind(videoListPage)
|
||||
]
|
||||
|
||||
for (const p of promisesWithFilters) {
|
||||
await p.call(videoListPage)
|
||||
await p()
|
||||
|
||||
const filter = await videoListPage.getNSFWFilter()
|
||||
const filterText = await filter.getText()
|
||||
|
@ -69,11 +69,11 @@ describe('Videos list', () => {
|
|||
}
|
||||
|
||||
const promisesWithoutFilters = [
|
||||
videoListPage.goOnRootAccountChannels,
|
||||
videoListPage.goOnHomepage
|
||||
videoListPage.goOnRootAccountChannels.bind(videoListPage),
|
||||
videoListPage.goOnHomepage.bind(videoListPage)
|
||||
]
|
||||
for (const p of promisesWithoutFilters) {
|
||||
await p.call(videoListPage)
|
||||
await p()
|
||||
|
||||
await checkNormalVideo()
|
||||
await checkNSFWVideo(policy)
|
||||
|
|
|
@ -66,7 +66,7 @@ function buildConfig (suiteFile: string = undefined) {
|
|||
publish: {
|
||||
download_enabled: false,
|
||||
comments_enabled: false,
|
||||
privacy: 4,
|
||||
privacy: 2,
|
||||
licence: 4
|
||||
},
|
||||
p2p: {
|
||||
|
|
|
@ -10,7 +10,7 @@ if (!key) throw new Error('Miss browser stack key')
|
|||
function buildMainOptions (sessionName: string) {
|
||||
return {
|
||||
projectName: 'PeerTube',
|
||||
buildName: 'Main E2E - ' + new Date().toISOString().split('T')[0],
|
||||
buildName: 'Main E2E - ' + new Date().toISOString(),
|
||||
sessionName,
|
||||
consoleLogs: 'info',
|
||||
networkLogs: true
|
||||
|
@ -100,7 +100,7 @@ module.exports = {
|
|||
{
|
||||
browserName: 'Safari',
|
||||
|
||||
...buildBStackMobileOptions({ sessionName: 'Safari iPhone', deviceName: 'iPhone 8 Plus', osVersion: '12.4' })
|
||||
...buildBStackMobileOptions({ sessionName: 'Safari iPhone', deviceName: 'iPhone 8', osVersion: '13' })
|
||||
},
|
||||
{
|
||||
browserName: 'Safari',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "peertube-client",
|
||||
"version": "6.0.3",
|
||||
"version": "6.1.0",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0",
|
||||
"author": {
|
||||
|
@ -29,31 +29,31 @@
|
|||
],
|
||||
"typings": "*.d.ts",
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^16.0.2",
|
||||
"@angular-eslint/builder": "^16.0.2",
|
||||
"@angular-eslint/eslint-plugin": "^16.0.2",
|
||||
"@angular-eslint/eslint-plugin-template": "^16.0.2",
|
||||
"@angular-eslint/schematics": "^16.0.2",
|
||||
"@angular-eslint/template-parser": "^16.0.2",
|
||||
"@angular/animations": "^16.0.2",
|
||||
"@angular/cdk": "^16.0.1",
|
||||
"@angular/cli": "^16.0.2",
|
||||
"@angular/common": "^16.0.2",
|
||||
"@angular/compiler": "^16.0.2",
|
||||
"@angular/compiler-cli": "^16.0.2",
|
||||
"@angular/core": "^16.0.2",
|
||||
"@angular/forms": "^16.0.2",
|
||||
"@angular/localize": "^16.0.2",
|
||||
"@angular/platform-browser": "^16.0.2",
|
||||
"@angular/platform-browser-dynamic": "^16.0.2",
|
||||
"@angular/router": "^16.0.2",
|
||||
"@angular/service-worker": "^16.0.2",
|
||||
"@angular-devkit/build-angular": "^17.0.9",
|
||||
"@angular-eslint/builder": "^17.1.1",
|
||||
"@angular-eslint/eslint-plugin": "^17.1.1",
|
||||
"@angular-eslint/eslint-plugin-template": "^17.1.1",
|
||||
"@angular-eslint/schematics": "^17.1.1",
|
||||
"@angular-eslint/template-parser": "^17.1.1",
|
||||
"@angular/animations": "^17.0.8",
|
||||
"@angular/cdk": "^17.0.4",
|
||||
"@angular/cli": "^17.0.9",
|
||||
"@angular/common": "^17.0.8",
|
||||
"@angular/compiler": "^17.0.8",
|
||||
"@angular/compiler-cli": "^17.0.8",
|
||||
"@angular/core": "^17.0.8",
|
||||
"@angular/forms": "^17.0.8",
|
||||
"@angular/localize": "^17.0.8",
|
||||
"@angular/platform-browser": "^17.0.8",
|
||||
"@angular/platform-browser-dynamic": "^17.0.8",
|
||||
"@angular/router": "^17.0.8",
|
||||
"@angular/service-worker": "^17.0.8",
|
||||
"@babel/core": "^7.18.5",
|
||||
"@babel/preset-env": "^7.18.2",
|
||||
"@formatjs/intl-locale": "^3.3.1",
|
||||
"@formatjs/intl-pluralrules": "^5.2.2",
|
||||
"@ng-bootstrap/ng-bootstrap": "^15.1.1",
|
||||
"@ng-select/ng-select": "^11.2.0",
|
||||
"@ng-bootstrap/ng-bootstrap": "^16.0.0",
|
||||
"@ng-select/ng-select": "^12.0.4",
|
||||
"@ngx-loading-bar/core": "^6.0.0",
|
||||
"@ngx-loading-bar/http-client": "^6.0.0",
|
||||
"@ngx-loading-bar/router": "^6.0.0",
|
||||
|
@ -73,18 +73,19 @@
|
|||
"@types/lodash-es": "^4.17.0",
|
||||
"@types/markdown-it": "^13.0.2",
|
||||
"@types/node": "^18.13.0",
|
||||
"@types/sanitize-html": "2.9.2",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@types/sanitize-html": "2.11.0",
|
||||
"@types/sha.js": "^2.4.0",
|
||||
"@types/video.js": "^7.3.40",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.5",
|
||||
"@typescript-eslint/parser": "^6.7.5",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.2",
|
||||
"@typescript-eslint/parser": "^7.0.2",
|
||||
"@wdio/browserstack-service": "^8.10.5",
|
||||
"@wdio/cli": "^8.10.5",
|
||||
"@wdio/local-runner": "^8.10.5",
|
||||
"@wdio/mocha-framework": "^8.10.4",
|
||||
"@wdio/shared-store-service": "^8.10.5",
|
||||
"@wdio/spec-reporter": "^8.10.5",
|
||||
"angularx-qrcode": "16.0.0",
|
||||
"angularx-qrcode": "17.0.0",
|
||||
"babel-loader": "^9.1.0",
|
||||
"bootstrap": "^5.1.3",
|
||||
"buffer": "^6.0.3",
|
||||
|
@ -94,44 +95,45 @@
|
|||
"css-loader": "^6.2.0",
|
||||
"debug": "^4.3.1",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-plugin-import": "2.28.1",
|
||||
"eslint-plugin-jsdoc": "^46.8.2",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-jsdoc": "^48.1.0",
|
||||
"eslint-plugin-prefer-arrow": "latest",
|
||||
"expect-webdriverio": "^4.2.3",
|
||||
"focus-visible": "^5.0.2",
|
||||
"hls.js": "~1.3",
|
||||
"html-loader": "^4.1.0",
|
||||
"html-loader": "^5.0.0",
|
||||
"html-webpack-plugin": "^5.3.1",
|
||||
"intl-messageformat": "^10.1.0",
|
||||
"jschannel": "^1.0.2",
|
||||
"linkify-html": "^4.0.2",
|
||||
"linkifyjs": "^4.0.2",
|
||||
"lodash-es": "^4.17.4",
|
||||
"markdown-it": "13.0.2",
|
||||
"markdown-it": "14.0.0",
|
||||
"markdown-it-emoji": "^3.0.0",
|
||||
"mini-css-extract-plugin": "^2.2.0",
|
||||
"ngx-uploadx": "^6.1.0",
|
||||
"path-browserify": "^1.0.0",
|
||||
"postcss": "^8.4.14",
|
||||
"primeng": "^16.0.0-rc.2",
|
||||
"primeng": "^17.3.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rxjs": "^7.3.0",
|
||||
"sanitize-html": "^2.1.2",
|
||||
"sass": "^1.58.1",
|
||||
"sass-loader": "^13.2.0",
|
||||
"sass-loader": "^14.1.1",
|
||||
"sha.js": "^2.4.11",
|
||||
"socket.io-client": "^4.5.4",
|
||||
"stylelint": "^15.1.0",
|
||||
"stylelint-config-sass-guidelines": "^10.0.0",
|
||||
"stylelint": "^16.2.1",
|
||||
"stylelint-config-sass-guidelines": "^11.0.0",
|
||||
"tinykeys": "^2.1.0",
|
||||
"ts-loader": "^9.3.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"tslib": "^2.4.0",
|
||||
"typescript": "~5.1.0",
|
||||
"typescript": "~5.2",
|
||||
"video.js": "^7.19.2",
|
||||
"webpack": "^5.73.0",
|
||||
"webpack-bundle-analyzer": "^4.4.2",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"zone.js": "~0.13.0"
|
||||
"zone.js": "~0.14.2"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
<div class="row">
|
||||
<h1 class="visually-hidden" i18n>Follows</h1>
|
||||
<div class="margin-content mt-4">
|
||||
<div class="row">
|
||||
<h1 class="visually-hidden" i18n>Follows</h1>
|
||||
|
||||
<div class="col-xl-6 col-md-12">
|
||||
<h2 i18n class="fs-5-5 mb-4 fw-semibold">Followers of {{ instanceName }} ({{ followersPagination.totalItems }})</h2>
|
||||
<div class="col-xl-6 col-md-12">
|
||||
<h2 i18n class="fs-5-5 mb-4 fw-semibold">Followers of {{ instanceName }} ({{ followersPagination.totalItems }})</h2>
|
||||
|
||||
<div i18n class="no-results" *ngIf="followersPagination.totalItems === 0">{{ instanceName }} does not have followers.</div>
|
||||
<div i18n class="no-results" *ngIf="followersPagination.totalItems === 0">{{ instanceName }} does not have followers.</div>
|
||||
|
||||
<a *ngFor="let follower of followers" [href]="follower.url" target="_blank" rel="noopener noreferrer">
|
||||
{{ follower.name }}
|
||||
</a>
|
||||
<a *ngFor="let follower of followers" [href]="follower.url" target="_blank" rel="noopener noreferrer">
|
||||
{{ follower.name }}
|
||||
</a>
|
||||
|
||||
<button i18n class="peertube-button-link grey-button mt-1" *ngIf="!loadedAllFollowers && canLoadMoreFollowers()" (click)="loadAllFollowers()">Show full list</button>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6 col-md-12">
|
||||
<h2 i18n class="fs-5-5 mb-4 fw-semibold">Subscriptions of {{ instanceName }} ({{ followingsPagination.totalItems }})</h2>
|
||||
|
||||
<div i18n class="no-results" *ngIf="followingsPagination.totalItems === 0">{{ instanceName }} does not have subscriptions.</div>
|
||||
|
||||
<a *ngFor="let following of followings" [href]="following.url" target="_blank" rel="noopener noreferrer">
|
||||
{{ following.name }}
|
||||
</a>
|
||||
|
||||
<button i18n class="peertube-button-link grey-button mt-1" *ngIf="!loadedAllFollowings && canLoadMoreFollowings()" (click)="loadAllFollowings()">Show full list</button>
|
||||
</div>
|
||||
|
||||
<button i18n class="peertube-button-link grey-button mt-1" *ngIf="!loadedAllFollowers && canLoadMoreFollowers()" (click)="loadAllFollowers()">Show full list</button>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6 col-md-12">
|
||||
<h2 i18n class="fs-5-5 mb-4 fw-semibold">Subscriptions of {{ instanceName }} ({{ followingsPagination.totalItems }})</h2>
|
||||
|
||||
<div i18n class="no-results" *ngIf="followingsPagination.totalItems === 0">{{ instanceName }} does not have subscriptions.</div>
|
||||
|
||||
<a *ngFor="let following of followings" [href]="following.url" target="_blank" rel="noopener noreferrer">
|
||||
{{ following.name }}
|
||||
</a>
|
||||
|
||||
<button i18n class="peertube-button-link grey-button mt-1" *ngIf="!loadedAllFollowings && canLoadMoreFollowings()" (click)="loadAllFollowings()">Show full list</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import { SortMeta } from 'primeng/api'
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { ComponentPagination, hasMoreItems, Notifier, RestService, ServerService } from '@app/core'
|
||||
import { InstanceFollowService } from '@app/shared/shared-instance'
|
||||
import { Actor } from '@peertube/peertube-models'
|
||||
import { NgIf, NgFor } from '@angular/common'
|
||||
import { InstanceFollowService } from '@app/shared/shared-instance/instance-follow.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-about-follows',
|
||||
templateUrl: './about-follows.component.html',
|
||||
styleUrls: [ './about-follows.component.scss' ]
|
||||
styleUrls: [ './about-follows.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [ NgIf, NgFor ]
|
||||
})
|
||||
|
||||
export class AboutFollowsComponent implements OnInit {
|
||||
|
|
|
@ -1,226 +1,232 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12 col-xl-6">
|
||||
<div class="banner" *ngIf="instanceBannerUrl">
|
||||
<img [src]="instanceBannerUrl" alt="Instance banner">
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<h1 i18n class="fw-semibold fs-5">About {{ instanceName }}</h1>
|
||||
<div class="margin-content mt-4">
|
||||
<div class="row ">
|
||||
<div class="col-md-12 col-xl-6">
|
||||
|
||||
<a routerLink="/about/contact" i18n *ngIf="isContactFormEnabled" class="peertube-button-link orange-button h-100 d-flex align-items-center">Contact us</a>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between">
|
||||
<h1 i18n class="fw-semibold fs-5">About {{ instanceName }}</h1>
|
||||
|
||||
<div class="mb-4" *ngIf="categories.length !== 0 || languages.length !== 0">
|
||||
<span *ngFor="let category of categories" class="pt-badge badge-primary">{{ category }}</span>
|
||||
<a routerLink="/about/contact" i18n *ngIf="isContactFormEnabled" class="peertube-button-link orange-button h-100 d-flex align-items-center">Contact us</a>
|
||||
</div>
|
||||
|
||||
<span *ngFor="let language of languages" class="pt-badge badge-secondary">{{ language }}</span>
|
||||
</div>
|
||||
<div class="mb-4" *ngIf="categories.length !== 0 || languages.length !== 0">
|
||||
<span *ngFor="let category of categories" class="pt-badge badge-primary">{{ category }}</span>
|
||||
|
||||
<div class="mt-2">
|
||||
<div class="block">{{ shortDescription }}</div>
|
||||
<span *ngFor="let language of languages" class="pt-badge badge-secondary">{{ language }}</span>
|
||||
</div>
|
||||
|
||||
<div i18n *ngIf="isNSFW" class="block mt-4 fw-semibold">This instance is dedicated to sensitive/NSFW content.</div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<div class="block">{{ shortDescription }}</div>
|
||||
|
||||
<div class="anchor" id="administrators-and-sustainability"></div>
|
||||
<a
|
||||
*ngIf="aboutHTML.administrator || aboutHTML.maintenanceLifetime || aboutHTML.businessModel"
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="administrators-and-sustainability"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)"
|
||||
>
|
||||
<h2 i18n class="middle-title">
|
||||
ADMINISTRATORS & SUSTAINABILITY
|
||||
</h2>
|
||||
</a>
|
||||
<div i18n *ngIf="isNSFW" class="block mt-4 fw-semibold">This instance is dedicated to sensitive/NSFW content.</div>
|
||||
</div>
|
||||
|
||||
<div class="block administrator" *ngIf="aboutHTML.administrator">
|
||||
<div class="anchor" id="administrators"></div>
|
||||
<div class="anchor" id="administrators-and-sustainability"></div>
|
||||
<a
|
||||
*ngIf="aboutHTML.administrator || aboutHTML.maintenanceLifetime || aboutHTML.businessModel"
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="administrators"
|
||||
fragment="administrators-and-sustainability"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Who we are</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.administrator"></div>
|
||||
</div>
|
||||
|
||||
<div class="block creation-reason" *ngIf="aboutHTML.creationReason">
|
||||
<div class="anchor" id="creation-reason"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="creation-reason"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Why we created this instance</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.creationReason"></div>
|
||||
</div>
|
||||
|
||||
<div class="block maintenance-lifetime" *ngIf="aboutHTML.maintenanceLifetime">
|
||||
<div class="anchor" id="maintenance-lifetime"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="maintenance-lifetime"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">How long we plan to maintain this instance</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.maintenanceLifetime"></div>
|
||||
</div>
|
||||
|
||||
<div class="block business-model" *ngIf="aboutHTML.businessModel">
|
||||
<div class="anchor" id="business-model"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="business-model"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">How we will pay for keeping our instance running</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.businessModel"></div>
|
||||
</div>
|
||||
|
||||
<div class="anchor" id="information"></div>
|
||||
<a
|
||||
*ngIf="descriptionElement"
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="information"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h2 i18n class="middle-title">
|
||||
INFORMATION
|
||||
</h2>
|
||||
</a>
|
||||
|
||||
<div class="block description">
|
||||
<div class="anchor" id="description"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="description"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Description</h3>
|
||||
</a>
|
||||
|
||||
<my-custom-markup-container [content]="descriptionElement"></my-custom-markup-container>
|
||||
</div>
|
||||
|
||||
<div myPluginSelector pluginSelectorId="about-instance-moderation">
|
||||
<div class="anchor" id="moderation"></div>
|
||||
<a
|
||||
*ngIf="aboutHTML.moderationInformation || aboutHTML.codeOfConduct || aboutHTML.terms"
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="moderation"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
(click)="onClickCopyLink(anchorLink)"
|
||||
>
|
||||
<h2 i18n class="middle-title">
|
||||
MODERATION
|
||||
ADMINISTRATORS & SUSTAINABILITY
|
||||
</h2>
|
||||
</a>
|
||||
|
||||
<div class="block moderation-information" *ngIf="aboutHTML.moderationInformation">
|
||||
<div class="anchor" id="moderation-information"></div>
|
||||
<div class="block administrator" *ngIf="aboutHTML.administrator">
|
||||
<div class="anchor" id="administrators"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="moderation-information"
|
||||
fragment="administrators"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Moderation information</h3>
|
||||
<h3 i18n class="section-title">Who we are</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.moderationInformation"></div>
|
||||
<div [innerHTML]="aboutHTML.administrator"></div>
|
||||
</div>
|
||||
|
||||
<div class="block code-of-conduct" *ngIf="aboutHTML.codeOfConduct">
|
||||
<div class="anchor" id="code-of-conduct"></div>
|
||||
<div class="block creation-reason" *ngIf="aboutHTML.creationReason">
|
||||
<div class="anchor" id="creation-reason"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="code-of-conduct"
|
||||
fragment="creation-reason"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Code of conduct</h3>
|
||||
<h3 i18n class="section-title">Why we created this instance</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.codeOfConduct"></div>
|
||||
<div [innerHTML]="aboutHTML.creationReason"></div>
|
||||
</div>
|
||||
|
||||
<div class="block terms">
|
||||
<div class="anchor" id="terms"></div>
|
||||
<div class="block maintenance-lifetime" *ngIf="aboutHTML.maintenanceLifetime">
|
||||
<div class="anchor" id="maintenance-lifetime"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="terms"
|
||||
fragment="maintenance-lifetime"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Terms</h3>
|
||||
<h3 i18n class="section-title">How long we plan to maintain this instance</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.terms"></div>
|
||||
<div [innerHTML]="aboutHTML.maintenanceLifetime"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div myPluginSelector pluginSelectorId="about-instance-other-information">
|
||||
<div class="anchor" id="other-information"></div>
|
||||
<div class="block business-model" *ngIf="aboutHTML.businessModel">
|
||||
<div class="anchor" id="business-model"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="business-model"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">How we will pay for keeping our instance running</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.businessModel"></div>
|
||||
</div>
|
||||
|
||||
<div class="anchor" id="information"></div>
|
||||
<a
|
||||
*ngIf="aboutHTML.hardwareInformation"
|
||||
*ngIf="descriptionElement"
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="other-information"
|
||||
fragment="information"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h2 i18n class="middle-title">
|
||||
OTHER INFORMATION
|
||||
INFORMATION
|
||||
</h2>
|
||||
</a>
|
||||
|
||||
<div class="block hardware-information" *ngIf="aboutHTML.hardwareInformation">
|
||||
<div class="anchor" id="hardware-information"></div>
|
||||
<div class="block description">
|
||||
<div class="anchor" id="description"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="hardware-information"
|
||||
fragment="description"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Hardware information</h3>
|
||||
<h3 i18n class="section-title">Description</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.hardwareInformation"></div>
|
||||
<my-custom-markup-container [content]="descriptionElement"></my-custom-markup-container>
|
||||
</div>
|
||||
|
||||
<div myPluginSelector pluginSelectorId="about-instance-moderation">
|
||||
<div class="anchor" id="moderation"></div>
|
||||
<a
|
||||
*ngIf="aboutHTML.moderationInformation || aboutHTML.codeOfConduct || aboutHTML.terms"
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="moderation"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h2 i18n class="middle-title">
|
||||
MODERATION
|
||||
</h2>
|
||||
</a>
|
||||
|
||||
<div class="block moderation-information" *ngIf="aboutHTML.moderationInformation">
|
||||
<div class="anchor" id="moderation-information"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="moderation-information"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Moderation information</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.moderationInformation"></div>
|
||||
</div>
|
||||
|
||||
<div class="block code-of-conduct" *ngIf="aboutHTML.codeOfConduct">
|
||||
<div class="anchor" id="code-of-conduct"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="code-of-conduct"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Code of conduct</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.codeOfConduct"></div>
|
||||
</div>
|
||||
|
||||
<div class="block terms">
|
||||
<div class="anchor" id="terms"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="terms"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Terms</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.terms"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div myPluginSelector pluginSelectorId="about-instance-other-information">
|
||||
<div class="anchor" id="other-information"></div>
|
||||
<a
|
||||
*ngIf="aboutHTML.hardwareInformation"
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="other-information"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h2 i18n class="middle-title">
|
||||
OTHER INFORMATION
|
||||
</h2>
|
||||
</a>
|
||||
|
||||
<div class="block hardware-information" *ngIf="aboutHTML.hardwareInformation">
|
||||
<div class="anchor" id="hardware-information"></div>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="hardware-information"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h3 i18n class="section-title">Hardware information</h3>
|
||||
</a>
|
||||
|
||||
<div [innerHTML]="aboutHTML.hardwareInformation"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 col-xl-6" myPluginSelector pluginSelectorId="about-instance-features">
|
||||
<h2 class="visually-hidden" i18n>FEATURES</h2>
|
||||
<my-instance-features-table></my-instance-features-table>
|
||||
</div>
|
||||
<div class="col-md-12 col-xl-6" myPluginSelector pluginSelectorId="about-instance-features">
|
||||
<h2 class="visually-hidden" i18n>FEATURES</h2>
|
||||
<my-instance-features-table></my-instance-features-table>
|
||||
</div>
|
||||
|
||||
<div class="col" myPluginSelector pluginSelectorId="about-instance-statistics">
|
||||
<div class="anchor" id="statistics"></div>
|
||||
<div class="col" myPluginSelector pluginSelectorId="about-instance-statistics">
|
||||
<div class="anchor" id="statistics"></div>
|
||||
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="statistics"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h2 i18n class="middle-title">STATISTICS</h2>
|
||||
</a>
|
||||
<a
|
||||
class="anchor-link"
|
||||
routerLink="/about/instance"
|
||||
fragment="statistics"
|
||||
#anchorLink
|
||||
(click)="onClickCopyLink(anchorLink)">
|
||||
<h2 i18n class="middle-title">STATISTICS</h2>
|
||||
</a>
|
||||
|
||||
<my-instance-statistics [serverStats]="serverStats"></my-instance-statistics>
|
||||
<my-instance-statistics [serverStats]="serverStats"></my-instance-statistics>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,17 +1,33 @@
|
|||
import { ViewportScroller } from '@angular/common'
|
||||
import { NgFor, NgIf, ViewportScroller } from '@angular/common'
|
||||
import { AfterViewChecked, Component, ElementRef, OnInit, ViewChild } from '@angular/core'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
import { ActivatedRoute, RouterLink } from '@angular/router'
|
||||
import { Notifier, ServerService } from '@app/core'
|
||||
import { AboutHTML } from '@app/shared/shared-instance'
|
||||
import { AboutHTML } from '@app/shared/shared-main/instance/instance.service'
|
||||
import { maxBy } from '@peertube/peertube-core-utils'
|
||||
import { HTMLServerConfig, ServerStats } from '@peertube/peertube-models'
|
||||
import { copyToClipboard } from '@root-helpers/utils'
|
||||
import { CustomMarkupContainerComponent } from '../../shared/shared-custom-markup/custom-markup-container.component'
|
||||
import { InstanceFeaturesTableComponent } from '../../shared/shared-instance/instance-features-table.component'
|
||||
import { PluginSelectorDirective } from '../../shared/shared-main/plugins/plugin-selector.directive'
|
||||
import { ResolverData } from './about-instance.resolver'
|
||||
import { ContactAdminModalComponent } from './contact-admin-modal.component'
|
||||
import { InstanceStatisticsComponent } from './instance-statistics.component'
|
||||
|
||||
@Component({
|
||||
selector: 'my-about-instance',
|
||||
templateUrl: './about-instance.component.html',
|
||||
styleUrls: [ './about-instance.component.scss' ]
|
||||
styleUrls: [ './about-instance.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgIf,
|
||||
RouterLink,
|
||||
NgFor,
|
||||
CustomMarkupContainerComponent,
|
||||
PluginSelectorDirective,
|
||||
InstanceFeaturesTableComponent,
|
||||
InstanceStatisticsComponent,
|
||||
ContactAdminModalComponent
|
||||
]
|
||||
})
|
||||
export class AboutInstanceComponent implements OnInit, AfterViewChecked {
|
||||
@ViewChild('descriptionWrapper') descriptionWrapper: ElementRef<HTMLInputElement>
|
||||
|
@ -20,6 +36,8 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked {
|
|||
aboutHTML: AboutHTML
|
||||
descriptionElement: HTMLDivElement
|
||||
|
||||
instanceBannerUrl: string
|
||||
|
||||
languages: string[] = []
|
||||
categories: string[] = []
|
||||
shortDescription = ''
|
||||
|
@ -64,6 +82,10 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked {
|
|||
|
||||
this.shortDescription = about.instance.shortDescription
|
||||
|
||||
this.instanceBannerUrl = about.instance.banners.length !== 0
|
||||
? maxBy(about.instance.banners, 'width').path
|
||||
: undefined
|
||||
|
||||
this.serverConfig = this.serverService.getHTMLConfig()
|
||||
|
||||
this.route.data.subscribe(data => {
|
||||
|
|
|
@ -2,9 +2,9 @@ import { forkJoin, Observable } from 'rxjs'
|
|||
import { map, switchMap } from 'rxjs/operators'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ServerService } from '@app/core'
|
||||
import { CustomMarkupService } from '@app/shared/shared-custom-markup'
|
||||
import { AboutHTML, InstanceService } from '@app/shared/shared-instance'
|
||||
import { About, ServerStats } from '@peertube/peertube-models'
|
||||
import { AboutHTML, InstanceService } from '@app/shared/shared-main/instance/instance.service'
|
||||
import { CustomMarkupService } from '@app/shared/shared-custom-markup/custom-markup.service'
|
||||
|
||||
export type ResolverData = {
|
||||
serverStats: ServerStats
|
||||
|
|
|
@ -7,11 +7,15 @@ import {
|
|||
FROM_NAME_VALIDATOR,
|
||||
SUBJECT_VALIDATOR
|
||||
} from '@app/shared/form-validators/instance-validators'
|
||||
import { FormReactive, FormReactiveService } from '@app/shared/shared-forms'
|
||||
import { InstanceService } from '@app/shared/shared-instance'
|
||||
import { FormReactive } from '@app/shared/shared-forms/form-reactive'
|
||||
import { FormReactiveService } from '@app/shared/shared-forms/form-reactive.service'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
|
||||
import { HTMLServerConfig, HttpStatusCode } from '@peertube/peertube-models'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { NgIf, NgClass } from '@angular/common'
|
||||
import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component'
|
||||
import { InstanceService } from '@app/shared/shared-main/instance/instance.service'
|
||||
|
||||
type Prefill = {
|
||||
subject?: string
|
||||
|
@ -21,7 +25,9 @@ type Prefill = {
|
|||
@Component({
|
||||
selector: 'my-contact-admin-modal',
|
||||
templateUrl: './contact-admin-modal.component.html',
|
||||
styleUrls: [ './contact-admin-modal.component.scss' ]
|
||||
styleUrls: [ './contact-admin-modal.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [ GlobalIconComponent, NgIf, FormsModule, ReactiveFormsModule, NgClass ]
|
||||
})
|
||||
export class ContactAdminModalComponent extends FormReactive implements OnInit {
|
||||
@ViewChild('modal', { static: true }) modal: NgbModal
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import { Component, Input } from '@angular/core'
|
||||
import { ServerStats } from '@peertube/peertube-models'
|
||||
import { BytesPipe } from '../../shared/shared-main/angular/bytes.pipe'
|
||||
import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component'
|
||||
import { NgIf, DecimalPipe } from '@angular/common'
|
||||
|
||||
@Component({
|
||||
selector: 'my-instance-statistics',
|
||||
templateUrl: './instance-statistics.component.html',
|
||||
styleUrls: [ './instance-statistics.component.scss' ]
|
||||
styleUrls: [ './instance-statistics.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [ NgIf, GlobalIconComponent, DecimalPipe, BytesPipe ]
|
||||
})
|
||||
export class InstanceStatisticsComponent {
|
||||
@Input() serverStats: ServerStats
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="root">
|
||||
<div class="margin-content mt-4">
|
||||
<h1 i18n class="fs-3 text-center fw-semibold mb-3">
|
||||
This website is powered by PeerTube
|
||||
</h1>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
@use '_variables' as *;
|
||||
@use '_mixins' as *;
|
||||
|
||||
.root {
|
||||
.margin-content {
|
||||
max-width: 1200px;
|
||||
margin: auto;
|
||||
margin-inline-start: auto;
|
||||
margin-inline-end: auto;
|
||||
}
|
||||
|
||||
.card {
|
||||
|
|
|
@ -4,7 +4,8 @@ import { ViewportScroller } from '@angular/common'
|
|||
@Component({
|
||||
selector: 'my-about-peertube',
|
||||
templateUrl: './about-peertube.component.html',
|
||||
styleUrls: [ './about-peertube.component.scss' ]
|
||||
styleUrls: [ './about-peertube.component.scss' ],
|
||||
standalone: true
|
||||
})
|
||||
|
||||
export class AboutPeertubeComponent implements AfterViewChecked {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div>
|
||||
<div class="sub-menu" [ngClass]="{ 'sub-menu-fixed': !isBroadcastMessageDisplayed }">
|
||||
<div class="sub-menu mb-0" [ngClass]="{ 'sub-menu-fixed': !isBroadcastMessageDisplayed }">
|
||||
<a myPluginSelector pluginSelectorId="about-menu-instance" i18n routerLink="instance" routerLinkActive="active" class="sub-menu-entry">Instance</a>
|
||||
|
||||
<a myPluginSelector pluginSelectorId="about-menu-peertube" i18n routerLink="peertube" routerLinkActive="active" class="sub-menu-entry">PeerTube</a>
|
||||
|
@ -7,7 +7,7 @@
|
|||
<a myPluginSelector pluginSelectorId="about-menu-network" i18n routerLink="follows" routerLinkActive="active" class="sub-menu-entry">Network</a>
|
||||
</div>
|
||||
|
||||
<div class="margin-content" [ngClass]="{ 'offset-content': !isBroadcastMessageDisplayed }">
|
||||
<div [ngClass]="{ 'sub-menu-offset-content': !isBroadcastMessageDisplayed }">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
import { Component } from '@angular/core'
|
||||
import { ScreenService } from '@app/core'
|
||||
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router'
|
||||
import { PluginSelectorDirective } from '../shared/shared-main/plugins/plugin-selector.directive'
|
||||
import { NgClass } from '@angular/common'
|
||||
|
||||
@Component({
|
||||
selector: 'my-about',
|
||||
templateUrl: './about.component.html'
|
||||
templateUrl: './about.component.html',
|
||||
standalone: true,
|
||||
imports: [ NgClass, PluginSelectorDirective, RouterLink, RouterLinkActive, RouterOutlet ]
|
||||
})
|
||||
|
||||
export class AboutComponent {
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
import { NgModule } from '@angular/core'
|
||||
import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component'
|
||||
import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component'
|
||||
import { AboutInstanceResolver } from '@app/+about/about-instance/about-instance.resolver'
|
||||
import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component'
|
||||
import { InstanceStatisticsComponent } from '@app/+about/about-instance/instance-statistics.component'
|
||||
import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component'
|
||||
import { SharedCustomMarkupModule } from '@app/shared/shared-custom-markup'
|
||||
import { SharedFormModule } from '@app/shared/shared-forms'
|
||||
import { SharedGlobalIconModule } from '@app/shared/shared-icons'
|
||||
import { SharedInstanceModule } from '@app/shared/shared-instance'
|
||||
import { SharedMainModule } from '@app/shared/shared-main'
|
||||
import { AboutRoutingModule } from './about-routing.module'
|
||||
import { AboutComponent } from './about.component'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
AboutRoutingModule,
|
||||
|
||||
SharedMainModule,
|
||||
SharedFormModule,
|
||||
SharedInstanceModule,
|
||||
SharedGlobalIconModule,
|
||||
SharedCustomMarkupModule
|
||||
],
|
||||
|
||||
declarations: [
|
||||
AboutComponent,
|
||||
|
||||
AboutInstanceComponent,
|
||||
ContactAdminModalComponent,
|
||||
InstanceStatisticsComponent,
|
||||
|
||||
AboutPeertubeComponent,
|
||||
AboutFollowsComponent
|
||||
],
|
||||
|
||||
exports: [
|
||||
AboutComponent
|
||||
],
|
||||
|
||||
providers: [
|
||||
AboutInstanceResolver
|
||||
]
|
||||
})
|
||||
export class AboutModule { }
|
|
@ -1,3 +0,0 @@
|
|||
export * from './about-routing.module'
|
||||
export * from './about.component'
|
||||
export * from './about.module'
|
|
@ -1,15 +1,23 @@
|
|||
import { NgModule } from '@angular/core'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { Routes } from '@angular/router'
|
||||
import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component'
|
||||
import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component'
|
||||
import { AboutInstanceResolver } from '@app/+about/about-instance/about-instance.resolver'
|
||||
import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component'
|
||||
import { AboutComponent } from './about.component'
|
||||
import { CustomMarkupService } from '@app/shared/shared-custom-markup/custom-markup.service'
|
||||
import { DynamicElementService } from '@app/shared/shared-custom-markup/dynamic-element.service'
|
||||
import { InstanceFollowService } from '@app/shared/shared-instance/instance-follow.service'
|
||||
|
||||
const aboutRoutes: Routes = [
|
||||
export default [
|
||||
{
|
||||
path: '',
|
||||
component: AboutComponent,
|
||||
providers: [
|
||||
AboutInstanceResolver,
|
||||
InstanceFollowService,
|
||||
CustomMarkupService,
|
||||
DynamicElementService
|
||||
],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
|
@ -61,10 +69,4 @@ const aboutRoutes: Routes = [
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(aboutRoutes) ],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class AboutRoutingModule {}
|
||||
] satisfies Routes
|
|
@ -55,7 +55,7 @@
|
|||
}
|
||||
|
||||
.description-html {
|
||||
@include fade-text(30px, pvar(--channelBackgroundColor));
|
||||
@include fade-text(50px, pvar(--channelBackgroundColor));
|
||||
|
||||
grid-column: 2 / 4;
|
||||
grid-row: 2;
|
||||
|
@ -87,7 +87,7 @@ my-subscribe-button {
|
|||
|
||||
.videos-overflow-workaround {
|
||||
@include margin-top(2rem);
|
||||
|
||||
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,14 +3,26 @@ import { concatMap, map, switchMap, tap } from 'rxjs/operators'
|
|||
import { Component, OnDestroy, OnInit } from '@angular/core'
|
||||
import { ComponentPagination, hasMoreItems, MarkdownService, User, UserService } from '@app/core'
|
||||
import { SimpleMemoize } from '@app/helpers'
|
||||
import { Account, AccountService, Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
|
||||
import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature'
|
||||
import { NSFWPolicyType, VideoSortField } from '@peertube/peertube-models'
|
||||
import { MiniatureDisplayOptions, VideoMiniatureComponent } from '../../shared/shared-video-miniature/video-miniature.component'
|
||||
import { SubscribeButtonComponent } from '../../shared/shared-user-subscription/subscribe-button.component'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component'
|
||||
import { InfiniteScrollerDirective } from '../../shared/shared-main/angular/infinite-scroller.directive'
|
||||
import { NgIf, NgFor } from '@angular/common'
|
||||
import { AccountService } from '@app/shared/shared-main/account/account.service'
|
||||
import { VideoChannelService } from '@app/shared/shared-main/video-channel/video-channel.service'
|
||||
import { VideoService } from '@app/shared/shared-main/video/video.service'
|
||||
import { VideoChannel } from '@app/shared/shared-main/video-channel/video-channel.model'
|
||||
import { Account } from '@app/shared/shared-main/account/account.model'
|
||||
import { Video } from '@app/shared/shared-main/video/video.model'
|
||||
|
||||
@Component({
|
||||
selector: 'my-account-video-channels',
|
||||
templateUrl: './account-video-channels.component.html',
|
||||
styleUrls: [ './account-video-channels.component.scss' ]
|
||||
styleUrls: [ './account-video-channels.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [ NgIf, InfiniteScrollerDirective, NgFor, ActorAvatarComponent, RouterLink, SubscribeButtonComponent, VideoMiniatureComponent ]
|
||||
})
|
||||
export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
|
||||
account: Account
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<my-videos-list
|
||||
#videosList
|
||||
|
||||
*ngIf="account"
|
||||
|
||||
[title]="title"
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
import { Subscription } from 'rxjs'
|
||||
import { first } from 'rxjs/operators'
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core'
|
||||
import { NgIf } from '@angular/common'
|
||||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
|
||||
import { ComponentPaginationLight, DisableForReuseHook, ScreenService } from '@app/core'
|
||||
import { Account, AccountService, VideoService } from '@app/shared/shared-main'
|
||||
import { VideoFilters } from '@app/shared/shared-video-miniature'
|
||||
import { Account } from '@app/shared/shared-main/account/account.model'
|
||||
import { AccountService } from '@app/shared/shared-main/account/account.service'
|
||||
import { VideoService } from '@app/shared/shared-main/video/video.service'
|
||||
import { VideoFilters } from '@app/shared/shared-video-miniature/video-filters.model'
|
||||
import { VideoSortField } from '@peertube/peertube-models'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { VideosListComponent } from '../../shared/shared-video-miniature/videos-list.component'
|
||||
|
||||
@Component({
|
||||
selector: 'my-account-videos',
|
||||
templateUrl: './account-videos.component.html'
|
||||
templateUrl: './account-videos.component.html',
|
||||
standalone: true,
|
||||
imports: [ NgIf, VideosListComponent ]
|
||||
})
|
||||
export class AccountVideosComponent implements OnInit, OnDestroy, DisableForReuseHook {
|
||||
@ViewChild('videosList') videosList: VideosListComponent
|
||||
|
||||
getVideosObservableFunction = this.getVideosObservable.bind(this)
|
||||
getSyndicationItemsFunction = this.getSyndicationItems.bind(this)
|
||||
|
||||
|
@ -20,6 +27,8 @@ export class AccountVideosComponent implements OnInit, OnDestroy, DisableForReus
|
|||
account: Account
|
||||
disabled = false
|
||||
|
||||
private alreadyLoaded = false
|
||||
|
||||
private accountSub: Subscription
|
||||
|
||||
constructor (
|
||||
|
@ -31,8 +40,13 @@ export class AccountVideosComponent implements OnInit, OnDestroy, DisableForReus
|
|||
|
||||
ngOnInit () {
|
||||
// Parent get the account for us
|
||||
this.accountService.accountLoaded.pipe(first())
|
||||
.subscribe(account => this.account = account)
|
||||
this.accountSub = this.accountService.accountLoaded
|
||||
.subscribe(account => {
|
||||
this.account = account
|
||||
if (this.alreadyLoaded) this.videosList.reloadVideos()
|
||||
|
||||
this.alreadyLoaded = true
|
||||
})
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="account-info d-md-grid d-block">
|
||||
|
||||
<div class="account-avatar-row">
|
||||
<my-actor-avatar class="main-avatar" actorType="account" [actor]="account"></my-actor-avatar>
|
||||
<my-actor-avatar [size]="getAccountAvatarSize()" actorType="account" [actor]="account"></my-actor-avatar>
|
||||
|
||||
<div>
|
||||
<div class="section-label" i18n>ACCOUNT</div>
|
||||
|
@ -24,7 +24,7 @@
|
|||
</div>
|
||||
|
||||
<div class="actor-handle">
|
||||
<span>@{{ account.nameWithHost }}</span>
|
||||
<span>@{{ account.nameWithHost }}</span>
|
||||
|
||||
<my-copy-button
|
||||
[value]="account.nameWithHostForced" i18n-notification notification="Username copied"
|
||||
|
|
|
@ -1,23 +1,48 @@
|
|||
import { Subscription } from 'rxjs'
|
||||
import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators'
|
||||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import { ActivatedRoute, Router, RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router'
|
||||
import { AuthService, MarkdownService, Notifier, RedirectService, RestExtractor, ScreenService, UserService } from '@app/core'
|
||||
import {
|
||||
Account,
|
||||
AccountService,
|
||||
DropdownAction,
|
||||
ListOverflowItem,
|
||||
VideoChannel,
|
||||
VideoChannelService,
|
||||
VideoService
|
||||
} from '@app/shared/shared-main'
|
||||
import { AccountReportComponent, BlocklistService } from '@app/shared/shared-moderation'
|
||||
import { HttpStatusCode, User, UserRight } from '@peertube/peertube-models'
|
||||
import { SimpleSearchInputComponent } from '../shared/shared-main/misc/simple-search-input.component'
|
||||
import { ListOverflowComponent, ListOverflowItem } from '../shared/shared-main/misc/list-overflow.component'
|
||||
import { SubscribeButtonComponent } from '../shared/shared-user-subscription/subscribe-button.component'
|
||||
import { CopyButtonComponent } from '../shared/shared-main/buttons/copy-button.component'
|
||||
import { AccountBlockBadgesComponent } from '../shared/shared-moderation/account-block-badges.component'
|
||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { UserModerationDropdownComponent } from '../shared/shared-moderation/user-moderation-dropdown.component'
|
||||
import { ActorAvatarComponent } from '../shared/shared-actor-image/actor-avatar.component'
|
||||
import { NgIf, NgClass, DatePipe } from '@angular/common'
|
||||
import { AccountService } from '@app/shared/shared-main/account/account.service'
|
||||
import { DropdownAction } from '@app/shared/shared-main/buttons/action-dropdown.component'
|
||||
import { VideoChannelService } from '@app/shared/shared-main/video-channel/video-channel.service'
|
||||
import { VideoService } from '@app/shared/shared-main/video/video.service'
|
||||
import { Account } from '@app/shared/shared-main/account/account.model'
|
||||
import { VideoChannel } from '@app/shared/shared-main/video-channel/video-channel.model'
|
||||
import { BlocklistService } from '@app/shared/shared-moderation/blocklist.service'
|
||||
import { AccountReportComponent } from '@app/shared/shared-moderation/report-modals'
|
||||
|
||||
@Component({
|
||||
templateUrl: './accounts.component.html',
|
||||
styleUrls: [ './accounts.component.scss' ]
|
||||
styleUrls: [ './accounts.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgIf,
|
||||
ActorAvatarComponent,
|
||||
UserModerationDropdownComponent,
|
||||
NgbTooltip,
|
||||
AccountBlockBadgesComponent,
|
||||
CopyButtonComponent,
|
||||
NgClass,
|
||||
RouterLink,
|
||||
SubscribeButtonComponent,
|
||||
RouterLinkActive,
|
||||
ListOverflowComponent,
|
||||
SimpleSearchInputComponent,
|
||||
RouterOutlet,
|
||||
AccountReportComponent,
|
||||
DatePipe
|
||||
]
|
||||
})
|
||||
export class AccountsComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('accountReportModal') accountReportModal: AccountReportComponent
|
||||
|
@ -101,6 +126,12 @@ export class AccountsComponent implements OnInit, OnDestroy {
|
|||
return this.screenService.isInSmallView()
|
||||
}
|
||||
|
||||
getAccountAvatarSize () {
|
||||
if (this.isInSmallView()) return 80
|
||||
|
||||
return 120
|
||||
}
|
||||
|
||||
isManageable () {
|
||||
if (!this.isUserLoggedIn()) return false
|
||||
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
import { NgModule } from '@angular/core'
|
||||
import { SharedFormModule } from '@app/shared/shared-forms'
|
||||
import { SharedGlobalIconModule } from '@app/shared/shared-icons'
|
||||
import { SharedMainModule } from '@app/shared/shared-main'
|
||||
import { SharedModerationModule } from '@app/shared/shared-moderation'
|
||||
import { SharedUserSubscriptionModule } from '@app/shared/shared-user-subscription'
|
||||
import { SharedVideoMiniatureModule } from '@app/shared/shared-video-miniature'
|
||||
import { SharedActorImageModule } from '../shared/shared-actor-image/shared-actor-image.module'
|
||||
import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component'
|
||||
import { AccountVideosComponent } from './account-videos/account-videos.component'
|
||||
import { AccountsRoutingModule } from './accounts-routing.module'
|
||||
import { AccountsComponent } from './accounts.component'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
AccountsRoutingModule,
|
||||
|
||||
SharedMainModule,
|
||||
SharedFormModule,
|
||||
SharedUserSubscriptionModule,
|
||||
SharedModerationModule,
|
||||
SharedVideoMiniatureModule,
|
||||
SharedGlobalIconModule,
|
||||
SharedActorImageModule
|
||||
],
|
||||
|
||||
declarations: [
|
||||
AccountsComponent,
|
||||
AccountVideosComponent,
|
||||
AccountVideoChannelsComponent
|
||||
],
|
||||
|
||||
exports: [
|
||||
AccountsComponent
|
||||
],
|
||||
|
||||
providers: []
|
||||
})
|
||||
export class AccountsModule { }
|
|
@ -1,3 +0,0 @@
|
|||
export * from './accounts-routing.module'
|
||||
export * from './accounts.component'
|
||||
export * from './accounts.module'
|
|
@ -1,10 +1,16 @@
|
|||
import { NgModule } from '@angular/core'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { Routes } from '@angular/router'
|
||||
import { AbuseService } from '@app/shared/shared-moderation/abuse.service'
|
||||
import { BlocklistService } from '@app/shared/shared-moderation/blocklist.service'
|
||||
import { BulkService } from '@app/shared/shared-moderation/bulk.service'
|
||||
import { VideoBlockService } from '@app/shared/shared-moderation/video-block.service'
|
||||
import { UserSubscriptionService } from '@app/shared/shared-user-subscription/user-subscription.service'
|
||||
import { UserAdminService } from '@app/shared/shared-users/user-admin.service'
|
||||
import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service'
|
||||
import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component'
|
||||
import { AccountVideosComponent } from './account-videos/account-videos.component'
|
||||
import { AccountsComponent } from './accounts.component'
|
||||
|
||||
const accountsRoutes: Routes = [
|
||||
export default [
|
||||
{
|
||||
path: 'peertube',
|
||||
redirectTo: '/videos/local'
|
||||
|
@ -12,6 +18,15 @@ const accountsRoutes: Routes = [
|
|||
{
|
||||
path: ':accountId',
|
||||
component: AccountsComponent,
|
||||
providers: [
|
||||
UserSubscriptionService,
|
||||
BlocklistService,
|
||||
VideoPlaylistService,
|
||||
VideoBlockService,
|
||||
AbuseService,
|
||||
UserAdminService,
|
||||
BulkService
|
||||
],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
|
@ -48,10 +63,4 @@ const accountsRoutes: Routes = [
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(accountsRoutes) ],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class AccountsRoutingModule {}
|
||||
] satisfies Routes
|
|
@ -1,36 +0,0 @@
|
|||
import { NgModule } from '@angular/core'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { ConfigRoutes } from '@app/+admin/config'
|
||||
import { ModerationRoutes } from '@app/+admin/moderation/moderation.routes'
|
||||
import { PluginsRoutes } from '@app/+admin/plugins/plugins.routes'
|
||||
import { SystemRoutes } from '@app/+admin/system'
|
||||
import { AdminComponent } from './admin.component'
|
||||
import { FollowsRoutes } from './follows'
|
||||
import { OverviewRoutes } from './overview'
|
||||
|
||||
const adminRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: AdminComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'users',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
|
||||
...FollowsRoutes,
|
||||
...OverviewRoutes,
|
||||
...ModerationRoutes,
|
||||
...SystemRoutes,
|
||||
...ConfigRoutes,
|
||||
...PluginsRoutes
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(adminRoutes) ],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class AdminRoutingModule {}
|
|
@ -1,7 +1,7 @@
|
|||
<div class="root">
|
||||
<my-top-menu-dropdown [menuEntries]="menuEntries"></my-top-menu-dropdown>
|
||||
|
||||
<div class="margin-content" [ngClass]="{ 'offset-content': !isBroadcastMessageDisplayed }">
|
||||
<div class="margin-content" [ngClass]="{ 'sub-menu-offset-content': !isBroadcastMessageDisplayed }">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import { Component, OnInit } from '@angular/core'
|
||||
import { AuthService, ScreenService, ServerService } from '@app/core'
|
||||
import { ListOverflowItem } from '@app/shared/shared-main'
|
||||
import { TopMenuDropdownParam } from '@app/shared/shared-main/misc/top-menu-dropdown.component'
|
||||
import { UserRight } from '@peertube/peertube-models'
|
||||
import { RouterOutlet } from '@angular/router'
|
||||
import { NgClass } from '@angular/common'
|
||||
import { TopMenuDropdownComponent } from '../shared/shared-main/misc/top-menu-dropdown.component'
|
||||
import { ListOverflowItem } from '@app/shared/shared-main/misc/list-overflow.component'
|
||||
|
||||
@Component({
|
||||
templateUrl: './admin.component.html',
|
||||
styleUrls: [ './admin.component.scss' ]
|
||||
styleUrls: [ './admin.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [ TopMenuDropdownComponent, NgClass, RouterOutlet ]
|
||||
})
|
||||
export class AdminComponent implements OnInit {
|
||||
items: ListOverflowItem[] = []
|
||||
|
@ -57,6 +62,9 @@ export class AdminComponent implements OnInit {
|
|||
overviewItems.children.push({
|
||||
label: $localize`Videos`,
|
||||
routerLink: '/admin/videos',
|
||||
queryParams: {
|
||||
search: 'isLocal:true'
|
||||
},
|
||||
iconName: 'videos'
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,159 +0,0 @@
|
|||
import { ChartModule } from 'primeng/chart'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { NgModule } from '@angular/core'
|
||||
import { SharedAbuseListModule } from '@app/shared/shared-abuse-list'
|
||||
import { SharedActorImageEditModule } from '@app/shared/shared-actor-image-edit'
|
||||
import { SharedActorImageModule } from '@app/shared/shared-actor-image/shared-actor-image.module'
|
||||
import { SharedCustomMarkupModule } from '@app/shared/shared-custom-markup'
|
||||
import { SharedFormModule } from '@app/shared/shared-forms'
|
||||
import { SharedGlobalIconModule } from '@app/shared/shared-icons'
|
||||
import { SharedMainModule } from '@app/shared/shared-main'
|
||||
import { SharedModerationModule } from '@app/shared/shared-moderation'
|
||||
import { SharedTablesModule } from '@app/shared/shared-tables'
|
||||
import { SharedUsersModule } from '@app/shared/shared-users'
|
||||
import { SharedVideoCommentModule } from '@app/shared/shared-video-comment'
|
||||
import { SharedVideoMiniatureModule } from '@app/shared/shared-video-miniature'
|
||||
import { AdminRoutingModule } from './admin-routing.module'
|
||||
import { AdminComponent } from './admin.component'
|
||||
import {
|
||||
EditAdvancedConfigurationComponent,
|
||||
EditBasicConfigurationComponent,
|
||||
EditConfigurationService,
|
||||
EditCustomConfigComponent,
|
||||
EditHomepageComponent,
|
||||
EditInstanceInformationComponent,
|
||||
EditLiveConfigurationComponent,
|
||||
EditVODTranscodingComponent
|
||||
} from './config'
|
||||
import { ConfigService } from './config/shared/config.service'
|
||||
import { FollowersListComponent, FollowModalComponent, VideoRedundanciesListComponent } from './follows'
|
||||
import { FollowingListComponent } from './follows/following-list/following-list.component'
|
||||
import { RedundancyCheckboxComponent } from './follows/shared/redundancy-checkbox.component'
|
||||
import { VideoRedundancyInformationComponent } from './follows/video-redundancies-list/video-redundancy-information.component'
|
||||
import {
|
||||
AbuseListComponent,
|
||||
AdminRegistrationService,
|
||||
ProcessRegistrationModalComponent,
|
||||
RegistrationListComponent,
|
||||
VideoBlockListComponent
|
||||
} from './moderation'
|
||||
import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } from './moderation/instance-blocklist'
|
||||
import {
|
||||
UserCreateComponent,
|
||||
UserListComponent,
|
||||
UserPasswordComponent,
|
||||
UserUpdateComponent,
|
||||
VideoAdminService,
|
||||
VideoCommentListComponent,
|
||||
VideoListComponent
|
||||
} from './overview'
|
||||
import {
|
||||
PluginApiService,
|
||||
PluginCardComponent,
|
||||
PluginListInstalledComponent,
|
||||
PluginNavigationComponent,
|
||||
PluginSearchComponent,
|
||||
PluginShowInstalledComponent
|
||||
} from './plugins'
|
||||
import { SharedAdminModule } from './shared'
|
||||
import {
|
||||
JobService,
|
||||
LogsComponent,
|
||||
LogsService,
|
||||
RunnerJobListComponent,
|
||||
RunnerListComponent,
|
||||
RunnerRegistrationTokenListComponent,
|
||||
RunnerService
|
||||
} from './system'
|
||||
import { DebugComponent, DebugService } from './system/debug'
|
||||
import { JobsComponent } from './system/jobs'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
AdminRoutingModule,
|
||||
|
||||
SharedMainModule,
|
||||
SharedFormModule,
|
||||
SharedModerationModule,
|
||||
SharedGlobalIconModule,
|
||||
SharedAbuseListModule,
|
||||
SharedVideoCommentModule,
|
||||
SharedActorImageModule,
|
||||
SharedActorImageEditModule,
|
||||
SharedCustomMarkupModule,
|
||||
SharedVideoMiniatureModule,
|
||||
SharedTablesModule,
|
||||
SharedUsersModule,
|
||||
SharedAdminModule,
|
||||
|
||||
TableModule,
|
||||
ChartModule
|
||||
],
|
||||
|
||||
declarations: [
|
||||
AdminComponent,
|
||||
|
||||
VideoListComponent,
|
||||
|
||||
FollowersListComponent,
|
||||
FollowingListComponent,
|
||||
FollowModalComponent,
|
||||
RedundancyCheckboxComponent,
|
||||
VideoRedundanciesListComponent,
|
||||
VideoRedundancyInformationComponent,
|
||||
|
||||
UserCreateComponent,
|
||||
UserUpdateComponent,
|
||||
UserPasswordComponent,
|
||||
UserListComponent,
|
||||
|
||||
VideoBlockListComponent,
|
||||
AbuseListComponent,
|
||||
VideoCommentListComponent,
|
||||
|
||||
InstanceServerBlocklistComponent,
|
||||
InstanceAccountBlocklistComponent,
|
||||
|
||||
PluginListInstalledComponent,
|
||||
PluginSearchComponent,
|
||||
PluginShowInstalledComponent,
|
||||
PluginCardComponent,
|
||||
PluginNavigationComponent,
|
||||
|
||||
JobsComponent,
|
||||
LogsComponent,
|
||||
DebugComponent,
|
||||
|
||||
EditCustomConfigComponent,
|
||||
EditBasicConfigurationComponent,
|
||||
EditVODTranscodingComponent,
|
||||
EditLiveConfigurationComponent,
|
||||
EditAdvancedConfigurationComponent,
|
||||
EditInstanceInformationComponent,
|
||||
EditHomepageComponent,
|
||||
|
||||
RegistrationListComponent,
|
||||
ProcessRegistrationModalComponent,
|
||||
|
||||
RunnerRegistrationTokenListComponent,
|
||||
RunnerListComponent,
|
||||
RunnerJobListComponent
|
||||
],
|
||||
|
||||
exports: [
|
||||
AdminComponent
|
||||
],
|
||||
|
||||
providers: [
|
||||
JobService,
|
||||
LogsService,
|
||||
DebugService,
|
||||
ConfigService,
|
||||
PluginApiService,
|
||||
EditConfigurationService,
|
||||
VideoAdminService,
|
||||
AdminRegistrationService,
|
||||
RunnerService
|
||||
]
|
||||
})
|
||||
export class AdminModule { }
|
|
@ -1,15 +1,15 @@
|
|||
<ng-container [formGroup]="form">
|
||||
|
||||
<div class="row mt-5"> <!-- cache grid -->
|
||||
<div class="pt-two-cols mt-5"> <!-- cache grid -->
|
||||
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">CACHE</h2>
|
||||
<div class="title-col">
|
||||
<h2 i18n>CACHE</h2>
|
||||
<div i18n class="inner-form-description">
|
||||
Some files are not federated, and fetched when necessary. Define their caching policies.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
<ng-container formGroupName="cache">
|
||||
<div class="form-group" formGroupName="previews">
|
||||
<label i18n for="cachePreviewsSize">Number of previews to keep in cache</label>
|
||||
|
@ -71,16 +71,16 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- cache grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<div class="pt-two-cols mt-4"> <!-- cache grid -->
|
||||
<div class="title-col">
|
||||
<div class="anchor" id="customizations"></div> <!-- customizations anchor -->
|
||||
<h2 i18n class="inner-form-title">CUSTOMIZATIONS</h2>
|
||||
<h2 i18n>CUSTOMIZATIONS</h2>
|
||||
<div i18n class="inner-form-description">
|
||||
Slight modifications to your PeerTube instance for when creating a plugin or theme is overkill.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
<ng-container formGroupName="instance">
|
||||
<ng-container formGroupName="customizations">
|
||||
<div class="form-group">
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import { Component, Input } from '@angular/core'
|
||||
import { FormGroup } from '@angular/forms'
|
||||
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { PeerTubeTemplateDirective } from '../../../shared/shared-main/angular/peertube-template.directive'
|
||||
import { HelpComponent } from '../../../shared/shared-main/misc/help.component'
|
||||
import { NgClass, NgIf } from '@angular/common'
|
||||
|
||||
@Component({
|
||||
selector: 'my-edit-advanced-configuration',
|
||||
templateUrl: './edit-advanced-configuration.component.html',
|
||||
styleUrls: [ './edit-custom-config.component.scss' ]
|
||||
styleUrls: [ './edit-custom-config.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [ FormsModule, ReactiveFormsModule, NgClass, NgIf, HelpComponent, PeerTubeTemplateDirective ]
|
||||
})
|
||||
export class EditAdvancedConfigurationComponent {
|
||||
@Input() form: FormGroup
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
<ng-container [formGroup]="form">
|
||||
<div class="row mt-5"> <!-- appearance grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">APPEARANCE</h2>
|
||||
<div class="pt-two-cols mt-5"> <!-- appearance grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>APPEARANCE</h2>
|
||||
|
||||
<div i18n class="inner-form-description">
|
||||
Use <a class="link-orange" routerLink="/admin/plugins">plugins & themes</a> for more involved changes, or add slight <a class="link-orange" routerLink="/admin/config/edit-custom" fragment="advanced-configuration">customizations</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="theme">
|
||||
<div class="form-group">
|
||||
|
@ -89,15 +90,15 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- broadcast grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">BROADCAST MESSAGE</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- broadcast grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>BROADCAST MESSAGE</h2>
|
||||
<div i18n class="inner-form-description">
|
||||
Display a message on your instance
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="broadcastMessage">
|
||||
|
||||
|
@ -145,15 +146,15 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- new users grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">NEW USERS</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- new users grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>NEW USERS</h2>
|
||||
<div i18n class="inner-form-description">
|
||||
Manage <a class="link-orange" routerLink="/admin/users">users</a> to set their quota individually.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="signup">
|
||||
<div class="form-group">
|
||||
|
@ -228,7 +229,7 @@
|
|||
[clearable]="false"
|
||||
></my-select-custom-value>
|
||||
|
||||
<my-user-real-quota-info [videoQuota]="getUserVideoQuota()"></my-user-real-quota-info>
|
||||
<my-user-real-quota-info class="mt-2 d-block small muted" [videoQuota]="getUserVideoQuota()"></my-user-real-quota-info>
|
||||
|
||||
<div *ngIf="formErrors.user.videoQuota" class="form-error" role="alert">{{ formErrors.user.videoQuota }}</div>
|
||||
</div>
|
||||
|
@ -262,12 +263,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- videos grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">VIDEOS</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- videos grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>VIDEOS</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="import">
|
||||
|
||||
|
@ -357,15 +358,29 @@
|
|||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-container formGroupName="storyboards">
|
||||
|
||||
<div class="form-group">
|
||||
<my-peertube-checkbox
|
||||
inputName="storyboardsEnabled" formControlName="enabled"
|
||||
i18n-labelText labelText="Enable video storyboards"
|
||||
>
|
||||
<ng-container ngProjectAs="description">
|
||||
<span i18n>Generate storyboards of local videos using ffmpeg so users can see the video preview in the player while scrubbing the video</span>
|
||||
</ng-container>
|
||||
</my-peertube-checkbox>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- video channels grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">VIDEO CHANNELS</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- video channels grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>VIDEO CHANNELS</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
<div class="form-group" formGroupName="videoChannels">
|
||||
<label i18n for="videoChannelsMaxPerUser">Max video channels per user</label>
|
||||
|
||||
|
@ -382,12 +397,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- search grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">SEARCH</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- search grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>SEARCH</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="search">
|
||||
<ng-container formGroupName="remoteUri">
|
||||
|
@ -471,15 +486,91 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- federation grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">FEDERATION</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- import/export grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>USER IMPORT/EXPORT</h2>
|
||||
</div>
|
||||
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="import">
|
||||
<ng-container formGroupName="users">
|
||||
<div class="form-group">
|
||||
<my-peertube-checkbox
|
||||
inputName="importUsersEnabled" formControlName="enabled"
|
||||
i18n-labelText labelText="Allow your users to import a data archive"
|
||||
>
|
||||
<ng-container ngProjectAs="description">
|
||||
<div i18n>Video quota is checked on import so the user doesn't upload a too big archive file</div>
|
||||
<div i18n>Video quota (daily quota is not taken into account) is also checked for each video when PeerTube is processing the import</div>
|
||||
</ng-container>
|
||||
</my-peertube-checkbox>
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-container formGroupName="export">
|
||||
|
||||
<ng-container formGroupName="users">
|
||||
|
||||
<div class="form-group">
|
||||
<my-peertube-checkbox
|
||||
inputName="exportUsersEnabled" formControlName="enabled"
|
||||
i18n-labelText labelText="Allow your users to export their data"
|
||||
>
|
||||
<ng-container ngProjectAs="description">
|
||||
<span i18n>Users can export their PeerTube data in a .zip for backup or re-import. Only one export at a time is allowed per user</span>
|
||||
</ng-container>
|
||||
|
||||
<ng-container ngProjectAs="extra">
|
||||
|
||||
<div class="form-group" [ngClass]="getDisabledExportUsersClass()">
|
||||
<label i18n for="exportUsersMaxUserVideoQuota">Max user video quota allowed to generate the export</label>
|
||||
|
||||
<span i18n class="ms-2 small muted">If the user decides to include the video files in the archive</span>
|
||||
|
||||
<my-select-custom-value
|
||||
id="exportUsersMaxUserVideoQuota"
|
||||
[items]="exportMaxUserVideoQuotaOptions"
|
||||
formControlName="maxUserVideoQuota"
|
||||
i18n-inputSuffix inputSuffix="bytes" inputType="number"
|
||||
[clearable]="false"
|
||||
></my-select-custom-value>
|
||||
|
||||
<div *ngIf="formErrors.export.users.maxUserVideoQuota" class="form-error" role="alert">{{ formErrors.export.users.maxUserVideoQuota }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" [ngClass]="getDisabledExportUsersClass()">
|
||||
<label i18n for="exportUsersExportExpiration">User export expiration</label>
|
||||
|
||||
<my-select-options
|
||||
labelForId="exportUsersExportExpiration" [items]="exportExpirationOptions" formControlName="exportExpiration"
|
||||
bindLabel="label" bindValue="value" [clearable]="false" [searchable]="false"
|
||||
></my-select-options>
|
||||
|
||||
<div i18n class="mt-1 small muted">The archive file is deleted after this period.</div>
|
||||
|
||||
<div *ngIf="formErrors.export.users.exportExpiration" class="form-error" role="alert">{{ formErrors.export.users.exportExpiration }}</div>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
</my-peertube-checkbox>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-two-cols mt-4"> <!-- federation grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>FEDERATION</h2>
|
||||
<div i18n class="inner-form-description">
|
||||
Manage <a class="link-orange" routerLink="/admin/follows">relations</a> with other instances.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="followers">
|
||||
<ng-container formGroupName="instance">
|
||||
|
@ -550,12 +641,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- administrators grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">ADMINISTRATORS</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- administrators grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>ADMINISTRATORS</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<div class="form-group" formGroupName="admin">
|
||||
<label i18n for="adminEmail">Admin email</label>
|
||||
|
@ -578,22 +669,28 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- Twitter grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">TWITTER</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- Twitter grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>TWITTER/X</h2>
|
||||
|
||||
<div i18n class="inner-form-description">
|
||||
Provide the Twitter account representing your instance to improve link previews.
|
||||
If you don't have a Twitter account, just leave the default value.
|
||||
Extra configuration required by Twitter/X. All other social media (Facebook, Mastodon, etc.) are supported out of the box.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="services">
|
||||
<ng-container formGroupName="twitter">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="servicesTwitterUsername" i18n>Your Twitter username</label>
|
||||
<label for="servicesTwitterUsername" i18n>Your Twitter/X username</label>
|
||||
|
||||
<div class="label-small-info">
|
||||
<p i18n class="mb-0">Indicates the Twitter/X account for the website or platform where the content was published.</p>
|
||||
|
||||
<p i18n>This is just an extra information injected in PeerTube HTML that is required by Twitter/X. If you don't have a Twitter/X account, just leave the default value.</p>
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="text" id="servicesTwitterUsername" class="form-control"
|
||||
|
@ -603,29 +700,6 @@
|
|||
<div *ngIf="formErrors.services.twitter.username" class="form-error" role="alert">{{ formErrors.services.twitter.username }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<my-peertube-checkbox inputName="servicesTwitterWhitelisted" formControlName="whitelisted">
|
||||
<ng-template ptTemplate="label">
|
||||
<ng-container i18n>Instance allowed by Twitter/X</ng-container>
|
||||
</ng-template>
|
||||
|
||||
<ng-template ptTemplate="help">
|
||||
<ng-container i18n>
|
||||
<p class="mb-2">
|
||||
If your instance is explicitly allowed by Twitter/X, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
|
||||
If the instance is not, we use an image link card that will redirect to your PeerTube instance.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/w/blabla) on
|
||||
<a class="link-orange" target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a>
|
||||
to see if you instance is allowed.
|
||||
</p>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</my-peertube-checkbox>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
|
|
|
@ -1,15 +1,40 @@
|
|||
import { pairwise } from 'rxjs/operators'
|
||||
import { SelectOptionsItem } from 'src/types/select-options-item.model'
|
||||
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'
|
||||
import { FormGroup } from '@angular/forms'
|
||||
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { MenuService, ThemeService } from '@app/core'
|
||||
import { HTMLServerConfig } from '@peertube/peertube-models'
|
||||
import { ConfigService } from '../shared/config.service'
|
||||
import { PeerTubeTemplateDirective } from '../../../shared/shared-main/angular/peertube-template.directive'
|
||||
import { SelectOptionsComponent } from '../../../shared/shared-forms/select/select-options.component'
|
||||
import { UserRealQuotaInfoComponent } from '../../shared/user-real-quota-info.component'
|
||||
import { MarkdownTextareaComponent } from '../../../shared/shared-forms/markdown-textarea.component'
|
||||
import { HelpComponent } from '../../../shared/shared-main/misc/help.component'
|
||||
import { PeertubeCheckboxComponent } from '../../../shared/shared-forms/peertube-checkbox.component'
|
||||
import { SelectCustomValueComponent } from '../../../shared/shared-forms/select/select-custom-value.component'
|
||||
import { NgFor, NgIf, NgClass } from '@angular/common'
|
||||
import { RouterLink } from '@angular/router'
|
||||
|
||||
@Component({
|
||||
selector: 'my-edit-basic-configuration',
|
||||
templateUrl: './edit-basic-configuration.component.html',
|
||||
styleUrls: [ './edit-custom-config.component.scss' ]
|
||||
styleUrls: [ './edit-custom-config.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
RouterLink,
|
||||
NgFor,
|
||||
SelectCustomValueComponent,
|
||||
NgIf,
|
||||
PeertubeCheckboxComponent,
|
||||
HelpComponent,
|
||||
MarkdownTextareaComponent,
|
||||
NgClass,
|
||||
UserRealQuotaInfoComponent,
|
||||
SelectOptionsComponent,
|
||||
PeerTubeTemplateDirective
|
||||
]
|
||||
})
|
||||
export class EditBasicConfigurationComponent implements OnInit, OnChanges {
|
||||
@Input() form: FormGroup
|
||||
|
@ -21,6 +46,9 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
|
|||
defaultLandingPageOptions: SelectOptionsItem[] = []
|
||||
availableThemes: SelectOptionsItem[]
|
||||
|
||||
exportExpirationOptions: SelectOptionsItem[] = []
|
||||
exportMaxUserVideoQuotaOptions: SelectOptionsItem[] = []
|
||||
|
||||
constructor (
|
||||
private configService: ConfigService,
|
||||
private menuService: MenuService,
|
||||
|
@ -33,6 +61,15 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
|
|||
this.checkImportSyncField()
|
||||
|
||||
this.availableThemes = this.themeService.buildAvailableThemes()
|
||||
|
||||
this.exportExpirationOptions = [
|
||||
{ id: 1000 * 3600 * 24, label: $localize`1 day` },
|
||||
{ id: 1000 * 3600 * 24 * 2, label: $localize`2 days` },
|
||||
{ id: 1000 * 3600 * 24 * 7, label: $localize`7 days` },
|
||||
{ id: 1000 * 3600 * 24 * 30, label: $localize`30 days` }
|
||||
]
|
||||
|
||||
this.exportMaxUserVideoQuotaOptions = this.configService.videoQuotaOptions.filter(o => (o.id as number) >= 1)
|
||||
}
|
||||
|
||||
ngOnChanges (changes: SimpleChanges) {
|
||||
|
@ -64,6 +101,14 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
|
|||
return this.form.value['user']['videoQuota']
|
||||
}
|
||||
|
||||
isExportUsersEnabled () {
|
||||
return this.form.value['export']['users']['enabled'] === true
|
||||
}
|
||||
|
||||
getDisabledExportUsersClass () {
|
||||
return { 'disabled-checkbox-extra': !this.isExportUsersEnabled() }
|
||||
}
|
||||
|
||||
isSignupEnabled () {
|
||||
return this.form.value['signup']['enabled'] === true
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
@use '_mixins' as *;
|
||||
|
||||
$form-base-input-width: 340px;
|
||||
$form-max-width: 500px;
|
||||
|
||||
form {
|
||||
padding-bottom: 1.5rem;
|
||||
|
@ -9,7 +10,7 @@ form {
|
|||
|
||||
my-markdown-textarea {
|
||||
display: block;
|
||||
max-width: 500px;
|
||||
max-width: $form-max-width;
|
||||
}
|
||||
|
||||
.homepage my-markdown-textarea {
|
||||
|
@ -78,10 +79,6 @@ input[type=submit] {
|
|||
}
|
||||
}
|
||||
|
||||
.inner-form-title {
|
||||
@include settings-big-title;
|
||||
}
|
||||
|
||||
.inner-form-description {
|
||||
font-size: 15px;
|
||||
margin-bottom: 15px;
|
||||
|
@ -151,8 +148,7 @@ ngb-tabset:not(.previews) ::ng-deep {
|
|||
}
|
||||
}
|
||||
|
||||
my-user-real-quota-info {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
font-size: 11px;
|
||||
my-actor-banner-edit {
|
||||
max-width: $form-max-width;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ import {
|
|||
ADMIN_EMAIL_VALIDATOR,
|
||||
CACHE_SIZE_VALIDATOR,
|
||||
CONCURRENCY_VALIDATOR,
|
||||
EXPORT_EXPIRATION_VALIDATOR,
|
||||
EXPORT_MAX_USER_VIDEO_QUOTA_VALIDATOR,
|
||||
INDEX_URL_VALIDATOR,
|
||||
INSTANCE_NAME_VALIDATOR,
|
||||
INSTANCE_SHORT_DESCRIPTION_VALIDATOR,
|
||||
|
@ -24,10 +26,20 @@ import {
|
|||
TRANSCODING_THREADS_VALIDATOR
|
||||
} from '@app/shared/form-validators/custom-config-validators'
|
||||
import { USER_VIDEO_QUOTA_DAILY_VALIDATOR, USER_VIDEO_QUOTA_VALIDATOR } from '@app/shared/form-validators/user-validators'
|
||||
import { FormReactive, FormReactiveService } from '@app/shared/shared-forms'
|
||||
import { CustomPageService } from '@app/shared/shared-main/custom-page'
|
||||
import { FormReactive } from '@app/shared/shared-forms/form-reactive'
|
||||
import { FormReactiveService } from '@app/shared/shared-forms/form-reactive.service'
|
||||
import { CustomConfig, CustomPage, HTMLServerConfig } from '@peertube/peertube-models'
|
||||
import { EditConfigurationService } from './edit-configuration.service'
|
||||
import { EditAdvancedConfigurationComponent } from './edit-advanced-configuration.component'
|
||||
import { EditLiveConfigurationComponent } from './edit-live-configuration.component'
|
||||
import { EditVODTranscodingComponent } from './edit-vod-transcoding.component'
|
||||
import { EditBasicConfigurationComponent } from './edit-basic-configuration.component'
|
||||
import { EditInstanceInformationComponent } from './edit-instance-information.component'
|
||||
import { EditHomepageComponent } from './edit-homepage.component'
|
||||
import { NgbNav, NgbNavItem, NgbNavLink, NgbNavLinkBase, NgbNavContent, NgbNavOutlet } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { NgIf, NgFor } from '@angular/common'
|
||||
import { CustomPageService } from '@app/shared/shared-main/custom-page/custom-page.service'
|
||||
|
||||
type ComponentCustomConfig = CustomConfig & {
|
||||
instanceCustomHomepage: CustomPage
|
||||
|
@ -36,7 +48,26 @@ type ComponentCustomConfig = CustomConfig & {
|
|||
@Component({
|
||||
selector: 'my-edit-custom-config',
|
||||
templateUrl: './edit-custom-config.component.html',
|
||||
styleUrls: [ './edit-custom-config.component.scss' ]
|
||||
styleUrls: [ './edit-custom-config.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgIf,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
NgbNav,
|
||||
NgbNavItem,
|
||||
NgbNavLink,
|
||||
NgbNavLinkBase,
|
||||
NgbNavContent,
|
||||
EditHomepageComponent,
|
||||
EditInstanceInformationComponent,
|
||||
EditBasicConfigurationComponent,
|
||||
EditVODTranscodingComponent,
|
||||
EditLiveConfigurationComponent,
|
||||
EditAdvancedConfigurationComponent,
|
||||
NgbNavOutlet,
|
||||
NgFor
|
||||
]
|
||||
})
|
||||
export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||
activeNav: string
|
||||
|
@ -100,8 +131,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
},
|
||||
services: {
|
||||
twitter: {
|
||||
username: SERVICES_TWITTER_USERNAME_VALIDATOR,
|
||||
whitelisted: null
|
||||
username: SERVICES_TWITTER_USERNAME_VALIDATOR
|
||||
}
|
||||
},
|
||||
client: {
|
||||
|
@ -149,6 +179,16 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
},
|
||||
videoChannelSynchronization: {
|
||||
enabled: null
|
||||
},
|
||||
users: {
|
||||
enabled: null
|
||||
}
|
||||
},
|
||||
export: {
|
||||
users: {
|
||||
enabled: null,
|
||||
maxUserVideoQuota: EXPORT_MAX_USER_VIDEO_QUOTA_VALIDATOR,
|
||||
exportExpiration: EXPORT_EXPIRATION_VALIDATOR
|
||||
}
|
||||
},
|
||||
trending: {
|
||||
|
@ -186,6 +226,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
concurrency: CONCURRENCY_VALIDATOR,
|
||||
resolutions: {},
|
||||
alwaysTranscodeOriginalResolution: null,
|
||||
originalFile: {
|
||||
keep: null
|
||||
},
|
||||
hls: {
|
||||
enabled: null
|
||||
},
|
||||
|
@ -274,6 +317,10 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
|||
|
||||
instanceCustomHomepage: {
|
||||
content: null
|
||||
},
|
||||
|
||||
storyboards: {
|
||||
enabled: null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
<ng-container formGroupName="instanceCustomHomepage">
|
||||
|
||||
<div class="homepage row mt-5"> <!-- homepage grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">INSTANCE HOMEPAGE</h2>
|
||||
<div class="homepage pt-two-cols mt-5"> <!-- homepage grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>INSTANCE HOMEPAGE</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<div class="form-group">
|
||||
<label i18n for="instanceCustomHomepageContent">Homepage</label>
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
import { Component, Input } from '@angular/core'
|
||||
import { FormGroup } from '@angular/forms'
|
||||
import { CustomMarkupService } from '@app/shared/shared-custom-markup'
|
||||
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { NgIf } from '@angular/common'
|
||||
import { MarkdownTextareaComponent } from '../../../shared/shared-forms/markdown-textarea.component'
|
||||
import { CustomMarkupHelpComponent } from '../../../shared/shared-custom-markup/custom-markup-help.component'
|
||||
import { CustomMarkupService } from '@app/shared/shared-custom-markup/custom-markup.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-edit-homepage',
|
||||
templateUrl: './edit-homepage.component.html',
|
||||
styleUrls: [ './edit-custom-config.component.scss' ]
|
||||
styleUrls: [ './edit-custom-config.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [ FormsModule, ReactiveFormsModule, CustomMarkupHelpComponent, MarkdownTextareaComponent, NgIf ]
|
||||
})
|
||||
export class EditHomepageComponent {
|
||||
@Input() form: FormGroup
|
||||
|
|
|
@ -2,12 +2,40 @@
|
|||
|
||||
<ng-container formGroupName="instance">
|
||||
|
||||
<div class="row mt-5"> <!-- instance grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">INSTANCE</h2>
|
||||
<div class="pt-two-cols mt-5"> <!-- instance grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>INSTANCE</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
<div class="form-group">
|
||||
<label i18n for="avatarfile">Square icon</label>
|
||||
|
||||
<div class="label-small-info">
|
||||
<p i18n class="mb-0">Square icon can be used on your custom homepage.</p>
|
||||
</div>
|
||||
|
||||
<my-actor-avatar-edit
|
||||
class="d-block mb-4"
|
||||
actorType="account" previewImage="false" [username]="instanceName" displayUsername="false"
|
||||
[avatars]="instanceAvatars" (avatarChange)="onAvatarChange($event)" (avatarDelete)="onAvatarDelete()"
|
||||
></my-actor-avatar-edit>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label i18n for="bannerfile">Banner</label>
|
||||
|
||||
<div class="label-small-info">
|
||||
<p i18n class="mb-0">Banner is displayed in the about, login and registration pages and be used on your custom homepage.</p>
|
||||
<p i18n>It can also be displayed on external websites to promote your instance, such as <a target="_blank" href="https://joinpeertube.org/instances">JoinPeerTube.org</a>.</p>
|
||||
</div>
|
||||
|
||||
<my-actor-banner-edit
|
||||
[previewImage]="false" class="d-block mb-4"
|
||||
[bannerUrl]="instanceBannerUrl" (bannerChange)="onBannerChange($event)" (bannerDelete)="onBannerDelete()"
|
||||
></my-actor-banner-edit>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label i18n for="instanceName">Name</label>
|
||||
|
||||
|
@ -74,15 +102,15 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- moderation & nsfw grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">MODERATION & NSFW</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- moderation & nsfw grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>MODERATION & NSFW</h2>
|
||||
<div i18n class="inner-form-description">
|
||||
Manage <a class="link-orange" routerLink="/admin/users">users</a> to build a moderation team.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
<div class="form-group">
|
||||
<my-peertube-checkbox inputName="instanceIsNSFW" formControlName="isNSFW">
|
||||
<ng-template ptTemplate="label">
|
||||
|
@ -152,12 +180,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- you and your instance grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">YOU AND YOUR INSTANCE</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- you and your instance grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>YOU AND YOUR INSTANCE</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<div class="form-group">
|
||||
<label i18n for="instanceAdministrator">Who is behind the instance?</label><my-help helpType="markdownText"></my-help>
|
||||
|
@ -202,12 +230,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- other information grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">OTHER INFORMATION</h2>
|
||||
<div class="pt-two-cols mt-4"> <!-- other information grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>OTHER INFORMATION</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<div class="form-group">
|
||||
<label i18n for="instanceHardwareInformation">What server/hardware does the instance run on?</label>
|
||||
|
|
|
@ -1,25 +1,144 @@
|
|||
import { NgClass, NgIf } from '@angular/common'
|
||||
import { HttpErrorResponse } from '@angular/common/http'
|
||||
import { Component, Input, OnInit } from '@angular/core'
|
||||
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import { Notifier, ServerService } from '@app/core'
|
||||
import { genericUploadErrorHandler } from '@app/helpers'
|
||||
import { CustomMarkupService } from '@app/shared/shared-custom-markup/custom-markup.service'
|
||||
import { InstanceService } from '@app/shared/shared-main/instance/instance.service'
|
||||
import { maxBy } from '@peertube/peertube-core-utils'
|
||||
import { ActorImage, HTMLServerConfig } from '@peertube/peertube-models'
|
||||
import { SelectOptionsItem } from 'src/types/select-options-item.model'
|
||||
import { Component, Input } from '@angular/core'
|
||||
import { FormGroup } from '@angular/forms'
|
||||
import { CustomMarkupService } from '@app/shared/shared-custom-markup'
|
||||
import { ActorAvatarEditComponent } from '../../../shared/shared-actor-image-edit/actor-avatar-edit.component'
|
||||
import { ActorBannerEditComponent } from '../../../shared/shared-actor-image-edit/actor-banner-edit.component'
|
||||
import { CustomMarkupHelpComponent } from '../../../shared/shared-custom-markup/custom-markup-help.component'
|
||||
import { MarkdownTextareaComponent } from '../../../shared/shared-forms/markdown-textarea.component'
|
||||
import { PeertubeCheckboxComponent } from '../../../shared/shared-forms/peertube-checkbox.component'
|
||||
import { SelectCheckboxComponent } from '../../../shared/shared-forms/select/select-checkbox.component'
|
||||
import { PeerTubeTemplateDirective } from '../../../shared/shared-main/angular/peertube-template.directive'
|
||||
import { HelpComponent } from '../../../shared/shared-main/misc/help.component'
|
||||
|
||||
@Component({
|
||||
selector: 'my-edit-instance-information',
|
||||
templateUrl: './edit-instance-information.component.html',
|
||||
styleUrls: [ './edit-custom-config.component.scss' ]
|
||||
styleUrls: [ './edit-custom-config.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
ActorAvatarEditComponent,
|
||||
ActorBannerEditComponent,
|
||||
NgClass,
|
||||
NgIf,
|
||||
CustomMarkupHelpComponent,
|
||||
MarkdownTextareaComponent,
|
||||
SelectCheckboxComponent,
|
||||
RouterLink,
|
||||
PeertubeCheckboxComponent,
|
||||
PeerTubeTemplateDirective,
|
||||
HelpComponent
|
||||
]
|
||||
})
|
||||
export class EditInstanceInformationComponent {
|
||||
export class EditInstanceInformationComponent implements OnInit {
|
||||
@Input() form: FormGroup
|
||||
@Input() formErrors: any
|
||||
|
||||
@Input() languageItems: SelectOptionsItem[] = []
|
||||
@Input() categoryItems: SelectOptionsItem[] = []
|
||||
|
||||
constructor (private customMarkup: CustomMarkupService) {
|
||||
instanceBannerUrl: string
|
||||
instanceAvatars: ActorImage[] = []
|
||||
|
||||
private serverConfig: HTMLServerConfig
|
||||
|
||||
constructor (
|
||||
private customMarkup: CustomMarkupService,
|
||||
private notifier: Notifier,
|
||||
private instanceService: InstanceService,
|
||||
private server: ServerService
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
get instanceName () {
|
||||
return this.server.getHTMLConfig().instance.name
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
this.serverConfig = this.server.getHTMLConfig()
|
||||
|
||||
this.updateActorImages()
|
||||
}
|
||||
|
||||
getCustomMarkdownRenderer () {
|
||||
return this.customMarkup.getCustomMarkdownRenderer()
|
||||
}
|
||||
|
||||
onBannerChange (formData: FormData) {
|
||||
this.instanceService.updateInstanceBanner(formData)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.notifier.success($localize`Banner changed.`)
|
||||
|
||||
this.resetActorImages()
|
||||
},
|
||||
|
||||
error: (err: HttpErrorResponse) => genericUploadErrorHandler({ err, name: $localize`banner`, notifier: this.notifier })
|
||||
})
|
||||
}
|
||||
|
||||
onBannerDelete () {
|
||||
this.instanceService.deleteInstanceBanner()
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.notifier.success($localize`Banner deleted.`)
|
||||
|
||||
this.resetActorImages()
|
||||
},
|
||||
|
||||
error: err => this.notifier.error(err.message)
|
||||
})
|
||||
}
|
||||
|
||||
onAvatarChange (formData: FormData) {
|
||||
this.instanceService.updateInstanceAvatar(formData)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.notifier.success($localize`Avatar changed.`)
|
||||
|
||||
this.resetActorImages()
|
||||
},
|
||||
|
||||
error: (err: HttpErrorResponse) => genericUploadErrorHandler({ err, name: $localize`avatar`, notifier: this.notifier })
|
||||
})
|
||||
}
|
||||
|
||||
onAvatarDelete () {
|
||||
this.instanceService.deleteInstanceAvatar()
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.notifier.success($localize`Avatar deleted.`)
|
||||
|
||||
this.resetActorImages()
|
||||
},
|
||||
|
||||
error: err => this.notifier.error(err.message)
|
||||
})
|
||||
}
|
||||
|
||||
private updateActorImages () {
|
||||
this.instanceBannerUrl = maxBy(this.serverConfig.instance.banners, 'width')?.path
|
||||
this.instanceAvatars = this.serverConfig.instance.avatars
|
||||
}
|
||||
|
||||
private resetActorImages () {
|
||||
this.server.resetConfig()
|
||||
.subscribe(config => {
|
||||
this.serverConfig = config
|
||||
|
||||
this.updateActorImages()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<ng-container [formGroup]="form">
|
||||
|
||||
<div class="row mt-5">
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">LIVE</h2>
|
||||
<div class="pt-two-cols mt-5">
|
||||
<div class="title-col">
|
||||
<h2 i18n>LIVE</h2>
|
||||
|
||||
<div i18n class="inner-form-description">
|
||||
Enable users of your instance to stream live.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="live">
|
||||
|
||||
|
@ -87,15 +88,15 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row"> <!-- transcoding live streams grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">TRANSCODING</h2>
|
||||
<div class="pt-two-cols"> <!-- transcoding live streams grid -->
|
||||
<div class="title-col">
|
||||
<h2 i18n>TRANSCODING</h2>
|
||||
<div i18n class="inner-form-description">
|
||||
Same as VOD transcoding, transcoding live streams so that they are in a streamable form that any device can play. Requires a beefy CPU, and then some.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="live">
|
||||
<ng-container formGroupName="transcoding">
|
||||
|
|
|
@ -1,14 +1,33 @@
|
|||
import { SelectOptionsItem } from 'src/types/select-options-item.model'
|
||||
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'
|
||||
import { FormGroup } from '@angular/forms'
|
||||
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { HTMLServerConfig } from '@peertube/peertube-models'
|
||||
import { ConfigService } from '../shared/config.service'
|
||||
import { EditConfigurationService, ResolutionOption } from './edit-configuration.service'
|
||||
import { SelectCustomValueComponent } from '../../../shared/shared-forms/select/select-custom-value.component'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import { SelectOptionsComponent } from '../../../shared/shared-forms/select/select-options.component'
|
||||
import { NgClass, NgIf, NgFor } from '@angular/common'
|
||||
import { PeerTubeTemplateDirective } from '../../../shared/shared-main/angular/peertube-template.directive'
|
||||
import { PeertubeCheckboxComponent } from '../../../shared/shared-forms/peertube-checkbox.component'
|
||||
|
||||
@Component({
|
||||
selector: 'my-edit-live-configuration',
|
||||
templateUrl: './edit-live-configuration.component.html',
|
||||
styleUrls: [ './edit-custom-config.component.scss' ]
|
||||
styleUrls: [ './edit-custom-config.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
PeertubeCheckboxComponent,
|
||||
PeerTubeTemplateDirective,
|
||||
NgClass,
|
||||
NgIf,
|
||||
SelectOptionsComponent,
|
||||
NgFor,
|
||||
RouterLink,
|
||||
SelectCustomValueComponent
|
||||
]
|
||||
})
|
||||
export class EditLiveConfigurationComponent implements OnInit, OnChanges {
|
||||
@Input() form: FormGroup
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<ng-container [formGroup]="form">
|
||||
|
||||
<div class="row mt-4"> <!-- transcoding grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3"></div>
|
||||
<div class="col-12 col-lg-8">
|
||||
<div class="pt-two-cols mt-4">
|
||||
<div class="title-col"></div>
|
||||
<div class="content-col">
|
||||
|
||||
<div class="callout callout-orange">
|
||||
<span i18n>
|
||||
|
@ -16,20 +16,21 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4"> <!-- transcoding grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">TRANSCODING</h2>
|
||||
<div class="pt-two-cols mt-4">
|
||||
<div class="title-col">
|
||||
<h2 i18n>TRANSCODING</h2>
|
||||
|
||||
<div i18n class="inner-form-description">
|
||||
Process uploaded videos so that they are in a streamable form that any device can play. Though costly in
|
||||
resources, this is a critical part of PeerTube, so tread carefully.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="transcoding">
|
||||
|
||||
<div class="col-12 col-xl-11">
|
||||
<div>
|
||||
<my-peertube-checkbox inputName="transcodingEnabled" formControlName="enabled" [recommended]="true">
|
||||
<ng-template ptTemplate="label">
|
||||
<ng-container i18n>Transcoding enabled</ng-container>
|
||||
|
@ -38,7 +39,7 @@
|
|||
<ng-container ngProjectAs="extra">
|
||||
|
||||
<div class="callout callout-light pt-2 pb-0">
|
||||
<h3 class="callout-title" i18n>Input formats</h3>
|
||||
<h3 class="callout-title" i18n>Input</h3>
|
||||
|
||||
<div class="form-group" [ngClass]="getTranscodingDisabledClass()">
|
||||
<my-peertube-checkbox
|
||||
|
@ -62,10 +63,21 @@
|
|||
</ng-container>
|
||||
</my-peertube-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="form-group" formGroupName="originalFile" [ngClass]="getTranscodingDisabledClass()">
|
||||
<my-peertube-checkbox
|
||||
inputName="transcodingOriginalFileKeep" formControlName="keep"
|
||||
i18n-labelText labelText="Keep a version of the input file"
|
||||
>
|
||||
<ng-container ngProjectAs="description">
|
||||
<div i18n>If enabled, the input file is not deleted after transcoding but moved in a dedicated folder or object storage</div>
|
||||
</ng-container>
|
||||
</my-peertube-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="callout callout-light pt-2 mt-2 pb-0">
|
||||
<h3 class="callout-title" i18n>Output formats</h3>
|
||||
<h3 class="callout-title" i18n>Output</h3>
|
||||
|
||||
<ng-container formGroupName="webVideos">
|
||||
<div class="form-group" [ngClass]="getTranscodingDisabledClass()">
|
||||
|
@ -209,15 +221,15 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-2"> <!-- video studio grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<h2 i18n class="inner-form-title">VIDEO STUDIO</h2>
|
||||
<div class="pt-two-cols mt-2">
|
||||
<div class="title-col">
|
||||
<h2 i18n>VIDEO STUDIO</h2>
|
||||
<div i18n class="inner-form-description">
|
||||
Allows your users to edit their video (cut, add intro/outro, add a watermark etc)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<ng-container formGroupName="videoStudio">
|
||||
<div class="form-group" [ngClass]="getTranscodingDisabledClass()">
|
||||
|
|
|
@ -1,14 +1,33 @@
|
|||
import { SelectOptionsItem } from 'src/types/select-options-item.model'
|
||||
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'
|
||||
import { FormGroup } from '@angular/forms'
|
||||
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { HTMLServerConfig } from '@peertube/peertube-models'
|
||||
import { ConfigService } from '../shared/config.service'
|
||||
import { EditConfigurationService, ResolutionOption } from './edit-configuration.service'
|
||||
import { SelectOptionsComponent } from '../../../shared/shared-forms/select/select-options.component'
|
||||
import { SelectCustomValueComponent } from '../../../shared/shared-forms/select/select-custom-value.component'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import { NgClass, NgFor, NgIf } from '@angular/common'
|
||||
import { PeerTubeTemplateDirective } from '../../../shared/shared-main/angular/peertube-template.directive'
|
||||
import { PeertubeCheckboxComponent } from '../../../shared/shared-forms/peertube-checkbox.component'
|
||||
|
||||
@Component({
|
||||
selector: 'my-edit-vod-transcoding',
|
||||
templateUrl: './edit-vod-transcoding.component.html',
|
||||
styleUrls: [ './edit-custom-config.component.scss' ]
|
||||
styleUrls: [ './edit-custom-config.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
PeertubeCheckboxComponent,
|
||||
PeerTubeTemplateDirective,
|
||||
NgClass,
|
||||
NgFor,
|
||||
NgIf,
|
||||
RouterLink,
|
||||
SelectCustomValueComponent,
|
||||
SelectOptionsComponent
|
||||
]
|
||||
})
|
||||
export class EditVODTranscodingComponent implements OnInit, OnChanges {
|
||||
@Input() form: FormGroup
|
||||
|
|
|
@ -1,16 +1,37 @@
|
|||
import { SortMeta } from 'primeng/api'
|
||||
import { SortMeta, SharedModule } from 'primeng/api'
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
|
||||
import { formatICU } from '@app/helpers'
|
||||
import { AdvancedInputFilter } from '@app/shared/shared-forms'
|
||||
import { InstanceFollowService } from '@app/shared/shared-instance'
|
||||
import { DropdownAction } from '@app/shared/shared-main'
|
||||
import { ActorFollow } from '@peertube/peertube-models'
|
||||
import { AutoColspanDirective } from '../../../shared/shared-main/angular/auto-colspan.directive'
|
||||
import { DeleteButtonComponent } from '../../../shared/shared-main/buttons/delete-button.component'
|
||||
import { ButtonComponent } from '../../../shared/shared-main/buttons/button.component'
|
||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
|
||||
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
|
||||
import { NgIf, DatePipe } from '@angular/common'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
import { InstanceFollowService } from '@app/shared/shared-instance/instance-follow.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-followers-list',
|
||||
templateUrl: './followers-list.component.html',
|
||||
styleUrls: [ './followers-list.component.scss' ]
|
||||
styleUrls: [ './followers-list.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
GlobalIconComponent,
|
||||
TableModule,
|
||||
SharedModule,
|
||||
NgIf,
|
||||
ActionDropdownComponent,
|
||||
AdvancedInputFilterComponent,
|
||||
NgbTooltip,
|
||||
ButtonComponent,
|
||||
DeleteButtonComponent,
|
||||
AutoColspanDirective,
|
||||
DatePipe
|
||||
]
|
||||
})
|
||||
export class FollowersListComponent extends RestTable <ActorFollow> implements OnInit {
|
||||
followers: ActorFollow[] = []
|
||||
|
|
|
@ -2,15 +2,21 @@ import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/cor
|
|||
import { Notifier } from '@app/core'
|
||||
import { formatICU } from '@app/helpers'
|
||||
import { splitAndGetNotEmpty, UNIQUE_HOSTS_OR_HANDLE_VALIDATOR } from '@app/shared/form-validators/host-validators'
|
||||
import { FormReactive, FormReactiveService } from '@app/shared/shared-forms'
|
||||
import { InstanceFollowService } from '@app/shared/shared-instance'
|
||||
import { FormReactive } from '@app/shared/shared-forms/form-reactive'
|
||||
import { FormReactiveService } from '@app/shared/shared-forms/form-reactive.service'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
|
||||
import { NgClass, NgIf } from '@angular/common'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
import { InstanceFollowService } from '@app/shared/shared-instance/instance-follow.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-follow-modal',
|
||||
templateUrl: './follow-modal.component.html',
|
||||
styleUrls: [ './follow-modal.component.scss' ]
|
||||
styleUrls: [ './follow-modal.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [ GlobalIconComponent, FormsModule, ReactiveFormsModule, NgClass, NgIf ]
|
||||
})
|
||||
export class FollowModalComponent extends FormReactive implements OnInit {
|
||||
@ViewChild('modal', { static: true }) modal: NgbModal
|
||||
|
|
|
@ -1,16 +1,36 @@
|
|||
import { SortMeta } from 'primeng/api'
|
||||
import { SortMeta, SharedModule } from 'primeng/api'
|
||||
import { Component, OnInit, ViewChild } from '@angular/core'
|
||||
import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
|
||||
import { AdvancedInputFilter } from '@app/shared/shared-forms'
|
||||
import { InstanceFollowService } from '@app/shared/shared-instance'
|
||||
import { ActorFollow } from '@peertube/peertube-models'
|
||||
import { FollowModalComponent } from './follow-modal.component'
|
||||
import { DropdownAction } from '@app/shared/shared-main'
|
||||
import { formatICU } from '@app/helpers'
|
||||
import { AutoColspanDirective } from '../../../shared/shared-main/angular/auto-colspan.directive'
|
||||
import { RedundancyCheckboxComponent } from '../shared/redundancy-checkbox.component'
|
||||
import { DeleteButtonComponent } from '../../../shared/shared-main/buttons/delete-button.component'
|
||||
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
|
||||
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
|
||||
import { NgIf, DatePipe } from '@angular/common'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
import { InstanceFollowService } from '@app/shared/shared-instance/instance-follow.service'
|
||||
|
||||
@Component({
|
||||
templateUrl: './following-list.component.html',
|
||||
styleUrls: [ './following-list.component.scss' ]
|
||||
styleUrls: [ './following-list.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
GlobalIconComponent,
|
||||
TableModule,
|
||||
SharedModule,
|
||||
NgIf,
|
||||
ActionDropdownComponent,
|
||||
AdvancedInputFilterComponent,
|
||||
DeleteButtonComponent,
|
||||
RedundancyCheckboxComponent,
|
||||
AutoColspanDirective,
|
||||
FollowModalComponent,
|
||||
DatePipe
|
||||
]
|
||||
})
|
||||
export class FollowingListComponent extends RestTable <ActorFollow> implements OnInit {
|
||||
@ViewChild('followModal') followModal: FollowModalComponent
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import { Component, Input } from '@angular/core'
|
||||
import { Notifier } from '@app/core'
|
||||
import { RedundancyService } from '@app/shared/shared-main'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { PeertubeCheckboxComponent } from '../../../shared/shared-forms/peertube-checkbox.component'
|
||||
import { RedundancyService } from '@app/shared/shared-main/video/redundancy.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-redundancy-checkbox',
|
||||
templateUrl: './redundancy-checkbox.component.html'
|
||||
templateUrl: './redundancy-checkbox.component.html',
|
||||
standalone: true,
|
||||
imports: [ PeertubeCheckboxComponent, FormsModule ]
|
||||
})
|
||||
export class RedundancyCheckboxComponent {
|
||||
@Input() redundancyAllowed: boolean
|
||||
|
|
|
@ -1,15 +1,42 @@
|
|||
import { ChartData, ChartOptions, TooltipItem } from 'chart.js'
|
||||
import { SortMeta } from 'primeng/api'
|
||||
import { SortMeta, SharedModule } from 'primeng/api'
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { ConfirmService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
|
||||
import { BytesPipe, RedundancyService } from '@app/shared/shared-main'
|
||||
import { VideoRedundanciesTarget, VideoRedundancy, VideosRedundancyStats } from '@peertube/peertube-models'
|
||||
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
|
||||
import { ChartModule } from 'primeng/chart'
|
||||
import { VideoRedundancyInformationComponent } from './video-redundancy-information.component'
|
||||
import { AutoColspanDirective } from '../../../shared/shared-main/angular/auto-colspan.directive'
|
||||
import { DeleteButtonComponent } from '../../../shared/shared-main/buttons/delete-button.component'
|
||||
import { TableExpanderIconComponent } from '../../../shared/shared-tables/table-expander-icon.component'
|
||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgIf, NgFor } from '@angular/common'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
import { BytesPipe } from '@app/shared/shared-main/angular/bytes.pipe'
|
||||
import { RedundancyService } from '@app/shared/shared-main/video/redundancy.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-video-redundancies-list',
|
||||
templateUrl: './video-redundancies-list.component.html',
|
||||
styleUrls: [ './video-redundancies-list.component.scss' ]
|
||||
styleUrls: [ './video-redundancies-list.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
GlobalIconComponent,
|
||||
FormsModule,
|
||||
TableModule,
|
||||
SharedModule,
|
||||
NgIf,
|
||||
NgbTooltip,
|
||||
TableExpanderIconComponent,
|
||||
DeleteButtonComponent,
|
||||
AutoColspanDirective,
|
||||
NgFor,
|
||||
VideoRedundancyInformationComponent,
|
||||
ChartModule,
|
||||
BytesPipe
|
||||
]
|
||||
})
|
||||
export class VideoRedundanciesListComponent extends RestTable implements OnInit {
|
||||
private static LOCAL_STORAGE_DISPLAY_TYPE = 'video-redundancies-list-display-type'
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import { Component, Input } from '@angular/core'
|
||||
import { FileRedundancyInformation, StreamingPlaylistRedundancyInformation } from '@peertube/peertube-models'
|
||||
import { BytesPipe } from '../../../shared/shared-main/angular/bytes.pipe'
|
||||
import { DatePipe } from '@angular/common'
|
||||
|
||||
@Component({
|
||||
selector: 'my-video-redundancy-information',
|
||||
templateUrl: './video-redundancy-information.component.html',
|
||||
styleUrls: [ './video-redundancy-information.component.scss' ]
|
||||
styleUrls: [ './video-redundancy-information.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [ DatePipe, BytesPipe ]
|
||||
})
|
||||
export class VideoRedundancyInformationComponent {
|
||||
@Input() redundancyElement: FileRedundancyInformation | StreamingPlaylistRedundancyInformation
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import { Component } from '@angular/core'
|
||||
import { AbuseListTableComponent } from '../../../shared/shared-abuse-list/abuse-list-table.component'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
|
||||
@Component({
|
||||
selector: 'my-abuse-list',
|
||||
templateUrl: './abuse-list.component.html',
|
||||
styleUrls: [ ]
|
||||
styleUrls: [],
|
||||
standalone: true,
|
||||
imports: [ GlobalIconComponent, AbuseListTableComponent ]
|
||||
})
|
||||
export class AbuseListComponent {
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
export * from './abuse-list'
|
||||
export * from './instance-blocklist'
|
||||
export * from './video-block-list'
|
||||
export * from './registration-list'
|
||||
export * from './moderation.routes'
|
|
@ -1,10 +1,31 @@
|
|||
import { Component } from '@angular/core'
|
||||
import { BlocklistComponentType, GenericAccountBlocklistComponent } from '@app/shared/shared-moderation'
|
||||
import { NgIf, DatePipe } from '@angular/common'
|
||||
import { AutoColspanDirective } from '../../../shared/shared-main/angular/auto-colspan.directive'
|
||||
import { ActorAvatarComponent } from '../../../shared/shared-actor-image/actor-avatar.component'
|
||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
|
||||
import { SharedModule } from 'primeng/api'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
import { GenericAccountBlocklistComponent } from '@app/shared/shared-moderation/account-blocklist.component'
|
||||
import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-instance-account-blocklist',
|
||||
styleUrls: [ '../../../shared/shared-moderation/moderation.scss' ],
|
||||
templateUrl: '../../../shared/shared-moderation/account-blocklist.component.html'
|
||||
templateUrl: '../../../shared/shared-moderation/account-blocklist.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
GlobalIconComponent,
|
||||
TableModule,
|
||||
SharedModule,
|
||||
AdvancedInputFilterComponent,
|
||||
NgbTooltip,
|
||||
ActorAvatarComponent,
|
||||
AutoColspanDirective,
|
||||
NgIf,
|
||||
DatePipe
|
||||
]
|
||||
})
|
||||
export class InstanceAccountBlocklistComponent extends GenericAccountBlocklistComponent {
|
||||
mode = BlocklistComponentType.Instance
|
||||
|
|
|
@ -1,10 +1,31 @@
|
|||
import { Component } from '@angular/core'
|
||||
import { GenericServerBlocklistComponent, BlocklistComponentType } from '@app/shared/shared-moderation'
|
||||
import { BatchDomainsModalComponent } from '../../../shared/shared-moderation/batch-domains-modal.component'
|
||||
import { NgIf, DatePipe } from '@angular/common'
|
||||
import { AutoColspanDirective } from '../../../shared/shared-main/angular/auto-colspan.directive'
|
||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
|
||||
import { SharedModule } from 'primeng/api'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
import { GenericServerBlocklistComponent } from '@app/shared/shared-moderation/server-blocklist.component'
|
||||
import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-instance-server-blocklist',
|
||||
styleUrls: [ '../../../shared/shared-moderation/server-blocklist.component.scss' ],
|
||||
templateUrl: '../../../shared/shared-moderation/server-blocklist.component.html'
|
||||
templateUrl: '../../../shared/shared-moderation/server-blocklist.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
GlobalIconComponent,
|
||||
TableModule,
|
||||
SharedModule,
|
||||
AdvancedInputFilterComponent,
|
||||
NgbTooltip,
|
||||
AutoColspanDirective,
|
||||
NgIf,
|
||||
BatchDomainsModalComponent,
|
||||
DatePipe
|
||||
]
|
||||
})
|
||||
export class InstanceServerBlocklistComponent extends GenericServerBlocklistComponent {
|
||||
mode = BlocklistComponentType.Instance
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'
|
||||
import { Notifier, ServerService } from '@app/core'
|
||||
import { FormReactive, FormReactiveService } from '@app/shared/shared-forms'
|
||||
import { FormReactive } from '@app/shared/shared-forms/form-reactive'
|
||||
import { FormReactiveService } from '@app/shared/shared-forms/form-reactive.service'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
|
||||
import { UserRegistration } from '@peertube/peertube-models'
|
||||
import { AdminRegistrationService } from './admin-registration.service'
|
||||
import { REGISTRATION_MODERATION_RESPONSE_VALIDATOR } from './process-registration-validators'
|
||||
import { PeertubeCheckboxComponent } from '../../../shared/shared-forms/peertube-checkbox.component'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
import { NgIf, NgClass } from '@angular/common'
|
||||
|
||||
@Component({
|
||||
selector: 'my-process-registration-modal',
|
||||
templateUrl: './process-registration-modal.component.html'
|
||||
templateUrl: './process-registration-modal.component.html',
|
||||
standalone: true,
|
||||
imports: [ NgIf, GlobalIconComponent, FormsModule, ReactiveFormsModule, NgClass, PeertubeCheckboxComponent ]
|
||||
})
|
||||
export class ProcessRegistrationModalComponent extends FormReactive implements OnInit {
|
||||
@ViewChild('modal', { static: true }) modal: NgbModal
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Validators } from '@angular/forms'
|
||||
import { BuildFormValidator } from '@app/shared/form-validators'
|
||||
import { BuildFormValidator } from '@app/shared/form-validators/form-validator.model'
|
||||
|
||||
export const REGISTRATION_MODERATION_RESPONSE_VALIDATOR: BuildFormValidator = {
|
||||
VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
</td>
|
||||
|
||||
<td>
|
||||
<my-user-email-info [entry]="registration" [requiresEmailVerification]="requiresEmailVerification"></my-user-email-info>
|
||||
<my-user-email-info [entry]="registration" [showEmailVerifyInformation]="requiresEmailVerification"></my-user-email-info>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
@ -91,8 +91,14 @@
|
|||
</td>
|
||||
|
||||
<td class="c-hand abuse-states" [pRowToggler]="registration">
|
||||
<my-global-icon *ngIf="isRegistrationAccepted(registration)" [title]="registration.state.label" iconName="tick"></my-global-icon>
|
||||
<my-global-icon *ngIf="isRegistrationRejected(registration)" [title]="registration.state.label" iconName="cross"></my-global-icon>
|
||||
|
||||
<div *ngIf="isRegistrationAccepted(registration)" [title]="registration.state.label" class="pt-badge badge-success">
|
||||
<my-global-icon iconName="tick"></my-global-icon>
|
||||
</div>
|
||||
|
||||
<div *ngIf="isRegistrationRejected(registration)" [title]="registration.state.label" class="pt-badge badge-danger">
|
||||
<my-global-icon iconName="cross"></my-global-icon>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td container="body" placement="left auto" [ngbTooltip]="registration.moderationResponse">
|
||||
|
|
|
@ -1,18 +1,41 @@
|
|||
import { SortMeta } from 'primeng/api'
|
||||
import { SortMeta, SharedModule } from 'primeng/api'
|
||||
import { Component, OnInit, ViewChild } from '@angular/core'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
|
||||
import { formatICU } from '@app/helpers'
|
||||
import { AdvancedInputFilter } from '@app/shared/shared-forms'
|
||||
import { DropdownAction } from '@app/shared/shared-main'
|
||||
import { UserRegistration, UserRegistrationState } from '@peertube/peertube-models'
|
||||
import { AdminRegistrationService } from './admin-registration.service'
|
||||
import { ProcessRegistrationModalComponent } from './process-registration-modal.component'
|
||||
import { AutoColspanDirective } from '../../../shared/shared-main/angular/auto-colspan.directive'
|
||||
import { UserEmailInfoComponent } from '../../shared/user-email-info.component'
|
||||
import { TableExpanderIconComponent } from '../../../shared/shared-tables/table-expander-icon.component'
|
||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
|
||||
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
|
||||
import { NgIf, NgClass, DatePipe } from '@angular/common'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
|
||||
@Component({
|
||||
selector: 'my-registration-list',
|
||||
templateUrl: './registration-list.component.html',
|
||||
styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './registration-list.component.scss' ]
|
||||
styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './registration-list.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
GlobalIconComponent,
|
||||
TableModule,
|
||||
SharedModule,
|
||||
NgIf,
|
||||
ActionDropdownComponent,
|
||||
AdvancedInputFilterComponent,
|
||||
NgbTooltip,
|
||||
TableExpanderIconComponent,
|
||||
NgClass,
|
||||
UserEmailInfoComponent,
|
||||
AutoColspanDirective,
|
||||
ProcessRegistrationModalComponent,
|
||||
DatePipe
|
||||
]
|
||||
})
|
||||
export class RegistrationListComponent extends RestTable <UserRegistration> implements OnInit {
|
||||
@ViewChild('processRegistrationModal', { static: true }) processRegistrationModal: ProcessRegistrationModalComponent
|
||||
|
|
|
@ -1,20 +1,45 @@
|
|||
import { SortMeta } from 'primeng/api'
|
||||
import { SortMeta, SharedModule } from 'primeng/api'
|
||||
import { switchMap } from 'rxjs/operators'
|
||||
import { environment } from 'src/environments/environment'
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
|
||||
import { AdvancedInputFilter } from '@app/shared/shared-forms'
|
||||
import { DropdownAction, VideoService } from '@app/shared/shared-main'
|
||||
import { VideoBlockService } from '@app/shared/shared-moderation'
|
||||
import { buildVideoEmbedLink, decorateVideoLink } from '@peertube/peertube-core-utils'
|
||||
import { VideoBlacklist, VideoBlacklistType, VideoBlacklistType_Type } from '@peertube/peertube-models'
|
||||
import { buildVideoOrPlaylistEmbed } from '@root-helpers/video'
|
||||
import { EmbedComponent } from '../../../shared/shared-main/video/embed.component'
|
||||
import { AutoColspanDirective } from '../../../shared/shared-main/angular/auto-colspan.directive'
|
||||
import { VideoCellComponent } from '../../../shared/shared-tables/video-cell.component'
|
||||
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
|
||||
import { TableExpanderIconComponent } from '../../../shared/shared-tables/table-expander-icon.component'
|
||||
import { NgIf, NgClass, DatePipe } from '@angular/common'
|
||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
import { VideoService } from '@app/shared/shared-main/video/video.service'
|
||||
import { VideoBlockService } from '@app/shared/shared-moderation/video-block.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-video-block-list',
|
||||
templateUrl: './video-block-list.component.html',
|
||||
styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './video-block-list.component.scss' ]
|
||||
styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './video-block-list.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
GlobalIconComponent,
|
||||
TableModule,
|
||||
SharedModule,
|
||||
AdvancedInputFilterComponent,
|
||||
NgbTooltip,
|
||||
NgIf,
|
||||
TableExpanderIconComponent,
|
||||
ActionDropdownComponent,
|
||||
NgClass,
|
||||
VideoCellComponent,
|
||||
AutoColspanDirective,
|
||||
EmbedComponent,
|
||||
DatePipe
|
||||
]
|
||||
})
|
||||
export class VideoBlockListComponent extends RestTable implements OnInit {
|
||||
blocklist: (VideoBlacklist & { reasonHtml?: string })[] = []
|
||||
|
@ -155,6 +180,7 @@ export class VideoBlockListComponent extends RestTable implements OnInit {
|
|||
title: false,
|
||||
warningTitle: false
|
||||
}),
|
||||
aspectRatio: entry.video.aspectRatio,
|
||||
embedTitle: entry.video.name
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,18 +1,45 @@
|
|||
import { SortMeta } from 'primeng/api'
|
||||
import { SortMeta, SharedModule } from 'primeng/api'
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import { AuthService, ConfirmService, MarkdownService, Notifier, RestPagination, RestTable } from '@app/core'
|
||||
import { AdvancedInputFilter } from '@app/shared/shared-forms'
|
||||
import { DropdownAction } from '@app/shared/shared-main'
|
||||
import { BulkService } from '@app/shared/shared-moderation'
|
||||
import { VideoCommentAdmin, VideoCommentService } from '@app/shared/shared-video-comment'
|
||||
import { FeedFormat, UserRight } from '@peertube/peertube-models'
|
||||
import { formatICU } from '@app/helpers'
|
||||
import { AutoColspanDirective } from '../../../shared/shared-main/angular/auto-colspan.directive'
|
||||
import { ActorAvatarComponent } from '../../../shared/shared-actor-image/actor-avatar.component'
|
||||
import { TableExpanderIconComponent } from '../../../shared/shared-tables/table-expander-icon.component'
|
||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ButtonComponent } from '../../../shared/shared-main/buttons/button.component'
|
||||
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
|
||||
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
|
||||
import { NgIf, NgClass, DatePipe } from '@angular/common'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { FeedComponent } from '../../../shared/shared-main/feeds/feed.component'
|
||||
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
|
||||
import { VideoCommentAdmin } from '@app/shared/shared-video-comment/video-comment.model'
|
||||
import { BulkService } from '@app/shared/shared-moderation/bulk.service'
|
||||
import { VideoCommentService } from '@app/shared/shared-video-comment/video-comment.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-video-comment-list',
|
||||
templateUrl: './video-comment-list.component.html',
|
||||
styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './video-comment-list.component.scss' ]
|
||||
styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './video-comment-list.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
GlobalIconComponent,
|
||||
FeedComponent,
|
||||
TableModule,
|
||||
SharedModule,
|
||||
NgIf,
|
||||
ActionDropdownComponent,
|
||||
AdvancedInputFilterComponent,
|
||||
ButtonComponent,
|
||||
NgbTooltip,
|
||||
TableExpanderIconComponent,
|
||||
NgClass,
|
||||
ActorAvatarComponent,
|
||||
AutoColspanDirective,
|
||||
DatePipe
|
||||
]
|
||||
})
|
||||
export class VideoCommentListComponent extends RestTable <VideoCommentAdmin> implements OnInit {
|
||||
comments: VideoCommentAdmin[]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Component, OnInit } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import { Router, RouterLink } from '@angular/router'
|
||||
import { ConfigService } from '@app/+admin/config/shared/config.service'
|
||||
import { AuthService, Notifier, ScreenService, ServerService } from '@app/core'
|
||||
import {
|
||||
|
@ -12,15 +12,45 @@ import {
|
|||
USER_VIDEO_QUOTA_DAILY_VALIDATOR,
|
||||
USER_VIDEO_QUOTA_VALIDATOR
|
||||
} from '@app/shared/form-validators/user-validators'
|
||||
import { FormReactiveService } from '@app/shared/shared-forms'
|
||||
import { UserAdminService } from '@app/shared/shared-users'
|
||||
import { FormReactiveService } from '@app/shared/shared-forms/form-reactive.service'
|
||||
import { UserCreate, UserRole } from '@peertube/peertube-models'
|
||||
import { UserEdit } from './user-edit'
|
||||
import { BytesPipe } from '../../../../shared/shared-main/angular/bytes.pipe'
|
||||
import { UserPasswordComponent } from './user-password.component'
|
||||
import { PeertubeCheckboxComponent } from '../../../../shared/shared-forms/peertube-checkbox.component'
|
||||
import { UserRealQuotaInfoComponent } from '../../../shared/user-real-quota-info.component'
|
||||
import { SelectCustomValueComponent } from '../../../../shared/shared-forms/select/select-custom-value.component'
|
||||
import { InputTextComponent } from '../../../../shared/shared-forms/input-text.component'
|
||||
import { PeerTubeTemplateDirective } from '../../../../shared/shared-main/angular/peertube-template.directive'
|
||||
import { HelpComponent } from '../../../../shared/shared-main/misc/help.component'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { ActorAvatarEditComponent } from '../../../../shared/shared-actor-image-edit/actor-avatar-edit.component'
|
||||
import { NgIf, NgTemplateOutlet, NgClass, NgFor } from '@angular/common'
|
||||
import { UserAdminService } from '@app/shared/shared-users/user-admin.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-user-create',
|
||||
templateUrl: './user-edit.component.html',
|
||||
styleUrls: [ './user-edit.component.scss' ]
|
||||
styleUrls: [ './user-edit.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
RouterLink,
|
||||
NgIf,
|
||||
NgTemplateOutlet,
|
||||
ActorAvatarEditComponent,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
NgClass,
|
||||
HelpComponent,
|
||||
PeerTubeTemplateDirective,
|
||||
InputTextComponent,
|
||||
NgFor,
|
||||
SelectCustomValueComponent,
|
||||
UserRealQuotaInfoComponent,
|
||||
PeertubeCheckboxComponent,
|
||||
UserPasswordComponent,
|
||||
BytesPipe
|
||||
]
|
||||
})
|
||||
export class UserCreateComponent extends UserEdit implements OnInit {
|
||||
error: string
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<ol class="pt-breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a routerLink="/admin/users" i18n>Users</a>
|
||||
</li>
|
||||
|
||||
<ng-container *ngIf="isCreation()">
|
||||
@if (isCreation()) {
|
||||
<li class="breadcrumb-item active" i18n>Create</li>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!isCreation()">
|
||||
} @else {
|
||||
<li class="breadcrumb-item active" i18n>Edit</li>
|
||||
|
||||
<li class="breadcrumb-item active" aria-current="page">
|
||||
<a *ngIf="user" [routerLink]="[ '/a', user?.username ]">{{ user?.username }}</a>
|
||||
</li>
|
||||
</ng-container>
|
||||
}
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
|
@ -57,26 +57,33 @@
|
|||
</div>
|
||||
</ng-template>
|
||||
|
||||
<div class="row d-xxl-none"> <!-- hidden on large screens, as it is then displayed on the right side of the form -->
|
||||
<div class="col-12 col-xl-3"></div>
|
||||
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
||||
|
||||
<div class="pt-two-cols d-xxl-none"> <!-- hidden on large screens, as it is then displayed on the right side of the form -->
|
||||
<div class="col-0 col-xl-3"></div>
|
||||
|
||||
<div class="col-12 col-xl-9">
|
||||
<ng-template *ngTemplateOutlet="dashboard"></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
||||
|
||||
<div class="row mt-4"> <!-- user grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<div class="pt-two-cols mt-4"> <!-- user grid -->
|
||||
<div class="title-col">
|
||||
<div class="anchor" id="user"></div> <!-- user anchor -->
|
||||
<div *ngIf="isCreation()" class="account-title" i18n>NEW USER</div>
|
||||
<div *ngIf="!isCreation() && user" class="account-title">
|
||||
<my-actor-avatar-edit [actor]="user.account" [editable]="false" [displaySubscribers]="false" [displayUsername]="false"></my-actor-avatar-edit>
|
||||
</div>
|
||||
|
||||
@if (isCreation()) {
|
||||
<h2 i18n>NEW USER</h2>
|
||||
} @else if (user) {
|
||||
<h2 class="visually-hidden">EDIT USER {{ user.username }}</h2>
|
||||
|
||||
<my-actor-avatar-edit
|
||||
actorType="account" [displayName]="user.account.displayName" [avatars]="user.account.avatars"
|
||||
editable="false" [username]="user.username" displayUsername="false"
|
||||
></my-actor-avatar-edit>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
<div class="row">
|
||||
<form class="col" role="form" (ngSubmit)="formValidated()" [formGroup]="form">
|
||||
<div class="form-group" *ngIf="isCreation()">
|
||||
|
@ -198,7 +205,7 @@
|
|||
</my-peertube-checkbox>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="{{ getFormButtonTitle() }}" [disabled]="!form.valid">
|
||||
<input class="peertube-button orange-button" type="submit" value="{{ getFormButtonTitle() }}" [disabled]="!form.valid">
|
||||
</form>
|
||||
|
||||
<div class="d-none d-xxl-block col-7">
|
||||
|
@ -209,18 +216,18 @@
|
|||
</div>
|
||||
|
||||
|
||||
<div *ngIf="displayDangerZone()" class="row mt-4"> <!-- danger zone grid -->
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
<div *ngIf="displayDangerZone()" class="pt-two-cols mt-5"> <!-- danger zone grid -->
|
||||
<div class="title-col">
|
||||
<div class="anchor" id="danger"></div> <!-- danger zone anchor -->
|
||||
<div i18n class="account-title account-title-danger">DANGER ZONE</div>
|
||||
<h2 i18n class="pt-title-danger">DANGER ZONE</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
<div class="content-col">
|
||||
|
||||
<div class="danger-zone">
|
||||
<div class="form-group">
|
||||
<div class="mb-1 fw-bold" i18n>Send a link to reset the password by email to the user</div>
|
||||
<button (click)="resetPassword()" i18n>Ask for new password</button>
|
||||
<button class="peertube-button" (click)="resetPassword()" i18n>Ask for new password</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -230,7 +237,7 @@
|
|||
|
||||
<div *ngIf="user.twoFactorEnabled" class="form-group">
|
||||
<div class="mb-1 fw-bold" i18n>This user has two factor authentication enabled</div>
|
||||
<button (click)="disableTwoFactorAuth()" i18n>Disable two factor authentication</button>
|
||||
<button class="peertube-button" (click)="disableTwoFactorAuth()" i18n>Disable two factor authentication</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,19 +1,10 @@
|
|||
@use 'sass:math';
|
||||
@use 'sass:color';
|
||||
|
||||
@use '_variables' as *;
|
||||
@use '_mixins' as *;
|
||||
|
||||
$form-base-input-width: 340px;
|
||||
|
||||
.account-title {
|
||||
@include settings-big-title;
|
||||
|
||||
&.account-title-danger {
|
||||
color: color.adjust($color: #c54130, $lightness: 10%);
|
||||
}
|
||||
}
|
||||
|
||||
input:not([type=submit]) {
|
||||
@include peertube-input-text($form-base-input-width);
|
||||
display: block;
|
||||
|
@ -35,36 +26,62 @@ my-select-custom-value {
|
|||
display: block;
|
||||
}
|
||||
|
||||
input[type=submit],
|
||||
button {
|
||||
@include peertube-button;
|
||||
@include orange-button;
|
||||
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
my-user-real-quota-info {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.danger-zone {
|
||||
button {
|
||||
@include peertube-button;
|
||||
@include danger-button;
|
||||
@include disable-outline;
|
||||
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
@include breadcrumb;
|
||||
}
|
||||
|
||||
.dashboard {
|
||||
@include dashboard;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -5px;
|
||||
max-width: 900px;
|
||||
|
||||
> div {
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 math.percentage(math.div(1, 3));
|
||||
padding: 0 5px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
> a {
|
||||
@include disable-default-a-behaviour;
|
||||
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
|
||||
&:active,
|
||||
&:focus,
|
||||
&:hover {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
|
||||
> a,
|
||||
> div {
|
||||
padding: 20px;
|
||||
background: pvar(--submenuBackgroundColor);
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-num,
|
||||
.dashboard-text {
|
||||
text-align: center;
|
||||
font-size: 130%;
|
||||
color: pvar(--mainForegroundColor);
|
||||
line-height: 30px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.dashboard-label {
|
||||
font-size: 90%;
|
||||
color: pvar(--inputPlaceholderColor);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue