Merge branch 'details-in-card-and-add-dialog-title-change'
@@ -8,7 +8,8 @@
|
|||||||
> `http://192.168.78.4:8090` - correct
|
> `http://192.168.78.4:8090` - correct
|
||||||
>
|
>
|
||||||
> `http://192.168.78.4:8090/` - wrong
|
> `http://192.168.78.4:8090/` - wrong
|
||||||
3. `yarn start`
|
3. in `.env` file add TMDB api key
|
||||||
|
4. `yarn start`
|
||||||
|
|
||||||
### Eslint
|
### Eslint
|
||||||
> Prettier will fix the code every time the code is saved
|
> Prettier will fix the code every time the code is saved
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
"@material-ui/icons": "^4.11.2",
|
"@material-ui/icons": "^4.11.2",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"clsx": "^1.1.1",
|
"clsx": "^1.1.1",
|
||||||
"fontsource-roboto": "^4.0.0",
|
|
||||||
"i18next": "^20.3.1",
|
"i18next": "^20.3.1",
|
||||||
"i18next-browser-languagedetector": "^6.1.1",
|
"i18next-browser-languagedetector": "^6.1.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
|||||||
BIN
web/public/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
web/public/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
web/public/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
9
web/public/browserconfig.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square150x150logo src="/mstile-150x150.png"/>
|
||||||
|
<TileColor>#da532c</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
||||||
BIN
web/public/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
web/public/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
web/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
web/public/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
265
web/public/safari-pinned-tab.svg
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1200.000000pt" height="1200.000000pt" viewBox="0 0 1200.000000 1200.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,1200.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M5719 11396 c-2 -2 -58 -7 -124 -10 -66 -4 -127 -9 -135 -11 -8 -2
|
||||||
|
-42 -7 -75 -10 -703 -70 -1491 -334 -2125 -710 -473 -281 -931 -656 -1281
|
||||||
|
-1051 -95 -106 -113 -127 -175 -204 -565 -701 -934 -1492 -1110 -2385 -4 -19
|
||||||
|
-31 -182 -39 -235 -10 -60 -35 -293 -42 -385 -16 -198 -8 -823 12 -923 2 -11
|
||||||
|
7 -53 10 -94 4 -40 8 -75 10 -78 2 -3 6 -36 10 -75 3 -38 8 -72 10 -75 1 -3 6
|
||||||
|
-27 9 -54 4 -28 14 -82 22 -120 9 -39 18 -84 21 -101 2 -16 25 -111 50 -210
|
||||||
|
146 -582 397 -1146 736 -1655 78 -117 230 -326 287 -393 10 -12 44 -53 76 -92
|
||||||
|
130 -156 353 -388 494 -515 265 -237 517 -428 803 -605 107 -67 154 -101 145
|
||||||
|
-107 -7 -4 -9 -8 -4 -8 5 0 -1 -11 -14 -25 -13 -14 -19 -25 -14 -25 5 0 1 -5
|
||||||
|
-9 -11 -9 -6 -15 -14 -12 -19 3 -4 -2 -11 -11 -14 -9 -4 -14 -13 -10 -21 3 -9
|
||||||
|
0 -15 -9 -15 -8 0 -14 -3 -13 -8 3 -11 -23 -55 -43 -73 -10 -9 -15 -19 -11
|
||||||
|
-23 4 -4 -1 -12 -11 -17 -9 -6 -15 -14 -12 -19 3 -4 -2 -11 -11 -14 -8 -3 -13
|
||||||
|
-10 -9 -15 3 -6 -3 -14 -12 -20 -10 -6 -13 -11 -8 -11 6 0 3 -5 -5 -10 -8 -5
|
||||||
|
-15 -15 -15 -22 -1 -7 -6 -12 -12 -11 -6 1 -9 -6 -5 -19 3 -14 1 -19 -6 -14
|
||||||
|
-8 5 -12 -2 -12 -18 0 -14 3 -26 8 -26 12 1 72 59 72 70 0 6 4 9 9 6 5 -3 19
|
||||||
|
10 32 28 13 19 27 32 31 30 4 -3 8 -1 8 4 0 15 208 221 216 214 4 -4 4 1 1 11
|
||||||
|
-4 11 -3 16 3 12 6 -3 10 -1 10 4 0 21 34 10 168 -57 580 -289 1207 -469 1869
|
||||||
|
-537 154 -15 252 -19 518 -20 297 0 430 6 595 26 47 5 103 12 125 15 194 22
|
||||||
|
496 81 690 135 39 11 86 24 105 29 346 96 782 278 1127 471 1188 665 2073
|
||||||
|
1735 2502 3027 97 292 181 648 216 912 3 25 8 56 10 70 4 23 13 104 21 190 14
|
||||||
|
145 19 283 19 530 0 334 -8 458 -46 730 -25 183 -28 204 -46 285 -8 39 -17 84
|
||||||
|
-20 100 -2 17 -14 66 -25 110 -11 44 -22 90 -24 103 -3 13 -24 92 -49 175
|
||||||
|
-181 624 -470 1200 -869 1732 -49 66 -92 122 -95 125 -4 3 -22 25 -41 50 -19
|
||||||
|
25 -49 61 -66 80 -17 19 -55 62 -84 95 -293 335 -743 718 -1130 962 -91 57
|
||||||
|
-305 183 -362 212 -21 11 -25 18 -18 31 5 10 7 20 3 23 -3 4 2 9 11 13 9 3 14
|
||||||
|
10 11 14 -3 4 2 11 11 14 8 3 13 10 10 15 -3 5 1 12 10 15 8 3 12 10 9 16 -3
|
||||||
|
5 -1 10 4 10 6 0 10 3 9 8 -4 10 68 123 75 116 3 -3 5 1 4 8 -1 32 4 49 13 43
|
||||||
|
5 -3 12 6 16 20 3 14 10 25 15 25 5 0 8 6 7 13 -2 6 2 11 8 10 7 -1 10 6 7 17
|
||||||
|
-3 11 0 20 6 20 6 0 11 9 11 19 0 14 -6 19 -20 18 -11 -1 -20 -5 -20 -10 0 -4
|
||||||
|
-4 -6 -9 -3 -5 3 -8 -2 -7 -12 0 -9 -5 -16 -11 -14 -7 1 -13 -3 -13 -10 0 -11
|
||||||
|
-24 -38 -152 -169 -32 -33 -58 -64 -58 -69 0 -6 -4 -10 -8 -10 -5 0 -17 -7
|
||||||
|
-28 -16 -10 -8 -13 -12 -5 -8 10 5 12 3 7 -5 -5 -7 -15 -10 -23 -7 -8 3 -11 2
|
||||||
|
-8 -4 3 -5 -2 -18 -11 -28 -16 -19 -19 -18 -148 39 -72 33 -140 64 -151 69
|
||||||
|
-144 67 -624 228 -757 254 -13 2 -70 16 -128 30 -198 47 -471 91 -690 112 -36
|
||||||
|
3 -85 8 -110 11 -56 6 -686 14 -691 9z m602 -1203 c13 -16 12 -17 -3 -4 -10 7
|
||||||
|
-18 15 -18 17 0 8 8 3 21 -13z m844 -102 c3 -5 2 -12 -3 -15 -5 -3 -9 1 -9 9
|
||||||
|
0 17 3 19 12 6z m-644 -98 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3
|
||||||
|
21 -13z m-1670 -70 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z
|
||||||
|
m-201 -3 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z
|
||||||
|
m320 0 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11
|
||||||
|
-10z m50 -74 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m425 -75 c3 -5 2 -12 -3 -15 -5 -3 -9 1 -9 9 0 17 3 19 12 6z m125 5 c0 -2 -8
|
||||||
|
-10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-520 -18 c0 -4 -4 -8
|
||||||
|
-9 -8 -6 0 -12 4 -15 8 -3 5 1 9 9 9 8 0 15 -4 15 -9z m3157 -3 c0 -8 -4 -12
|
||||||
|
-9 -9 -5 3 -6 10 -3 15 9 13 12 11 12 -6z m-2526 -42 c13 -16 12 -17 -3 -4
|
||||||
|
-10 7 -18 15 -18 17 0 8 8 3 21 -13z m-551 -153 c0 -5 -5 -10 -11 -10 -5 0 -7
|
||||||
|
5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m330 6 c0 -2 -8 -10 -17 -17 -16 -13
|
||||||
|
-17 -12 -4 4 13 16 21 21 21 13z m2385 -14 c-3 -3 -11 0 -18 7 -9 10 -8 11 6
|
||||||
|
5 10 -3 15 -9 12 -12z m481 -27 c-1 -8 -5 -17 -8 -21 -5 -4 -4 16 1 34 3 9 9
|
||||||
|
-1 7 -13z m-3202 -131 c3 -8 2 -12 -4 -9 -6 3 -10 10 -10 16 0 14 7 11 14 -7z
|
||||||
|
m606 -258 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m-1769 -23 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m219 11
|
||||||
|
c0 -8 -19 -13 -24 -6 -3 5 1 9 9 9 8 0 15 -2 15 -3z m1341 -51 c13 -16 12 -17
|
||||||
|
-3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m2880 0 c13 -16 12 -17 -3 -4 -10
|
||||||
|
7 -18 15 -18 17 0 8 8 3 21 -13z m-4760 -40 c13 -16 12 -17 -3 -4 -10 7 -18
|
||||||
|
15 -18 17 0 8 8 3 21 -13z m530 -30 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17
|
||||||
|
0 8 8 3 21 -13z m2079 -43 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4
|
||||||
|
10 6 0 11 -4 11 -10z m1671 -47 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8
|
||||||
|
8 3 21 -13z m-3791 -17 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21
|
||||||
|
21 21 13z m730 -10 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21
|
||||||
|
13z m-2089 -163 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z
|
||||||
|
m1840 0 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m160 0 c13
|
||||||
|
-16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m160 0 c13 -16 12 -17
|
||||||
|
-3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m160 0 c13 -16 12 -17 -3 -4 -10 7
|
||||||
|
-18 15 -18 17 0 8 8 3 21 -13z m3480 -40 c13 -16 12 -17 -3 -4 -10 7 -18 15
|
||||||
|
-18 17 0 8 8 3 21 -13z m-81 -37 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6
|
||||||
|
5 11 10 11 6 0 10 -2 10 -4z m475 -134 c-3 -3 -11 0 -18 7 -9 10 -8 11 6 5 10
|
||||||
|
-3 15 -9 12 -12z m46 -29 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3
|
||||||
|
21 -13z m-1637 -1 c3 -5 -1 -9 -9 -9 -8 0 -12 4 -9 9 3 4 7 8 9 8 2 0 6 -4 9
|
||||||
|
-8z m-1443 -39 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z
|
||||||
|
m3289 3 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m240 0
|
||||||
|
c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-2139 -53 c13
|
||||||
|
-16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m1169 -73 c0 -5 -2 -10
|
||||||
|
-4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m320 0 c0 -5 -2
|
||||||
|
-10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m640 0 c0 -5
|
||||||
|
-5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m-89 -47 c13
|
||||||
|
-16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-387 -71 c3 -5 -1 -9
|
||||||
|
-9 -9 -8 0 -12 4 -9 9 3 4 7 8 9 8 2 0 6 -4 9 -8z m-5893 -55 c-10 -9 -11 -8
|
||||||
|
-5 6 3 10 9 15 12 12 3 -3 0 -11 -7 -18z m169 19 c0 -3 -4 -8 -10 -11 -5 -3
|
||||||
|
-10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z m311 -13 c13 -16 12 -17 -3 -4
|
||||||
|
-10 7 -18 15 -18 17 0 8 8 3 21 -13z m334 7 c-3 -5 -12 -10 -18 -10 -7 0 -6 4
|
||||||
|
3 10 19 12 23 12 15 0z m3685 -74 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4
|
||||||
|
13 16 21 21 21 13z m748 -51 c-3 -3 -9 2 -12 12 -6 14 -5 15 5 6 7 -7 10 -15
|
||||||
|
7 -18z m323 8 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z
|
||||||
|
m-641 -3 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10
|
||||||
|
-10z m1641 -37 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z
|
||||||
|
m-201 -3 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z
|
||||||
|
m370 -74 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m-6930 -82 c0 -8 -19 -13 -24 -6 -3 5 1 9 9 9 8 0 15 -2 15 -3z m880 2 c0 -2
|
||||||
|
-7 -7 -16 -10 -8 -3 -12 -2 -9 4 6 10 25 14 25 6z m325 -5 c-9 -8 -36 -10 -30
|
||||||
|
-2 2 4 11 8 20 8 8 0 13 -3 10 -6z m280 -1 c3 -6 -1 -7 -9 -4 -18 7 -21 14 -7
|
||||||
|
14 6 0 13 -4 16 -10z m4270 1 c3 -5 2 -12 -3 -15 -5 -3 -9 1 -9 9 0 17 3 19
|
||||||
|
12 6z m-6545 -35 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21
|
||||||
|
13z m1951 -43 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z
|
||||||
|
m4230 -10 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-4991
|
||||||
|
-17 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m80 -56 c0
|
||||||
|
-5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m320 0
|
||||||
|
c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m210 6
|
||||||
|
c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m110 -6 c0 -5
|
||||||
|
-5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m3130 6 c0 -2
|
||||||
|
-8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m1115 -5 c-9 -8 -36
|
||||||
|
-10 -30 -2 2 4 11 8 20 8 8 0 13 -3 10 -6z m-6124 -78 c13 -16 12 -17 -3 -4
|
||||||
|
-10 7 -18 15 -18 17 0 8 8 3 21 -13z m679 -27 c0 -2 -8 -10 -17 -17 -16 -13
|
||||||
|
-17 -12 -4 4 13 16 21 21 21 13z m561 -13 c13 -16 12 -17 -3 -4 -10 7 -18 15
|
||||||
|
-18 17 0 8 8 3 21 -13z m5399 -27 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4
|
||||||
|
13 16 21 21 21 13z m-120 -12 c0 -8 -19 -13 -24 -6 -3 5 1 9 9 9 8 0 15 -2 15
|
||||||
|
-3z m400 -2 c0 -5 -7 -9 -15 -9 -8 0 -12 4 -9 9 3 4 9 8 15 8 5 0 9 -4 9 -8z
|
||||||
|
m325 -1 c-9 -8 -36 -10 -30 -2 2 4 11 8 20 8 8 0 13 -3 10 -6z m-5915 -35 c0
|
||||||
|
-2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m5421 -13 c13 -16
|
||||||
|
12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m130 -30 c13 -16 12 -17 -3
|
||||||
|
-4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-5006 -83 c3 -5 1 -10 -4 -10 -6 0
|
||||||
|
-11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m5925 -120 c0 -5 -2 -10 -4 -10
|
||||||
|
-3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-7683 -35 c0 -8 -4 -12
|
||||||
|
-9 -9 -5 3 -6 10 -3 15 9 13 12 11 12 -6z m7008 -5 c3 -6 -1 -7 -9 -4 -18 7
|
||||||
|
-21 14 -7 14 6 0 13 -4 16 -10z m510 -160 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11
|
||||||
|
10 0 6 2 10 4 10 3 0 8 -4 11 -10z m320 -8 c-3 -3 -11 0 -18 7 -9 10 -8 11 6
|
||||||
|
5 10 -3 15 -9 12 -12z m-7844 -39 c13 -16 12 -17 -3 -4 -17 13 -22 21 -14 21
|
||||||
|
2 0 10 -8 17 -17z m5680 0 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3
|
||||||
|
21 -13z m-186 -113 c-3 -5 -12 -10 -18 -10 -7 0 -6 4 3 10 19 12 23 12 15 0z
|
||||||
|
m285 -34 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m-5970 -30 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m1481 -53 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-1446
|
||||||
|
-43 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z
|
||||||
|
m116 -7 c13 -16 12 -17 -3 -4 -17 13 -22 21 -14 21 2 0 10 -8 17 -17z m209 7
|
||||||
|
c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m5551
|
||||||
|
-87 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-4511 -17 c0
|
||||||
|
-2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-839 -53 c13 -16
|
||||||
|
12 -17 -3 -4 -17 13 -22 21 -14 21 2 0 10 -8 17 -17z m6676 2 c0 -8 -4 -12 -9
|
||||||
|
-9 -5 3 -6 10 -3 15 9 13 12 11 12 -6z m-5762 -4 c3 -5 2 -12 -3 -15 -5 -3 -9
|
||||||
|
1 -9 9 0 17 3 19 12 6z m-705 -35 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4
|
||||||
|
13 16 21 21 21 13z m6560 0 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16
|
||||||
|
21 21 21 13z m-4376 -55 c-2 -3 -12 3 -22 13 -16 17 -16 18 5 5 12 -7 20 -15
|
||||||
|
17 -18z m4886 25 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21
|
||||||
|
13z m-5440 -90 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10
|
||||||
|
-2 10 -4z m4290 -40 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21
|
||||||
|
21 13z m541 -13 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z
|
||||||
|
m650 -70 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-5566
|
||||||
|
-51 c-3 -3 -11 0 -18 7 -9 10 -8 11 6 5 10 -3 15 -9 12 -12z m3245 6 c0 -4 -4
|
||||||
|
-8 -9 -8 -6 0 -12 4 -15 8 -3 5 1 9 9 9 8 0 15 -4 15 -9z m-5889 -85 c13 -16
|
||||||
|
12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m5329 11 c0 -8 -19 -13 -24
|
||||||
|
-6 -3 5 1 9 9 9 8 0 15 -2 15 -3z m1040 -28 c0 -2 -8 -10 -17 -17 -16 -13 -17
|
||||||
|
-12 -4 4 13 16 21 21 21 13z m-2960 -16 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10
|
||||||
|
3 6 8 10 11 10 2 0 4 -4 4 -10z m3040 -40 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11
|
||||||
|
10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-4329 -53 c-10 -9 -11 -8 -5 6 3 10 9
|
||||||
|
15 12 12 3 -3 0 -11 -7 -18z m4330 -64 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18
|
||||||
|
17 0 8 8 3 21 -13z m-5928 -78 c-3 -9 -8 -14 -10 -11 -3 3 -2 9 2 15 9 16 15
|
||||||
|
13 8 -4z m-482 -12 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z
|
||||||
|
m5924 7 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z
|
||||||
|
m1685 -64 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m-7605 -56 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11
|
||||||
|
-10z m965 0 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4
|
||||||
|
-10z m6720 0 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4
|
||||||
|
11 -10z m320 0 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4
|
||||||
|
4 -10z m320 6 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10
|
||||||
|
-2 10 -4z m-8230 -40 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21
|
||||||
|
21 13z m1760 0 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m-1694 -52 c1 -9 0 -13 -4 -10 -3 4 -7 14 -8 22 -1 9 0 13 4 10 3 -4 7 -14 8
|
||||||
|
-22z m2560 11 c-1 -8 -5 -17 -8 -21 -5 -4 -4 16 1 34 3 9 9 -1 7 -13z m-2476
|
||||||
|
-29 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m7441 -13
|
||||||
|
c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-6730 -90 c13 -16
|
||||||
|
12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m1779 13 c0 -2 -8 -10 -17
|
||||||
|
-17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-2520 -40 c0 -2 -8 -10 -17 -17
|
||||||
|
-16 -13 -17 -12 -4 4 13 16 21 21 21 13z m745 -86 c3 -5 1 -10 -4 -10 -6 0
|
||||||
|
-11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-804 -47 c13 -16 12 -17 -3 -4
|
||||||
|
-10 7 -18 15 -18 17 0 8 8 3 21 -13z m899 13 c0 -2 -8 -10 -17 -17 -16 -13
|
||||||
|
-17 -12 -4 4 13 16 21 21 21 13z m4541 -19 c-10 -9 -11 -8 -5 6 3 10 9 15 12
|
||||||
|
12 3 -3 0 -11 -7 -18z m-3711 -11 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4
|
||||||
|
13 16 21 21 21 13z m791 -23 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8
|
||||||
|
3 21 -13z m2894 7 c3 -6 -1 -7 -9 -4 -18 7 -21 14 -7 14 6 0 13 -4 16 -10z
|
||||||
|
m146 -7 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m99 13 c0
|
||||||
|
-2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m1030 -86 c0 -5
|
||||||
|
-2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m1320 6 c0
|
||||||
|
-3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z m320 0
|
||||||
|
c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z
|
||||||
|
m-1679 -123 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m639
|
||||||
|
13 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-720 -50
|
||||||
|
c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z
|
||||||
|
m-639 -83 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m553 -9
|
||||||
|
c3 -8 2 -12 -4 -9 -6 3 -10 10 -10 16 0 14 7 11 14 -7z m1446 -18 c0 -2 -8
|
||||||
|
-10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-2350 -50 c0 -2 -8 -10
|
||||||
|
-17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m1750 -70 c0 -2 -8 -10 -17
|
||||||
|
-17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-559 -93 c13 -16 12 -17 -3 -4
|
||||||
|
-10 7 -18 15 -18 17 0 8 8 3 21 -13z m-597 -1 c3 -5 -1 -9 -9 -9 -8 0 -12 4
|
||||||
|
-9 9 3 4 7 8 9 8 2 0 6 -4 9 -8z m396 -2 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4
|
||||||
|
10 3 6 8 10 11 10 2 0 4 -4 4 -10z m320 0 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11
|
||||||
|
10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m50 -74 c0 -2 -8 -10 -17 -17 -16 -13
|
||||||
|
-17 -12 -4 4 13 16 21 21 21 13z m-1690 -50 c0 -2 -8 -10 -17 -17 -16 -13 -17
|
||||||
|
-12 -4 4 13 16 21 21 21 13z m-3640 -32 c0 -8 -19 -13 -24 -6 -3 5 1 9 9 9 8
|
||||||
|
0 15 -2 15 -3z m634 -42 c3 -5 -1 -9 -9 -9 -8 0 -12 4 -9 9 3 4 7 8 9 8 2 0 6
|
||||||
|
-4 9 -8z m4326 -122 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0
|
||||||
|
4 -4 4 -10z m-6160 -104 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21
|
||||||
|
21 21 13z m1120 0 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21
|
||||||
|
13z m-230 -90 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m3231 -43 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m1020
|
||||||
|
-160 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-4310 -10
|
||||||
|
c13 -16 12 -17 -3 -4 -17 13 -22 21 -14 21 2 0 10 -8 17 -17z m3086 -68 c0 -8
|
||||||
|
-4 -12 -9 -9 -5 3 -6 10 -3 15 9 13 12 11 12 -6z m3040 0 c0 -8 -4 -12 -9 -9
|
||||||
|
-5 3 -6 10 -3 15 9 13 12 11 12 -6z m-323 -3 c3 -5 -1 -9 -9 -9 -8 0 -12 4 -9
|
||||||
|
9 3 4 7 8 9 8 2 0 6 -4 9 -8z m-1273 -119 c13 -16 12 -17 -3 -4 -10 7 -18 15
|
||||||
|
-18 17 0 8 8 3 21 -13z m1590 -90 c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0
|
||||||
|
8 8 3 21 -13z m-6911 -17 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21
|
||||||
|
21 21 13z m7235 -85 c3 -5 2 -12 -3 -15 -5 -3 -9 1 -9 9 0 17 3 19 12 6z
|
||||||
|
m-310 -11 c-3 -5 -12 -10 -18 -10 -7 0 -6 4 3 10 19 12 23 12 15 0z m-6555
|
||||||
|
-34 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m4581 -53
|
||||||
|
c13 -16 12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-4106 -33 c-3 -5
|
||||||
|
-12 -10 -18 -10 -7 0 -6 4 3 10 19 12 23 12 15 0z m-485 -40 c0 -5 -5 -10 -11
|
||||||
|
-10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m320 0 c0 -5 -2 -10 -4
|
||||||
|
-10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-409 -47 c13 -16 12
|
||||||
|
-17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m4739 13 c0 -2 -8 -10 -17 -17
|
||||||
|
-16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-3610 -70 c0 -2 -8 -10 -17 -17 -16
|
||||||
|
-13 -17 -12 -4 4 13 16 21 21 21 13z m-245 -55 c3 -5 2 -12 -3 -15 -5 -3 -9 1
|
||||||
|
-9 9 0 17 3 19 12 6z m4165 5 c0 -2 -7 -7 -16 -10 -8 -3 -12 -2 -9 4 6 10 25
|
||||||
|
14 25 6z m-3609 -53 c13 -16 12 -17 -3 -4 -17 13 -22 21 -14 21 2 0 10 -8 17
|
||||||
|
-17z m4975 -115 c3 -4 -1 -5 -10 -4 -8 1 -18 5 -22 8 -3 4 1 5 10 4 8 -1 18
|
||||||
|
-5 22 -8z m-5215 -51 c-10 -9 -11 -8 -5 6 3 10 9 15 12 12 3 -3 0 -11 -7 -18z
|
||||||
|
m339 19 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m4155
|
||||||
|
-6 c-3 -5 -12 -10 -18 -10 -7 0 -6 4 3 10 19 12 23 12 15 0z m635 4 c0 -8 -19
|
||||||
|
-13 -24 -6 -3 5 1 9 9 9 8 0 15 -2 15 -3z m-645 -113 c3 -5 2 -12 -3 -15 -5
|
||||||
|
-3 -9 1 -9 9 0 17 3 19 12 6z m-4804 -24 c-10 -9 -11 -8 -5 6 3 10 9 15 12 12
|
||||||
|
3 -3 0 -11 -7 -18z m654 13 c3 -6 -1 -7 -9 -4 -18 7 -21 14 -7 14 6 0 13 -4
|
||||||
|
16 -10z m1835 -104 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21
|
||||||
|
13z m680 -120 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m-1560 -10 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2
|
||||||
|
10 -4z m3120 -30 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21
|
||||||
|
13z m-1842 -61 c-3 -3 -9 2 -12 12 -6 14 -5 15 5 6 7 -7 10 -15 7 -18z m-2998
|
||||||
|
5 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z
|
||||||
|
m120 4 c0 -8 -19 -13 -24 -6 -3 5 1 9 9 9 8 0 15 -2 15 -3z m2991 -11 c13 -16
|
||||||
|
12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m1603 1 c3 -8 2 -12 -4 -9
|
||||||
|
-6 3 -10 10 -10 16 0 14 7 11 14 -7z m-2994 -18 c0 -2 -8 -10 -17 -17 -16 -13
|
||||||
|
-17 -12 -4 4 13 16 21 21 21 13z m-1763 -51 c0 -8 -4 -15 -9 -15 -10 0 -11 14
|
||||||
|
-1 23 9 10 10 9 10 -8z m640 -160 c0 -8 -4 -12 -9 -9 -5 3 -6 10 -3 15 9 13
|
||||||
|
12 11 12 -6z m723 1 c0 -2 -7 -7 -16 -10 -8 -3 -12 -2 -9 4 6 10 25 14 25 6z
|
||||||
|
m1676 -92 c1 -9 0 -13 -4 -10 -3 4 -7 14 -8 22 -1 9 0 13 4 10 3 -4 7 -14 8
|
||||||
|
-22z m-2561 7 c3 -5 2 -12 -3 -15 -5 -3 -9 1 -9 9 0 17 3 19 12 6z m95 -35 c0
|
||||||
|
-2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m4080 0 c0 -2 -8
|
||||||
|
-10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-650 -70 c0 -2 -8 -10
|
||||||
|
-17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-3520 -10 c0 -3 -4 -8 -10
|
||||||
|
-11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z m4160 -46 c0 -5 -5
|
||||||
|
-10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m-49 -87 c13 -16
|
||||||
|
12 -17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-510 -30 c13 -16 12 -17
|
||||||
|
-3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-2841 -27 c0 -2 -8 -10 -17 -17
|
||||||
|
-16 -13 -17 -12 -4 4 13 16 21 21 21 13z m561 -13 c13 -16 12 -17 -3 -4 -17
|
||||||
|
13 -22 21 -14 21 2 0 10 -8 17 -17z m1120 0 c13 -16 12 -17 -3 -4 -17 13 -22
|
||||||
|
21 -14 21 2 0 10 -8 17 -17z m-207 -1 c3 -5 -1 -9 -9 -9 -8 0 -12 4 -9 9 3 4
|
||||||
|
7 8 9 8 2 0 6 -4 9 -8z m320 -8 c3 -8 2 -12 -4 -9 -6 3 -10 10 -10 16 0 14 7
|
||||||
|
11 14 -7z m-1024 -28 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21
|
||||||
|
21 13z m2160 0 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m-1400 -40 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m1394 -84 c3 -5 -1 -9 -9 -9 -8 0 -12 4 -9 9 3 4 7 8 9 8 2 0 6 -4 9 -8z
|
||||||
|
m-714 -36 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z
|
||||||
|
m-530 -126 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4
|
||||||
|
11 -10z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 19 KiB |
19
web/public/site.webmanifest
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"short_name": "",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import Button from '@material-ui/core/Button'
|
import Button from '@material-ui/core/Button'
|
||||||
import Dialog from '@material-ui/core/Dialog'
|
import Dialog from '@material-ui/core/Dialog'
|
||||||
import { torrentsHost, torrentUploadHost } from 'utils/Hosts'
|
import { torrentsHost, torrentUploadHost } from 'utils/Hosts'
|
||||||
@@ -9,6 +9,9 @@ import useChangeLanguage from 'utils/useChangeLanguage'
|
|||||||
import { useMediaQuery } from '@material-ui/core'
|
import { useMediaQuery } from '@material-ui/core'
|
||||||
import CircularProgress from '@material-ui/core/CircularProgress'
|
import CircularProgress from '@material-ui/core/CircularProgress'
|
||||||
import usePreviousState from 'utils/usePreviousState'
|
import usePreviousState from 'utils/usePreviousState'
|
||||||
|
import { useQuery } from 'react-query'
|
||||||
|
import { getTorrents } from 'utils/Utils'
|
||||||
|
import parseTorrent from 'parse-torrent'
|
||||||
|
|
||||||
import { checkImageURL, getMoviePosters, chechTorrentSource, parseTorrentTitle } from './helpers'
|
import { checkImageURL, getMoviePosters, chechTorrentSource, parseTorrentTitle } from './helpers'
|
||||||
import { ButtonWrapper, Content, Header } from './style'
|
import { ButtonWrapper, Content, Header } from './style'
|
||||||
@@ -23,31 +26,75 @@ export default function AddDialog({
|
|||||||
poster: originalPoster,
|
poster: originalPoster,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const isEditMode = !!originalHash
|
||||||
const [torrentSource, setTorrentSource] = useState(originalHash || '')
|
const [torrentSource, setTorrentSource] = useState(originalHash || '')
|
||||||
const [title, setTitle] = useState(originalTitle || '')
|
const [title, setTitle] = useState(originalTitle || '')
|
||||||
|
const [originalTorrentTitle, setOriginalTorrentTitle] = useState('')
|
||||||
|
const [parsedTitle, setParsedTitle] = useState('')
|
||||||
const [posterUrl, setPosterUrl] = useState(originalPoster || '')
|
const [posterUrl, setPosterUrl] = useState(originalPoster || '')
|
||||||
const [isPosterUrlCorrect, setIsPosterUrlCorrect] = useState(false)
|
const [isPosterUrlCorrect, setIsPosterUrlCorrect] = useState(false)
|
||||||
const [isTorrentSourceCorrect, setIsTorrentSourceCorrect] = useState(false)
|
const [isTorrentSourceCorrect, setIsTorrentSourceCorrect] = useState(false)
|
||||||
|
const [isHashAlreadyExists, setIsHashAlreadyExists] = useState(false)
|
||||||
const [posterList, setPosterList] = useState()
|
const [posterList, setPosterList] = useState()
|
||||||
const [isUserInteractedWithPoster, setIsUserInteractedWithPoster] = useState(false)
|
const [isUserInteractedWithPoster, setIsUserInteractedWithPoster] = useState(isEditMode)
|
||||||
const [currentLang] = useChangeLanguage()
|
const [currentLang] = useChangeLanguage()
|
||||||
const [selectedFile, setSelectedFile] = useState()
|
const [selectedFile, setSelectedFile] = useState()
|
||||||
const [posterSearchLanguage, setPosterSearchLanguage] = useState(currentLang === 'ru' ? 'ru' : 'en')
|
const [posterSearchLanguage, setPosterSearchLanguage] = useState(currentLang === 'ru' ? 'ru' : 'en')
|
||||||
const [isLoadingButton, setIsLoadingButton] = useState(false)
|
const [isLoadingButton, setIsLoadingButton] = useState(false)
|
||||||
const [skipDebounce, setSkipDebounce] = useState(false)
|
const [skipDebounce, setSkipDebounce] = useState(false)
|
||||||
const [isEditMode, setIsEditMode] = useState(false)
|
const [isCustomTitleEnabled, setIsCustomTitleEnabled] = useState(false)
|
||||||
|
|
||||||
|
const { data: torrents } = useQuery('torrents', getTorrents, {
|
||||||
|
retry: 1,
|
||||||
|
refetchInterval: 1000,
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const allHashes = torrents.map(({ hash }) => hash)
|
||||||
|
|
||||||
|
parseTorrent.remote(selectedFile || torrentSource, (err, { infoHash } = {}) => {
|
||||||
|
setIsHashAlreadyExists(allHashes.includes(infoHash))
|
||||||
|
})
|
||||||
|
}, [selectedFile, torrentSource, torrents])
|
||||||
|
|
||||||
const fullScreen = useMediaQuery('@media (max-width:930px)')
|
const fullScreen = useMediaQuery('@media (max-width:930px)')
|
||||||
|
|
||||||
|
const updateTitleFromSource = useCallback(() => {
|
||||||
|
parseTorrentTitle(selectedFile || torrentSource, ({ parsedTitle, originalName }) => {
|
||||||
|
if (!originalName) return
|
||||||
|
|
||||||
|
setSkipDebounce(true)
|
||||||
|
setTitle('')
|
||||||
|
setIsCustomTitleEnabled(false)
|
||||||
|
setOriginalTorrentTitle(originalName)
|
||||||
|
setParsedTitle(parsedTitle)
|
||||||
|
})
|
||||||
|
}, [selectedFile, torrentSource])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!selectedFile && !torrentSource) {
|
||||||
|
setTitle('')
|
||||||
|
setOriginalTorrentTitle('')
|
||||||
|
setParsedTitle('')
|
||||||
|
setIsCustomTitleEnabled(false)
|
||||||
|
setPosterList()
|
||||||
|
removePoster()
|
||||||
|
setIsUserInteractedWithPoster(false)
|
||||||
|
}
|
||||||
|
}, [selectedFile, torrentSource])
|
||||||
|
|
||||||
|
const removePoster = () => {
|
||||||
|
setIsPosterUrlCorrect(false)
|
||||||
|
setPosterUrl('')
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (originalHash) {
|
if (originalHash) {
|
||||||
setIsEditMode(true)
|
|
||||||
|
|
||||||
checkImageURL(posterUrl).then(correctImage => {
|
checkImageURL(posterUrl).then(correctImage => {
|
||||||
correctImage ? setIsPosterUrlCorrect(true) : removePoster()
|
correctImage ? setIsPosterUrlCorrect(true) : removePoster()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// This is needed only on mount
|
// This is needed only on mount. Do not remove line below
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@@ -85,54 +132,51 @@ export default function AddDialog({
|
|||||||
|
|
||||||
const delayedPosterSearch = useMemo(() => debounce(posterSearch, 700), [posterSearch])
|
const delayedPosterSearch = useMemo(() => debounce(posterSearch, 700), [posterSearch])
|
||||||
|
|
||||||
const prevTitleState = usePreviousState(title)
|
|
||||||
const prevTorrentSourceState = usePreviousState(torrentSource)
|
const prevTorrentSourceState = usePreviousState(torrentSource)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// if torrentSource is updated then we are checking that source is valid and getting title from the source
|
|
||||||
const torrentSourceChanged = torrentSource !== prevTorrentSourceState
|
|
||||||
|
|
||||||
const isCorrectSource = chechTorrentSource(torrentSource)
|
const isCorrectSource = chechTorrentSource(torrentSource)
|
||||||
if (!isCorrectSource) return setIsTorrentSourceCorrect(false)
|
if (!isCorrectSource) return setIsTorrentSourceCorrect(false)
|
||||||
|
|
||||||
setIsTorrentSourceCorrect(true)
|
setIsTorrentSourceCorrect(true)
|
||||||
|
|
||||||
if (torrentSourceChanged) {
|
// if torrentSource is updated then we are getting title from the source
|
||||||
parseTorrentTitle(selectedFile || torrentSource, newTitle => {
|
const torrentSourceChanged = torrentSource !== prevTorrentSourceState
|
||||||
if (!newTitle) return
|
if (!torrentSourceChanged) return
|
||||||
|
|
||||||
setSkipDebounce(true)
|
updateTitleFromSource()
|
||||||
setTitle(newTitle)
|
}, [prevTorrentSourceState, selectedFile, torrentSource, updateTitleFromSource])
|
||||||
})
|
|
||||||
}
|
const prevTitleState = usePreviousState(title)
|
||||||
}, [prevTorrentSourceState, selectedFile, torrentSource])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// if title exists and title was changed then search poster.
|
// if title exists and title was changed then search poster.
|
||||||
const titleChanged = title !== prevTitleState
|
const titleChanged = title !== prevTitleState
|
||||||
if (!titleChanged) return
|
if (!titleChanged && !parsedTitle) return
|
||||||
|
|
||||||
if (skipDebounce) {
|
if (skipDebounce) {
|
||||||
posterSearch(title, posterSearchLanguage)
|
posterSearch(title || parsedTitle, posterSearchLanguage)
|
||||||
setSkipDebounce(false)
|
setSkipDebounce(false)
|
||||||
|
} else if (!title) {
|
||||||
|
if (parsedTitle) {
|
||||||
|
posterSearch(parsedTitle, posterSearchLanguage)
|
||||||
} else {
|
} else {
|
||||||
title === '' ? removePoster() : delayedPosterSearch(title, posterSearchLanguage)
|
delayedPosterSearch.cancel()
|
||||||
|
!isUserInteractedWithPoster && removePoster()
|
||||||
}
|
}
|
||||||
}, [title, prevTitleState, delayedPosterSearch, posterSearch, posterSearchLanguage, skipDebounce])
|
} else {
|
||||||
|
delayedPosterSearch(title, posterSearchLanguage)
|
||||||
const removePoster = () => {
|
|
||||||
setIsPosterUrlCorrect(false)
|
|
||||||
setPosterUrl('')
|
|
||||||
}
|
}
|
||||||
|
}, [
|
||||||
useEffect(() => {
|
title,
|
||||||
if (!selectedFile && !torrentSource) {
|
parsedTitle,
|
||||||
setTitle('')
|
prevTitleState,
|
||||||
setPosterList()
|
delayedPosterSearch,
|
||||||
removePoster()
|
posterSearch,
|
||||||
setIsUserInteractedWithPoster(false)
|
posterSearchLanguage,
|
||||||
}
|
skipDebounce,
|
||||||
}, [selectedFile, torrentSource])
|
isUserInteractedWithPoster,
|
||||||
|
])
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
setIsLoadingButton(true)
|
setIsLoadingButton(true)
|
||||||
@@ -142,7 +186,7 @@ export default function AddDialog({
|
|||||||
.post(torrentsHost(), {
|
.post(torrentsHost(), {
|
||||||
action: 'set',
|
action: 'set',
|
||||||
hash: originalHash,
|
hash: originalHash,
|
||||||
title: title === '' ? originalName : title,
|
title: title || originalName,
|
||||||
poster: posterUrl,
|
poster: posterUrl,
|
||||||
})
|
})
|
||||||
.finally(handleClose)
|
.finally(handleClose)
|
||||||
@@ -185,13 +229,16 @@ export default function AddDialog({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<RightSideComponent
|
<RightSideComponent
|
||||||
|
originalTorrentTitle={originalTorrentTitle}
|
||||||
setTitle={setTitle}
|
setTitle={setTitle}
|
||||||
setPosterUrl={setPosterUrl}
|
setPosterUrl={setPosterUrl}
|
||||||
setIsPosterUrlCorrect={setIsPosterUrlCorrect}
|
setIsPosterUrlCorrect={setIsPosterUrlCorrect}
|
||||||
setIsUserInteractedWithPoster={setIsUserInteractedWithPoster}
|
setIsUserInteractedWithPoster={setIsUserInteractedWithPoster}
|
||||||
setPosterList={setPosterList}
|
setPosterList={setPosterList}
|
||||||
isTorrentSourceCorrect={isTorrentSourceCorrect}
|
isTorrentSourceCorrect={isTorrentSourceCorrect}
|
||||||
|
isHashAlreadyExists={isHashAlreadyExists}
|
||||||
title={title}
|
title={title}
|
||||||
|
parsedTitle={parsedTitle}
|
||||||
posterUrl={posterUrl}
|
posterUrl={posterUrl}
|
||||||
isPosterUrlCorrect={isPosterUrlCorrect}
|
isPosterUrlCorrect={isPosterUrlCorrect}
|
||||||
posterList={posterList}
|
posterList={posterList}
|
||||||
@@ -200,7 +247,11 @@ export default function AddDialog({
|
|||||||
setPosterSearchLanguage={setPosterSearchLanguage}
|
setPosterSearchLanguage={setPosterSearchLanguage}
|
||||||
posterSearch={posterSearch}
|
posterSearch={posterSearch}
|
||||||
removePoster={removePoster}
|
removePoster={removePoster}
|
||||||
|
updateTitleFromSource={updateTitleFromSource}
|
||||||
torrentSource={torrentSource}
|
torrentSource={torrentSource}
|
||||||
|
isCustomTitleEnabled={isCustomTitleEnabled}
|
||||||
|
setIsCustomTitleEnabled={setIsCustomTitleEnabled}
|
||||||
|
isEditMode={isEditMode}
|
||||||
/>
|
/>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
||||||
@@ -212,7 +263,7 @@ export default function AddDialog({
|
|||||||
<Button
|
<Button
|
||||||
variant='contained'
|
variant='contained'
|
||||||
style={{ minWidth: '110px' }}
|
style={{ minWidth: '110px' }}
|
||||||
disabled={!torrentSource}
|
disabled={!torrentSource || (isHashAlreadyExists && !isEditMode) || !isTorrentSourceCorrect}
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
color='primary'
|
color='primary'
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ export default function LeftSideComponent({
|
|||||||
onChange={handleTorrentSourceChange}
|
onChange={handleTorrentSourceChange}
|
||||||
value={torrentSource}
|
value={torrentSource}
|
||||||
margin='dense'
|
margin='dense'
|
||||||
label={t('TorrentSourceLink')}
|
label={t('AddDialog.TorrentSourceLink')}
|
||||||
helperText={t('TorrentSourceOptions')}
|
helperText={t('AddDialog.TorrentSourceOptions')}
|
||||||
type='text'
|
type='text'
|
||||||
fullWidth
|
fullWidth
|
||||||
onFocus={() => setIsTorrentSourceActive(true)}
|
onFocus={() => setIsTorrentSourceActive(true)}
|
||||||
@@ -74,11 +74,11 @@ export default function LeftSideComponent({
|
|||||||
) : (
|
) : (
|
||||||
<LeftSideBottomSectionNoFile isDragActive={isDragActive} {...getRootProps()}>
|
<LeftSideBottomSectionNoFile isDragActive={isDragActive} {...getRootProps()}>
|
||||||
<input {...getInputProps()} />
|
<input {...getInputProps()} />
|
||||||
<div>{t('AppendFile.Or')}</div>
|
<div>{t('AddDialog.AppendFile.Or')}</div>
|
||||||
|
|
||||||
<IconWrapper>
|
<IconWrapper>
|
||||||
<AddItemIcon color='primary' />
|
<AddItemIcon color='primary' />
|
||||||
<div>{t('AppendFile.ClickOrDrag')}</div>
|
<div>{t('AddDialog.AppendFile.ClickOrDrag')}</div>
|
||||||
</IconWrapper>
|
</IconWrapper>
|
||||||
</LeftSideBottomSectionNoFile>
|
</LeftSideBottomSectionNoFile>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { NoImageIcon } from 'icons'
|
import { NoImageIcon } from 'icons'
|
||||||
import { TextField } from '@material-ui/core'
|
import { IconButton, InputAdornment, TextField } from '@material-ui/core'
|
||||||
|
import { CheckBox as CheckBoxIcon } from '@material-ui/icons'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ClearPosterButton,
|
ClearPosterButton,
|
||||||
@@ -21,7 +22,9 @@ export default function RightSideComponent({
|
|||||||
setIsUserInteractedWithPoster,
|
setIsUserInteractedWithPoster,
|
||||||
setPosterList,
|
setPosterList,
|
||||||
isTorrentSourceCorrect,
|
isTorrentSourceCorrect,
|
||||||
|
isHashAlreadyExists,
|
||||||
title,
|
title,
|
||||||
|
parsedTitle,
|
||||||
posterUrl,
|
posterUrl,
|
||||||
isPosterUrlCorrect,
|
isPosterUrlCorrect,
|
||||||
posterList,
|
posterList,
|
||||||
@@ -31,6 +34,11 @@ export default function RightSideComponent({
|
|||||||
posterSearch,
|
posterSearch,
|
||||||
removePoster,
|
removePoster,
|
||||||
torrentSource,
|
torrentSource,
|
||||||
|
originalTorrentTitle,
|
||||||
|
updateTitleFromSource,
|
||||||
|
isCustomTitleEnabled,
|
||||||
|
setIsCustomTitleEnabled,
|
||||||
|
isEditMode,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
@@ -49,13 +57,61 @@ export default function RightSideComponent({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RightSide>
|
<RightSide>
|
||||||
<RightSideContainer isHidden={!isTorrentSourceCorrect}>
|
<RightSideContainer isHidden={!isTorrentSourceCorrect || (isHashAlreadyExists && !isEditMode)}>
|
||||||
<TextField onChange={handleTitleChange} value={title} margin='dense' label={t('Title')} type='text' fullWidth />
|
{originalTorrentTitle ? (
|
||||||
|
<>
|
||||||
|
<TextField
|
||||||
|
value={originalTorrentTitle}
|
||||||
|
margin='dense'
|
||||||
|
label={t('AddDialog.OriginalTorrentTitle')}
|
||||||
|
type='text'
|
||||||
|
fullWidth
|
||||||
|
disabled={isCustomTitleEnabled}
|
||||||
|
InputProps={{ readOnly: true }}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
onChange={handleTitleChange}
|
||||||
|
onFocus={() => setIsCustomTitleEnabled(true)}
|
||||||
|
onBlur={({ target: { value } }) => !value && setIsCustomTitleEnabled(false)}
|
||||||
|
value={title}
|
||||||
|
margin='dense'
|
||||||
|
label={t('AddDialog.CustomTorrentTitle')}
|
||||||
|
type='text'
|
||||||
|
fullWidth
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position='end'>
|
||||||
|
<IconButton
|
||||||
|
style={{ padding: '0 0 0 7px' }}
|
||||||
|
onClick={() => {
|
||||||
|
setTitle('')
|
||||||
|
setIsCustomTitleEnabled(!isCustomTitleEnabled)
|
||||||
|
updateTitleFromSource()
|
||||||
|
setIsUserInteractedWithPoster(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CheckBoxIcon style={{ color: isCustomTitleEnabled ? 'green' : 'gray' }} />
|
||||||
|
</IconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<TextField
|
||||||
|
onChange={handleTitleChange}
|
||||||
|
value={title}
|
||||||
|
margin='dense'
|
||||||
|
label={t('AddDialog.TitleBlank')}
|
||||||
|
type='text'
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<TextField
|
<TextField
|
||||||
onChange={handlePosterUrlChange}
|
onChange={handlePosterUrlChange}
|
||||||
value={posterUrl}
|
value={posterUrl}
|
||||||
margin='dense'
|
margin='dense'
|
||||||
label={t('AddPosterLinkInput')}
|
label={t('AddDialog.AddPosterLinkInput')}
|
||||||
type='url'
|
type='url'
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
@@ -81,7 +137,9 @@ export default function RightSideComponent({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
const newLanguage = posterSearchLanguage === 'en' ? 'ru' : 'en'
|
const newLanguage = posterSearchLanguage === 'en' ? 'ru' : 'en'
|
||||||
setPosterSearchLanguage(newLanguage)
|
setPosterSearchLanguage(newLanguage)
|
||||||
posterSearch(title, newLanguage, { shouldRefreshMainPoster: true })
|
posterSearch(isCustomTitleEnabled ? title : originalTorrentTitle ? parsedTitle : title, newLanguage, {
|
||||||
|
shouldRefreshMainPoster: true,
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
showbutton={+isPosterUrlCorrect}
|
showbutton={+isPosterUrlCorrect}
|
||||||
color='primary'
|
color='primary'
|
||||||
@@ -108,11 +166,15 @@ export default function RightSideComponent({
|
|||||||
</RightSideContainer>
|
</RightSideContainer>
|
||||||
|
|
||||||
<RightSideContainer
|
<RightSideContainer
|
||||||
isError={torrentSource && !isTorrentSourceCorrect}
|
isError={torrentSource && (!isTorrentSourceCorrect || isHashAlreadyExists)}
|
||||||
notificationMessage={
|
notificationMessage={
|
||||||
!torrentSource ? t('AddTorrentSourceNotification') : !isTorrentSourceCorrect && t('WrongTorrentSource')
|
!torrentSource
|
||||||
|
? t('AddDialog.AddTorrentSourceNotification')
|
||||||
|
: !isTorrentSourceCorrect
|
||||||
|
? t('AddDialog.WrongTorrentSource')
|
||||||
|
: isHashAlreadyExists && t('AddDialog.HashExists')
|
||||||
}
|
}
|
||||||
isHidden={isTorrentSourceCorrect}
|
isHidden={isEditMode || (isTorrentSourceCorrect && !isHashAlreadyExists)}
|
||||||
/>
|
/>
|
||||||
</RightSide>
|
</RightSide>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -32,14 +32,14 @@ export const checkImageURL = async url => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const magnetRegex = /^magnet:\?xt=urn:[a-z0-9].*/i
|
const magnetRegex = /^magnet:\?xt=urn:[a-z0-9].*/i
|
||||||
const hashRegex = /^\b[0-9a-f]{32}\b$|^\b[0-9a-f]{40}\b$|^\b[0-9a-f]{64}\b$/i
|
export const hashRegex = /^\b[0-9a-f]{32}\b$|^\b[0-9a-f]{40}\b$|^\b[0-9a-f]{64}\b$/i
|
||||||
const torrentRegex = /^.*\.(torrent)$/i
|
const torrentRegex = /^.*\.(torrent)$/i
|
||||||
export const chechTorrentSource = source =>
|
export const chechTorrentSource = source =>
|
||||||
source.match(hashRegex) !== null || source.match(magnetRegex) !== null || source.match(torrentRegex) !== null
|
source.match(hashRegex) !== null || source.match(magnetRegex) !== null || source.match(torrentRegex) !== null
|
||||||
|
|
||||||
export const parseTorrentTitle = (parsingSource, callback) => {
|
export const parseTorrentTitle = (parsingSource, callback) => {
|
||||||
parseTorrent.remote(parsingSource, (err, { name, files } = {}) => {
|
parseTorrent.remote(parsingSource, (err, { name, files } = {}) => {
|
||||||
if (!name || err) return callback(null)
|
if (!name || err) return callback({ parsedTitle: null, originalName: null })
|
||||||
|
|
||||||
const torrentName = ptt.parse(name).title
|
const torrentName = ptt.parse(name).title
|
||||||
const nameOfFileInsideTorrent = files ? ptt.parse(files[0].name).title : null
|
const nameOfFileInsideTorrent = files ? ptt.parse(files[0].name).title : null
|
||||||
@@ -50,6 +50,6 @@ export const parseTorrentTitle = (parsingSource, callback) => {
|
|||||||
newTitle = torrentName.length < nameOfFileInsideTorrent.length ? torrentName : nameOfFileInsideTorrent
|
newTitle = torrentName.length < nameOfFileInsideTorrent.length ? torrentName : nameOfFileInsideTorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(newTitle)
|
callback({ parsedTitle: newTitle, originalName: name })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const Header = styled.div`
|
|||||||
color: rgba(0, 0, 0, 0.87);
|
color: rgba(0, 0, 0, 0.87);
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%);
|
box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%);
|
||||||
padding: 15px 24px;
|
padding: 15px 24px;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -14,6 +14,7 @@ export const Header = styled.div`
|
|||||||
|
|
||||||
export const Content = styled.div`
|
export const Content = styled.div`
|
||||||
${({ isEditMode }) => css`
|
${({ isEditMode }) => css`
|
||||||
|
height: 550px;
|
||||||
background: linear-gradient(145deg, #e4f6ed, #b5dec9);
|
background: linear-gradient(145deg, #e4f6ed, #b5dec9);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -29,6 +30,10 @@ export const Content = styled.div`
|
|||||||
@media (max-width: 930px) {
|
@media (max-width: 930px) {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
align-content: start;
|
||||||
|
}
|
||||||
`}
|
`}
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -38,7 +43,7 @@ export const RightSide = styled.div`
|
|||||||
|
|
||||||
export const RightSideContainer = styled.div`
|
export const RightSideContainer = styled.div`
|
||||||
${({ isHidden, notificationMessage, isError }) => css`
|
${({ isHidden, notificationMessage, isError }) => css`
|
||||||
height: 455px;
|
height: 530px;
|
||||||
|
|
||||||
${notificationMessage &&
|
${notificationMessage &&
|
||||||
css`
|
css`
|
||||||
@@ -54,7 +59,7 @@ export const RightSideContainer = styled.div`
|
|||||||
background: ${isError ? '#cda184' : '#84cda7'};
|
background: ${isError ? '#cda184' : '#84cda7'};
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 52%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@@ -65,6 +70,10 @@ export const RightSideContainer = styled.div`
|
|||||||
css`
|
css`
|
||||||
display: none;
|
display: none;
|
||||||
`};
|
`};
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
height: 170px;
|
||||||
|
}
|
||||||
`}
|
`}
|
||||||
`
|
`
|
||||||
export const LeftSide = styled.div`
|
export const LeftSide = styled.div`
|
||||||
@@ -88,7 +97,7 @@ export const LeftSideBottomSectionNoFile = styled.div`
|
|||||||
${({ isDragActive }) => isDragActive && `border: 4px dashed green`};
|
${({ isDragActive }) => isDragActive && `border: 4px dashed green`};
|
||||||
|
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
grid-template-rows: 100px 1fr;
|
grid-template-rows: 130px 1fr;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
:hover {
|
:hover {
|
||||||
@@ -104,6 +113,15 @@ export const LeftSideBottomSectionNoFile = styled.div`
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
grid-template-rows: 40% 1fr;
|
grid-template-rows: 40% 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
height: 170px;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
|
||||||
|
> div:first-of-type {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const LeftSideBottomSectionFileSelected = styled.div`
|
export const LeftSideBottomSectionFileSelected = styled.div`
|
||||||
@@ -113,6 +131,10 @@ export const LeftSideBottomSectionFileSelected = styled.div`
|
|||||||
@media (max-width: 930px) {
|
@media (max-width: 930px) {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
height: 170px;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const TorrentIconWrapper = styled.div`
|
export const TorrentIconWrapper = styled.div`
|
||||||
@@ -281,7 +303,7 @@ export const PosterLanguageSwitch = styled.div`
|
|||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
color: #e1f4eb;
|
color: #e1f4eb;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import { playlistAllHost } from 'utils/Hosts'
|
|
||||||
import Divider from '@material-ui/core/Divider'
|
import Divider from '@material-ui/core/Divider'
|
||||||
import ListItem from '@material-ui/core/ListItem'
|
import ListItem from '@material-ui/core/ListItem'
|
||||||
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
||||||
import ListItemText from '@material-ui/core/ListItemText'
|
import ListItemText from '@material-ui/core/ListItemText'
|
||||||
import { CreditCard as CreditCardIcon, List as ListIcon, Language as LanguageIcon } from '@material-ui/icons'
|
import { CreditCard as CreditCardIcon } from '@material-ui/icons'
|
||||||
import List from '@material-ui/core/List'
|
import List from '@material-ui/core/List'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import useChangeLanguage from 'utils/useChangeLanguage'
|
|
||||||
import AddDialogButton from 'components/Add'
|
import AddDialogButton from 'components/Add'
|
||||||
import SettingsDialog from 'components/Settings'
|
import SettingsDialog from 'components/Settings'
|
||||||
import RemoveAll from 'components/RemoveAll'
|
import RemoveAll from 'components/RemoveAll'
|
||||||
@@ -16,7 +14,6 @@ import CloseServer from 'components/CloseServer'
|
|||||||
import { AppSidebarStyle } from './style'
|
import { AppSidebarStyle } from './style'
|
||||||
|
|
||||||
export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) {
|
export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) {
|
||||||
const [currentLang, changeLang] = useChangeLanguage()
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -24,12 +21,6 @@ export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) {
|
|||||||
<List>
|
<List>
|
||||||
<AddDialogButton />
|
<AddDialogButton />
|
||||||
<RemoveAll />
|
<RemoveAll />
|
||||||
<ListItem button component='a' target='_blank' href={playlistAllHost()}>
|
|
||||||
<ListItemIcon>
|
|
||||||
<ListIcon />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText primary={t('PlaylistAll')} />
|
|
||||||
</ListItem>
|
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
@@ -37,20 +28,14 @@ export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) {
|
|||||||
<List>
|
<List>
|
||||||
<SettingsDialog />
|
<SettingsDialog />
|
||||||
|
|
||||||
<ListItem button onClick={() => (currentLang === 'en' ? changeLang('ru') : changeLang('en'))}>
|
|
||||||
<ListItemIcon>
|
|
||||||
<LanguageIcon />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText primary={t('ChooseLanguage')} />
|
|
||||||
</ListItem>
|
|
||||||
|
|
||||||
<AboutDialog />
|
|
||||||
<CloseServer />
|
<CloseServer />
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<List>
|
<List>
|
||||||
|
<AboutDialog />
|
||||||
|
|
||||||
<ListItem button onClick={() => setIsDonationDialogOpen(true)}>
|
<ListItem button onClick={() => setIsDonationDialogOpen(true)}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<CreditCardIcon />
|
<CreditCardIcon />
|
||||||
|
|||||||
@@ -10,19 +10,22 @@ import axios from 'axios'
|
|||||||
import TorrentList from 'components/TorrentList'
|
import TorrentList from 'components/TorrentList'
|
||||||
import DonateSnackbar from 'components/Donate'
|
import DonateSnackbar from 'components/Donate'
|
||||||
import DonateDialog from 'components/Donate/DonateDialog'
|
import DonateDialog from 'components/Donate/DonateDialog'
|
||||||
|
import useChangeLanguage from 'utils/useChangeLanguage'
|
||||||
|
|
||||||
import { AppWrapper, AppHeader } from './style'
|
import { AppWrapper, AppHeader, LanguageSwitch } from './style'
|
||||||
import Sidebar from './Sidebar'
|
import Sidebar from './Sidebar'
|
||||||
|
|
||||||
const baseTheme = createMuiTheme({
|
const baseTheme = createMuiTheme({
|
||||||
overrides: { MuiCssBaseline: { '@global': { html: { WebkitFontSmoothing: 'auto' } } } },
|
overrides: { MuiCssBaseline: { '@global': { html: { WebkitFontSmoothing: 'auto' } } } },
|
||||||
palette: { primary: { main: '#00a572' }, secondary: { main: '#ffa724' }, tonalOffset: 0.2 },
|
palette: { primary: { main: '#00a572' }, secondary: { main: '#ffa724' }, tonalOffset: 0.2 },
|
||||||
|
typography: { fontFamily: 'Open Sans, sans-serif' },
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false)
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false)
|
||||||
const [isDonationDialogOpen, setIsDonationDialogOpen] = useState(false)
|
const [isDonationDialogOpen, setIsDonationDialogOpen] = useState(false)
|
||||||
const [torrServerVersion, setTorrServerVersion] = useState('')
|
const [torrServerVersion, setTorrServerVersion] = useState('')
|
||||||
|
const [currentLang, changeLang] = useChangeLanguage()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
axios.get(echoHost()).then(({ data }) => setTorrServerVersion(data))
|
axios.get(echoHost()).then(({ data }) => setTorrServerVersion(data))
|
||||||
@@ -48,6 +51,12 @@ export default function App() {
|
|||||||
<Typography variant='h6' noWrap>
|
<Typography variant='h6' noWrap>
|
||||||
TorrServer {torrServerVersion}
|
TorrServer {torrServerVersion}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
|
<div style={{ justifySelf: 'end' }}>
|
||||||
|
<LanguageSwitch onClick={() => (currentLang === 'en' ? changeLang('ru') : changeLang('en'))}>
|
||||||
|
{currentLang === 'en' ? 'RU' : 'EN'}
|
||||||
|
</LanguageSwitch>
|
||||||
|
</div>
|
||||||
</AppHeader>
|
</AppHeader>
|
||||||
|
|
||||||
<Sidebar isDrawerOpen={isDrawerOpen} setIsDonationDialogOpen={setIsDonationDialogOpen} />
|
<Sidebar isDrawerOpen={isDrawerOpen} setIsDonationDialogOpen={setIsDonationDialogOpen} />
|
||||||
|
|||||||
@@ -21,8 +21,10 @@ export const AppHeader = styled.div`
|
|||||||
background: #00a572;
|
background: #00a572;
|
||||||
color: rgba(0, 0, 0, 0.87);
|
color: rgba(0, 0, 0, 0.87);
|
||||||
grid-area: head;
|
grid-area: head;
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-auto-flow: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
grid-template-columns: repeat(2, max-content) 1fr;
|
||||||
box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%);
|
box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%);
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
@@ -63,3 +65,26 @@ export const TorrentListWrapper = styled.div`
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const LanguageSwitch = styled.div`
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #56b887;
|
||||||
|
height: 35px;
|
||||||
|
width: 35px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-weight: 600;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
color: #44795e;
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
background: #7ec9a3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
height: 28px;
|
||||||
|
width: 28px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ export const pieceSizeForMiniMap = 23
|
|||||||
export const gapBetweenPieces = 3
|
export const gapBetweenPieces = 3
|
||||||
export const miniCacheMaxHeight = 340
|
export const miniCacheMaxHeight = 340
|
||||||
|
|
||||||
export const defaultBorderColor = '#eef2f4'
|
export const defaultBorderColor = '#dbf2e8'
|
||||||
export const defaultBackgroundColor = '#fff'
|
export const defaultBackgroundColor = '#fff'
|
||||||
export const completeColor = '#00a572'
|
export const completeColor = '#00a572'
|
||||||
export const progressColor = '#ffa724'
|
export const progressColor = '#ffa724'
|
||||||
export const activeColor = '#000'
|
export const activeColor = '#000'
|
||||||
export const rangeColor = '#9a9aff'
|
export const rangeColor = '#ffa724'
|
||||||
|
|||||||
@@ -62,5 +62,5 @@ export const SnakeWrapper = styled.div`
|
|||||||
|
|
||||||
export const PercentagePiece = styled.div`
|
export const PercentagePiece = styled.div`
|
||||||
background: ${completeColor};
|
background: ${completeColor};
|
||||||
height: ${({ percentage }) => (percentage / 100) * 12}px;
|
height: ${({ percentage }) => percentage}%;
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { NoImageIcon } from 'icons'
|
import { NoImageIcon } from 'icons'
|
||||||
import { humanizeSize, shortenText } from 'utils/Utils'
|
import { humanizeSize, removeRedundantCharacters } from 'utils/Utils'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Button, ButtonGroup } from '@material-ui/core'
|
import { Button, ButtonGroup } from '@material-ui/core'
|
||||||
import ptt from 'parse-torrent-title'
|
import ptt from 'parse-torrent-title'
|
||||||
@@ -102,18 +102,27 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
|
|||||||
const bufferSize = settings?.PreloadBuffer ? Capacity : 33554432 // Default is 32mb if PreloadBuffer is false
|
const bufferSize = settings?.PreloadBuffer ? Capacity : 33554432 // Default is 32mb if PreloadBuffer is false
|
||||||
|
|
||||||
const getParsedTitle = () => {
|
const getParsedTitle = () => {
|
||||||
const newNameStrings = []
|
const newNameStringArr = []
|
||||||
|
|
||||||
const torrentParsedName = name && ptt.parse(name)
|
const torrentParsedName = name && ptt.parse(name)
|
||||||
|
|
||||||
if (title !== name) {
|
if (title !== name) {
|
||||||
newNameStrings.push(title)
|
newNameStringArr.push(removeRedundantCharacters(title))
|
||||||
} else if (torrentParsedName?.title) newNameStrings.push(torrentParsedName?.title)
|
} else if (torrentParsedName?.title) newNameStringArr.push(removeRedundantCharacters(torrentParsedName?.title))
|
||||||
|
|
||||||
if (torrentParsedName?.year) newNameStrings.push(torrentParsedName?.year)
|
// These 2 checks are needed to get year and resolution from torrent name if title does not have this info
|
||||||
if (torrentParsedName?.resolution) newNameStrings.push(torrentParsedName?.resolution)
|
if (torrentParsedName?.year && !newNameStringArr[0].includes(torrentParsedName?.year))
|
||||||
|
newNameStringArr.push(torrentParsedName?.year)
|
||||||
|
if (torrentParsedName?.resolution && !newNameStringArr[0].includes(torrentParsedName?.resolution))
|
||||||
|
newNameStringArr.push(torrentParsedName?.resolution)
|
||||||
|
|
||||||
return newNameStrings.join('. ')
|
const newNameString = newNameStringArr.join('. ')
|
||||||
|
|
||||||
|
// removeRedundantCharacters is returning ".." if it was "..."
|
||||||
|
const lastDotShouldBeAdded =
|
||||||
|
newNameString[newNameString.length - 1] === '.' && newNameString[newNameString.length - 2] === '.'
|
||||||
|
|
||||||
|
return lastDotShouldBeAdded ? `${newNameString}.` : newNameString
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -145,12 +154,19 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
{title && name !== title ? (
|
{title && name !== title ? (
|
||||||
|
getParsedTitle().length > 90 ? (
|
||||||
<>
|
<>
|
||||||
<SectionTitle>{shortenText(getParsedTitle(), 55)}</SectionTitle>
|
<SectionTitle>{ptt.parse(name).title}</SectionTitle>
|
||||||
<SectionSubName mb={20}>{shortenText(ptt.parse(name).title, 110)}</SectionSubName>
|
<SectionSubName mb={20}>{getParsedTitle()}</SectionSubName>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<SectionTitle mb={20}>{shortenText(getParsedTitle(), 55)}</SectionTitle>
|
<>
|
||||||
|
<SectionTitle>{getParsedTitle()}</SectionTitle>
|
||||||
|
<SectionSubName mb={20}>{ptt.parse(name).title}</SectionSubName>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<SectionTitle mb={20}>{getParsedTitle()}</SectionTitle>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<WidgetWrapper>
|
<WidgetWrapper>
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export const SectionTitle = styled.div`
|
|||||||
${({ mb }) => css`
|
${({ mb }) => css`
|
||||||
${mb && `margin-bottom: ${mb}px`};
|
${mb && `margin-bottom: ${mb}px`};
|
||||||
font-size: 35px;
|
font-size: 35px;
|
||||||
font-weight: 200;
|
font-weight: 300;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ export const WidgetFieldTitle = styled.div`
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
`
|
`
|
||||||
|
|
||||||
export const WidgetFieldIcon = styled.div`
|
export const WidgetFieldIcon = styled.div`
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'fontsource-roboto'
|
|
||||||
import { forwardRef, memo, useState } from 'react'
|
import { forwardRef, memo, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
UnfoldMore as UnfoldMoreIcon,
|
UnfoldMore as UnfoldMoreIcon,
|
||||||
@@ -6,7 +5,7 @@ import {
|
|||||||
Close as CloseIcon,
|
Close as CloseIcon,
|
||||||
Delete as DeleteIcon,
|
Delete as DeleteIcon,
|
||||||
} from '@material-ui/icons'
|
} from '@material-ui/icons'
|
||||||
import { getPeerString, humanizeSize, shortenText } from 'utils/Utils'
|
import { getPeerString, humanizeSize, removeRedundantCharacters } from 'utils/Utils'
|
||||||
import { torrentsHost } from 'utils/Hosts'
|
import { torrentsHost } from 'utils/Hosts'
|
||||||
import { NoImageIcon } from 'icons'
|
import { NoImageIcon } from 'icons'
|
||||||
import DialogTorrentDetailsContent from 'components/DialogTorrentDetailsContent'
|
import DialogTorrentDetailsContent from 'components/DialogTorrentDetailsContent'
|
||||||
@@ -40,7 +39,21 @@ const Torrent = ({ torrent }) => {
|
|||||||
const dropTorrent = () => axios.post(torrentsHost(), { action: 'drop', hash })
|
const dropTorrent = () => axios.post(torrentsHost(), { action: 'drop', hash })
|
||||||
const deleteTorrent = () => axios.post(torrentsHost(), { action: 'rem', hash })
|
const deleteTorrent = () => axios.post(torrentsHost(), { action: 'rem', hash })
|
||||||
|
|
||||||
const parsedTitle = (title || name) && ptt.parse(title || name).title
|
const getParsedTitle = () => {
|
||||||
|
const parse = key => ptt.parse(title || '')?.[key] || ptt.parse(name || '')?.[key]
|
||||||
|
|
||||||
|
const titleStrings = []
|
||||||
|
|
||||||
|
let parsedTitle = removeRedundantCharacters(parse('title'))
|
||||||
|
const parsedYear = parse('year')
|
||||||
|
const parsedResolution = parse('resolution')
|
||||||
|
if (parsedTitle) titleStrings.push(parsedTitle)
|
||||||
|
if (parsedYear) titleStrings.push(`(${parsedYear})`)
|
||||||
|
if (parsedResolution) titleStrings.push(`[${parsedResolution}]`)
|
||||||
|
parsedTitle = titleStrings.join(' ')
|
||||||
|
return { parsedTitle }
|
||||||
|
}
|
||||||
|
const { parsedTitle } = getParsedTitle()
|
||||||
|
|
||||||
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
|
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
|
||||||
const handleClickOpenEditDialog = () => setIsEditDialogOpen(true)
|
const handleClickOpenEditDialog = () => setIsEditDialogOpen(true)
|
||||||
@@ -78,7 +91,7 @@ const Torrent = ({ torrent }) => {
|
|||||||
<TorrentCardDescription>
|
<TorrentCardDescription>
|
||||||
<div className='description-title-wrapper'>
|
<div className='description-title-wrapper'>
|
||||||
<div className='description-section-name'>{t('Name')}</div>
|
<div className='description-section-name'>{t('Name')}</div>
|
||||||
<div className='description-torrent-title'>{shortenText(parsedTitle, 100)}</div>
|
<div className='description-torrent-title'>{parsedTitle}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='description-statistics-wrapper'>
|
<div className='description-statistics-wrapper'>
|
||||||
|
|||||||
@@ -87,10 +87,6 @@ export const TorrentCardDescription = styled.div`
|
|||||||
gap: 3px;
|
gap: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 770px) {
|
|
||||||
grid-template-rows: 56% 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description-title-wrapper {
|
.description-title-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -99,7 +95,7 @@ export const TorrentCardDescription = styled.div`
|
|||||||
.description-section-name {
|
.description-section-name {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
letter-spacing: 0.4px;
|
letter-spacing: 0.4px;
|
||||||
color: #216e47;
|
color: #216e47;
|
||||||
|
|
||||||
@@ -170,7 +166,6 @@ export const StyledButton = styled.button`
|
|||||||
background: #268757;
|
background: #268757;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
|
|
||||||
letter-spacing: 0.009em;
|
letter-spacing: 0.009em;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
svg {
|
svg {
|
||||||
|
|||||||
@@ -1,21 +1,11 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Typography } from '@material-ui/core'
|
import { Typography } from '@material-ui/core'
|
||||||
import { torrentsHost } from 'utils/Hosts'
|
|
||||||
import TorrentCard from 'components/TorrentCard'
|
import TorrentCard from 'components/TorrentCard'
|
||||||
import axios from 'axios'
|
|
||||||
import CircularProgress from '@material-ui/core/CircularProgress'
|
import CircularProgress from '@material-ui/core/CircularProgress'
|
||||||
import { TorrentListWrapper, CenteredGrid } from 'components/App/style'
|
import { TorrentListWrapper, CenteredGrid } from 'components/App/style'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useQuery } from 'react-query'
|
import { useQuery } from 'react-query'
|
||||||
|
import { getTorrents } from 'utils/Utils'
|
||||||
const getTorrents = async () => {
|
|
||||||
try {
|
|
||||||
const { data } = await axios.post(torrentsHost(), { action: 'list' })
|
|
||||||
return data
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function TorrentList() {
|
export default function TorrentList() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
body {
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
padding: 0;
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
box-sizing: inherit;
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
body {
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
font-family: "Open Sans", sans-serif;
|
||||||
monospace;
|
box-sizing: border-box;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
letter-spacing: -0.1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-family: "Open Sans", sans-serif;
|
||||||
|
letter-spacing: -0.1px;
|
||||||
}
|
}
|
||||||
@@ -2,21 +2,29 @@
|
|||||||
"About": "About",
|
"About": "About",
|
||||||
"Actions": "Actions",
|
"Actions": "Actions",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
"AddFromLink": "Add from Link",
|
"AddDialog": {
|
||||||
"AddNewTorrent": "Add new torrent",
|
|
||||||
"AddPosterLinkInput": "Poster link",
|
"AddPosterLinkInput": "Poster link",
|
||||||
"AddRetrackers": "Add retrackers",
|
|
||||||
"AddTorrentSourceNotification": "First add your torrent source",
|
"AddTorrentSourceNotification": "First add your torrent source",
|
||||||
"AppendFile": {
|
"AppendFile": {
|
||||||
"Or": "OR",
|
"Or": "OR",
|
||||||
"ClickOrDrag": "CLICK / DRAG & DROP (.torrent)"
|
"ClickOrDrag": "CLICK / DRAG & DROP (.torrent)"
|
||||||
},
|
},
|
||||||
|
"CustomTorrentTitle": "Custom title (optional)",
|
||||||
|
"HashExists": "This torrent is already in database",
|
||||||
|
"OriginalTorrentTitle": "Original torrent title",
|
||||||
|
"TitleBlank": "Title (blank for orig. torrent title)",
|
||||||
|
"TorrentSourceLink": "Torrent source link",
|
||||||
|
"TorrentSourceOptions": "magnet / hash / .torrent file link",
|
||||||
|
"WrongTorrentSource": "Wrong torrent source"
|
||||||
|
},
|
||||||
|
"AddFromLink": "Add from Link",
|
||||||
|
"AddNewTorrent": "Add new torrent",
|
||||||
|
"AddRetrackers": "Add retrackers",
|
||||||
"Buffer": "Preload Buffer / Cache",
|
"Buffer": "Preload Buffer / Cache",
|
||||||
"BufferNote": "Enable “Preload Buffer” in settings to see cache loading progress",
|
"BufferNote": "Enable “Preload Buffer” in settings to see cache loading progress",
|
||||||
"Cache": "Cache",
|
"Cache": "Cache",
|
||||||
"CacheSize": "Cache Size (Megabytes)",
|
"CacheSize": "Cache Size (Megabytes)",
|
||||||
"Cancel": "Cancel",
|
"Cancel": "Cancel",
|
||||||
"ChooseLanguage": "Russian",
|
|
||||||
"Clear": "Clear",
|
"Clear": "Clear",
|
||||||
"Close": "Close",
|
"Close": "Close",
|
||||||
"CloseServer?": "Do you want to turn off server?",
|
"CloseServer?": "Do you want to turn off server?",
|
||||||
@@ -63,7 +71,6 @@
|
|||||||
"PEX": "PEX (Peer Exchange)",
|
"PEX": "PEX (Peer Exchange)",
|
||||||
"PiecesCount": "Pieces count",
|
"PiecesCount": "Pieces count",
|
||||||
"PiecesLength": "Pieces length",
|
"PiecesLength": "Pieces length",
|
||||||
"PlaylistAll": "Playlist All",
|
|
||||||
"Preload": "Preload",
|
"Preload": "Preload",
|
||||||
"PreloadBuffer": "Preload Buffer",
|
"PreloadBuffer": "Preload Buffer",
|
||||||
"ReaderReadAHead": "Reader Read Ahead (5-100%)",
|
"ReaderReadAHead": "Reader Read Ahead (5-100%)",
|
||||||
@@ -86,7 +93,6 @@
|
|||||||
"Support": "Support",
|
"Support": "Support",
|
||||||
"TCP": "TCP (Transmission Control Protocol)",
|
"TCP": "TCP (Transmission Control Protocol)",
|
||||||
"ThanksToEveryone": "Thanks to everyone who tested and helped.",
|
"ThanksToEveryone": "Thanks to everyone who tested and helped.",
|
||||||
"Title": "Title",
|
|
||||||
"TorrentAdded": "Added",
|
"TorrentAdded": "Added",
|
||||||
"TorrentClosed": "Сlosed",
|
"TorrentClosed": "Сlosed",
|
||||||
"TorrentContent": "Torrent Content",
|
"TorrentContent": "Torrent Content",
|
||||||
@@ -96,8 +102,6 @@
|
|||||||
"TorrentInDb": "In DB",
|
"TorrentInDb": "In DB",
|
||||||
"TorrentPreload": "Preload",
|
"TorrentPreload": "Preload",
|
||||||
"TorrentSize": "Torrent size",
|
"TorrentSize": "Torrent size",
|
||||||
"TorrentSourceLink": "Torrent source link",
|
|
||||||
"TorrentSourceOptions": "magnet / hash / .torrent file link",
|
|
||||||
"TorrentsSavePath": "Torrents Save Path",
|
"TorrentsSavePath": "Torrents Save Path",
|
||||||
"TorrentState": "Torrent State",
|
"TorrentState": "Torrent State",
|
||||||
"TorrentStatus": "Torrent Status",
|
"TorrentStatus": "Torrent Status",
|
||||||
@@ -111,6 +115,5 @@
|
|||||||
"UseDisk": "Use Disk for Cache",
|
"UseDisk": "Use Disk for Cache",
|
||||||
"UseDiskDesc": "Better use external media on flash-based devices",
|
"UseDiskDesc": "Better use external media on flash-based devices",
|
||||||
"UTP": "μTP (Micro Transport Protocol)",
|
"UTP": "μTP (Micro Transport Protocol)",
|
||||||
"Viewed": "Viewed",
|
"Viewed": "Viewed"
|
||||||
"WrongTorrentSource": "Wrong torrent source"
|
|
||||||
}
|
}
|
||||||
@@ -2,21 +2,29 @@
|
|||||||
"About": "О сервере",
|
"About": "О сервере",
|
||||||
"Actions": "Действия",
|
"Actions": "Действия",
|
||||||
"Add": "Добавить",
|
"Add": "Добавить",
|
||||||
"AddFromLink": "Добавить",
|
"AddDialog": {
|
||||||
"AddNewTorrent": "Добавить новый торрент",
|
|
||||||
"AddPosterLinkInput": "Ссылка на постер",
|
"AddPosterLinkInput": "Ссылка на постер",
|
||||||
"AddRetrackers": "Добавлять",
|
|
||||||
"AddTorrentSourceNotification": "Сначала добавьте torrent-источник",
|
"AddTorrentSourceNotification": "Сначала добавьте torrent-источник",
|
||||||
"AppendFile": {
|
"AppendFile": {
|
||||||
"Or": "ИЛИ",
|
"Or": "ИЛИ",
|
||||||
"ClickOrDrag": "НАЖМИТЕ / ПЕРЕТАЩИТЕ ФАЙЛ (.torrent)"
|
"ClickOrDrag": "НАЖМИТЕ / ПЕРЕТАЩИТЕ ФАЙЛ (.torrent)"
|
||||||
},
|
},
|
||||||
|
"CustomTorrentTitle": "Cвое имя (не обязательно)",
|
||||||
|
"HashExists": "Этот торрент уже есть в базе данных",
|
||||||
|
"OriginalTorrentTitle": "Оригинальное имя торрента",
|
||||||
|
"TitleBlank": "Имя (пустое - ориг. имя торрента)",
|
||||||
|
"TorrentSourceLink": "Ссылка на источник торрента",
|
||||||
|
"TorrentSourceOptions": "magnet-ссылка / хеш / ссылка на .torrent файл",
|
||||||
|
"WrongTorrentSource": "Неправильный torrent-источник"
|
||||||
|
},
|
||||||
|
"AddFromLink": "Добавить",
|
||||||
|
"AddNewTorrent": "Добавить новый торрент",
|
||||||
|
"AddRetrackers": "Добавлять",
|
||||||
"Buffer": "Предзагрузка / Кеш",
|
"Buffer": "Предзагрузка / Кеш",
|
||||||
"BufferNote": "Включите «Наполнять кеш перед началом воспроизведения» в настройках для показа заполнения кеша",
|
"BufferNote": "Включите «Наполнять кеш перед началом воспроизведения» в настройках для показа заполнения кеша",
|
||||||
"Cache": "Кеш",
|
"Cache": "Кеш",
|
||||||
"CacheSize": "Размер кеша (Мегабайты)",
|
"CacheSize": "Размер кеша (Мегабайты)",
|
||||||
"Cancel": "Отмена",
|
"Cancel": "Отмена",
|
||||||
"ChooseLanguage": "Английский",
|
|
||||||
"Clear": "Очистить",
|
"Clear": "Очистить",
|
||||||
"Close": "Закрыть",
|
"Close": "Закрыть",
|
||||||
"CloseServer?": "Хотите выключить сервер?",
|
"CloseServer?": "Хотите выключить сервер?",
|
||||||
@@ -58,12 +66,11 @@
|
|||||||
"Offline": "Сервер не доступен",
|
"Offline": "Сервер не доступен",
|
||||||
"OK": "OK",
|
"OK": "OK",
|
||||||
"OpenLink": "Открыть",
|
"OpenLink": "Открыть",
|
||||||
"Peers": "Подкл./Пиры",
|
"Peers": "Пиры",
|
||||||
"PeersListenPort": "Порт для входящих подключений",
|
"PeersListenPort": "Порт для входящих подключений",
|
||||||
"PEX": "PEX (Peer Exchange)",
|
"PEX": "PEX (Peer Exchange)",
|
||||||
"PiecesCount": "Кол-во блоков",
|
"PiecesCount": "Кол-во блоков",
|
||||||
"PiecesLength": "Размер блока",
|
"PiecesLength": "Размер блока",
|
||||||
"PlaylistAll": "Плейлист всех",
|
|
||||||
"Preload": "Предзагр.",
|
"Preload": "Предзагр.",
|
||||||
"PreloadBuffer": "Наполнять кеш перед началом воспроизведения",
|
"PreloadBuffer": "Наполнять кеш перед началом воспроизведения",
|
||||||
"ReaderReadAHead": "Кеш предзагрузки (5-100%, рек. 95%)",
|
"ReaderReadAHead": "Кеш предзагрузки (5-100%, рек. 95%)",
|
||||||
@@ -86,7 +93,6 @@
|
|||||||
"Support": "Поддержать",
|
"Support": "Поддержать",
|
||||||
"TCP": "TCP (Transmission Control Protocol)",
|
"TCP": "TCP (Transmission Control Protocol)",
|
||||||
"ThanksToEveryone": "Спасибо всем, кто тестировал и помогал!",
|
"ThanksToEveryone": "Спасибо всем, кто тестировал и помогал!",
|
||||||
"Title": "Название",
|
|
||||||
"TorrentAdded": "Добавлен",
|
"TorrentAdded": "Добавлен",
|
||||||
"TorrentClosed": "Закрыт",
|
"TorrentClosed": "Закрыт",
|
||||||
"TorrentContent": "Содержимое торрента",
|
"TorrentContent": "Содержимое торрента",
|
||||||
@@ -96,8 +102,6 @@
|
|||||||
"TorrentInDb": "Торрент в БД",
|
"TorrentInDb": "Торрент в БД",
|
||||||
"TorrentPreload": "Предзагрузка",
|
"TorrentPreload": "Предзагрузка",
|
||||||
"TorrentSize": "Размер торрента",
|
"TorrentSize": "Размер торрента",
|
||||||
"TorrentSourceLink": "Ссылка на источник торрента",
|
|
||||||
"TorrentSourceOptions": "magnet-ссылка / хеш / ссылка на .torrent файл",
|
|
||||||
"TorrentsSavePath": "Путь хранения кеша",
|
"TorrentsSavePath": "Путь хранения кеша",
|
||||||
"TorrentState": "Данные торрента",
|
"TorrentState": "Данные торрента",
|
||||||
"TorrentStatus": "Состояние торрента",
|
"TorrentStatus": "Состояние торрента",
|
||||||
@@ -111,6 +115,5 @@
|
|||||||
"UseDisk": "Использовать диск для кеша",
|
"UseDisk": "Использовать диск для кеша",
|
||||||
"UseDiskDesc": "Рекомендуется использовать внешние носители на устройствах с flash-памятью",
|
"UseDiskDesc": "Рекомендуется использовать внешние носители на устройствах с flash-памятью",
|
||||||
"UTP": "μTP (Micro Transport Protocol)",
|
"UTP": "μTP (Micro Transport Protocol)",
|
||||||
"Viewed": "Просм.",
|
"Viewed": "Просм."
|
||||||
"WrongTorrentSource": "Неправильный torrent-источник"
|
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,6 @@ export const settingsHost = () => `${torrserverHost}/settings`
|
|||||||
export const streamHost = () => `${torrserverHost}/stream`
|
export const streamHost = () => `${torrserverHost}/stream`
|
||||||
export const shutdownHost = () => `${torrserverHost}/shutdown`
|
export const shutdownHost = () => `${torrserverHost}/shutdown`
|
||||||
export const echoHost = () => `${torrserverHost}/echo`
|
export const echoHost = () => `${torrserverHost}/echo`
|
||||||
export const playlistAllHost = () => `${torrserverHost}/playlistall/all.m3u`
|
|
||||||
export const playlistTorrHost = () => `${torrserverHost}/stream`
|
export const playlistTorrHost = () => `${torrserverHost}/stream`
|
||||||
|
|
||||||
export const getTorrServerHost = () => torrserverHost
|
export const getTorrServerHost = () => torrserverHost
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
import { torrentsHost } from './Hosts'
|
||||||
|
|
||||||
export function humanizeSize(size) {
|
export function humanizeSize(size) {
|
||||||
if (!size) return ''
|
if (!size) return ''
|
||||||
const i = Math.floor(Math.log(size) / Math.log(1024))
|
const i = Math.floor(Math.log(size) / Math.log(1024))
|
||||||
return `${(size / Math.pow(1024, i)).toFixed(2) * 1} ${['B', 'kB', 'MB', 'GB', 'TB'][i]}`
|
return `${(size / Math.pow(1024, i)).toFixed(2) * 1} ${['B', 'KB', 'MB', 'GB', 'TB'][i]}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPeerString(torrent) {
|
export function getPeerString(torrent) {
|
||||||
@@ -10,4 +14,43 @@ export function getPeerString(torrent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const shortenText = (text, sympolAmount) =>
|
export const shortenText = (text, sympolAmount) =>
|
||||||
text ? text.slice(0, sympolAmount) + (text.length > sympolAmount ? '...' : '') : ''
|
text ? text.slice(0, sympolAmount) + (text.length > sympolAmount ? '…' : '') : ''
|
||||||
|
|
||||||
|
export const removeRedundantCharacters = string => {
|
||||||
|
let newString = string
|
||||||
|
const brackets = [
|
||||||
|
['(', ')'],
|
||||||
|
['[', ']'],
|
||||||
|
['{', '}'],
|
||||||
|
]
|
||||||
|
|
||||||
|
brackets.forEach(el => {
|
||||||
|
const leftBracketRegexFormula = `\\${el[0]}`
|
||||||
|
const leftBracketRegex = new RegExp(leftBracketRegexFormula, 'g')
|
||||||
|
const leftBracketAmount = [...newString.matchAll(leftBracketRegex)].length
|
||||||
|
const rightBracketRegexFormula = `\\${el[1]}`
|
||||||
|
const rightBracketRegex = new RegExp(rightBracketRegexFormula, 'g')
|
||||||
|
const rightBracketAmount = [...newString.matchAll(rightBracketRegex)].length
|
||||||
|
|
||||||
|
if (leftBracketAmount !== rightBracketAmount) {
|
||||||
|
const removeFormula = `(\\${el[0]})(?!.*\\1).*`
|
||||||
|
const removeRegex = new RegExp(removeFormula, 'g')
|
||||||
|
newString = newString.replace(removeRegex, '')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const hasThreeDotsAtTheEnd = !!newString.match(/\.{3}$/g)
|
||||||
|
|
||||||
|
const trimmedString = newString.replace(/[\\.| ]+$/g, '').trim()
|
||||||
|
|
||||||
|
return hasThreeDotsAtTheEnd ? `${trimmedString}..` : trimmedString
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getTorrents = async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.post(torrentsHost(), { action: 'list' })
|
||||||
|
return data
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5808,11 +5808,6 @@ follow-redirects@^1.0.0, follow-redirects@^1.10.0:
|
|||||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
|
||||||
integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==
|
integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==
|
||||||
|
|
||||||
fontsource-roboto@^4.0.0:
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/fontsource-roboto/-/fontsource-roboto-4.0.0.tgz#35eacd4fb8d90199053c0eec9b34a57fb79cd820"
|
|
||||||
integrity sha512-zD6L8nvdWRcwSgp4ojxFchG+MPj8kXXQKDEAH9bfhbxy+lkpvpC1WgAK0lCa4dwobv+hvAe0uyHaawcgH7WH/g==
|
|
||||||
|
|
||||||
for-each@^0.3.3:
|
for-each@^0.3.3:
|
||||||
version "0.3.3"
|
version "0.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||||
|
|||||||