Compare commits
454 Commits
15cfed217b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a45fd152df | |||
| 60f01d859e | |||
| 6d4e033fb7 | |||
| bf635df863 | |||
| 1732b4cf4d | |||
| a2e268913a | |||
| dfb04e5e01 | |||
| c0ce844169 | |||
| 56acc42f17 | |||
| 7cee6639e7 | |||
| 62753a4af0 | |||
| 2d4d2b1105 | |||
| 09ed130327 | |||
| 1414a846ec | |||
| 19dc029e28 | |||
| 67176db933 | |||
| 95e8982696 | |||
| b8a03cd6fb | |||
| aad4ff8079 | |||
| 8821b3a00d | |||
| db43102487 | |||
| a3072a4967 | |||
| 983e24835f | |||
| 1c982124b0 | |||
| 6aaa3ad30c | |||
| 57dfa621df | |||
| e98254d444 | |||
| 56defe2c6f | |||
| a2f08c540c | |||
| 217decee06 | |||
| d93baf80ab | |||
| e409f3c214 | |||
| a1e080c20d | |||
| 6c8fce49d6 | |||
| 1a84f899e7 | |||
| ce107e6b65 | |||
| 515d3885c7 | |||
| 5194c5e156 | |||
| 5b53f53fd3 | |||
| 750b30d896 | |||
| b9afa61e01 | |||
| 490be8800a | |||
| 49ee6b4eee | |||
| ada81340ef | |||
| 5ae3b5d91c | |||
| bff3bc6a0b | |||
| 5496bced59 | |||
| 030d6dc835 | |||
| fc46ae00f8 | |||
| e22978cbe4 | |||
| 70049ed495 | |||
| 9e20af925f | |||
| 457afa5043 | |||
| c536a75f3d | |||
| a2d5828fda | |||
| 52d041c591 | |||
| 3bee1ac97d | |||
| 428d86b1ee | |||
| 5facacd066 | |||
| 0bf0b716b2 | |||
| 31c62e01f9 | |||
| a57b66cd95 | |||
| e4675e6e97 | |||
| bac0b768e2 | |||
| 74c69c698e | |||
| 87604ed848 | |||
| b6ca08727f | |||
| af99491533 | |||
| 461f6cf8fd | |||
| 2ad17c2279 | |||
| 9f3bc6e8de | |||
| 6dedf10846 | |||
| 6b6e31a1bb | |||
| f7016609a0 | |||
| fde2d607b8 | |||
| 54e9fd9f6a | |||
| 886f02c5fc | |||
| 8d57dfd2d2 | |||
| f9ba519dea | |||
| 2eb4678afc | |||
| 9558ce80b4 | |||
| 4569930a81 | |||
| 52b012402e | |||
| 82ff813225 | |||
| b7bd0fac03 | |||
| 9933b4fbf0 | |||
| c272e6c8b3 | |||
| 302f6a0621 | |||
| 23155520d2 | |||
| b788d78aab | |||
| cd9e4a5e8d | |||
| 8ec48ec43e | |||
| a27bc2c815 | |||
| 16f43066a4 | |||
| 6191e17c4e | |||
| 5ac7cfbc9a | |||
| bf802771de | |||
| 559dc21189 | |||
| 7fdb915921 | |||
| 19f0752b0f | |||
| 471ee42c0e | |||
| 1e089f731a | |||
| c026988a7b | |||
| 6281842a14 | |||
| 2380342328 | |||
| e28904b791 | |||
| ad7f1ce1fa | |||
| 327c7ab1db | |||
| 30303a80d3 | |||
| 66c1cbab6a | |||
| 34348890ec | |||
| edb4be379f | |||
| 363a6b4084 | |||
| fc5a0d209c | |||
| 63bee8f5e0 | |||
| 166f4ee7ce | |||
| 7702839b7a | |||
| cb1c884503 | |||
| 7bc9a90b81 | |||
| b2ca5a6713 | |||
| a4325f6ff6 | |||
| 03f57c1ef4 | |||
| 378e0edc75 | |||
| a2622aa536 | |||
| 602765bfbb | |||
| e32dd55220 | |||
| 4e181d5ff7 | |||
| ba971035a0 | |||
| c214ccf201 | |||
| 414499636e | |||
| d9bbd95fa1 | |||
| b63037ef74 | |||
| 37ccc3c3dd | |||
| a8bacaf083 | |||
| 0e23115cfe | |||
| e67ec5eca4 | |||
| 7a452db2f8 | |||
| 8b3e9d32d6 | |||
| d8d2ee6785 | |||
| 77b9acea32 | |||
| 68f15d4f74 | |||
| 42a83b2126 | |||
| a19c39d8eb | |||
| f06df01e70 | |||
| 0527674333 | |||
| 8d6da08519 | |||
| 2b338e32eb | |||
| aa8412863b | |||
| d4a486d2ae | |||
| ceac4ecc56 | |||
| 233829223e | |||
| 456b69f1ca | |||
| 83efdf59d4 | |||
| 02f2629f6b | |||
| 6796f7f258 | |||
| 84b9bbd1b6 | |||
| bc26e07812 | |||
| e05ca80f7c | |||
| 79eacee3f0 | |||
| 1fc77587ed | |||
| 77d37ce6b5 | |||
| 5dc829674a | |||
| 5ffc865c00 | |||
| ae085ad5ec | |||
| 05a93293fe | |||
| 117923ff1d | |||
| 47a748c623 | |||
| e9e0cf3600 | |||
| c530751a70 | |||
| f4acee53c4 | |||
| 14bca958fd | |||
| 0b5ce620d6 | |||
| 0435472489 | |||
| 253052f75a | |||
| 27acb09ced | |||
| 8f145e926e | |||
| 0dd4bcc7fe | |||
| b9c1c9914d | |||
| 90da4b592a | |||
| ac1e44f427 | |||
| 880d6369e4 | |||
| aad922ac30 | |||
| 9c99e464aa | |||
| ebc2895d7e | |||
| 45ed3be747 | |||
| 2afcdd6050 | |||
| b355ef4bf5 | |||
| 50280692e8 | |||
| 35699becf5 | |||
| 6237aa0c03 | |||
| b6398197ea | |||
| ea398a51aa | |||
| 87a800edc9 | |||
| 50d280a3c9 | |||
| 1de174a8c4 | |||
| c90d0c3f3c | |||
| 32202d8ab5 | |||
| 37b40f1744 | |||
| bd9a794e34 | |||
| 63ee4cae31 | |||
| ddaf5c3b42 | |||
| 7b78724bb4 | |||
| e4f410f293 | |||
| 55680b5150 | |||
| 1f7ad45393 | |||
| 243d28a030 | |||
| fecebee0c5 | |||
| cb47e3fd9e | |||
| 6492439f56 | |||
| 5ca478772c | |||
| dc876e7aa2 | |||
| 99cd551fc0 | |||
| c37a2ce1a1 | |||
| 0dabbc7233 | |||
| 538e6ede5b | |||
| fe1a9ed26b | |||
| 2121c51ae6 | |||
| f5d8c30ff3 | |||
| acef14b02c | |||
| 7dc1f78c80 | |||
| 73569704a5 | |||
| 1025285796 | |||
| 09bba4fe1e | |||
| c93a7189ce | |||
| 95008f9815 | |||
| 3bb96c3433 | |||
| 10a4201354 | |||
| 2a30aa5508 | |||
| 8f9baf6bc5 | |||
| e8f36ad9e4 | |||
| 8e9af7d6c4 | |||
| a8ceb41f02 | |||
| 9b90189b07 | |||
| 9ba5d45153 | |||
| 2330d8ebb7 | |||
| 9b7876753f | |||
| 7cebb1bcce | |||
| 4e15c4ca03 | |||
| 04d98a61f6 | |||
| 45ba0b8ebc | |||
| 43efc440ba | |||
| 298c54cdbb | |||
| 5c03b59082 | |||
| 57d3615f71 | |||
| 2bae1de247 | |||
| a63009509a | |||
| c6c4dcad7c | |||
| 61ed171c9d | |||
| 45a0631c9b | |||
| 7ad424c389 | |||
| 8ada96c8bc | |||
| 65edafad54 | |||
| 20eb79bafa | |||
| d6f5e1912c | |||
| fd6dd9e9be | |||
| 5f9359144e | |||
| 1d60ea0b0b | |||
| bead604fd6 | |||
| 19b2a56925 | |||
| 8da96090ee | |||
| 072c8da922 | |||
| 4c7bf2231c | |||
| e248de53a2 | |||
| 8fa5f5b405 | |||
| 49f1bc9ce2 | |||
| 48331c1c5a | |||
| 6265caeb62 | |||
| c0dec0b5f5 | |||
| 9b0003b1ff | |||
| c2624f180d | |||
| 7b96f8fc83 | |||
| 42167b062d | |||
| 304a9c41bb | |||
| 0565ad062b | |||
| 684c269f87 | |||
| 1cf789d8f7 | |||
| db8aeb97a7 | |||
| 651f3bba84 | |||
| 1bb39573e0 | |||
| 341b9267e6 | |||
| ed8c9a71fa | |||
| 1cfc3baf95 | |||
| 750b55aa47 | |||
| b225d5af99 | |||
| 22b5561d69 | |||
| 428cdabac1 | |||
| 19af103bc4 | |||
| 30408673f5 | |||
| 293072c659 | |||
| 34c413da77 | |||
| e767b80076 | |||
| 442a564fa1 | |||
| 3505282aa3 | |||
| aa672fd641 | |||
| 5d50f0b032 | |||
| 3c598bdb6f | |||
| b41ee2e5cf | |||
| cb759e7a09 | |||
| 4fba6ff71e | |||
| 5f9893e0c6 | |||
| 8f3701fd59 | |||
| de60b67cb9 | |||
| 208f1dfde4 | |||
| 89c55cea93 | |||
| 94ebc92789 | |||
| 8f5b7e9c45 | |||
| cd85e46594 | |||
| 2c49e0f9fe | |||
| f8aa903817 | |||
| bcde0d8cd5 | |||
| d655ed9faa | |||
| 855a698eae | |||
| 2293e10af7 | |||
| 5ff522311e | |||
| fa560c179b | |||
| a6af10ee20 | |||
| 6b5aa9505e | |||
| d1caf5d7ac | |||
| 57227c4bed | |||
| 831f92683e | |||
| 3e6ad72416 | |||
| a1069225c0 | |||
| 3e118f5faa | |||
| 77ec461ff6 | |||
| aed9b5bc21 | |||
| 23838889a3 | |||
| 9e64dd788c | |||
| eb4234e978 | |||
| fabd57bbef | |||
| f56ed29e21 | |||
| d975d2b6c7 | |||
| 2bdb3d24a0 | |||
| b82d5efb2a | |||
| 760cef3551 | |||
| 254050ec80 | |||
| 39a7cf2ec0 | |||
| 192aeeaafd | |||
| 05bd7b703d | |||
| d0cf9bf5d0 | |||
| 3967745fb3 | |||
| b5bef49f73 | |||
| feb77ab0c4 | |||
| 3aedfbf2d1 | |||
| 63b1198fca | |||
| 7bef4b232a | |||
| 26772b0122 | |||
| 03d56ac06a | |||
| 78108296de | |||
| fdce7b0232 | |||
| 211f600242 | |||
| 0c9e8a4a06 | |||
| 06eb24d93a | |||
| 19828d5ed1 | |||
| 47d3e50a6d | |||
| 067d414cd9 | |||
| 9e87c47b24 | |||
| 50b2fa02ca | |||
| bd2a1e4514 | |||
| 11fddcdac9 | |||
| a9e610a82c | |||
| 145ee198ff | |||
| 99c10cf394 | |||
| 8f843f321d | |||
| 8bf9e22b39 | |||
| 4b8dfba289 | |||
| 2c386e4880 | |||
| 6751ff39a2 | |||
| e12fc47f47 | |||
| 2287d7be4a | |||
| 476f9bff2e | |||
| 415c6f3e18 | |||
| 77c6136a05 | |||
| 6458264abf | |||
| 08795b2ebe | |||
| 3cf8fd1bb8 | |||
| 858a1f7087 | |||
| 9bf906a096 | |||
| 772fc813d6 | |||
| 437d0b5b57 | |||
| ced3ecb08a | |||
| 60c7e2a876 | |||
| c3362e614e | |||
| f0cf35f634 | |||
| 8bbb2107f5 | |||
| cc7ca7544b | |||
| 235d097f08 | |||
| 05fff7608e | |||
| 2cf7f2a692 | |||
| 8fba01dbdd | |||
| 4f4ff0b4bc | |||
| 1407d656dd | |||
| 6e130dd96e | |||
| 2882bd59e9 | |||
| 29a474f471 | |||
| 59ebb94af8 | |||
| ec4f9768a8 | |||
| a0d38a179a | |||
| 19dfc506e3 | |||
| 7c59479f29 | |||
| a16d17399b | |||
| e8864ce35b | |||
| da893c1a76 | |||
| 128f930c7e | |||
| 3d4d7cc307 | |||
| edb10c6d1a | |||
| 706ccf1ab3 | |||
| 0909e8d74c | |||
| 33e8fbea0b | |||
| aa3eb3df33 | |||
| e3ed54fe3c | |||
| 52d9558698 | |||
| c5c51a9560 | |||
| 9e9fd087ba | |||
| 6a0d5b8030 | |||
| ea3ef0fc1a | |||
| 1a389ef843 | |||
| 24f5597521 | |||
| e727745e7d | |||
| 5321b08f76 | |||
| ba47d25ab5 | |||
| 9e8a20494b | |||
| 3fdeddb272 | |||
| b2ea29d72c | |||
| 3bf9a6f09f | |||
| 80d8a8109a | |||
| fa991c0294 | |||
| e2cffbdde2 | |||
| d2c9b447ee | |||
| 978dcbaa25 | |||
| c134416b46 | |||
| 8e473d5e3e | |||
| b3a3562bb8 | |||
| 0d383c35b5 | |||
| b683653af4 | |||
| 222456dd55 | |||
| a4d8d5859f | |||
| c38206bbbf | |||
| a903c7f31f | |||
| 8226742aab | |||
| 333df9c141 | |||
| be957a9212 | |||
| b09b18ecd8 | |||
| 80d6216790 | |||
| 0ca847a878 | |||
| 527484b617 | |||
| 24a4bd5204 | |||
| 1ea8e52ab1 | |||
| 0cc9ee51e2 | |||
| becd196b01 | |||
| 0ad62a7305 | |||
| fb574e62d4 | |||
| b3b529faac | |||
| 6e56f8c9fe | |||
| b9b4a8e773 |
@@ -21,7 +21,7 @@
|
||||
"no-console": 0,
|
||||
"no-param-reassign": ["error", {
|
||||
"props": true,
|
||||
"ignorePropertyModificationsFor": ["state", "acc"]
|
||||
"ignorePropertyModificationsFor": ["state", "acc", "req"]
|
||||
}],
|
||||
"vue/multi-word-component-names": 0,
|
||||
"vue/no-reserved-component-names": 0,
|
||||
@@ -32,7 +32,8 @@
|
||||
"vue/html-indent": ["error", "tab"],
|
||||
"vue/multiline-html-element-content-newline": 0,
|
||||
"vue/no-v-html": 0,
|
||||
"vue/singleline-html-element-content-newline": 0
|
||||
"vue/singleline-html-element-content-newline": 0,
|
||||
"vue/comment-directive": 0,
|
||||
},
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
|
||||
5
.gitignore
vendored
@@ -3,4 +3,7 @@ dist/
|
||||
config/*
|
||||
!config/default.*js
|
||||
log/
|
||||
media/
|
||||
/media
|
||||
data/
|
||||
assets/*.mmdb
|
||||
assets/.geoipupdate.lock
|
||||
|
||||
3
.gitmodules
vendored
@@ -2,3 +2,6 @@
|
||||
path = static
|
||||
ignore = all
|
||||
url = git@unknown.name:DebaucheryLibrarian/traxxx-assets.git
|
||||
[submodule "common"]
|
||||
path = common
|
||||
url = git@unknown.name:DebaucheryLibrarian/traxxx-common.git
|
||||
|
||||
@@ -57,3 +57,11 @@
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.noshrink {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.capitalize {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
@@ -29,5 +29,37 @@ body {
|
||||
|
||||
.heading {
|
||||
margin: 0 0 1rem 0;
|
||||
color: var(--primary-light-20);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.icon.icon-social.icon-twitter {
|
||||
fill: #008ad8;
|
||||
}
|
||||
|
||||
.icon.icon-social.icon-onlyfans {
|
||||
fill: #00adef;
|
||||
}
|
||||
|
||||
.icon.icon-social.icon-fansly {
|
||||
fill: #2699f6;
|
||||
}
|
||||
|
||||
.icon.icon-social.icon-linktree {
|
||||
fill: #43e660;
|
||||
}
|
||||
|
||||
.icon.icon-social.icon-pornhub {
|
||||
fill: #ff9000;
|
||||
}
|
||||
|
||||
.icon.icon-social.icon-cashapp {
|
||||
fill: #00c853;
|
||||
}
|
||||
|
||||
.icon.icon-social.icon-loyalfans {
|
||||
fill: #d90a16;
|
||||
}
|
||||
|
||||
.icon.icon-social {
|
||||
fill: var(--highlight-strong-10);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
--background-level-20: #eee;
|
||||
--background-level-30: #eee;
|
||||
--background-dim: var(--shadow-weak-10);
|
||||
--background-error: rgba(255, 0, 0, .1);
|
||||
|
||||
--shadow-weak-50: rgba(0, 0, 0, .02);
|
||||
--shadow-weak-40: rgba(0, 0, 0, .05);
|
||||
@@ -62,7 +63,8 @@
|
||||
--text: #222;
|
||||
--text-light: #fff;
|
||||
|
||||
--link: #48f;
|
||||
/* --link: #48f; */
|
||||
--link: var(--primary);
|
||||
|
||||
--male: #0af;
|
||||
--female: #f0a;
|
||||
@@ -79,6 +81,9 @@
|
||||
--success: #5c2;
|
||||
--notice: #25c;
|
||||
|
||||
--approve: #3a1;
|
||||
--reject: #a22;
|
||||
|
||||
--gold: #d5b522;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
outline: none;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.v-popper__wrapper {
|
||||
margin: 0 .25rem .25rem .25rem; /* arrow provides top clearance */
|
||||
}
|
||||
|
||||
.v-popper__popper.v-popper__popper--hidden {
|
||||
|
||||
4
assets/img/icons/backspace2.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15.25 3h-9c-0.412 0-0.989 0.239-1.28 0.53l-4.439 4.439c-0.292 0.292-0.292 0.769 0 1.061l4.439 4.439c0.292 0.292 0.868 0.53 1.28 0.53h9c0.412 0 0.75-0.338 0.75-0.75v-9.5c0-0.413-0.338-0.75-0.75-0.75zM14 10.5l-1.5 1.5-2-2-2 2-1.5-1.5 2-2-2-2 1.5-1.5 2 2 2-2 1.5 1.5-2 2 2 2z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 430 B |
4
assets/img/icons/bubble-blocked.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M8 3.188c0.561 0 1.084 0.165 1.523 0.449l-3.887 3.887c-0.284-0.439-0.449-0.962-0.449-1.523 0-1.551 1.262-2.813 2.813-2.813zM6.477 8.363l3.887-3.887c0.284 0.439 0.449 0.962 0.449 1.523 0 1.551-1.262 2.812-2.813 2.812-0.561 0-1.084-0.165-1.523-0.449zM14.5 0h-13c-0.825 0-1.5 0.675-1.5 1.5v9c0 0.825 0.675 1.5 1.5 1.5h2.5v4l4.8-4h5.7c0.825 0 1.5-0.675 1.5-1.5v-9c0-0.825-0.675-1.5-1.5-1.5zM8 10c-2.209 0-4-1.791-4-4s1.791-4 4-4 4 1.791 4 4-1.791 4-4 4z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 606 B |
4
assets/img/icons/bubble-cancel.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M14.5 0h-13c-0.825 0-1.5 0.675-1.5 1.5v9c0 0.825 0.675 1.5 1.5 1.5h2.5v4l4.8-4h5.7c0.825 0 1.5-0.675 1.5-1.5v-9c0-0.825-0.675-1.5-1.5-1.5zM11 4.282l-1.718 1.718 1.718 1.718v1.282h-1.282l-1.718-1.718-1.718 1.718h-1.282v-1.282l1.718-1.718-1.718-1.718v-1.282h1.282l1.718 1.718 1.718-1.718h1.282v1.282z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 455 B |
4
assets/img/icons/bubble-check.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M14.5 0h-13c-0.825 0-1.5 0.675-1.5 1.5v9c0 0.825 0.675 1.5 1.5 1.5h2.5v4l4.8-4h5.7c0.825 0 1.5-0.675 1.5-1.5v-9c0-0.825-0.675-1.5-1.5-1.5zM7 9.414l-3.207-3.707 0.914-0.914 2.293 1.793 4.293-3.793 0.914 0.914-5.207 5.707z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 377 B |
4
assets/img/icons/bubble-lines3.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M14.5 1h-13c-0.825 0-1.5 0.675-1.5 1.5v8c0 0.825 0.675 1.5 1.5 1.5h2.5v4l4.8-4h5.7c0.825 0 1.5-0.675 1.5-1.5v-8c0-0.825-0.675-1.5-1.5-1.5zM7 9h-4v-1h4v1zM11 7h-8v-1h8v1zM13 5h-10v-1h10v1z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 344 B |
4
assets/img/icons/bubble-link.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M14.5 0h-13c-0.825 0-1.5 0.675-1.5 1.5v9c0 0.825 0.675 1.5 1.5 1.5h2.5v4l4.8-4h5.7c0.825 0 1.5-0.675 1.5-1.5v-9c0-0.825-0.675-1.5-1.5-1.5zM7 9h-3c-1.1 0-2-0.9-2-2v-1c0-1.1 0.9-2 2-2h3v1h-3c-0.265 0-0.515 0.105-0.705 0.295s-0.295 0.441-0.295 0.705v1c0 0.265 0.105 0.515 0.295 0.705s0.441 0.295 0.705 0.295h3v1zM6 7v-1h4v1h-4zM14 7c0 1.1-0.9 2-2 2h-3v-1h3c0.265 0 0.515-0.105 0.705-0.295s0.295-0.441 0.295-0.705v-1c0-0.265-0.105-0.515-0.295-0.705s-0.44-0.295-0.705-0.295h-3v-1h3c1.1 0 2 0.9 2 2v1z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 652 B |
4
assets/img/icons/bubble-notification2.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M14.5 0h-13c-0.825 0-1.5 0.675-1.5 1.5v9c0 0.825 0.675 1.5 1.5 1.5h2.5v4l4.8-4h5.7c0.825 0 1.5-0.675 1.5-1.5v-9c0-0.825-0.675-1.5-1.5-1.5zM9 10h-2v-2h2v2zM9 6h-2v-4h2v4z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 326 B |
4
assets/img/icons/bubble-plus.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M14.5 0h-13c-0.825 0-1.5 0.675-1.5 1.5v9c0 0.825 0.675 1.5 1.5 1.5h2.5v4l4.8-4h5.7c0.825 0 1.5-0.675 1.5-1.5v-9c0-0.825-0.675-1.5-1.5-1.5zM12 7h-3v3h-2v-3h-3v-2h3v-3h2v3h3v2z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 331 B |
37
assets/img/icons/cashapp.svg
Executable file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
class="app-icon"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
sodipodi:docname="cashapp.svg"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="namedview2"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="4.2922526"
|
||||
inkscape:cx="-6.4068923"
|
||||
inkscape:cy="41.004111"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<path
|
||||
id="path1"
|
||||
style="fill-rule:nonzero"
|
||||
d="M 22.300781 0 C 15.900781 0 12.699219 -0.000390625 9.1992188 1.0996094 A 13.6 13.6 0 0 0 1.0996094 9.1992188 C -0.000390625 12.659219 0 15.880781 0 22.300781 L 0 41.689453 C 0 48.099453 -0.000390625 51.300781 1.0996094 54.800781 A 13.6 13.6 0 0 0 9.1992188 62.900391 C 12.659219 64.000391 15.880781 64 22.300781 64 L 41.699219 64 C 48.099219 64 51.300781 64.000859 54.800781 62.880859 A 13.6 13.6 0 0 0 62.900391 54.779297 C 64.000391 51.319297 64 48.099688 64 41.679688 L 64 22.310547 C 64 15.900547 64.000391 12.699219 62.900391 9.1992188 A 13.6 13.6 0 0 0 54.800781 1.0996094 C 51.300781 -0.000390625 48.099219 0 41.699219 0 L 22.300781 0 z M 34.660156 10.009766 L 39.5 10.009766 C 40.33 10.009766 40.949297 10.789141 40.779297 11.619141 L 39.990234 15.419922 A 19.73 19.73 0 0 1 46.710938 19.259766 C 47.270938 19.799766 47.299531 20.699219 46.769531 21.199219 L 44.269531 23.800781 C 43.799531 24.300781 42.970703 24.300781 42.470703 23.800781 L 42.490234 23.820312 C 40.380234 21.920312 37.149062 20.529297 33.789062 20.529297 C 31.149062 20.529297 28.519531 21.490156 28.519531 23.910156 C 28.519531 26.400156 31.339609 27.229453 34.599609 28.439453 C 40.299609 30.409453 45 32.830312 45 38.570312 C 45 44.800312 40.27925 49.069844 32.53125 49.589844 L 31.832031 52.980469 A 1.32 1.32 0 0 1 30.53125 54.039062 L 25.681641 54 C 24.851641 53.99 24.242109 53.220625 24.412109 52.390625 L 25.152344 48.820312 C 22.120344 47.990313 19.459375 46.489922 17.359375 44.419922 A 1.36 1.36 0 0 1 17.359375 42.5 L 20.060547 39.800781 A 1.3 1.3 0 0 1 21.900391 39.800781 C 24.500391 42.410781 27.860547 43.480469 31.060547 43.480469 C 34.580547 43.480469 36.960938 42.019297 36.960938 39.529297 C 36.960937 37.109297 34.570547 36.47 30.060547 34.75 C 25.290547 33.04 20.779297 30.55 20.779297 24.75 C 20.779297 18.05 26.239687 14.779219 32.679688 14.449219 L 33.380859 11.070312 A 1.32 1.32 0 0 1 34.660156 10.009766 z " />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
4
assets/img/icons/circle-code.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM6.707 10.293c0.391 0.391 0.391 1.024 0 1.414-0.195 0.195-0.451 0.293-0.707 0.293s-0.512-0.098-0.707-0.293l-3-3c-0.391-0.391-0.391-1.024 0-1.414l3-3c0.391-0.391 1.024-0.391 1.414 0s0.391 1.024 0 1.414l-2.293 2.293 2.293 2.293zM10.707 11.707c-0.391 0.391-1.024 0.391-1.414 0s-0.391-1.024 0-1.414l2.293-2.293-2.293-2.293c-0.391-0.391-0.391-1.024 0-1.414 0.195-0.195 0.451-0.293 0.707-0.293s0.512 0.098 0.707 0.293l3 3c0.391 0.391 0.391 1.024 0 1.414l-3 3z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 672 B |
4
assets/img/icons/circle-css.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM7 4.111c-0.552 0-1 0.497-1 1.111v1.111c0 0.92-0.672 1.667-1.5 1.667 0.828 0 1.5 0.746 1.5 1.667v1.111c0 0.614 0.448 1.111 1 1.111v1.111h-1c-1.103 0-2-0.997-2-2.222v-1.111c0-0.614-0.448-1.111-1-1.111v-1.111c0.552 0 1-0.497 1-1.111v-1.111c0-1.225 0.897-2.222 2-2.222h1v1.111zM13 8.556c-0.552 0-1 0.498-1 1.111v1.111c0 1.225-0.897 2.222-2 2.222h-1v-1.111c0.552 0 1-0.497 1-1.111v-1.111c0-0.92 0.672-1.667 1.5-1.667-0.828 0-1.5-0.746-1.5-1.667v-1.111c0-0.614-0.448-1.111-1-1.111v-1.111h1c1.103 0 2 0.997 2 2.222v1.111c0 0.614 0.448 1.111 1 1.111v1.111z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 768 B |
5
assets/img/icons/database-remove.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M16 8.414l-1.414-1.414-2.086 2.086-2.086-2.086-1.414 1.414 2.086 2.086-2.086 2.086 1.414 1.414 2.086-2.086 2.086 2.086 1.414-1.414-2.086-2.086z"></path>
|
||||
<path d="M8 13.421c-0.752 0.173-1.611 0.266-2.5 0.266-1.242 0-2.429-0.181-3.342-0.51-0.763-0.275-1.074-0.562-1.158-0.677v-2.594c0.995 0.643 2.64 1.062 4.5 1.062 0.9 0 1.75-0.098 2.5-0.273v-1.306c-0.752 0.173-1.611 0.266-2.5 0.266-1.242 0-2.429-0.181-3.342-0.51-0.762-0.275-1.074-0.562-1.158-0.677v-2.531c0.995 0.643 2.64 1.062 4.5 1.062 3.038 0 5.5-1.119 5.5-2.5s-2.462-2.5-5.5-2.5-5.5 1.119-5.5 2.5v8c0 1.381 2.462 2.5 5.5 2.5 0.9 0 1.75-0.098 2.5-0.273v-1.306zM2.402 3.823c0.846-0.329 1.946-0.51 3.098-0.51s2.252 0.181 3.098 0.51c0.707 0.275 0.995 0.562 1.074 0.677-0.078 0.115-0.367 0.402-1.074 0.677-0.846 0.329-1.946 0.51-3.098 0.51s-2.252-0.181-3.098-0.51c-0.707-0.275-0.996-0.562-1.074-0.677 0.078-0.115 0.367-0.402 1.074-0.677z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
33
assets/img/icons/discord-full.svg
Executable file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 725.59998 198.3"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
width="725.59998"
|
||||
height="198.3">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<path
|
||||
d="m 105.9,83.2 c -5.7,0 -10.2,4.9 -10.2,11 0,6.1 4.6,11 10.2,11 5.7,0 10.2,-4.9 10.2,-11 0,-6.1 -4.6,-11 -10.2,-11 z m -36.5,0 c -5.7,0 -10.2,4.9 -10.2,11 0,6.1 4.6,11 10.2,11 5.7,0 10.2,-4.9 10.2,-11 0.1,-6.1 -4.5,-11 -10.2,-11 z"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M 154.5,0 H 20.5 C 9.2,0 0,9.2 0,20.5 v 134 C 0,165.8 9.2,175 20.5,175 h 113.4 l -5.3,-18.3 12.8,11.8 12.1,11.1 21.6,18.7 V 20.5 C 175,9.2 165.8,0 154.5,0 Z m -38.6,129.5 c 0,0 -3.6,-4.3 -6.6,-8 13.1,-3.7 18.1,-11.8 18.1,-11.8 -4.1,2.7 -8,4.6 -11.5,5.9 -5,2.1 -9.8,3.4 -14.5,4.3 -9.6,1.8 -18.4,1.3 -25.9,-0.1 -5.7,-1.1 -10.6,-2.6 -14.7,-4.3 -2.3,-0.9 -4.8,-2 -7.3,-3.4 -0.3,-0.2 -0.6,-0.3 -0.9,-0.5 -0.2,-0.1 -0.3,-0.2 -0.4,-0.2 -1.8,-1 -2.8,-1.7 -2.8,-1.7 0,0 4.8,7.9 17.5,11.7 -3,3.8 -6.7,8.2 -6.7,8.2 C 38.1,128.9 29.7,114.5 29.7,114.5 29.7,82.6 44.1,56.7 44.1,56.7 58.5,46 72.1,46.3 72.1,46.3 l 1,1.2 c -18,5.1 -26.2,13 -26.2,13 0,0 2.2,-1.2 5.9,-2.8 10.7,-4.7 19.2,-5.9 22.7,-6.3 0.6,-0.1 1.1,-0.2 1.7,-0.2 6.1,-0.8 13,-1 20.2,-0.2 9.5,1.1 19.7,3.9 30.1,9.5 0,0 -7.9,-7.5 -24.9,-12.6 l 1.4,-1.6 c 0,0 13.7,-0.3 28,10.4 0,0 14.4,25.9 14.4,57.8 0,-0.1 -8.4,14.3 -30.5,15 z m 151,-86.7 H 233.7 V 80.1 L 255.8,100 V 63.8 h 11.8 c 7.5,0 11.2,3.6 11.2,9.4 v 27.7 c 0,5.8 -3.5,9.7 -11.2,9.7 h -34 v 21.1 h 33.2 c 17.8,0.1 34.5,-8.8 34.5,-29.2 V 72.7 C 301.4,51.9 284.7,42.8 266.9,42.8 Z m 174,59.7 V 71.9 c 0,-11 19.8,-13.5 25.8,-2.5 L 485,62 C 477.8,46.2 464.7,41.6 453.8,41.6 436,41.6 418.4,51.9 418.4,71.9 v 30.6 c 0,20.2 17.6,30.3 35,30.3 11.2,0 24.6,-5.5 32,-19.9 l -19.6,-9 c -4.8,12.3 -24.9,9.3 -24.9,-1.4 z M 380.4,76.1 c -6.9,-1.5 -11.5,-4 -11.8,-8.3 0.4,-10.3 16.3,-10.7 25.6,-0.8 l 14.7,-11.3 c -9.2,-11.2 -19.6,-14.2 -30.3,-14.2 -16.3,0 -32.1,9.2 -32.1,26.6 0,16.9 13,26 27.3,28.2 7.3,1 15.4,3.9 15.2,8.9 -0.6,9.5 -20.2,9 -29.1,-1.8 l -14.2,13.3 c 8.3,10.7 19.6,16.1 30.2,16.1 16.3,0 34.4,-9.4 35.1,-26.6 C 412,84.5 396.2,79 380.4,76.1 Z m -67,55.5 h 22.4 V 42.8 H 313.4 Z M 691.1,42.8 H 657.9 V 80.1 L 680,100 V 63.8 h 11.8 c 7.5,0 11.2,3.6 11.2,9.4 v 27.7 c 0,5.8 -3.5,9.7 -11.2,9.7 h -34 v 21.1 h 33.3 c 17.8,0.1 34.5,-8.8 34.5,-29.2 V 72.7 c 0,-20.8 -16.7,-29.9 -34.5,-29.9 z M 528.2,41.6 c -18.4,0 -36.7,10 -36.7,30.5 v 30.3 c 0,20.3 18.4,30.5 36.9,30.5 18.4,0 36.7,-10.2 36.7,-30.5 V 72.1 c 0,-20.4 -18.5,-30.5 -36.9,-30.5 z m 14.4,60.8 c 0,6.4 -7.2,9.7 -14.3,9.7 -7.2,0 -14.4,-3.1 -14.4,-9.7 V 72.1 c 0,-6.5 7,-10 14,-10 7.3,0 14.7,3.1 14.7,10 z M 645.5,72.1 C 645,51.3 630.8,42.9 612.5,42.9 H 577 v 88.8 h 22.7 v -28.2 h 4 l 20.6,28.2 h 28 l -24.2,-30.5 c 10.7,-3.4 17.4,-12.7 17.4,-29.1 z m -32.6,12 H 599.7 V 63.8 h 13.2 c 14.1,0 14.1,20.3 0,20.3 z"
|
||||
id="path4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
21
assets/img/icons/discord.svg
Executable file → Normal file
@@ -1,15 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 725.59998 198.3"
|
||||
viewBox="0 0 200 200"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
width="725.59998"
|
||||
height="198.3">
|
||||
width="200"
|
||||
height="200"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
@@ -18,16 +18,15 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<path
|
||||
d="m 105.9,83.2 c -5.7,0 -10.2,4.9 -10.2,11 0,6.1 4.6,11 10.2,11 5.7,0 10.2,-4.9 10.2,-11 0,-6.1 -4.6,-11 -10.2,-11 z m -36.5,0 c -5.7,0 -10.2,4.9 -10.2,11 0,6.1 4.6,11 10.2,11 5.7,0 10.2,-4.9 10.2,-11 0.1,-6.1 -4.5,-11 -10.2,-11 z"
|
||||
d="m 118.35,84.05 c -5.7,0 -10.2,4.9 -10.2,11 0,6.1 4.6,11 10.2,11 5.7,0 10.2,-4.9 10.2,-11 0,-6.1 -4.6,-11 -10.2,-11 z m -36.5,0 c -5.7,0 -10.2,4.9 -10.2,11 0,6.1 4.6,11 10.2,11 5.7,0 10.2,-4.9 10.2,-11 0.1,-6.1 -4.5,-11 -10.2,-11 z"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M 154.5,0 H 20.5 C 9.2,0 0,9.2 0,20.5 v 134 C 0,165.8 9.2,175 20.5,175 h 113.4 l -5.3,-18.3 12.8,11.8 12.1,11.1 21.6,18.7 V 20.5 C 175,9.2 165.8,0 154.5,0 Z m -38.6,129.5 c 0,0 -3.6,-4.3 -6.6,-8 13.1,-3.7 18.1,-11.8 18.1,-11.8 -4.1,2.7 -8,4.6 -11.5,5.9 -5,2.1 -9.8,3.4 -14.5,4.3 -9.6,1.8 -18.4,1.3 -25.9,-0.1 -5.7,-1.1 -10.6,-2.6 -14.7,-4.3 -2.3,-0.9 -4.8,-2 -7.3,-3.4 -0.3,-0.2 -0.6,-0.3 -0.9,-0.5 -0.2,-0.1 -0.3,-0.2 -0.4,-0.2 -1.8,-1 -2.8,-1.7 -2.8,-1.7 0,0 4.8,7.9 17.5,11.7 -3,3.8 -6.7,8.2 -6.7,8.2 C 38.1,128.9 29.7,114.5 29.7,114.5 29.7,82.6 44.1,56.7 44.1,56.7 58.5,46 72.1,46.3 72.1,46.3 l 1,1.2 c -18,5.1 -26.2,13 -26.2,13 0,0 2.2,-1.2 5.9,-2.8 10.7,-4.7 19.2,-5.9 22.7,-6.3 0.6,-0.1 1.1,-0.2 1.7,-0.2 6.1,-0.8 13,-1 20.2,-0.2 9.5,1.1 19.7,3.9 30.1,9.5 0,0 -7.9,-7.5 -24.9,-12.6 l 1.4,-1.6 c 0,0 13.7,-0.3 28,10.4 0,0 14.4,25.9 14.4,57.8 0,-0.1 -8.4,14.3 -30.5,15 z m 151,-86.7 H 233.7 V 80.1 L 255.8,100 V 63.8 h 11.8 c 7.5,0 11.2,3.6 11.2,9.4 v 27.7 c 0,5.8 -3.5,9.7 -11.2,9.7 h -34 v 21.1 h 33.2 c 17.8,0.1 34.5,-8.8 34.5,-29.2 V 72.7 C 301.4,51.9 284.7,42.8 266.9,42.8 Z m 174,59.7 V 71.9 c 0,-11 19.8,-13.5 25.8,-2.5 L 485,62 C 477.8,46.2 464.7,41.6 453.8,41.6 436,41.6 418.4,51.9 418.4,71.9 v 30.6 c 0,20.2 17.6,30.3 35,30.3 11.2,0 24.6,-5.5 32,-19.9 l -19.6,-9 c -4.8,12.3 -24.9,9.3 -24.9,-1.4 z M 380.4,76.1 c -6.9,-1.5 -11.5,-4 -11.8,-8.3 0.4,-10.3 16.3,-10.7 25.6,-0.8 l 14.7,-11.3 c -9.2,-11.2 -19.6,-14.2 -30.3,-14.2 -16.3,0 -32.1,9.2 -32.1,26.6 0,16.9 13,26 27.3,28.2 7.3,1 15.4,3.9 15.2,8.9 -0.6,9.5 -20.2,9 -29.1,-1.8 l -14.2,13.3 c 8.3,10.7 19.6,16.1 30.2,16.1 16.3,0 34.4,-9.4 35.1,-26.6 C 412,84.5 396.2,79 380.4,76.1 Z m -67,55.5 h 22.4 V 42.8 H 313.4 Z M 691.1,42.8 H 657.9 V 80.1 L 680,100 V 63.8 h 11.8 c 7.5,0 11.2,3.6 11.2,9.4 v 27.7 c 0,5.8 -3.5,9.7 -11.2,9.7 h -34 v 21.1 h 33.3 c 17.8,0.1 34.5,-8.8 34.5,-29.2 V 72.7 c 0,-20.8 -16.7,-29.9 -34.5,-29.9 z M 528.2,41.6 c -18.4,0 -36.7,10 -36.7,30.5 v 30.3 c 0,20.3 18.4,30.5 36.9,30.5 18.4,0 36.7,-10.2 36.7,-30.5 V 72.1 c 0,-20.4 -18.5,-30.5 -36.9,-30.5 z m 14.4,60.8 c 0,6.4 -7.2,9.7 -14.3,9.7 -7.2,0 -14.4,-3.1 -14.4,-9.7 V 72.1 c 0,-6.5 7,-10 14,-10 7.3,0 14.7,3.1 14.7,10 z M 645.5,72.1 C 645,51.3 630.8,42.9 612.5,42.9 H 577 v 88.8 h 22.7 v -28.2 h 4 l 20.6,28.2 h 28 l -24.2,-30.5 c 10.7,-3.4 17.4,-12.7 17.4,-29.1 z m -32.6,12 H 599.7 V 63.8 h 13.2 c 14.1,0 14.1,20.3 0,20.3 z"
|
||||
d="m 166.95,0.85 h -134 c -11.3,0 -20.5,9.2 -20.5,20.5 v 134 c 0,11.3 9.2,20.5 20.5,20.5 h 113.4 l -5.3,-18.3 12.8,11.8 12.1,11.1 21.6,18.7 V 21.35 c -0.1,-11.3 -9.3,-20.5 -20.6,-20.5 z m -38.6,129.5 c 0,0 -3.6,-4.3 -6.6,-8 13.1,-3.7 18.1,-11.8 18.1,-11.8 -4.1,2.7 -8,4.6 -11.5,5.9 -5,2.1 -9.8,3.4 -14.5,4.3 -9.6,1.8 -18.4,1.3 -25.9,-0.1 -5.7,-1.1 -10.6,-2.6 -14.7,-4.3 -2.3,-0.9 -4.8,-2 -7.3,-3.4 -0.3,-0.2 -0.6,-0.3 -0.9,-0.5 -0.2,-0.1 -0.3,-0.2 -0.4,-0.2 -1.8,-1 -2.8,-1.7 -2.8,-1.7 0,0 4.8,7.9 17.5,11.7 -3,3.8 -6.7,8.2 -6.7,8.2 -22.1,-0.7 -30.5,-15.1 -30.5,-15.1 0,-31.9 14.4,-57.8 14.4,-57.8 14.4,-10.7 28,-10.4 28,-10.4 l 1,1.2 c -18,5.1 -26.2,13 -26.2,13 0,0 2.2,-1.2 5.9,-2.8 10.7,-4.7 19.2,-5.9 22.7,-6.3 0.6,-0.1 1.1,-0.2 1.7,-0.2 6.1,-0.8 13,-1 20.2,-0.2 9.5,1.1 19.7,3.9 30.1,9.5 0,0 -7.9,-7.5 -24.9,-12.6 l 1.4,-1.6 c 0,0 13.7,-0.3 28,10.4 0,0 14.4,25.9 14.4,57.8 0,-0.1 -8.4,14.3 -30.5,15 z"
|
||||
id="path4" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.8 KiB |
5
assets/img/icons/embed.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M9 11.5l1.5 1.5 5-5-5-5-1.5 1.5 3.5 3.5z"></path>
|
||||
<path d="M7 4.5l-1.5-1.5-5 5 5 5 1.5-1.5-3.5-3.5z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 256 B |
6
assets/img/icons/embed2.svg
Executable file
@@ -0,0 +1,6 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="20" height="16" viewBox="0 0 20 16">
|
||||
<path d="M13 11.5l1.5 1.5 5-5-5-5-1.5 1.5 3.5 3.5z"></path>
|
||||
<path d="M7 4.5l-1.5-1.5-5 5 5 5 1.5-1.5-3.5-3.5z"></path>
|
||||
<path d="M10.958 2.352l1.085 0.296-3 11-1.085-0.296 3-11z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 324 B |
17
assets/img/icons/fansly.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="250mm"
|
||||
height="250mm"
|
||||
viewBox="0 0 250 250"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs1" /><g
|
||||
id="layer1"
|
||||
transform="translate(24.386144,-19.654193)"><path
|
||||
d="m 97.694468,246.49306 c -3.29163,-0.77463 -0.47054,1.91978 -54.511619,-52.06397 -50.6807564,-50.62701 -53.322727,-53.34287 -56.39996,-57.97743 -27.178147,-40.932394 2.576397,-95.055377 51.592389,-93.845613 18.803333,0.464085 29.67869,5.96299 47.82344,24.180963 l 8.13594,8.168766 v 1.17671 1.17671 l -9.5952,9.5952 -9.59519,9.59519 h -1.17012 -1.17011 l -8.747713,-8.68541 C 53.42233,77.255906 51.16241,75.641266 44.558703,73.883746 22.440946,67.99732 2.0677986,88.370466 7.9542296,110.48822 c 1.854298,6.96737 3.0461774,8.54843 17.0298114,22.59053 L 36.775364,144.91938 80.437818,101.307 C 104.45218,77.320186 125.11232,56.891924 126.34924,55.910863 c 41.54647,-32.952327 102.5948,-0.905053 98.18473,51.541997 -1.50182,17.86043 -6.90484,27.66745 -25.34204,45.99828 l -6.85255,6.81302 h -1.30245 -1.30245 l -9.23084,-9.19427 c -5.23119,-5.21045 -9.3927,-9.56782 -9.60439,-10.05639 -0.68655,-1.5845 -0.44769,-1.89305 8.34481,-10.77954 10.07564,-10.18335 11.76153,-12.45408 13.61891,-18.34331 7.36307,-23.346184 -14.7662,-45.211633 -37.93595,-37.483684 -6.11717,2.04029 -7.63165,3.23438 -21.10859,16.64299 l -11.71311,11.653724 31.35842,31.36255 c 34.29087,34.29538 32.03326,31.83093 30.97951,33.81784 -0.76337,1.4394 -76.38158,76.6301 -77.82527,77.3853 -2.61462,1.36771 -6.21408,1.86131 -8.923512,1.22369 z m 6.844022,-50.26472 c 24.80444,-3.44998 34.77631,-34.05871 16.6922,-51.23684 -18.69981,-17.76299 -49.500062,-5.18911 -50.373192,20.56433 -0.6271,18.49668 15.51714,33.19887 33.680992,30.67251 z m -8.748622,-11.08611 c -19.05073,-5.06896 -18.95399,-32.29299 0.13229,-37.22612 3.38201,-0.87413 10.621562,-0.39034 10.164072,0.67923 -1.05639,2.46975 -1.14575,3.85862 -0.37986,5.90421 1.62525,4.34083 6.42005,6.18157 10.40675,3.9952 l 1.53784,-0.84338 0.53717,1.24025 c 6.33111,14.61762 -7.07381,30.32809 -22.398262,26.25061 z"
|
||||
id="path1" /></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
5
assets/img/icons/file-css2.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M11 4h3.627c-0.078-0.126-0.172-0.266-0.286-0.421-0.347-0.473-0.831-1.027-1.362-1.558s-1.085-1.015-1.558-1.362c-0.155-0.114-0.295-0.208-0.421-0.286v3.627z"></path>
|
||||
<path d="M10.5 5c-0.276 0-0.5-0.224-0.5-0.5v-4.5h-7.75c-0.689 0-1.25 0.561-1.25 1.25v13.5c0 0.689 0.561 1.25 1.25 1.25h11.5c0.689 0 1.25-0.561 1.25-1.25v-9.75h-4.5zM6 11.25v1.25c0 0.276 0.224 0.5 0.5 0.5s0.5 0.224 0.5 0.5-0.224 0.5-0.5 0.5c-0.827 0-1.5-0.673-1.5-1.5v-1.25c0-0.138-0.112-0.25-0.25-0.25h-0.25c-0.276 0-0.5-0.224-0.5-0.5s0.224-0.5 0.5-0.5h0.25c0.138 0 0.25-0.112 0.25-0.25v-1.25c0-0.827 0.673-1.5 1.5-1.5 0.276 0 0.5 0.224 0.5 0.5s-0.224 0.5-0.5 0.5c-0.276 0-0.5 0.224-0.5 0.5v1.25c0 0.281-0.093 0.541-0.251 0.75 0.157 0.209 0.251 0.469 0.251 0.75zM11.5 11h-0.25c-0.138 0-0.25 0.112-0.25 0.25v1.25c0 0.827-0.673 1.5-1.5 1.5-0.276 0-0.5-0.224-0.5-0.5s0.224-0.5 0.5-0.5c0.276 0 0.5-0.224 0.5-0.5v-1.25c0-0.281 0.093-0.541 0.251-0.75-0.157-0.209-0.251-0.469-0.251-0.75v-1.25c0-0.276-0.224-0.5-0.5-0.5s-0.5-0.224-0.5-0.5 0.224-0.5 0.5-0.5c0.827 0 1.5 0.673 1.5 1.5v1.25c0 0.138 0.112 0.25 0.25 0.25h0.25c0.276 0 0.5 0.224 0.5 0.5s-0.224 0.5-0.5 0.5z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
6
assets/img/icons/file-eye2.svg
Executable file
@@ -0,0 +1,6 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M11 4h3.627c-0.078-0.126-0.172-0.266-0.286-0.421-0.347-0.473-0.831-1.027-1.362-1.558s-1.085-1.015-1.558-1.362c-0.155-0.114-0.295-0.208-0.421-0.286v3.627z"></path>
|
||||
<path d="M5.755 15.881c-1.241-0.806-2.19-1.932-2.743-3.254-0.167-0.399-0.167-0.856 0-1.254 0.553-1.322 1.502-2.448 2.743-3.254 1.253-0.814 2.721-1.244 4.245-1.244s2.992 0.43 4.245 1.244c0.266 0.172 0.518 0.36 0.755 0.56v-3.679h-4.5c-0.276 0-0.5-0.224-0.5-0.5v-4.5h-7.75c-0.689 0-1.25 0.561-1.25 1.25v13.5c0 0.689 0.561 1.25 1.25 1.25h3.695c-0.064-0.039-0.127-0.078-0.19-0.119z"></path>
|
||||
<path d="M15.95 11.807c-0.466-1.113-1.267-2.062-2.318-2.745-1.070-0.695-2.326-1.062-3.632-1.062s-2.562 0.367-3.632 1.062c-1.051 0.683-1.853 1.632-2.318 2.745-0.052 0.123-0.052 0.262 0 0.386 0.466 1.113 1.267 2.062 2.318 2.745 1.070 0.695 2.326 1.062 3.632 1.062s2.562-0.367 3.632-1.062c1.051-0.683 1.853-1.632 2.318-2.745 0.052-0.123 0.052-0.262-0-0.386zM10 11c0 0.552-0.448 1-1 1s-1-0.448-1-1 0.448-1 1-1 1 0.448 1 1zM13.087 14.099c-0.908 0.589-1.975 0.901-3.087 0.901s-2.18-0.312-3.087-0.901c-0.82-0.533-1.458-1.255-1.855-2.099 0.397-0.844 1.035-1.566 1.855-2.099 0.102-0.066 0.206-0.128 0.311-0.188-0.199 0.405-0.311 0.86-0.311 1.342 0 1.681 1.363 3.044 3.044 3.044s3.044-1.363 3.044-3.044c0-0.508-0.125-0.986-0.344-1.407 0.147 0.078 0.292 0.162 0.432 0.253 0.82 0.533 1.457 1.255 1.855 2.099-0.397 0.844-1.035 1.566-1.855 2.099v0 0z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
5
assets/img/icons/file-plus.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M14.341 3.579c-0.347-0.473-0.831-1.027-1.362-1.558s-1.085-1.015-1.558-1.362c-0.806-0.591-1.197-0.659-1.421-0.659h-7.75c-0.689 0-1.25 0.561-1.25 1.25v13.5c0 0.689 0.561 1.25 1.25 1.25h6.25c0.276 0 0.5-0.224 0.5-0.5s-0.224-0.5-0.5-0.5h-6.25c-0.135 0-0.25-0.114-0.25-0.25v-13.5c0-0.135 0.115-0.25 0.25-0.25 0 0 7.749-0 7.75 0v3.5c0 0.276 0.224 0.5 0.5 0.5h3.5v3.5c0 0.276 0.224 0.5 0.5 0.5s0.5-0.224 0.5-0.5v-3.5c0-0.224-0.068-0.615-0.659-1.421zM11 4v-2.405c0.359 0.278 0.792 0.654 1.271 1.134s0.856 0.912 1.134 1.271h-2.406z"></path>
|
||||
<path d="M16 12h-2v-2h-2v2h-2v2h2v2h2v-2h2z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 732 B |
6
assets/img/icons/file-plus2.svg
Executable file
@@ -0,0 +1,6 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M11 4h3.627c-0.078-0.126-0.172-0.266-0.286-0.421-0.347-0.473-0.831-1.027-1.362-1.558s-1.085-1.015-1.558-1.362c-0.155-0.114-0.295-0.208-0.421-0.286v3.627z"></path>
|
||||
<path d="M7.875 12.5c0-2.55 2.075-4.625 4.625-4.625 0.92 0 1.779 0.27 2.5 0.736v-3.611h-4.5c-0.276 0-0.5-0.224-0.5-0.5v-4.5h-7.75c-0.689 0-1.25 0.561-1.25 1.25v13.5c0 0.689 0.561 1.25 1.25 1.25h7.23c-0.982-0.849-1.605-2.103-1.605-3.5z"></path>
|
||||
<path d="M12.5 9c-1.933 0-3.5 1.567-3.5 3.5s1.567 3.5 3.5 3.5c1.933 0 3.5-1.567 3.5-3.5s-1.567-3.5-3.5-3.5zM13 13v2h-1v-2h-2v-1h2v-2h1v2h2v1h-2z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 708 B |
5
assets/img/icons/file-text3.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M11 4h3.627c-0.078-0.126-0.172-0.266-0.286-0.421-0.347-0.473-0.831-1.027-1.362-1.558s-1.085-1.015-1.558-1.362c-0.155-0.114-0.295-0.208-0.421-0.286v3.627z"></path>
|
||||
<path d="M10.5 5c-0.276 0-0.5-0.224-0.5-0.5v-4.5h-7.75c-0.689 0-1.25 0.561-1.25 1.25v13.5c0 0.689 0.561 1.25 1.25 1.25h11.5c0.689 0 1.25-0.561 1.25-1.25v-9.75h-4.5zM11.5 13h-7c-0.276 0-0.5-0.224-0.5-0.5s0.224-0.5 0.5-0.5h7c0.276 0 0.5 0.224 0.5 0.5s-0.224 0.5-0.5 0.5zM11.5 11h-7c-0.276 0-0.5-0.224-0.5-0.5s0.224-0.5 0.5-0.5h7c0.276 0 0.5 0.224 0.5 0.5s-0.224 0.5-0.5 0.5zM11.5 9h-7c-0.276 0-0.5-0.224-0.5-0.5s0.224-0.5 0.5-0.5h7c0.276 0 0.5 0.224 0.5 0.5s-0.224 0.5-0.5 0.5z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 795 B |
5
assets/img/icons/file-xml2.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M11 4h3.627c-0.078-0.126-0.172-0.266-0.286-0.421-0.347-0.473-0.831-1.027-1.362-1.558s-1.085-1.015-1.558-1.362c-0.155-0.114-0.295-0.208-0.421-0.286v3.627z"></path>
|
||||
<path d="M10.5 5c-0.276 0-0.5-0.224-0.5-0.5v-4.5h-7.75c-0.689 0-1.25 0.561-1.25 1.25v13.5c0 0.689 0.561 1.25 1.25 1.25h11.5c0.689 0 1.25-0.561 1.25-1.25v-9.75h-4.5zM7.5 13l-1 1-3-3 3-3 1 1-2 2 2 2zM9.5 14l-1-1 2-2-2-2 1-1 3 3-3 3z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 550 B |
4
assets/img/icons/folder-check.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15 4h-14l1-2h5.5l0.5 1h6.5zM0 5l1 10h14l1-10h-16zM6.719 13.352l-3.207-3.707 0.914-0.914 2.293 1.793 4.293-3.793 0.914 0.914-5.207 5.707z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 294 B |
4
assets/img/icons/folder-minus.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15 4h-14l1-2h5.5l0.5 1h6.5zM7.813 12.5c0 0.918 0.266 1.776 0.724 2.5h-7.537l-1-10h16l-0.399 3.988c-0.827-0.731-1.913-1.176-3.101-1.176-2.585 0-4.688 2.103-4.688 4.687zM12.5 9c-1.933 0-3.5 1.567-3.5 3.5s1.567 3.5 3.5 3.5 3.5-1.567 3.5-3.5-1.567-3.5-3.5-3.5zM10 13v-1h5v1h-5z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 431 B |
4
assets/img/icons/folder-minus2.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15 4h-14l1-2h5.5l0.5 1h6.5zM0 5l1 10h14l1-10h-16zM11 11h-6v-2h6v2z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 224 B |
4
assets/img/icons/folder-plus.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15 4h-14l1-2h5.5l0.5 1h6.5zM7.813 12.5c0 0.918 0.266 1.776 0.724 2.5h-7.537l-1-10h16l-0.399 3.988c-0.827-0.731-1.913-1.176-3.101-1.176-2.585 0-4.688 2.103-4.688 4.687zM12.5 9c-1.933 0-3.5 1.567-3.5 3.5s1.567 3.5 3.5 3.5 3.5-1.567 3.5-3.5-1.567-3.5-3.5-3.5zM13 13v2h-1v-2h-2v-1h2v-2h1v2h2v1h-2z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 451 B |
4
assets/img/icons/folder-plus2.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15 4h-14l1-2h5.5l0.5 1h6.5zM0 5l1 10h14l1-10h-16zM11 11h-2v2h-2v-2h-2v-2h2v-2h2v2h2v2z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 244 B |
4
assets/img/icons/folder-remove.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15 4h-14l1-2h5.5l0.5 1h6.5l0.5 1zM0 5l1 10h14l1-10h-16zM11.25 7.811l-2.189 2.189 2.189 2.189-1.061 1.061-2.189-2.189-2.189 2.189-1.061-1.061 2.189-2.189-2.189-2.189 1.061-1.061 2.189 2.189 2.189-2.189 1.061 1.061z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 371 B |
6
assets/img/icons/folder-search.svg
Executable file
@@ -0,0 +1,6 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M14.5 2h-6.5l-0.5-1h-5.5l-1 2h14z"></path>
|
||||
<path d="M14.13 11h1.17l0.7-7h-16l1 10h7.564c-1.639-0.59-2.814-2.16-2.814-4 0-2.343 1.907-4.25 4.25-4.25s4.25 1.907 4.25 4.25c0 0.339-0.041 0.674-0.12 1z"></path>
|
||||
<path d="M15.672 14.277l-3.101-2.73c0.273-0.452 0.43-0.981 0.43-1.548 0-1.657-1.343-3-3-3s-3 1.343-3 3 1.343 3 3 3c0.566 0 1.096-0.157 1.548-0.43l2.73 3.101c0.359 0.417 0.971 0.44 1.359 0.051l0.086-0.086c0.389-0.389 0.366-1.001-0.051-1.359zM10 11.938c-1.070 0-1.938-0.867-1.938-1.938s0.867-1.938 1.938-1.938 1.938 0.867 1.938 1.938-0.867 1.938-1.938 1.938z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 719 B |
4
assets/img/icons/hammer2.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15.784 14.309l-8.572-7.804 0.399-0.4c0.326-0.327 0.503-0.75 0.53-1.181 0.016-0.007 0.031-0.014 0.046-0.023l1.609-1.006c0.218-0.256 0.202-0.66-0.036-0.898l-2.799-2.806c-0.237-0.238-0.641-0.254-0.896-0.036l-1.004 1.614c-0.008 0.015-0.015 0.031-0.022 0.046-0.43 0.027-0.852 0.204-1.178 0.531l-1.522 1.527c-0.327 0.327-0.503 0.75-0.53 1.181-0.016 0.007-0.031 0.014-0.046 0.023l-1.609 1.006c-0.218 0.256-0.202 0.66 0.036 0.898l2.799 2.806c0.237 0.238 0.641 0.254 0.896 0.036l1.004-1.614c0.008-0.015 0.015-0.031 0.023-0.046 0.43-0.027 0.852-0.204 1.178-0.531l0.442-0.443 7.783 8.596c0.226 0.249 0.573 0.289 0.773 0.089l0.787-0.789c0.199-0.2 0.159-0.549-0.089-0.775z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 817 B |
4
assets/img/icons/hand.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M12 16h-5c-0.133 0-0.26-0.053-0.354-0.146l-3-3c-0.027-0.027-0.050-0.056-0.070-0.089l-2.5-4c-0.143-0.229-0.078-0.531 0.147-0.681l1.5-1c0.213-0.142 0.498-0.1 0.661 0.096l1.616 1.939v-7.619c0-0.276 0.224-0.5 0.5-0.5h1.5v-0.5c0-0.276 0.224-0.5 0.5-0.5h2c0.276 0 0.5 0.224 0.5 0.5v0.5h1.5c0.276 0 0.5 0.224 0.5 0.5v1.5h1.5c0.276 0 0.5 0.224 0.5 0.5v9c0 0.078-0.018 0.154-0.053 0.224l-1.5 3c-0.085 0.169-0.258 0.276-0.447 0.276zM7.207 15h4.484l1.309-2.618v-8.382h-1v4.5c0 0.276-0.224 0.5-0.5 0.5s-0.5-0.224-0.5-0.5v-6.5h-1v6.5c0 0.276-0.224 0.5-0.5 0.5s-0.5-0.224-0.5-0.5v-7.5h-1v7.5c0 0.276-0.224 0.5-0.5 0.5s-0.5-0.224-0.5-0.5v-6.5h-1v8.5c0 0.21-0.132 0.398-0.33 0.47s-0.42 0.012-0.554-0.15l-2.212-2.655-0.722 0.481 2.213 3.54 2.813 2.813z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 892 B |
4
assets/img/icons/history.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="17" height="16" viewBox="0 0 17 16">
|
||||
<path d="M10 1c3.866 0 7 3.134 7 7s-3.134 7-7 7v-1.5c1.469 0 2.85-0.572 3.889-1.611s1.611-2.42 1.611-3.889c0-1.469-0.572-2.85-1.611-3.889s-2.42-1.611-3.889-1.611c-1.469 0-2.85 0.572-3.889 1.611-0.799 0.799-1.322 1.801-1.52 2.889h2.909l-3.5 4-3.5-4h2.571c0.485-3.392 3.402-6 6.929-6zM13 7v2h-4v-5h2v3z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 448 B |
16
assets/img/icons/linktree-full.svg
Executable file
@@ -0,0 +1,16 @@
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 494.1 100" style="enable-background:new 0 0 494.1 100;" xml:space="preserve">
|
||||
<path d="M0,10.7h14.2v74.5h39.3v13.1H0V10.7z M67.5,10.7c4.8,0,8.9,3.7,8.9,8.6c0,4.9-4,8.8-8.9,8.8c-4.9,0-8.9-3.9-8.9-8.8
|
||||
C58.6,14.5,62.5,10.7,67.5,10.7z M60.5,35.2h13.6v63.2H60.5V35.2z M82.2,35.2h13.6v8.7c4-6.7,10.9-10.4,20.1-10.4
|
||||
c14.8,0,24,11.5,24,29.7v35.1h-13.6V64.5c0-11.8-5.2-18.5-14.5-18.5c-10.3,0-15.9,7-15.9,19.6v32.7H82.2L82.2,35.2L82.2,35.2z
|
||||
M147.1,10.7h13.6v55.4l25.4-30.9h17.1l-27.1,31.6l27.1,31.5h-17.1l-25.4-30.8v30.8h-13.6V10.7z M208.6,19.1h13.9v16.1h16.2v11.3
|
||||
h-16.2v32.5c0,4.1,2.5,6.7,6.5,6.7h9.1v12.7h-10.9c-11.8,0-18.5-7-18.5-19.4L208.6,19.1L208.6,19.1z M245.6,35.2h12.6V43
|
||||
c3.4-6,9-9.5,15.9-9.5c2.1,0,3.2,0.1,4.8,0.6v12.6c-0.9-0.2-2.3-0.5-5.1-0.5c-10,0-15.5,8.4-15.5,22.8v29.2h-13.6V35.2H245.6z
|
||||
M310.8,33.5c15,0,31.3,9,31.3,34.7V70h-48.8c1.1,11.3,7.6,17.5,18.6,17.5c7.9,0,14.5-4.2,16-10.1h13.9
|
||||
C340.3,90,327.1,100,311.8,100c-19.6,0-32-12.7-32-33.3C279.8,48.4,291.7,33.5,310.8,33.5z M327.5,58.8c-1.9-7.8-8.1-12.7-16.7-12.7
|
||||
c-8.3,0-14.2,5-16.5,12.7H327.5z M379.1,33.5c15,0,31.3,9,31.3,34.7V70h-48.8c1.1,11.3,7.6,17.5,18.6,17.5c7.9,0,14.5-4.2,16-10.1
|
||||
H410C408.6,90,395.4,100,380.1,100c-19.6,0-32-12.7-32-33.3C348.1,48.4,360,33.5,379.1,33.5z M395.8,58.8
|
||||
c-1.9-7.8-8.1-12.7-16.8-12.7c-8.3,0-14.2,5-16.5,12.7H395.8z M413.7,33.3H438l-17.3-16.4l9.5-9.7L446.7,24V0h14.3v24l16.5-16.8
|
||||
l9.5,9.7l-17.3,16.4h24.3v13.6h-24.5L487,63.7l-9.5,9.5l-23.7-23.7l-23.7,23.7l-9.5-9.5L438,46.8h-24.5V33.3H413.7z M446.8,66.2
|
||||
h14.3v32.2h-14.3V66.2z">
|
||||
</path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
39
assets/img/icons/linktree.svg
Executable file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 98 98.000003"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="linktree.svg"
|
||||
width="98"
|
||||
height="98"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs1" /><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="3.7971541"
|
||||
inkscape:cx="-1.1850981"
|
||||
inkscape:cy="63.205231"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<path
|
||||
d="M 9.2,33.2 H 33.4 L 16.1,16.8 25.6,7.2 42,23.9 V 0.1 H 56.2 V 23.9 L 72.6,7.2 82.1,16.8 64.8,33.1 H 89 V 46.6 H 64.7 L 82,63.3 72.5,72.7 49,49.2 25.5,72.8 16,63.3 33.3,46.6 H 9 V 33.2 Z m 32.9,32.7 h 14.2 v 32 H 42.1 Z"
|
||||
id="path1">
|
||||
</path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
40
assets/img/icons/loyalfans.svg
Executable file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 213.99999 214"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="loyalfans.svg"
|
||||
width="214"
|
||||
height="214"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs1" /><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.5023135"
|
||||
inkscape:cx="-47.593262"
|
||||
inkscape:cy="179.72281"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<path
|
||||
d="m 71.2,29.9 c 8.5,-8.5 22.5,-8.5 31,0 8.5,8.5 8.5,22.5 0,31 -8.5,8.5 -22.5,8.5 -31,0 -8.5,-8.5 -8.7,-22.5 0,-31 z M 212,0.4 133.9,97.3 c -1.2,1.4 -2.4,3 -3.6,4.4 -5.9,7.7 -11.1,16 -15.2,24.9 -8.3,17.6 -13.1,37.4 -13.1,58.3 v 28.7 H 71 v -30.1 c 0,-2.6 0,-5.1 -0.2,-7.7 -1,-18 -5.5,-34.8 -12.7,-50.2 -1.8,-3.8 -3.8,-7.5 -5.9,-11.3 L 51.4,112.9 2,30.5 l 84.8,72 v 0 0 z"
|
||||
id="path1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
8
assets/img/icons/make-group.svg
Executable file
@@ -0,0 +1,8 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M5 2h-2c-0.55 0-1 0.45-1 1v2c0 0.55 0.45 1 1 1h2c0.55 0 1-0.45 1-1v-2c0-0.55-0.45-1-1-1z"></path>
|
||||
<path d="M11 6h2c0.55 0 1-0.45 1-1v-2c0-0.55-0.45-1-1-1h-2c-0.55 0-1 0.45-1 1v2c0 0.55 0.45 1 1 1zM11 3h2v2h-2v-2z"></path>
|
||||
<path d="M5 10h-2c-0.55 0-1 0.45-1 1v2c0 0.55 0.45 1 1 1h2c0.55 0 1-0.45 1-1v-2c0-0.55-0.45-1-1-1zM5 13h-2v-2h2v2z"></path>
|
||||
<path d="M13 10h-2c-0.55 0-1 0.45-1 1v2c0 0.55 0.45 1 1 1h2c0.55 0 1-0.45 1-1v-2c0-0.55-0.45-1-1-1z"></path>
|
||||
<path d="M14 8h-1c-1.336 0-2.591-0.52-3.536-1.464s-1.464-2.2-1.464-3.536v-1c0-1.1-0.9-2-2-2h-4c-1.1 0-2 0.9-2 2v4c0 1.1 0.9 2 2 2h1c1.336 0 2.591 0.52 3.536 1.464s1.464 2.2 1.464 3.536v1c0 1.1 0.9 2 2 2h4c1.1 0 2-0.9 2-2v-4c0-1.1-0.9-2-2-2zM15 14c0 0.265-0.105 0.515-0.295 0.705s-0.44 0.295-0.705 0.295h-4c-0.265 0-0.515-0.105-0.705-0.295s-0.295-0.44-0.295-0.705v-1c0-3.314-2.686-6-6-6h-1c-0.265 0-0.515-0.105-0.705-0.295s-0.295-0.441-0.295-0.705v-4c0-0.265 0.105-0.515 0.295-0.705s0.44-0.295 0.705-0.295h4c0.265 0 0.515 0.105 0.705 0.295s0.295 0.44 0.295 0.705v1c0 3.314 2.686 6 6 6h1c0.265 0 0.515 0.105 0.705 0.295s0.295 0.44 0.295 0.705v4z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
3
assets/img/icons/manyvids-full.svg
Executable file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="logo-default" data-testid="logo-default-icon" viewBox="0 -0.04 154.28 24.03">
|
||||
<path d="m110.215 23.07 7.873-17.456h-3.862l-4.534 9.913-4.557-9.913h-3.858l7.89 17.465zm13.452-17.506h-3.537V23.07h3.537zm3.33.05v17.434h1.417v.031h3.51a8.76 8.76 0 0 0 6.154-2.567 7.963 7.963 0 0 0 1.868-2.761 8.624 8.624 0 0 0 0-6.8 8.348 8.348 0 0 0-1.868-2.793 8.586 8.586 0 0 0-6.154-2.54zm3.483 13.978V9.101h1.444a5.245 5.245 0 0 1 0 10.49zm17.339-3.885.077.027c1.818.623 2.892 1.493 2.892 2.441a1.919 1.919 0 0 1-1.918 1.769 6.034 6.034 0 0 1-4.68-1.965l-2.54 2.391a9.681 9.681 0 0 0 4.155 2.639 10.322 10.322 0 0 0 3.068.424 5.418 5.418 0 0 0 5.405-5.247 5.053 5.053 0 0 0-1.367-3.415 9.316 9.316 0 0 0-3.858-2.319c-.149-.05-.3-.1-.5-.149-1.6-.4-2.22-.9-2.242-1.791a1.225 1.225 0 0 1 .3-1 2.664 2.664 0 0 1 1.543-.65 5.379 5.379 0 0 1 3.366 1.2l.618.4 1.818-2.964-.573-.374a8.663 8.663 0 0 0-5.234-1.742 6.071 6.071 0 0 0-4.061 1.715 4.67 4.67 0 0 0-1.272 3.56 4.815 4.815 0 0 0 2.238 3.939 8.459 8.459 0 0 0 2.639 1.1zM95.543 5.61l-3.56 6.574-3.587-6.574h-3.858l5.7 11.059v6.4h3.483v-6.4L99.405 5.61zm-17.484 0v9.764L68.422 5.61h-1.1v17.461h3.488V12.882l9.809 10.188h.92V5.609zm-21.991 0-8.893 17.451h3.912l1.642-3.24h7.224l1.521 3.244h3.858l-8.244-17.46zm.42 6.849 1.818 3.889h-3.785zM43.21 5.605l-7.273 6.619L28.645 5.6h-1.2v17.461h3.488V12.377l5 4.557 5.008-4.557v10.684h3.488V5.6H43.21zM10.63 19.118a1.876 1.876 0 0 0-.041-.217c-.239-.911-.465-1.823-.726-2.725a.569.569 0 0 1 .176-.677 1.3 1.3 0 0 0 .221-1.543 1.418 1.418 0 0 0-1.313-.772 1.376 1.376 0 0 0-1.232.938 1.3 1.3 0 0 0 .415 1.507.358.358 0 0 1 .117.438c-.257.916-.492 1.836-.735 2.757a2.781 2.781 0 0 0-.041.289h3.158m-1.6-7.9a5.417 5.417 0 0 1 1.642-2.134 4.357 4.357 0 0 1 5.577.352 5.785 5.785 0 0 1 1.187 6.736 13.445 13.445 0 0 1-2.725 3.61 28.84 28.84 0 0 1-5.491 4.16.424.424 0 0 1-.352.027 27.5 27.5 0 0 1-6.4-5.094 9.672 9.672 0 0 1-2.279-3.84 5.677 5.677 0 0 1 1.8-5.766 4.324 4.324 0 0 1 6.6 1.169c.149.239.28.492.438.781M5.503 2.722c.4.379.79.781 1.214 1.132.352.293.537.262.772-.126.329-.546.618-1.11.9-1.683.036-.077-.036-.244-.108-.329A1.015 1.015 0 0 1 8.387.222a1.006 1.006 0 0 1 1.363 1.48.31.31 0 0 0-.072.438c.3.532.573 1.087.893 1.611.221.361.37.37.722.126a3.189 3.189 0 0 0 .447-.37c.266-.266.519-.541.776-.808-.492-.672-.4-1.358.2-1.678a1.006 1.006 0 0 1 1.354.406.985.985 0 0 1-.424 1.367.619.619 0 0 0-.388.492c-.23.947-.483 1.886-.717 2.833a.486.486 0 0 1-.532.415q-3-.007-5.992 0a.48.48 0 0 1-.532-.411c-.244-.966-.505-1.931-.74-2.9a.513.513 0 0 0-.334-.411 1 1 0 0 1-.564-1.132 1.026 1.026 0 0 1 .862-.767.982.982 0 0 1 1.074.659c.14.361.063.672-.284 1.142"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
17
assets/img/icons/manyvids.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
data-name="logo-default"
|
||||
data-testid="logo-default-icon"
|
||||
viewBox="0 -0.04 25 24.999999"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="25"
|
||||
height="25"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<path
|
||||
d="m 14.114527,19.614142 c -0.0094,-0.07308 -0.02308,-0.145535 -0.041,-0.217 -0.239,-0.911 -0.465,-1.823 -0.726,-2.725 -0.103352,-0.239339 -0.03083,-0.5183 0.176,-0.677 0.408042,-0.408238 0.498047,-1.036638 0.221,-1.543 -0.250584,-0.490502 -0.762542,-0.791516 -1.313,-0.772 -0.56432,0.03001 -1.052913,0.40201 -1.232,0.938 -0.212834,0.538692 -0.04361,1.15321 0.415,1.507 0.138253,0.09956 0.18719,0.28276 0.117,0.438 -0.257,0.916 -0.492,1.836 -0.735,2.757 -0.01872,0.09555 -0.0324,0.192015 -0.041,0.289 h 3.158 m -1.6,-7.9 c 0.359002,-0.838194 0.923783,-1.572203 1.642,-2.1340003 1.699386,-1.2472131 4.047914,-1.0989825 5.577,0.352 1.822799,1.7459463 2.303203,4.4721513 1.187,6.7360003 -0.697958,1.348581 -1.619326,2.569183 -2.725,3.61 -1.657551,1.601073 -3.501032,2.997701 -5.491,4.16 -0.107829,0.05974 -0.236321,0.0696 -0.352,0.027 -2.3753486,-1.369455 -4.5325397,-3.086444 -6.3999999,-5.094 -1.048787,-1.084717 -1.8292518,-2.39976 -2.2790001,-3.84 -0.5571739,-2.108189 0.1424143,-4.349203 1.8000001,-5.7660003 2.0738766,-1.7880035 5.2664089,-1.2225383 6.5999999,1.1690003 0.149,0.239 0.28,0.492 0.438,0.781 M 8.9875271,3.2181417 c 0.4,0.379 0.79,0.781 1.2139999,1.132 0.352,0.293 0.537,0.262 0.772,-0.126 0.329,-0.546 0.618,-1.11 0.9,-1.683 0.036,-0.077 -0.036,-0.244 -0.108,-0.329 -0.410242,-0.4325033 -0.361198,-1.1237515 0.106,-1.49399998 0.986666,-0.90866627 2.349666,0.57133368 1.363,1.47999998 -0.142839,0.099814 -0.17537,0.2977135 -0.072,0.438 0.3,0.532 0.573,1.087 0.893,1.611 0.221,0.361 0.37,0.37 0.722,0.126 0.159934,-0.109493 0.309554,-0.2333389 0.447,-0.37 0.266,-0.266 0.519,-0.541 0.776,-0.808 -0.492,-0.672 -0.4,-1.358 0.2,-1.678 0.486391,-0.2579836 1.089809,-0.077047 1.354,0.406 0.277315,0.4928925 0.08357,1.1175522 -0.424,1.367 -0.208917,0.081596 -0.357352,0.2698181 -0.388,0.492 -0.23,0.947 -0.483,1.886 -0.717,2.833 -0.03678,0.2589486 -0.271887,0.4423538 -0.532,0.415 -2,-0.00467 -3.997333,-0.00467 -5.9919999,0 -0.2596827,0.030788 -0.4962279,-0.1519569 -0.532,-0.411 -0.244,-0.966 -0.505,-1.931 -0.74,-2.9 -0.026543,-0.1883196 -0.15509,-0.3465019 -0.334,-0.411 -0.4330367,-0.1954461 -0.6687764,-0.6685975 -0.564,-1.132 0.1027353,-0.4083194 0.4445066,-0.7124244 0.862,-0.767 0.4703187,-0.069255 0.9227059,0.2083271 1.074,0.659 0.14,0.361 0.063,0.672 -0.284,1.142"
|
||||
id="path1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
6
assets/img/icons/markup.svg
Executable file
@@ -0,0 +1,6 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="16" viewBox="0 0 24 16">
|
||||
<path d="M17 7v-2h-2v-2h-2v2h-2v-2h-2v2h-2v2h2v2h-2v2h2v2h2v-2h2v2h2v-2h2v-2h-2v-2h2zM13 9h-2v-2h2v2z"></path>
|
||||
<path d="M8.707 1.707l-1.414-1.414-7.293 7.293v0.828l7.293 7.293 1.414-1.414-6.293-6.293z"></path>
|
||||
<path d="M15.293 1.707l1.414-1.414 7.293 7.293v0.828l-7.293 7.293-1.414-1.414 6.293-6.293z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 448 B |
52
assets/img/icons/matrix-full.svg
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
viewBox="0 0 75 32"
|
||||
id="svg1"
|
||||
sodipodi:docname="matrix-full.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="12.000629"
|
||||
inkscape:cx="27.79021"
|
||||
inkscape:cy="22.165505"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<title
|
||||
id="title1">Matrix (protocol) logo</title>
|
||||
<g
|
||||
id="g1">
|
||||
<path
|
||||
d="m0.936 0.732v30.52h2.194v0.732h-3.035v-31.98h3.034v0.732zm8.45 9.675v1.544h0.044a4.461 4.461 0 0 1 1.487-1.368c0.58-0.323 1.245-0.485 1.993-0.485 0.72 0 1.377 0.14 1.972 0.42 0.595 0.279 1.047 0.771 1.355 1.477 0.338-0.5 0.796-0.941 1.377-1.323 0.58-0.383 1.266-0.574 2.06-0.574 0.602 0 1.16 0.074 1.674 0.22 0.514 0.148 0.954 0.383 1.322 0.707 0.366 0.323 0.653 0.746 0.859 1.268 0.205 0.522 0.308 1.15 0.308 1.887v7.633h-3.127v-6.464c0-0.383-0.015-0.743-0.044-1.082a2.305 2.305 0 0 0-0.242-0.882 1.473 1.473 0 0 0-0.584-0.596c-0.257-0.146-0.606-0.22-1.047-0.22-0.44 0-0.796 0.085-1.068 0.253-0.272 0.17-0.485 0.39-0.639 0.662a2.654 2.654 0 0 0-0.308 0.927 7.074 7.074 0 0 0-0.078 1.048v6.354h-3.128v-6.398c0-0.338-7e-3 -0.673-0.021-1.004a2.825 2.825 0 0 0-0.188-0.916 1.411 1.411 0 0 0-0.55-0.673c-0.258-0.168-0.636-0.253-1.135-0.253a2.33 2.33 0 0 0-0.584 0.1 1.94 1.94 0 0 0-0.705 0.374c-0.228 0.184-0.422 0.449-0.584 0.794-0.161 0.346-0.242 0.798-0.242 1.357v6.619h-3.129v-11.41zm16.46 1.677a3.751 3.751 0 0 1 1.233-1.17 5.37 5.37 0 0 1 1.685-0.629 9.579 9.579 0 0 1 1.884-0.187c0.573 0 1.153 0.04 1.74 0.121 0.588 0.081 1.124 0.24 1.609 0.475 0.484 0.235 0.88 0.562 1.19 0.981 0.308 0.42 0.462 0.975 0.462 1.666v5.934c0 0.516 0.03 1.008 0.088 1.478 0.058 0.471 0.161 0.824 0.308 1.06h-3.171a4.435 4.435 0 0 1-0.22-1.104c-0.5 0.515-1.087 0.876-1.762 1.081a7.084 7.084 0 0 1-2.071 0.31c-0.544 0-1.05-0.067-1.52-0.2a3.472 3.472 0 0 1-1.234-0.617 2.87 2.87 0 0 1-0.826-1.059c-0.199-0.426-0.298-0.934-0.298-1.522 0-0.647 0.114-1.18 0.342-1.6 0.227-0.419 0.52-0.753 0.881-1.004 0.36-0.25 0.771-0.437 1.234-0.562 0.462-0.125 0.929-0.224 1.399-0.298 0.47-0.073 0.932-0.132 1.387-0.176 0.456-0.044 0.86-0.11 1.212-0.199 0.353-0.088 0.631-0.217 0.837-0.386s0.301-0.415 0.287-0.74c0-0.337-0.055-0.606-0.166-0.804a1.217 1.217 0 0 0-0.44-0.464 1.737 1.737 0 0 0-0.639-0.22 5.292 5.292 0 0 0-0.782-0.055c-0.617 0-1.101 0.132-1.454 0.397-0.352 0.264-0.558 0.706-0.617 1.323h-3.128c0.044-0.735 0.227-1.345 0.55-1.83zm6.179 4.423a5.095 5.095 0 0 1-0.639 0.165 9.68 9.68 0 0 1-0.716 0.11c-0.25 0.03-0.5 0.067-0.749 0.11a5.616 5.616 0 0 0-0.694 0.177 2.057 2.057 0 0 0-0.594 0.298c-0.17 0.125-0.305 0.284-0.408 0.474-0.103 0.192-0.154 0.434-0.154 0.728 0 0.28 0.051 0.515 0.154 0.706 0.103 0.192 0.242 0.342 0.419 0.453 0.176 0.11 0.381 0.187 0.617 0.231 0.234 0.044 0.477 0.066 0.726 0.066 0.617 0 1.094-0.102 1.432-0.309 0.338-0.205 0.587-0.452 0.75-0.739 0.16-0.286 0.26-0.576 0.297-0.87 0.036-0.295 0.055-0.53 0.055-0.707v-1.17a1.4 1.4 0 0 1-0.496 0.277zm11.86-6.1v2.096h-2.291v5.647c0 0.53 0.088 0.883 0.264 1.059 0.176 0.177 0.529 0.265 1.057 0.265 0.177 0 0.345-7e-3 0.507-0.022 0.161-0.015 0.316-0.037 0.463-0.066v2.426a7.49 7.49 0 0 1-0.882 0.089 21.67 21.67 0 0 1-0.947 0.022c-0.484 0-0.944-0.034-1.377-0.1a3.233 3.233 0 0 1-1.145-0.386 2.04 2.04 0 0 1-0.782-0.816c-0.191-0.353-0.287-0.816-0.287-1.39v-6.728h-1.894v-2.096h1.894v-3.42h3.129v3.42h2.29zm4.471 0v2.118h0.044a3.907 3.907 0 0 1 1.454-1.754 4.213 4.213 0 0 1 1.036-0.497 3.734 3.734 0 0 1 1.145-0.176c0.206 0 0.433 0.037 0.683 0.11v2.912a5.862 5.862 0 0 0-0.528-0.077 5.566 5.566 0 0 0-0.595-0.033c-0.573 0-1.058 0.096-1.454 0.287a2.52 2.52 0 0 0-0.958 0.783 3.143 3.143 0 0 0-0.518 1.158 6.32 6.32 0 0 0-0.154 1.434v5.14h-3.128v-11.4zm5.684-1.765v-2.582h3.128v2.582h-3.127zm3.128 1.765v11.4h-3.127v-11.4h3.128zm1.63 0h3.569l2.005 2.978 1.982-2.978h3.459l-3.745 5.339 4.208 6.067h-3.57l-2.378-3.596-2.38 3.596h-3.502l4.097-6.001zm15.3 20.84v-30.52h-2.194v-0.732h3.035v31.98h-3.035v-0.732z"
|
||||
id="path1" />
|
||||
</g>
|
||||
<metadata
|
||||
id="metadata1">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:title>Matrix (protocol) logo</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
41
assets/img/icons/matrix.svg
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
width="800px"
|
||||
height="800px"
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="matrix.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="0.23142407"
|
||||
inkscape:cx="412.66234"
|
||||
inkscape:cy="557.41825"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<path
|
||||
d="M0.844 0.735v30.531h2.197v0.735h-3.041v-32h3.041v0.735zM10.235 10.412v1.547h0.041c0.412-0.595 0.912-1.047 1.489-1.371 0.579-0.323 1.251-0.484 2-0.484 0.719 0 1.38 0.141 1.975 0.417 0.599 0.281 1.047 0.776 1.359 1.479 0.339-0.5 0.803-0.943 1.38-1.323 0.579-0.38 1.267-0.573 2.063-0.573 0.604 0 1.161 0.073 1.677 0.224 0.521 0.145 0.959 0.38 1.328 0.703 0.365 0.329 0.651 0.751 0.86 1.272 0.203 0.52 0.307 1.151 0.307 1.891v7.635h-3.129v-6.468c0-0.381-0.016-0.745-0.048-1.084-0.020-0.307-0.099-0.604-0.239-0.88-0.131-0.251-0.333-0.459-0.584-0.593-0.255-0.152-0.609-0.224-1.047-0.224-0.443 0-0.797 0.083-1.068 0.249-0.265 0.167-0.489 0.396-0.64 0.667-0.161 0.287-0.265 0.604-0.308 0.927-0.052 0.349-0.077 0.699-0.083 1.048v6.359h-3.131v-6.401c0-0.339-0.005-0.672-0.025-1-0.011-0.317-0.073-0.624-0.193-0.916-0.104-0.281-0.301-0.516-0.552-0.672-0.255-0.167-0.636-0.255-1.136-0.255-0.151 0-0.348 0.031-0.588 0.099-0.24 0.067-0.479 0.192-0.703 0.375-0.229 0.188-0.428 0.453-0.589 0.797-0.161 0.343-0.239 0.796-0.239 1.359v6.62h-3.131v-11.421zM31.156 31.265v-30.531h-2.197v-0.735h3.041v32h-3.041v-0.735z"
|
||||
id="path1"
|
||||
style="fill-opacity:1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
69
assets/img/icons/onlyfans.svg
Executable file → Normal file
@@ -1,66 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="icon-logo"
|
||||
viewBox="0 0 92.400002 92.399879"
|
||||
viewBox="0 0 400 400"
|
||||
version="1.1"
|
||||
sodipodi:docname="onlyfans.svg"
|
||||
width="92.400002"
|
||||
height="92.399879"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14">
|
||||
<metadata
|
||||
id="metadata21">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
id="svg2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs19" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
id="namedview17"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="6.1429902"
|
||||
inkscape:cx="26.40336"
|
||||
inkscape:cy="24.398909"
|
||||
inkscape:window-x="1047"
|
||||
inkscape:window-y="930"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="icon-logo" />
|
||||
id="defs2" />
|
||||
<path
|
||||
class="svg-logo-color-1"
|
||||
d="M 46.07999,3.9024059e-5 A 46.2,46.2 0 1 0 92.39999,46.170039 46.26,46.26 0 0 0 46.07999,3.9024059e-5 Z m 0,87.569999975941 a 41.38,41.38 0 1 1 41.48,-41.4 41.44,41.44 0 0 1 -41.48,41.38 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill-rule:evenodd" />
|
||||
d="M137.5 75a125 125 0 1 0 125 125 125 125 0 0 0-125-125zm0 162.5A37.5 37.5 0 1 1 175 200a37.45 37.45 0 0 1-37.5 37.5z"
|
||||
opacity=".7"
|
||||
id="path1" />
|
||||
<path
|
||||
d="m 65.28999,43.190039 v -3.77 a 16.75,16.75 0 0 0 -5.08,-12 17.31,17.31 0 0 0 -12.19,-5 h -3.1 a 17.31,17.31 0 0 0 -12.18,5 16.7,16.7 0 0 0 -5.07,12 v 3.77 l -2.14,3.86 v 5.56 a 18.64,18.64 0 0 0 5.64,13.33 19.37,19.37 0 0 0 13.59,5.54 h 3.45 a 19.33,19.33 0 0 0 13.55,-5.54 18.61,18.61 0 0 0 5.65,-13.33 v -5.56 z m -16.8,17.06 v 4.45 a 1.93,1.93 0 0 1 -0.89,1.64 h -0.84 a 1,1 0 0 1 -0.3,0 h -0.2 a 1.18,1.18 0 0 1 -0.25,0 h -0.38 a 2,2 0 0 1 -0.92,-1.67 v -4.42 a 5.3,5.3 0 0 1 2,-10.24 h 0.11 a 5.3,5.3 0 0 1 2,10.24 z m 9.09,-16.94 h -22.21 v -3.89 a 9.27,9.27 0 0 1 2.81,-6.63 9.62,9.62 0 0 1 6.74,-2.79 h 3.1 a 9.61,9.61 0 0 1 6.74,2.79 9.31,9.31 0 0 1 2.81,6.63 z"
|
||||
class="svg-logo-color-2"
|
||||
id="path14"
|
||||
inkscape:connector-curvature="0" />
|
||||
d="M278 168.75c31.76 9.14 69.25 0 69.25 0-10.88 47.5-45.38 77.25-95.13 80.87A124.73 124.73 0 0 1 137.5 325L175 205.81C213.55 83.3 233.31 75 324.73 75h62.77c-10.5 46.25-46.69 81.58-109.5 93.75z"
|
||||
id="path2" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 626 B |
66
assets/img/icons/onlyfans_lock.svg
Executable file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="icon-logo"
|
||||
viewBox="0 0 92.400002 92.399879"
|
||||
version="1.1"
|
||||
sodipodi:docname="onlyfans.svg"
|
||||
width="92.400002"
|
||||
height="92.399879"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14">
|
||||
<metadata
|
||||
id="metadata21">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs19" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
id="namedview17"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="6.1429902"
|
||||
inkscape:cx="26.40336"
|
||||
inkscape:cy="24.398909"
|
||||
inkscape:window-x="1047"
|
||||
inkscape:window-y="930"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="icon-logo" />
|
||||
<path
|
||||
class="svg-logo-color-1"
|
||||
d="M 46.07999,3.9024059e-5 A 46.2,46.2 0 1 0 92.39999,46.170039 46.26,46.26 0 0 0 46.07999,3.9024059e-5 Z m 0,87.569999975941 a 41.38,41.38 0 1 1 41.48,-41.4 41.44,41.44 0 0 1 -41.48,41.38 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill-rule:evenodd" />
|
||||
<path
|
||||
d="m 65.28999,43.190039 v -3.77 a 16.75,16.75 0 0 0 -5.08,-12 17.31,17.31 0 0 0 -12.19,-5 h -3.1 a 17.31,17.31 0 0 0 -12.18,5 16.7,16.7 0 0 0 -5.07,12 v 3.77 l -2.14,3.86 v 5.56 a 18.64,18.64 0 0 0 5.64,13.33 19.37,19.37 0 0 0 13.59,5.54 h 3.45 a 19.33,19.33 0 0 0 13.55,-5.54 18.61,18.61 0 0 0 5.65,-13.33 v -5.56 z m -16.8,17.06 v 4.45 a 1.93,1.93 0 0 1 -0.89,1.64 h -0.84 a 1,1 0 0 1 -0.3,0 h -0.2 a 1.18,1.18 0 0 1 -0.25,0 h -0.38 a 2,2 0 0 1 -0.92,-1.67 v -4.42 a 5.3,5.3 0 0 1 2,-10.24 h 0.11 a 5.3,5.3 0 0 1 2,10.24 z m 9.09,-16.94 h -22.21 v -3.89 a 9.27,9.27 0 0 1 2.81,-6.63 9.62,9.62 0 0 1 6.74,-2.79 h 3.1 a 9.61,9.61 0 0 1 6.74,2.79 9.31,9.31 0 0 1 2.81,6.63 z"
|
||||
class="svg-logo-color-2"
|
||||
id="path14"
|
||||
inkscape:connector-curvature="0" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
45
assets/img/icons/pornhub.svg
Executable file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.2"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 79.5 75"
|
||||
overflow="visible"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="pornhub.svg"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs3" /><sodipodi:namedview
|
||||
id="namedview3"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="10.906667"
|
||||
inkscape:cx="39.746333"
|
||||
inkscape:cy="37.5"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<path
|
||||
id="path1"
|
||||
d="M 64.099609 46 C 62.799609 46 61.599219 46.499609 60.699219 47.599609 C 59.799219 48.699609 59.300781 50.3 59.300781 52.5 C 59.300781 54.8 59.700391 56.4 60.400391 57.5 C 61.400391 59 62.700391 59.800781 64.400391 59.800781 C 65.600391 59.800781 66.699609 59.299219 67.599609 58.199219 C 68.499609 57.199219 68.9 55.4 69 53 C 69 50.5 68.499609 48.699609 67.599609 47.599609 C 66.699609 46.499609 65.499609 46 64.099609 46 z " /><path
|
||||
id="path4"
|
||||
d="M 3.6992188 25.300781 C 1.4992187 25.600781 0.2 26.900391 0 29.400391 L 0 70.800781 C 0.2 73.300781 1.3992187 74.700391 3.6992188 74.900391 L 75.900391 74.900391 C 78.100391 74.600391 79.399609 73.300781 79.599609 70.800781 L 79.599609 29.400391 C 79.299609 26.900391 78.100781 25.500781 75.800781 25.300781 L 3.6992188 25.300781 z M 7.0996094 33.900391 L 12.800781 33.900391 L 12.800781 43.699219 C 14.300781 42.299219 17.400781 41.599219 19.800781 41.699219 L 19.900391 41.699219 C 21.100391 41.699219 22.099609 42.000391 23.099609 42.400391 C 24.199609 42.900391 25 43.500781 25.5 44.300781 C 26 45.100781 26.400781 45.900391 26.800781 46.900391 C 27.000781 47.800391 27.099609 49.199219 27.099609 51.199219 L 27.099609 63.800781 L 21.300781 63.800781 L 21.300781 52.300781 C 21.300781 50.100781 21.2 48.6 21 48 C 20.7 47.4 20.400781 46.9 19.800781 46.5 C 19.200781 46.2 18.499219 46 17.699219 46 C 16.699219 46 15.899609 46.199219 15.099609 46.699219 C 14.299609 47.199219 13.700391 47.900781 13.400391 48.800781 C 13.100391 49.800781 12.900391 51.2 12.900391 53 L 12.900391 63.900391 L 7.0996094 63.900391 L 7.0996094 33.900391 z M 53.400391 33.900391 L 59.199219 33.900391 L 58.900391 43.599609 C 60.300391 42.399609 63.299219 41.499219 65.699219 41.699219 C 66.399219 41.799219 67 41.9 67.5 42 C 69.3 42.4 70.999219 43.199609 72.199219 44.599609 C 73.899219 46.499609 74.799609 49.199219 74.599609 52.699219 C 74.599609 56.399219 73.700391 59.300781 71.900391 61.300781 C 70.200391 63.300781 68 64.300781 65.5 64.300781 L 65.300781 64.300781 L 65 64.300781 C 62 64.300781 60.000781 63.199219 58.800781 62.199219 L 58.800781 63.900391 L 53.400391 63.900391 L 53.400391 33.900391 z M 30.300781 42.199219 L 36.099609 42.199219 L 36.099609 52.199219 C 36.099609 55.199219 36.200391 57.100781 36.400391 57.800781 C 36.700391 58.400781 37.099609 59.000391 37.599609 59.400391 C 38.099609 59.800391 38.799219 60 39.699219 60 C 40.599219 60 41.500781 59.699219 42.300781 59.199219 C 43.100781 58.699219 43.600391 57.999219 43.900391 57.199219 C 44.200391 56.399219 44.300781 54.400781 44.300781 51.300781 L 44.199219 42.199219 L 50 42.199219 L 50 64 L 44.699219 64 L 44.699219 61.599609 C 43.799219 62.699609 41.899219 64.4 38.199219 64.5 L 37.5 64.5 C 36.1 64.5 34.799609 64.1 33.599609 63.5 C 32.499609 62.9 31.599609 62.000781 31.099609 60.800781 C 30.599609 59.700781 30.300781 58 30.300781 56 L 30.300781 42.199219 z " />
|
||||
|
||||
<path
|
||||
d="M74.6,9.9c-0.2-0.7-0.5-1.3-0.9-1.9c-0.4-0.6-1-1-1.9-1.4c-0.8-0.4-1.7-0.5-2.7-0.5c-1.8-0.1-4.7,0.6-5.6,2V6.5h-4.2v17h4.5 v-7.7c0-1.9,0.1-3.2,0.3-3.9c0.2-0.7,0.7-1.3,1.3-1.7c0.6-0.4,1.3-0.6,2.1-0.6c0.6,0,1.1,0.2,1.6,0.4c0.4,0.3,0.7,0.7,0.9,1.3 c0.2,0.5,0.3,1.7,0.3,3.6v8.7h4.5V12.9C74.8,11.6,74.7,10.6,74.6,9.9 M53.1,6.2c-1.3,0.2-2.6,1.2-3.2,1.9V6.5h-4.2v17h4.5v-5.3 c0-2.9,0.1-4.8,0.4-5.7c0.3-0.9,0.6-1.5,1-1.9c0.4-0.3,1-0.5,1.6-0.5c0.7,0,1.4,0.2,2.1,0.7l1.4-3.9c-1-0.6-1.9-0.8-3-0.8 C53.6,6.1,53.3,6.1,53.1,6.2 M34.8,6.1c-1.7,0-3.2,0.4-4.5,1.1c-1.4,0.7-2.4,1.8-3.1,3.2c-0.7,1.4-1.1,2.8-1.1,4.3 c0,2,0.4,3.6,1.1,5c0.7,1.4,1.8,2.4,3.2,3.1c1.4,0.7,2.9,1.1,4.5,1.1c2.5,0,4.6-0.8,6.3-2.5c1.7-1.7,2.5-3.8,2.5-6.4 c0-2.6-0.8-4.7-2.5-6.3C39.4,6.9,37.3,6.1,34.8,6.1 M37.7,18.9c-0.8,0.9-1.8,1.3-3,1.3c-1.2,0-2.2-0.4-3-1.3 C31,18,30.6,16.7,30.6,15s0.4-3,1.2-3.9c0.8-0.9,1.8-1.3,3-1.3c1.2,0,2.2,0.4,3,1.3c0.8,0.9,1.2,2.2,1.2,3.8 C38.9,16.7,38.5,18,37.7,18.9 M20.3,0.4C19.4,0.1,17.5,0,14.6,0H7v23.5h4.7v-8.9h3.1c2.1,0,3.8-0.1,4.9-0.3c0.8-0.2,1.7-0.6,2.5-1.1 s1.5-1.3,2-2.3c0.5-1,0.8-2.2,0.8-3.6c0-1.9-0.5-3.4-1.4-4.6C22.8,1.5,21.6,0.7,20.3,0.4 M19.6,9.1c-0.4,0.5-0.9,0.9-1.5,1.2 s-1.9,0.4-3.7,0.4h-2.6V4h2.3c1.7,0,2.8,0.1,3.4,0.2c0.8,0.1,1.4,0.5,1.9,1c0.5,0.6,0.8,1.3,0.8,2.1C20.1,8,20,8.6,19.6,9.1"
|
||||
id="path3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
7
assets/img/icons/regexp.svg
Executable file
@@ -0,0 +1,7 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="21" height="16" viewBox="0 0 21 16">
|
||||
<path d="M14.964 7.134c-0.809-0.467-1.915-0.854-2.865-1.134 0.95-0.28 2.056-0.667 2.865-1.134 0.478-0.276 0.642-0.888 0.366-1.366s-0.888-0.642-1.366-0.366c-0.809 0.467-1.697 1.232-2.415 1.914 0.232-0.963 0.45-2.114 0.45-3.048 0-0.552-0.448-1-1-1s-1 0.448-1 1c0 0.934 0.218 2.086 0.45 3.048-0.717-0.683-1.606-1.447-2.415-1.914-0.478-0.276-1.090-0.112-1.366 0.366s-0.112 1.090 0.366 1.366c0.809 0.467 1.915 0.854 2.865 1.134-0.95 0.28-2.056 0.667-2.865 1.134-0.478 0.276-0.642 0.888-0.366 1.366s0.888 0.642 1.366 0.366c0.809-0.467 1.697-1.232 2.415-1.914-0.232 0.963-0.45 2.114-0.45 3.048 0 0.552 0.448 1 1 1s1-0.448 1-1c0-0.934-0.218-2.086-0.45-3.048 0.717 0.683 1.606 1.447 2.415 1.914 0.478 0.276 1.090 0.112 1.366-0.366s0.112-1.090-0.366-1.366z"></path>
|
||||
<path d="M7 13.5c0 0.828-0.672 1.5-1.5 1.5s-1.5-0.672-1.5-1.5c0-0.828 0.672-1.5 1.5-1.5s1.5 0.672 1.5 1.5z"></path>
|
||||
<path d="M0 16l4-16h2l-4 16z"></path>
|
||||
<path d="M15 16l4-16h2l-4 16z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
4
assets/img/icons/regexp2.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15.15 0h-11.235c-0.562 0-1.106 0.442-1.21 0.983l-2.688 14.034c-0.104 0.541 0.271 0.983 0.833 0.983h11.235c0.562 0 1.106-0.442 1.21-0.983l2.688-14.034c0.104-0.541-0.271-0.983-0.833-0.983zM11.964 9.134c0.478 0.276 0.642 0.888 0.366 1.366s-0.888 0.642-1.366 0.366c-0.809-0.467-1.697-1.232-2.415-1.914 0.232 0.963 0.45 2.114 0.45 3.048 0 0.552-0.448 1-1 1s-1-0.448-1-1c0-0.934 0.218-2.085 0.45-3.048-0.717 0.683-1.606 1.447-2.415 1.914-0.478 0.276-1.090 0.112-1.366-0.366s-0.112-1.090 0.366-1.366c0.809-0.467 1.915-0.854 2.865-1.134-0.95-0.28-2.056-0.667-2.865-1.134-0.478-0.276-0.642-0.888-0.366-1.366s0.888-0.642 1.366-0.366c0.809 0.467 1.697 1.232 2.415 1.914-0.232-0.963-0.45-2.114-0.45-3.048 0-0.552 0.448-1 1-1s1 0.448 1 1c0 0.934-0.218 2.086-0.45 3.048 0.717-0.683 1.606-1.447 2.415-1.914 0.478-0.276 1.090-0.112 1.366 0.366s0.112 1.090-0.366 1.366c-0.809 0.467-1.915 0.854-2.865 1.134 0.95 0.28 2.056 0.667 2.865 1.134z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
4
assets/img/icons/scissors.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M12.218 16c-0.85-0-1.912-0.519-2.369-1.678-0.064-0.151-0.133-0.335-0.214-0.547-0.259-0.68-0.65-1.707-1.059-2.132-0.15-0.156-0.265-0.269-0.359-0.36-0.084-0.081-0.154-0.15-0.217-0.219-0.063 0.069-0.134 0.138-0.217 0.219-0.093 0.091-0.209 0.204-0.358 0.359-0.409 0.425-0.8 1.453-1.059 2.132-0.081 0.212-0.151 0.396-0.214 0.547-0.457 1.159-1.519 1.678-2.369 1.678-0.166 0-0.317-0.020-0.449-0.060-0.837-0.251-1.344-1.186-1.263-2.325l0.012-0.131c0.103-0.919 0.662-1.827 1.576-2.556 0.792-0.632 1.728-1.025 2.444-1.025 0.142 0 0.272 0.015 0.391 0.046l0.491-1.007c-0.505-1.263-1.223-3.149-1.785-4.801-0.313-0.921-0.545-1.675-0.69-2.241-0.23-0.897-0.215-1.2-0.122-1.379l0.269-0.52 3.345 6.858 3.345-6.858 0.269 0.52c0.093 0.179 0.107 0.483-0.122 1.379-0.145 0.566-0.377 1.321-0.69 2.241-0.562 1.652-1.28 3.538-1.785 4.801l0.491 1.007c0.119-0.031 0.25-0.046 0.391-0.046 0.715 0 1.652 0.393 2.444 1.025 0.781 0.624 1.304 1.378 1.503 2.158l0.037-0.018 0.048 0.548c0.081 1.139-0.426 2.073-1.263 2.325-0.132 0.040-0.283 0.060-0.449 0.060-0 0-0 0-0 0zM10.839 13.78c0.592 1.074 1.12 1.234 1.383 1.234 0.358 0 0.626-0.289 0.678-0.568 0.034-0.183 0.040-0.372 0.018-0.561-0.089-0.755-0.604-1.403-1.021-1.814-0.573-0.565-1.215-0.939-1.628-1.103-0.041-0.014-0.066-0.016-0.078-0.016-0.008 0-0.011 0.001-0.011 0.001-0.12 0.078-0.264 0.985 0.658 2.827zM5.723 10.968c-0.41 0.164-1.048 0.539-1.618 1.103-0.414 0.411-0.927 1.059-1.015 1.814-0.022 0.188-0.016 0.377 0.018 0.561 0.052 0.279 0.318 0.568 0.674 0.568 0.261 0 0.787-0.161 1.375-1.234 0.916-1.842 0.774-2.748 0.653-2.828 0 0-0 0-0 0s-0.004-0.001-0.010-0.001c-0.011-0-0.037 0.002-0.077 0.016z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
4
assets/img/icons/scissors2.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M4.655 0l-0.269 0.52c-0.093 0.179-0.107 0.483 0.122 1.379 0.145 0.566 0.377 1.321 0.69 2.241 0.395 1.163 0.868 2.441 1.29 3.536l0.955-1.959-2.789-5.718zM13.93 13.616l-0.048-0.548-0.037 0.018c-0.199-0.78-0.722-1.534-1.503-2.158-0.792-0.633-1.729-1.025-2.444-1.025-0.142 0-0.272 0.015-0.391 0.046l-0.491-1.007c0.505-1.263 1.224-3.149 1.785-4.801 0.313-0.921 0.545-1.675 0.69-2.241 0.23-0.897 0.215-1.2 0.122-1.379l-0.269-0.52-4.852 9.948c-0.119-0.031-0.25-0.046-0.391-0.046-0.715 0-1.652 0.393-2.444 1.025-0.914 0.73-1.473 1.638-1.576 2.556l-0.012 0.131c-0.081 1.139 0.426 2.073 1.263 2.325 0.132 0.040 0.283 0.060 0.449 0.060 0.85 0 1.912-0.519 2.369-1.678 0.064-0.151 0.133-0.335 0.214-0.547 0.259-0.68 0.65-1.707 1.059-2.132 0.15-0.156 0.265-0.269 0.358-0.359 0.084-0.082 0.154-0.15 0.217-0.219 0.063 0.069 0.134 0.138 0.217 0.219 0.093 0.091 0.209 0.204 0.359 0.36 0.409 0.425 0.8 1.453 1.059 2.132 0.081 0.212 0.151 0.396 0.214 0.547 0.457 1.159 1.519 1.678 2.369 1.678 0 0 0 0 0 0 0.166 0 0.317-0.020 0.449-0.060 0.837-0.252 1.344-1.186 1.263-2.325zM5.157 13.78c-0.588 1.073-1.114 1.234-1.375 1.234-0.356 0-0.622-0.289-0.674-0.568-0.034-0.184-0.040-0.373-0.018-0.561 0.088-0.755 0.6-1.403 1.015-1.814 0.569-0.565 1.208-0.939 1.618-1.103 0.041-0.014 0.066-0.016 0.077-0.016 0.006 0 0.009 0.001 0.010 0.001s0 0 0-0c0.121 0.080 0.263 0.986-0.653 2.828zM12.9 14.446c-0.052 0.279-0.32 0.568-0.678 0.568-0.263 0-0.791-0.161-1.383-1.234-0.922-1.842-0.778-2.749-0.658-2.827 0 0 0.003-0.001 0.011-0.001 0.011 0 0.037 0.002 0.078 0.016 0.412 0.164 1.055 0.539 1.628 1.103 0.417 0.411 0.933 1.059 1.021 1.814 0.022 0.189 0.016 0.378-0.018 0.561z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
4
assets/img/icons/soundcloud.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M13.937 8.034c-0.283 0-0.552 0.055-0.798 0.154-0.164-1.787-1.723-3.188-3.625-3.188-0.465 0-0.917 0.088-1.317 0.237-0.156 0.058-0.197 0.117-0.197 0.233v6.292c0 0.121 0.098 0.222 0.221 0.234 0.005 0.001 5.68 0.003 5.717 0.003 1.139 0 2.062-0.888 2.062-1.983s-0.924-1.983-2.063-1.983zM6.25 12h0.5l0.25-3.503-0.25-3.497h-0.5l-0.25 3.497zM4.75 12h-0.5l-0.25-2.543 0.25-2.457h0.5l0.25 2.5zM2.25 12h0.5l0.25-2-0.25-2h-0.5l-0.25 2zM0.25 11h0.5l0.25-1-0.25-1h-0.5l-0.25 1z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 620 B |
4
assets/img/icons/soundcloud2.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M14.5 0h-13c-0.825 0-1.5 0.675-1.5 1.5v13c0 0.825 0.675 1.5 1.5 1.5h13c0.825 0 1.5-0.675 1.5-1.5v-13c0-0.825-0.675-1.5-1.5-1.5zM2.75 11h-0.5l-0.25-1.5 0.25-1.5h0.5l0.25 1.5-0.25 1.5zM4.75 11h-0.5l-0.25-2 0.25-2h0.5l0.25 2-0.25 2zM6.75 11h-0.5l-0.25-3 0.25-3h0.5l0.25 3-0.25 3zM12.894 11c-0.031 0-4.706-0.003-4.709-0.003-0.1-0.009-0.181-0.097-0.184-0.2v-5.394c0-0.1 0.034-0.15 0.162-0.2 0.331-0.128 0.703-0.203 1.088-0.203 1.566 0 2.85 1.2 2.987 2.734 0.203-0.084 0.425-0.131 0.656-0.131 0.938 0 1.7 0.762 1.7 1.7s-0.762 1.697-1.7 1.697z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 693 B |
4
assets/img/icons/spam.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M16 11.5l-4.5-11.5h-7l-4.5 4.5v7l4.5 4.5h7l4.5-4.5v-7l-4.5-4.5zM9 13h-2v-2h2v2zM9 9h-2v-6h2v6z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 251 B |
4
assets/img/icons/stack-cancel.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M5 1v1.155l-2.619 0.368 0.17 1.211-2.551 0.732 3.308 11.535 10.189-2.921 0.558-0.079h1.945v-12h-11zM3.929 14.879l-2.808-9.793 1.558-0.447 1.373 9.766 2.997-0.421-3.119 0.894zM4.822 13.382l-1.418-10.088 1.595-0.224v9.93h2.543l-2.721 0.382zM15 12h-9v-10h9v10zM13 8.939v1.061h-1.061l-1.439-1.439-1.439 1.439h-1.061v-1.061l1.439-1.439-1.439-1.439v-1.061h1.061l1.439 1.439 1.439-1.439h1.061v1.061l-1.439 1.439z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 562 B |
4
assets/img/icons/telegram.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M8 0c-4.419 0-8 3.581-8 8s3.581 8 8 8 8-3.581 8-8-3.581-8-8-8zM11.931 5.484l-1.313 6.184c-0.091 0.441-0.356 0.544-0.725 0.341l-2-1.478-0.959 0.934c-0.112 0.109-0.2 0.2-0.4 0.2-0.259 0-0.216-0.097-0.303-0.344l-0.681-2.237-1.978-0.616c-0.428-0.131-0.431-0.425 0.097-0.634l7.706-2.975c0.35-0.159 0.691 0.084 0.556 0.625z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 474 B |
6
assets/img/icons/twitch.svg
Executable file
@@ -0,0 +1,6 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M1.5 0l-1.5 2.5v11.5h4v2h2l2-2h2.5l4.5-4.5v-9.5h-13.5zM13 8.5l-2.5 2.5h-2.5l-2 2v-2h-3v-9h10v6.5z"></path>
|
||||
<path d="M9.5 4h1.5v4h-1.5v-4z"></path>
|
||||
<path d="M6.5 4h1.5v4h-1.5v-4z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 334 B |
3
assets/img/icons/twitter-x.svg
Executable file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-twitter-x" viewBox="0 0 16 16">
|
||||
<path d="M12.6.75h2.454l-5.36 6.142L16 15.25h-4.937l-3.867-5.07-4.425 5.07H.316l5.733-6.57L0 .75h5.063l3.495 4.633L12.601.75Zm-.86 13.028h1.36L4.323 2.145H2.865z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 301 B |
5
assets/img/icons/user-block.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M6 11.5c0-2.363 1.498-4.383 3.594-5.159 0.254-0.571 0.406-1.206 0.406-1.841 0-2.485 0-4.5-3-4.5s-3 2.015-3 4.5c0 1.548 0.898 3.095 2 3.716v0.825c-3.392 0.277-6 1.944-6 3.959h6.208c-0.135-0.477-0.208-0.98-0.208-1.5z"></path>
|
||||
<path d="M11.5 7c-2.485 0-4.5 2.015-4.5 4.5s2.015 4.5 4.5 4.5c2.485 0 4.5-2.015 4.5-4.5s-2.015-4.5-4.5-4.5zM8 11.5c0-1.933 1.567-3.5 3.5-3.5 0.763 0 1.47 0.245 2.045 0.659l-4.885 4.886c-0.415-0.575-0.66-1.282-0.66-2.045zM11.5 15c-0.763 0-1.47-0.245-2.045-0.659l4.886-4.886c0.415 0.575 0.659 1.282 0.659 2.045 0 1.933-1.567 3.5-3.5 3.5z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 716 B |
5
assets/img/icons/user-cancel.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M6 11.5c0-2.363 1.498-4.383 3.594-5.159 0.254-0.571 0.406-1.206 0.406-1.841 0-2.485 0-4.5-3-4.5s-3 2.015-3 4.5c0 1.548 0.898 3.095 2 3.716v0.825c-3.392 0.277-6 1.944-6 3.959h6.208c-0.135-0.477-0.208-0.98-0.208-1.5z"></path>
|
||||
<path d="M11.5 7c-2.485 0-4.5 2.015-4.5 4.5s2.015 4.5 4.5 4.5c2.485 0 4.5-2.015 4.5-4.5s-2.015-4.5-4.5-4.5zM13.898 13.102c0.22 0.22 0.22 0.576 0 0.795-0.11 0.11-0.254 0.165-0.398 0.165s-0.288-0.055-0.398-0.165l-1.602-1.602-1.602 1.602c-0.11 0.11-0.254 0.165-0.398 0.165s-0.288-0.055-0.398-0.165c-0.22-0.22-0.22-0.576 0-0.795l1.602-1.602-1.602-1.602c-0.22-0.22-0.22-0.576 0-0.795s0.576-0.22 0.795 0l1.602 1.602 1.602-1.602c0.22-0.22 0.576-0.22 0.795 0s0.22 0.576 0 0.795l-1.602 1.602 1.602 1.602z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 876 B |
5
assets/img/icons/user-check.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15 9.5l-4.5 4.5-1.5-1.5-1 1 2.5 2.5 5.5-5.5z"></path>
|
||||
<path d="M7 12h5v-1.799c-1.050-0.613-2.442-1.033-4-1.16v-0.825c1.102-0.621 2-2.168 2-3.716 0-2.485 0-4.5-3-4.5s-3 2.015-3 4.5c0 1.548 0.898 3.095 2 3.716v0.825c-3.392 0.277-6 1.944-6 3.959h7v-1z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 406 B |
5
assets/img/icons/user-lock.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M15.25 11h-0.25v-1c0-1.103-0.897-2-2-2s-2 0.897-2 2v1h-0.25c-0.412 0-0.75 0.338-0.75 0.75v3.5c0 0.412 0.338 0.75 0.75 0.75h4.5c0.412 0 0.75-0.338 0.75-0.75v-3.5c0-0.412-0.338-0.75-0.75-0.75zM12 10c0-0.551 0.449-1 1-1s1 0.449 1 1v1h-2v-1z"></path>
|
||||
<path d="M9 9.166c-0.324-0.055-0.658-0.097-1-0.125v-0.825c1.102-0.621 2-2.168 2-3.716 0-2.485 0-4.5-3-4.5s-3 2.015-3 4.5c0 1.548 0.898 3.095 2 3.716v0.825c-3.392 0.277-6 1.944-6 3.959h9v-3.834z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 597 B |
5
assets/img/icons/user-minus.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M6 11.5c0-2.363 1.498-4.383 3.594-5.159 0.254-0.571 0.406-1.206 0.406-1.841 0-2.485 0-4.5-3-4.5s-3 2.015-3 4.5c0 1.548 0.898 3.095 2 3.716v0.825c-3.392 0.277-6 1.944-6 3.959h6.208c-0.135-0.477-0.208-0.98-0.208-1.5z"></path>
|
||||
<path d="M11.5 7c-2.485 0-4.5 2.015-4.5 4.5s2.015 4.5 4.5 4.5c2.485 0 4.5-2.015 4.5-4.5s-2.015-4.5-4.5-4.5zM14 12h-5v-1h5v1z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 505 B |
5
assets/img/icons/user-plus.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M6 11.5c0-2.363 1.498-4.383 3.594-5.159 0.254-0.571 0.406-1.206 0.406-1.841 0-2.485 0-4.5-3-4.5s-3 2.015-3 4.5c0 1.548 0.898 3.095 2 3.716v0.825c-3.392 0.277-6 1.944-6 3.959h6.208c-0.135-0.477-0.208-0.98-0.208-1.5z"></path>
|
||||
<path d="M11.5 7c-2.485 0-4.5 2.015-4.5 4.5s2.015 4.5 4.5 4.5c2.485 0 4.5-2.015 4.5-4.5s-2.015-4.5-4.5-4.5zM14 12h-2v2h-1v-2h-2v-1h2v-2h1v2h2v1z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 525 B |
4
assets/img/icons/whatsapp.svg
Executable file
@@ -0,0 +1,4 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M13.641 2.325c-1.497-1.5-3.488-2.325-5.609-2.325-4.369 0-7.925 3.556-7.925 7.928 0 1.397 0.366 2.763 1.059 3.963l-1.125 4.109 4.203-1.103c1.159 0.631 2.463 0.966 3.787 0.966h0.003c0 0 0 0 0 0 4.369 0 7.928-3.556 7.928-7.928 0-2.119-0.825-4.109-2.322-5.609zM8.034 14.525v0c-1.184 0-2.344-0.319-3.356-0.919l-0.241-0.144-2.494 0.653 0.666-2.431-0.156-0.25c-0.663-1.047-1.009-2.259-1.009-3.506 0-3.634 2.956-6.591 6.594-6.591 1.759 0 3.416 0.688 4.659 1.931 1.244 1.247 1.928 2.9 1.928 4.662-0.003 3.637-2.959 6.594-6.591 6.594zM11.647 9.588c-0.197-0.1-1.172-0.578-1.353-0.644s-0.313-0.1-0.447 0.1c-0.131 0.197-0.512 0.644-0.628 0.778-0.116 0.131-0.231 0.15-0.428 0.050s-0.838-0.309-1.594-0.984c-0.588-0.525-0.987-1.175-1.103-1.372s-0.013-0.306 0.088-0.403c0.091-0.088 0.197-0.231 0.297-0.347s0.131-0.197 0.197-0.331c0.066-0.131 0.034-0.247-0.016-0.347s-0.447-1.075-0.609-1.472c-0.159-0.388-0.325-0.334-0.447-0.341-0.116-0.006-0.247-0.006-0.378-0.006s-0.347 0.050-0.528 0.247c-0.181 0.197-0.694 0.678-0.694 1.653s0.709 1.916 0.809 2.050c0.1 0.131 1.397 2.134 3.384 2.991 0.472 0.203 0.841 0.325 1.128 0.419 0.475 0.15 0.906 0.128 1.247 0.078 0.381-0.056 1.172-0.478 1.338-0.941s0.166-0.859 0.116-0.941c-0.047-0.088-0.178-0.137-0.378-0.238z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
14
assets/img/icons/x.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="300.25"
|
||||
height="300.25"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<path
|
||||
d="M 178.695,127.15 290.395,0 h -26.46 L 166.905,110.38 89.465,0 H 0.125 L 117.255,166.93 0.125,300.25 h 26.46 l 102.4,-116.59 81.8,116.59 h 89.34 M 36.135,19.54 h 40.65 l 187.13,262.13 h -40.66"
|
||||
id="path1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 470 B |
4
assets/markdown.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
- wrap: ['[Scene details](', ')']
|
||||
items:
|
||||
- link
|
||||
- text: 'on [traxxx](https://traxxx.me/).'
|
||||
45
assets/mockup-release.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
const now = new Date();
|
||||
|
||||
export default {
|
||||
id: 0,
|
||||
shootId: 12345,
|
||||
title: 'Nut For Human Consumption',
|
||||
slug: 'nut-for-human-consumption',
|
||||
link: 'https://traxxx.me/scene/0/nut-for-human-consumption',
|
||||
url: 'https://example.com/video/12345/nut-for-human-consumption',
|
||||
date: now,
|
||||
effectiveDate: now,
|
||||
createdAt: new Date(now.getFullYear(), 0, 1),
|
||||
actors: [
|
||||
{
|
||||
name: 'Chanel Chakra',
|
||||
gender: 'female',
|
||||
ageThen: 26,
|
||||
ageFromBirth: 31,
|
||||
dateOfBirth: new Date(1999, 2, 2),
|
||||
},
|
||||
{
|
||||
name: 'Mo The Fucker',
|
||||
gender: 'male',
|
||||
ageThen: 32,
|
||||
ageFromBirth: 37,
|
||||
dateOfBirth: new Date(1988, 5, 12),
|
||||
},
|
||||
],
|
||||
tags: [
|
||||
{ name: 'anal' },
|
||||
{ name: 'facefucking' },
|
||||
{ name: 'deepthroat' },
|
||||
{ name: 'blowjob' },
|
||||
{ name: 'facial' },
|
||||
],
|
||||
movies: [{
|
||||
title: `Best Of Traxxx ${String(now.getFullYear()).slice(2)}`,
|
||||
}],
|
||||
channel: {
|
||||
name: 'Traxxxed',
|
||||
},
|
||||
network: {
|
||||
name: 'Traxxx',
|
||||
},
|
||||
};
|
||||
125
assets/sfw.ejs
Normal file
@@ -0,0 +1,125 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/favicon/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon/favicon-16x16.png">
|
||||
<link rel="manifest" href="/img/favicon/site.webmanifest">
|
||||
<link rel="mask-icon" href="/img/favicon/safari-pinned-tab.svg" color="#5bbad5">
|
||||
<link rel="shortcut icon" href="/img/favicon/favicon.ico">
|
||||
|
||||
<meta name="msapplication-TileColor" content="#b91d47">
|
||||
<meta name="msapplication-config" content="/img/favicon/browserconfig.xml">
|
||||
<meta name="theme-color" content="#f65596">
|
||||
|
||||
<meta property="og:title" content="traxxx" />
|
||||
<meta property="og:image" content="https://traxxx.me/img/og_logo.png" />
|
||||
|
||||
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0,interactive-widget=resizes-content" />
|
||||
|
||||
<title>traxxx - None shall pass</title>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-dark-10: #e54485;
|
||||
--primary: #f65596;
|
||||
--primary-light-10: #f075a6;
|
||||
--primary-light-20: #f2a6c4;
|
||||
--primary-light-30: #f7c9dc;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.explainer {
|
||||
margin-bottom: 3rem;
|
||||
font-size: 1.25rem;
|
||||
text-align: justify;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.useful {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.links {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 1rem 0 0 0;
|
||||
}
|
||||
|
||||
.links li {
|
||||
padding: .25rem 0;
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.links a {
|
||||
padding: .5rem 1rem;
|
||||
border-radius: .5rem;
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.links a:hover {
|
||||
background: var(--primary-dark-10);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="content">
|
||||
<h2 class="heading">Not so fast, rascal.</h2>
|
||||
|
||||
<p class="explainer">The content offered by traxxx is restricted in your jurisdiction.</p>
|
||||
|
||||
<% if (!noVpn) { %>
|
||||
<div class="useful">
|
||||
Useful links:
|
||||
<ul class="links">
|
||||
<li>
|
||||
<a
|
||||
href="https://mullvad.net/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="link"
|
||||
>Mullvad VPN</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
href="https://protonvpn.com/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="link"
|
||||
>Proton VPN</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,8 +1,15 @@
|
||||
- ' - ':
|
||||
- delimit: ' - '
|
||||
items:
|
||||
- channel
|
||||
- - movie
|
||||
- scene|Scene $
|
||||
- items:
|
||||
- movie
|
||||
- scene
|
||||
- title
|
||||
- ', |(|)':
|
||||
- actors
|
||||
- date|yyyy-MM-dd
|
||||
- delimit: ', '
|
||||
wrap: ['(', ')']
|
||||
items:
|
||||
- key: actors
|
||||
genders: fmtou
|
||||
- key: date
|
||||
format: yyyy-MM-dd
|
||||
fallbackToAdded: false
|
||||
|
||||
1
common
Submodule
@@ -8,7 +8,7 @@
|
||||
type="search"
|
||||
placeholder="Search actors"
|
||||
class="input search"
|
||||
@keydown.enter="search"
|
||||
@search="search"
|
||||
>
|
||||
|
||||
<Icon
|
||||
@@ -265,6 +265,7 @@ function updateFilter(prop, value, reload = true) {
|
||||
.page {
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
align-items: stretch;
|
||||
background: var(--background-base-10);
|
||||
}
|
||||
@@ -280,7 +281,7 @@ function updateFilter(prop, value, reload = true) {
|
||||
.actors-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: .5rem 0 .25rem 2.25rem;
|
||||
padding: .5rem 0 .5rem 3rem;
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,15 @@
|
||||
class="avatar-container"
|
||||
>
|
||||
<img
|
||||
:src="getMediaPath(actor.avatar, 'thumbnail')"
|
||||
:src="getPath(actor.avatar, 'thumbnail')"
|
||||
:title="actor.avatar.credit && `© ${actor.avatar.credit}`"
|
||||
class="avatar"
|
||||
>
|
||||
|
||||
<span
|
||||
v-if="actor.avatar?.credit"
|
||||
class="avatar-credit"
|
||||
>{{ actor.avatar.credit }}</span>
|
||||
</div>
|
||||
|
||||
<ul class="bio nolist">
|
||||
@@ -22,11 +27,11 @@
|
||||
<dfn class="bio-label"><Icon icon="cake" />Date of birth</dfn>
|
||||
|
||||
<span class="birthdate">
|
||||
<span class="birthdate-long">{{ formatDate(actor.dateOfBirth, 'MMMM d, yyyy') }}</span>
|
||||
<span class="birthdate-short">{{ formatDate(actor.dateOfBirth, 'MMM d, yyyy') }}</span>
|
||||
<span class="birthdate-long">{{ formatDate(actor.dateOfBirth, actor.dateOfBirth.getFullYear() > 1 ? 'MMMM d, yyyy' : 'MMMM d') }}</span>
|
||||
<span class="birthdate-short">{{ formatDate(actor.dateOfBirth, actor.dateOfBirth.getFullYear() > 1 ? 'MMM d, yyyy' : 'MMM d') }}</span>
|
||||
|
||||
<span
|
||||
v-if="!actor.dateOfDeath"
|
||||
v-if="!actor.dateOfDeath && actor.dateOfBirth.getFullYear() > 1"
|
||||
class="age"
|
||||
>{{ actor.ageFromBirth }}</span>
|
||||
</span>
|
||||
@@ -97,7 +102,8 @@
|
||||
|
||||
<li
|
||||
v-if="actor.residence"
|
||||
class="bio-item residence hideable"
|
||||
class="bio-item residence"
|
||||
:class="{ hideable: !!actor.origin }"
|
||||
>
|
||||
<dfn class="bio-label"><Icon icon="location" />Lives in</dfn>
|
||||
|
||||
@@ -137,12 +143,59 @@
|
||||
>
|
||||
<dfn class="bio-label"><Icon icon="ruler" />Figure</dfn>
|
||||
<span class="bio-value">
|
||||
{{ actor.bust || '??' }}{{ actor.cup || '?' }}-{{ actor.waist || '??' }}-{{ actor.hip || '??' }}
|
||||
<Icon
|
||||
v-if="actor.naturalBoobs === false"
|
||||
:title="'Enhanced boobs'"
|
||||
v-if="actor.naturalBoobs === false || actor.naturalButt === false"
|
||||
v-tooltip="[actor.naturalBoobs === false ? 'Enhanced boobs' : null, actor.naturalButt === false ? 'Enhanced butt' : null].filter(Boolean).join(', ')"
|
||||
icon="magic-wand2"
|
||||
class="enhanced"
|
||||
/>{{ actor.bust || '??' }}{{ actor.cup || '?' }}-{{ actor.waist || '??' }}-{{ actor.hip || '??' }}
|
||||
/>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
<li
|
||||
v-if="actor.naturalLips === false || actor.naturalLabia === false
|
||||
|| (actor.naturalBoobs === false && !actor.bust) || actor.boobsVolume || actor.boobsPlacement || actor.boobsIncision || actor.boobsImplant
|
||||
|| actor.buttVolume || actor.buttImplant"
|
||||
class="bio-item augmentations hideable"
|
||||
>
|
||||
<dfn class="bio-label"><Icon icon="magic-wand2" />Enhancements</dfn>
|
||||
|
||||
<span class="bio-value">
|
||||
<div
|
||||
v-if="actor.naturalBoobs === false"
|
||||
:title="[
|
||||
actor.boobsVolume && `${actor.boobsVolume}cc`,
|
||||
augmentationMap[actor.boobsPlacement] || actor.boobsPlacement,
|
||||
augmentationMap[actor.boobsIncision] || actor.boobsIncision,
|
||||
augmentationMap[actor.boobsImplant] || actor.boobsImplant
|
||||
].filter(Boolean).join(' ')"
|
||||
class="augmentations-section"
|
||||
>Boobs<template v-if="actor.boobsVolume || actor.boobsImplant">: </template>
|
||||
<template v-if="actor.boobsVolume">{{ actor.boobsVolume }}cc</template>
|
||||
<template v-if="actor.boobsImplant"> {{ augmentationMap[actor.boobsImplant] || actor.boobsImplant }}</template>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="actor.naturalButt === false"
|
||||
class="augmentations-section"
|
||||
>Butt<template v-if="actor.buttVolume || actor.buttImplant">: </template>
|
||||
<template v-if="actor.buttVolume">{{ actor.buttVolume }}cc</template>
|
||||
<template v-if="actor.buttImplant"> {{ augmentationMap[actor.buttImplant] || actor.buttImplant }}</template>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="actor.naturalLips === false"
|
||||
class="augmentations-section"
|
||||
>Lip filler<template v-if="actor.lipsVolume || actor.lipsImplant">: </template>
|
||||
<template v-if="actor.lipsVolume">{{ actor.lipsVolume }}cc</template>
|
||||
<template v-if="actor.lipsImplant"> {{ augmentationMap[actor.lipsImplant] || actor.lipsImplant }}</template>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="actor.naturalLabia === false"
|
||||
class="augmentations-section"
|
||||
>Labiaplasty</div>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
@@ -154,20 +207,20 @@
|
||||
|
||||
<span>
|
||||
<Icon
|
||||
v-if="actor.circumcised"
|
||||
v-if="actor.isCircumcised"
|
||||
:title="'Circumcised'"
|
||||
icon="page-break"
|
||||
icon="pagebreak"
|
||||
class="circumcised"
|
||||
/>
|
||||
|
||||
<template v-if="actor.penisLengthMetric && actor.penisGirthMetric">
|
||||
<span>{{ actor.penisLengthMetric }} * {{ actor.penisGirthMetric }} cm</span>
|
||||
<span class="bio-segment">{{ actor.penisLengthImperial }}" * {{ actor.penisGirthImperial }}"</span>
|
||||
<template v-if="actor.penisLength && actor.penisGirth">
|
||||
<span>{{ actor.penisLength.imperial }}" × {{ actor.penisLength.imperial }}"</span>
|
||||
<span class="bio-segment">{{ actor.penisLength.metric }} × {{ actor.penisGirth.metric }} cm</span>
|
||||
</template>
|
||||
|
||||
<template v-else-if="actor.penisLengthMetric">
|
||||
<span>{{ actor.penisLengthMetric }} cm</span>
|
||||
<span class="bio-segment">{{ actor.penisLengthImperial }}"</span>
|
||||
<template v-else-if="actor.penisLength">
|
||||
<span>{{ actor.penisLength.imperial }}"</span>
|
||||
<span class="bio-segment">{{ actor.penisLength.metric }} cm</span>
|
||||
</template>
|
||||
</span>
|
||||
</li>
|
||||
@@ -239,7 +292,79 @@
|
||||
<span v-else>Yes</span>
|
||||
</li>
|
||||
|
||||
<li class="bio-item updated hideable">Updated {{ formatDate(actor.updatedAt, 'yyyy-MM-dd hh:mm') }}, ID: {{ actor.id }}</li>
|
||||
<li
|
||||
v-if="actor.agency"
|
||||
class="bio-item hideable"
|
||||
>
|
||||
<dfn class="bio-label"><Icon icon="user-tie" />Agency</dfn>
|
||||
|
||||
<span
|
||||
:title="actor.agency"
|
||||
class="bio-value"
|
||||
>{{ actor.agency }}</span>
|
||||
</li>
|
||||
|
||||
<div
|
||||
v-if="socials.length > 0"
|
||||
class="bio-item bio-socials hideable"
|
||||
>
|
||||
<ul class="socials">
|
||||
<a
|
||||
v-for="social in socials"
|
||||
:key="`social-${social.id}`"
|
||||
:href="getSocialUrl(social)"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
:title="social.platform || social.url"
|
||||
class="social ellipsis"
|
||||
>
|
||||
<Icon
|
||||
v-if="social.platform && env.socials.urls[social.platform]"
|
||||
:icon="iconMap[social.platform] || social.platform"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform}`"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="social.platform"
|
||||
icon="bubbles10"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform} icon-generic`"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="social.url"
|
||||
icon="sphere"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform} icon-generic`"
|
||||
/>
|
||||
|
||||
<template v-if="social.platform">{{ env.socials.prefix[social.platform] || env.socials.prefix.default }}</template>{{ social.handle }}
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<li class="bio-item updated">
|
||||
<span
|
||||
class="ellipsis"
|
||||
:title="formatDate(actor.updatedAt, 'yyyy-MM-dd hh:mm')"
|
||||
>{{ formatDate(actor.updatedAt, 'yyyy-MM-dd') }}</span>
|
||||
|
||||
<div class="actor-actions">
|
||||
<a
|
||||
v-if="user && user.role !== 'user'"
|
||||
:href="`/actor/edit/${actor.id}/${actor.slug}`"
|
||||
target="_blank"
|
||||
class="link"
|
||||
>Edit bio</a>
|
||||
|
||||
<a
|
||||
:href="`/actor/revs/${actor.id}/${actor.slug}`"
|
||||
target="_blank"
|
||||
class="link"
|
||||
>Revisions</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="descriptions-container">
|
||||
@@ -258,12 +383,14 @@
|
||||
v-if="description.entity.type === 'network' || !description.entity.parent || description.entity.isIndependent"
|
||||
:src="`/logos/${description.entity.slug}/thumbs/network.png`"
|
||||
class="description-logo"
|
||||
loading="lazy"
|
||||
>
|
||||
|
||||
<img
|
||||
v-else
|
||||
:src="`/logos/${description.entity.parent.slug}/thumbs/${description.entity.slug}.png`"
|
||||
class="description-logo"
|
||||
loading="lazy"
|
||||
>
|
||||
</a>
|
||||
</p>
|
||||
@@ -294,13 +421,17 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { ref, inject } from 'vue';
|
||||
import formatTemplate from 'template-format';
|
||||
|
||||
import { getMediaPath } from '#/utils/media-path.js';
|
||||
import getPath from '#/src/get-path.js';
|
||||
import { formatDate } from '#/utils/format.js';
|
||||
|
||||
const expanded = ref(false);
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const { user, env } = pageContext;
|
||||
|
||||
const props = defineProps({
|
||||
actor: {
|
||||
type: Object,
|
||||
@@ -308,12 +439,17 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const iconMap = {
|
||||
twitter: 'twitter-x',
|
||||
};
|
||||
|
||||
// if the profile is empty, the expand button overlaps the header
|
||||
const showExpand = [
|
||||
'age',
|
||||
'bust',
|
||||
'cup',
|
||||
'eyes',
|
||||
'ethnicity',
|
||||
'hairColor',
|
||||
'hasPiercings',
|
||||
'hasTattoos',
|
||||
@@ -326,12 +462,48 @@ const showExpand = [
|
||||
'weight',
|
||||
].some((attribute) => !!props.actor[attribute]);
|
||||
|
||||
const augmentationMap = {
|
||||
bbl: 'BBL',
|
||||
fat: 'fat transfer',
|
||||
lift: 'direct lift',
|
||||
lipo: 'lipo without BBL',
|
||||
filler: 'filler',
|
||||
mms: 'MMS',
|
||||
over: 'over-muscle',
|
||||
under: 'under-muscle',
|
||||
mammary: 'under breast',
|
||||
areolar: 'areolar',
|
||||
crescent: 'crescent areolar',
|
||||
lollipop: 'lollipop',
|
||||
axillary: 'armpit',
|
||||
umbilical: 'navel',
|
||||
};
|
||||
|
||||
const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
.filter((profile) => !!profile.description)
|
||||
.map((profile) => [profile.descriptionHash, {
|
||||
text: profile.description,
|
||||
entity: profile.entity,
|
||||
}])));
|
||||
|
||||
function getSocialUrl(social) {
|
||||
if (social.url) {
|
||||
return social.url;
|
||||
}
|
||||
|
||||
if (pageContext.env.socials.urls[social.platform]) {
|
||||
return formatTemplate(pageContext.env.socials.urls[social.platform], { handle: social.handle });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const socials = props.actor.socials.map((social) => ({
|
||||
...social,
|
||||
handle: social.url
|
||||
? new URL(social.url).hostname
|
||||
: social.handle,
|
||||
}));
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -344,7 +516,7 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
|
||||
.icon {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -365,17 +537,32 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
padding: 0 0 1rem 1rem;
|
||||
position: relative;
|
||||
margin: 0 .5rem 1rem 1rem;
|
||||
flex-shrink: 0;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
border: solid 3px var(--highlight-hint);
|
||||
margin: 0 .5rem 0 0;
|
||||
border: solid 3px var(--highlight-weak-30);
|
||||
border-radius: .5rem;
|
||||
}
|
||||
|
||||
.avatar-credit {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
padding: 0 .5rem;
|
||||
color: var(--text-light);
|
||||
font-size: .75rem;
|
||||
text-shadow: 1px 1px 0 var(--shadow-strong-20);
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
padding-bottom: 1.5rem;
|
||||
margin-bottom: .75rem;
|
||||
@@ -402,7 +589,6 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
}
|
||||
|
||||
.bio-item {
|
||||
width: calc(50% - 4rem);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
@@ -417,6 +603,10 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
&:not(:last-of-type) {
|
||||
border-bottom: solid 1px var(--highlight-weak-40);
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: auto; /* prevents jumping */
|
||||
}
|
||||
}
|
||||
|
||||
.bio-label,
|
||||
@@ -439,7 +629,9 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
}
|
||||
|
||||
.bio-value {
|
||||
display: inline-block;
|
||||
margin: 0 0 0 2rem;
|
||||
max-width: 20rem;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
@@ -452,6 +644,7 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
.flag {
|
||||
height: 1rem;
|
||||
margin: .25rem .5rem 0 0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.bio-name {
|
||||
@@ -494,7 +687,7 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
.penis-length-imperial,
|
||||
.bio-segment {
|
||||
padding: 0 0 0 .5rem;
|
||||
border-left: solid 1px var(--highlight-weak);
|
||||
border-left: solid 1px var(--highlight-weak-20);
|
||||
margin: 0 0 0 .5rem;
|
||||
}
|
||||
|
||||
@@ -502,6 +695,8 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
.circumcised.icon {
|
||||
fill: var(--primary);
|
||||
padding: 0 .5rem;
|
||||
margin-right: .25rem;
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
.enhanced.icon {
|
||||
@@ -519,9 +714,76 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
content: ',\00a0';
|
||||
}
|
||||
|
||||
.augmentations .bio-value {
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.updated {
|
||||
color: var(--highlight-weak-20);
|
||||
color: var(--highlight-weak-10);
|
||||
font-size: .8rem;
|
||||
text-align: left;
|
||||
|
||||
.ellipsis {
|
||||
width: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.bio-socials {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.socials {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||
grid-gap: 0 0;
|
||||
overflow: hidden;
|
||||
gap: .25rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.social {
|
||||
display: flex;
|
||||
height: 2rem;
|
||||
align-items: center;
|
||||
padding: .1rem .5rem;
|
||||
border-radius: .25rem;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-size: .9rem;
|
||||
font-weight: normal;
|
||||
background: var(--highlight-weak-40);
|
||||
|
||||
.icon {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
|
||||
.icon-generic {
|
||||
fill: var(--highlight);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--primary);
|
||||
cursor: pointer;
|
||||
|
||||
.icon {
|
||||
fill: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actor-actions {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: flex-start;
|
||||
gap: 1rem;
|
||||
margin-right: .5rem;
|
||||
|
||||
.link {
|
||||
color: inherit;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.descriptions-container {
|
||||
@@ -592,8 +854,8 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
display: none;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: -.75rem;
|
||||
z-index: 10;
|
||||
bottom: -.25rem;
|
||||
}
|
||||
|
||||
.expand {
|
||||
@@ -642,6 +904,10 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
.descriptions-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bio {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media(--compact) {
|
||||
@@ -661,7 +927,7 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
}
|
||||
}
|
||||
|
||||
@media(--small-15) {
|
||||
@media(--small) {
|
||||
.profile {
|
||||
height: auto;
|
||||
max-height: none;
|
||||
@@ -674,6 +940,11 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
|
||||
&:not(.expanded) .hideable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* only hide update/actions line if other bio lines and thus the expand button are present */
|
||||
&:not(.expanded) .bio-item + .updated {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,6 +960,10 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bio-value {
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
.expanded .bio-value {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
101
components/actors/search.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<VDropdown
|
||||
:disabled="disabled"
|
||||
class="trigger"
|
||||
@show="focus"
|
||||
>
|
||||
<slot />
|
||||
|
||||
<template #popper>
|
||||
<div>
|
||||
<input
|
||||
ref="queryInput"
|
||||
v-model="query"
|
||||
placeholder="Search actor"
|
||||
class="input"
|
||||
@input="search"
|
||||
>
|
||||
|
||||
<ul class="actors nolist">
|
||||
<li
|
||||
v-for="actor in actors"
|
||||
:key="`actor-${actor.slug}`"
|
||||
v-close-popper
|
||||
class="actor"
|
||||
@click="emit('actor', actor); query = '';"
|
||||
>{{ actor.name }} ({{ [actor.ageFromBirth, actor.origin?.country?.alpha2].filter(Boolean).join(', ') }})
|
||||
<img
|
||||
v-if="actor.avatar"
|
||||
:src="getPath(actor.avatar, 'thumbnail')"
|
||||
class="avatar"
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
</VDropdown>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { get } from '#/src/api.js';
|
||||
import getPath from '#/src/get-path.js';
|
||||
|
||||
const actors = ref([]);
|
||||
const query = ref(null);
|
||||
const queryInput = ref(null);
|
||||
|
||||
defineProps({
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['actor']);
|
||||
|
||||
async function search() {
|
||||
const data = await get('/actors', { q: query.value });
|
||||
|
||||
actors.value = data.actors;
|
||||
}
|
||||
|
||||
function focus() {
|
||||
setTimeout(() => {
|
||||
queryInput.value?.focus();
|
||||
}, 100);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.trigger {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.actor {
|
||||
display: block;
|
||||
padding: .25rem .5rem;
|
||||
|
||||
&:hover {
|
||||
background: var(--glass-weak-50);
|
||||
color: var(--primary);
|
||||
cursor: pointer;
|
||||
|
||||
.avatar {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
position: fixed;
|
||||
display: none;
|
||||
left: 7rem;
|
||||
width: 8rem;
|
||||
border-radius: .25rem;
|
||||
box-shadow: 0 0 3px var(--shadow-weak-10);
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
@@ -11,7 +11,7 @@
|
||||
class="avatar-link no-link"
|
||||
>
|
||||
<img
|
||||
v-if="actor.avatar"
|
||||
v-if="actor.avatar && !restriction"
|
||||
:src="getPath(actor.avatar, 'thumbnail')"
|
||||
:style="{ 'background-image': `url(${getPath(actor.avatar, 'lazy')})` }"
|
||||
loading="lazy"
|
||||
@@ -40,13 +40,20 @@
|
||||
<Gender :gender="actor.gender" />
|
||||
|
||||
<span
|
||||
v-if="actor.ageFromBirth"
|
||||
v-if="actor.ageAtDeath"
|
||||
:title="`Passed ${formatDate(actor.ageAtDeath, 'MMMM d, yyyy')}`"
|
||||
class="age age-death"
|
||||
>{{ actor.ageAtDeath }}</span>
|
||||
|
||||
<span
|
||||
v-else-if="actor.ageFromBirth"
|
||||
:title="`Born ${formatDate(actor.dateOfBirth, 'MMMM d, yyyy')}`"
|
||||
class="age"
|
||||
>{{ actor.ageFromBirth }}</span>
|
||||
|
||||
<!-- don't show 'age then' for scenes released after the performer's death, because it might show an age they sadly never reached -->
|
||||
<span
|
||||
v-if="actor.ageThen && actor.ageThen < actor.ageFromBirth"
|
||||
v-if="actor.ageThen && actor.ageThen < actor.ageFromBirth && (!actor.ageAtDeath || actor.ageThen < actor.ageAtDeath)"
|
||||
title="Age on date of release"
|
||||
class="age age-then"
|
||||
>{{ actor.ageThen }}</span>
|
||||
@@ -66,7 +73,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="name">{{ actor.name }}</span>
|
||||
<span class="label">
|
||||
<span class="name ellipsis">{{ actor.name }}</span>
|
||||
|
||||
<img
|
||||
v-if="actor.entity"
|
||||
v-tooltip="actor.entity.name"
|
||||
:src="`/logos/${actor.entity.slug}/favicon_dark.png`"
|
||||
class="favicon"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -87,11 +103,11 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const { user } = pageContext;
|
||||
const { user, restriction } = pageContext;
|
||||
const pageStash = pageContext.pageProps.stash;
|
||||
const currentStash = pageStash || user?.primaryStash;
|
||||
const currentStash = pageStash || pageContext.assets?.primaryStash;
|
||||
|
||||
const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id === currentStash.id));
|
||||
const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id === currentStash?.id));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -119,9 +135,11 @@ const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id ===
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
.label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
padding: .35rem .5rem;
|
||||
font-weight: bold;
|
||||
font-size: .9rem;
|
||||
white-space: nowrap;
|
||||
@@ -130,6 +148,15 @@ const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id ===
|
||||
user-select: all;
|
||||
}
|
||||
|
||||
.name {
|
||||
padding: .35rem .25rem .35rem .5rem;
|
||||
}
|
||||
|
||||
.favicon {
|
||||
height: 1rem;
|
||||
padding: .35rem .5rem .35rem .25rem;
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
@@ -189,7 +216,16 @@ const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id ===
|
||||
}
|
||||
|
||||
.age {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-right: .25rem;
|
||||
|
||||
.icon {
|
||||
width: .8rem;
|
||||
height: .8rem;
|
||||
fill: var(--highlight-weak-10);
|
||||
margin-left: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.age-then {
|
||||
@@ -197,6 +233,10 @@ const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id ===
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.age-death {
|
||||
color: var(--grey-light-20);
|
||||
}
|
||||
|
||||
.country {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
94
components/admin/admin.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<nav class="nav">
|
||||
<ul class="nav-items nolist">
|
||||
<li class="nav-item">
|
||||
<a
|
||||
href="/admin/revisions/scenes"
|
||||
class="nav-link nolink"
|
||||
:class="{ active: pageContext.routeParams.section === 'revisions' && pageContext.routeParams.domain === 'scenes' }"
|
||||
>Scene Revisions</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a
|
||||
href="/admin/revisions/actors"
|
||||
class="nav-link nolink"
|
||||
:class="{ active: pageContext.routeParams.section === 'revisions' && pageContext.routeParams.domain === 'actors' }"
|
||||
>Actor Revisions</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a
|
||||
href="/admin/entities"
|
||||
class="nav-link nolink"
|
||||
:class="{ active: pageContext.routeParams.section === 'entities' }"
|
||||
>Entity Health</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="content">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { inject } from 'vue';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
background: var(--background-base-10);
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
padding: 1rem 1rem .75rem 1rem;
|
||||
border-bottom: solid 1px var(--shadow-weak-30);
|
||||
margin-bottom: .25rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.nav-items {
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: var(--background-dark-20);
|
||||
border-radius: 1rem;
|
||||
color: var(--glass-strong-20);
|
||||
font-size: .9rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
display: block;
|
||||
padding: .5rem 1rem;
|
||||
font-weight: bold;
|
||||
|
||||
&.active {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding: 1rem;
|
||||
}
|
||||
</style>
|
||||
540
components/alerts/alerts.vue
Normal file
@@ -0,0 +1,540 @@
|
||||
<template>
|
||||
<section class="profile-section">
|
||||
<div class="section-header">
|
||||
<h3 class="heading">Alerts</h3>
|
||||
|
||||
<button
|
||||
class="button"
|
||||
@click="showAlertDialog = true"
|
||||
>
|
||||
<Icon icon="alarm-add" />
|
||||
<span class="button-label">New alert</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="filters">
|
||||
<input
|
||||
v-model="query"
|
||||
type="search"
|
||||
class="input filters-search"
|
||||
placeholder="Search alerts"
|
||||
>
|
||||
|
||||
<div class="filters-section">
|
||||
<Icon
|
||||
icon="star"
|
||||
title="Only show actor alerts"
|
||||
class="noselect"
|
||||
:class="{ active: filterActors }"
|
||||
@click="filterActors = !filterActors"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
icon="price-tags"
|
||||
title="Only show tag alerts"
|
||||
class="noselect"
|
||||
:class="{ active: filterTags }"
|
||||
@click="filterTags = !filterTags"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
icon="device_hub"
|
||||
title="Only show channel alerts"
|
||||
class="noselect"
|
||||
:class="{ active: filterEntities }"
|
||||
@click="filterEntities = !filterEntities"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
icon="regexp"
|
||||
title="Only show expression alerts"
|
||||
class="noselect"
|
||||
:class="{ active: filterExpressions }"
|
||||
@click="filterExpressions = !filterExpressions"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-if="filterCombined === false"
|
||||
icon="target3"
|
||||
title="Only show uncombined alerts"
|
||||
class="noselect active filters-uncombined"
|
||||
@click="toggleFilterCombined"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else
|
||||
icon="make-group"
|
||||
title="Only show combined alerts"
|
||||
class="noselect filters-uncombined"
|
||||
:class="{ active: filterCombined }"
|
||||
@click="toggleFilterCombined"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="alerts nolist">
|
||||
<li
|
||||
v-for="alert in filteredAlerts"
|
||||
:key="`alert-${alert.id}`"
|
||||
class="alert"
|
||||
>
|
||||
<div
|
||||
class="alert-details"
|
||||
:class="{ and: alert.and.fields, or: !alert.and.fields }"
|
||||
>
|
||||
<span
|
||||
v-if="alert.tags.length > 0"
|
||||
class="alert-detail alert-tags"
|
||||
:class="{ and: alert.and.tags, or: !alert.and.tags }"
|
||||
>
|
||||
<span class="alert-values">
|
||||
<span
|
||||
v-for="tag in alert.tags"
|
||||
:key="`tag-${alert.id}-${tag.id}`"
|
||||
class="alert-key"
|
||||
>
|
||||
<a
|
||||
:href="`/tag/${tag.slug}`"
|
||||
class="alert-value link"
|
||||
>{{ tag.name }}</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="alert.actors.length > 0"
|
||||
class="alert-detail alert-actors"
|
||||
:class="{ and: alert.and.actors, or: !alert.and.actors }"
|
||||
>
|
||||
<span class="alert-values">with
|
||||
<span
|
||||
v-for="actor in alert.actors"
|
||||
:key="`actor-${alert.id}-${actor.id}`"
|
||||
class="alert-key"
|
||||
>
|
||||
<a
|
||||
:href="`/actor/${actor.id}/${actor.slug}`"
|
||||
class="alert-value link"
|
||||
>{{ actor.name }}</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="alert.entities.length > 0"
|
||||
class="alert-detail alert-entities or"
|
||||
>
|
||||
<span class="alert-values">for
|
||||
<span
|
||||
v-for="entity in alert.entities"
|
||||
:key="`entity-${alert.id}-${entity.id}`"
|
||||
class="alert-key"
|
||||
>
|
||||
<a
|
||||
:href="`/${entity.type}/${entity.slug}`"
|
||||
class="alert-value link"
|
||||
>
|
||||
<Icon
|
||||
v-if="entity.type === 'network'"
|
||||
icon="device_hub"
|
||||
/>{{ entity.name }}
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="alert.matches.length > 0"
|
||||
class="alert-detail alert-matches"
|
||||
:class="{ and: alert.and.matches, or: !alert.and.matches }"
|
||||
>
|
||||
<span class="alert-values">matching
|
||||
<span
|
||||
v-for="match in alert.matches"
|
||||
:key="`match-${alert.id}-${match.id}`"
|
||||
class="alert-key"
|
||||
>
|
||||
<span class="alert-value">{{ match.property }}:
|
||||
<span
|
||||
class="alert-regex"
|
||||
title="If your original expression was not a /regular expression/, it was converted, and new characters may have been added for syntactical purposes. These characters do not alter the function of the expression; they ensure it."
|
||||
>{{ match.expression }}</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="alert-meta">
|
||||
<div class="alert-triggers">
|
||||
<Icon
|
||||
v-if="alert.notify && alert.isFromPreset"
|
||||
v-tooltip="'Notify in traxxx, added as quick alert'"
|
||||
icon="bell-plus"
|
||||
class="trigger"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="alert.notify"
|
||||
v-tooltip="'Notify in traxxx'"
|
||||
icon="bell2"
|
||||
class="trigger"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-if="alert.stashes.some((stash) => !stash.isPrimary)"
|
||||
v-tooltip="`Add to ${alert.stashes.map((stash) => stash.name).join(', ')}`"
|
||||
icon="folder-heart"
|
||||
class="trigger"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="alert.stashes.length > 0"
|
||||
v-tooltip="alert.stashes.length > 0 ? 'Add to Favorites' : undefined"
|
||||
icon="heart7"
|
||||
class="trigger"
|
||||
/>
|
||||
|
||||
<!--
|
||||
<Icon
|
||||
icon="envelop5"
|
||||
title="E-mail me"
|
||||
:class="{ trigger: alert.email }"
|
||||
/>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div class="alert-actions">
|
||||
<span
|
||||
v-tooltip="format(alert.createdAt, 'yyyy-MM-dd hh:mm')"
|
||||
class="alert-id"
|
||||
title="Alert ID"
|
||||
>#{{ alert.id }}</span>
|
||||
|
||||
<Icon
|
||||
icon="bin"
|
||||
@click="removeAlert(alert)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<AlertDialog
|
||||
v-if="showAlertDialog"
|
||||
@close="showAlertDialog = false; reloadAlerts();"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, inject } from 'vue';
|
||||
import { format } from 'date-fns';
|
||||
|
||||
import AlertDialog from '#/components/alerts/create.vue';
|
||||
|
||||
import { get, del } from '#/src/api.js';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
|
||||
const alerts = ref(pageContext.pageProps.alerts);
|
||||
const showAlertDialog = ref(false);
|
||||
const done = ref(true);
|
||||
|
||||
const query = ref('');
|
||||
const filterActors = ref(false);
|
||||
const filterEntities = ref(false);
|
||||
const filterTags = ref(false);
|
||||
const filterExpressions = ref(false);
|
||||
const filterCombined = ref(null);
|
||||
|
||||
const filteredAlerts = computed(() => {
|
||||
const queryRegex = new RegExp(query.value, 'i');
|
||||
|
||||
return alerts.value.filter((alert) => {
|
||||
if (filterActors.value && alert.actors.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filterEntities.value && alert.entities.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filterTags.value && alert.tags.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filterExpressions.value && alert.matches.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filterCombined.value === false && [...alert.actors, ...alert.entities, ...alert.tags, ...alert.matches].length > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filterCombined.value === true && [...alert.actors, ...alert.entities, ...alert.tags, ...alert.matches].length === 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (queryRegex.test(alert.id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (alert.actors.some((actor) => queryRegex.test(actor.name))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (alert.tags.some((tag) => queryRegex.test(tag.name))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (alert.entities.some((entity) => queryRegex.test(entity.name))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (alert.matches.some((match) => queryRegex.test(match.expression))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
async function reloadAlerts() {
|
||||
alerts.value = await get('/alerts');
|
||||
}
|
||||
|
||||
async function removeAlert(alert) {
|
||||
if (done.value === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm(`Are you sure you want to remove alert #${alert.id}?`)) { // eslint-disable-line no-restricted-globals, no-alert
|
||||
return;
|
||||
}
|
||||
|
||||
done.value = false;
|
||||
|
||||
const alertLabel = [
|
||||
...alert.actors.map((actor) => actor.name),
|
||||
...alert.tags.map((tag) => tag.name),
|
||||
...alert.entities.map((entity) => entity.name),
|
||||
...alert.matches.map((match) => match.expression),
|
||||
].filter(Boolean).join(', ');
|
||||
|
||||
try {
|
||||
await del(`/alerts/${alert.id}`, {
|
||||
undoFeedback: `Removed alert for '${alertLabel}'`,
|
||||
errorFeedback: `Failed to remove alert for '${alertLabel}'`,
|
||||
appendErrorMessage: true,
|
||||
});
|
||||
|
||||
await reloadAlerts();
|
||||
} finally {
|
||||
done.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
const filterCombinedStates = [null, true, false];
|
||||
|
||||
function toggleFilterCombined() {
|
||||
const index = filterCombinedStates.indexOf(filterCombined.value);
|
||||
|
||||
filterCombined.value = filterCombinedStates[(index + 1) % filterCombinedStates.length];
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.alerts {
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.filters {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
box-sizing: border-box;
|
||||
padding: 0 .5rem;
|
||||
margin: .5rem 0 .75rem 0;
|
||||
overflow: hidden;
|
||||
|
||||
.input {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
padding: .25rem .5rem;
|
||||
fill: var(--glass);
|
||||
|
||||
&:hover {
|
||||
fill: var(--glass-strong-10);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.active {
|
||||
fill: var(--primary);
|
||||
}
|
||||
|
||||
&.success {
|
||||
fill: var(--success);
|
||||
}
|
||||
|
||||
&.error {
|
||||
fill: var(--error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filters-uncombined.icon {
|
||||
padding-left: .75rem;
|
||||
border-left: solid 1px var(--glass-weak-30);
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 0 0 0 .5rem;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
border-bottom: solid 1px var(--glass-weak-40);
|
||||
|
||||
&:hover {
|
||||
border-color: var(--glass-weak-30);
|
||||
}
|
||||
}
|
||||
|
||||
.alert-triggers {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
margin-right: .75rem;
|
||||
|
||||
.icon {
|
||||
fill: var(--glass-weak-40);
|
||||
}
|
||||
|
||||
.icon.trigger {
|
||||
fill: var(--glass-weak-10);
|
||||
}
|
||||
}
|
||||
|
||||
.alert-details {
|
||||
padding: .25rem 0;
|
||||
flex-grow: 1;
|
||||
line-height: 2.5;
|
||||
color: var(--glass);
|
||||
|
||||
&.and .alert-detail:not(:last-child):after {
|
||||
content: ' and ';
|
||||
}
|
||||
|
||||
&.or .alert-detail:not(:last-child):after {
|
||||
content: ' or ';
|
||||
}
|
||||
}
|
||||
|
||||
.alert-value {
|
||||
color: var(--text);
|
||||
|
||||
.icon {
|
||||
margin-right: .25rem;
|
||||
fill: var(--glass);
|
||||
transform: translateY(2px);
|
||||
}
|
||||
}
|
||||
|
||||
.alert-values {
|
||||
padding: .5rem .5rem;
|
||||
border-bottom: solid 1px var(--primary-light-20);
|
||||
border-radius: .3rem;
|
||||
}
|
||||
|
||||
.alert-detail {
|
||||
&.and .alert-key:not(:last-child):after {
|
||||
content: ' and ';
|
||||
}
|
||||
|
||||
&.or .alert-key:not(:last-child):after {
|
||||
content: ' or ';
|
||||
}
|
||||
}
|
||||
|
||||
.alert-regex {
|
||||
&:before,
|
||||
&:after {
|
||||
content: '╱';
|
||||
padding: 0 .1rem;
|
||||
color: var(--primary-light-20);
|
||||
}
|
||||
}
|
||||
|
||||
.alert-meta {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.alert-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: .9rem;
|
||||
color: var(--glass-weak-10);
|
||||
|
||||
.icon {
|
||||
height: 100%;
|
||||
padding: 0 .75rem;
|
||||
fill: var(--glass);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
fill: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media(--compact) {
|
||||
.profile-header {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
padding: .5rem 1rem .5rem 1rem;
|
||||
}
|
||||
|
||||
.stashes {
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 0 .5rem;
|
||||
}
|
||||
|
||||
.filters {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
@media(--small-20) {
|
||||
.alert {
|
||||
flex-direction: column;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.alert-meta {
|
||||
padding: .5rem 0 .5rem 0;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
@media(--small-30) {
|
||||
.filters {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -329,13 +329,13 @@
|
||||
/>
|
||||
</li>
|
||||
|
||||
<template v-if="stashes.length < user.stashes.length">
|
||||
<template v-if="stashes.length < assets.stashes.length">
|
||||
<li class="field-add">
|
||||
<button
|
||||
v-if="stashes.length === 0"
|
||||
type="button"
|
||||
class="button favorites"
|
||||
@click="selectStash(user.primaryStash)"
|
||||
@click="selectStash(assets.primaryStash)"
|
||||
><Icon icon="heart7" />Add to favorites</button>
|
||||
</li>
|
||||
|
||||
@@ -349,7 +349,7 @@
|
||||
<template #popper>
|
||||
<ul class="nolist">
|
||||
<li
|
||||
v-for="stash in user.stashes.filter((stash) => !stashes.some((selectedStash) => selectedStash.id === stash.id))"
|
||||
v-for="stash in assets.stashes.filter((stash) => !stashes.some((selectedStash) => selectedStash.id === stash.id))"
|
||||
:key="`stash-result-${stash.id}`"
|
||||
v-close-popper
|
||||
class="result-item result-stash result-label"
|
||||
@@ -384,21 +384,36 @@ import getPath from '#/src/get-path.js';
|
||||
import Dialog from '#/components/dialog/dialog.vue';
|
||||
import Checkbox from '#/components/form/checkbox.vue';
|
||||
|
||||
const { user } = inject('pageContext');
|
||||
const { assets } = inject('pageContext');
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
const props = defineProps({
|
||||
presetActors: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
presetEntities: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
presetTags: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const actors = ref([]);
|
||||
const emit = defineEmits(['alert', 'close']);
|
||||
|
||||
const actors = ref(props.presetActors);
|
||||
const actorResults = ref([]);
|
||||
const actorInput = ref(null);
|
||||
const actorQuery = ref('');
|
||||
|
||||
const entities = ref([]);
|
||||
const entities = ref(props.presetEntities);
|
||||
const entityResults = ref([]);
|
||||
const entityInput = ref(null);
|
||||
const entityQuery = ref('');
|
||||
|
||||
const tags = ref([]);
|
||||
const tags = ref(props.presetTags);
|
||||
const tagResults = ref([]);
|
||||
const tagInput = ref(null);
|
||||
const tagQuery = ref('');
|
||||
@@ -418,22 +433,32 @@ const email = ref(false);
|
||||
const stashes = ref([]);
|
||||
|
||||
async function createAlert() {
|
||||
console.log('creating alert');
|
||||
const alertLabel = [
|
||||
...actors.value.map((actor) => actor.name),
|
||||
...tags.value.map((tag) => tag.name),
|
||||
...entities.value.map((entity) => entity.name),
|
||||
...matches.value.map((match) => match.expression),
|
||||
].filter(Boolean).join(', ');
|
||||
|
||||
await post('/alerts', {
|
||||
const newAlert = await post('/alerts', {
|
||||
all: fieldsAnd.value,
|
||||
allActors: actorAnd.value,
|
||||
allTags: tagAnd.value,
|
||||
allMatches: matchAnd.value,
|
||||
actors: actors.value.map((actor) => actor.id),
|
||||
tags: tags.value.map((tag) => tag.id),
|
||||
tagIds: tags.value.map((tag) => tag.id),
|
||||
matches: matches.value,
|
||||
entities: entities.value.map((entity) => entity.id),
|
||||
entityIds: entities.value.map((entity) => entity.id),
|
||||
notify: notify.value,
|
||||
email: email.value,
|
||||
stashes: stashes.value.map((stash) => stash.id),
|
||||
}, { appendErrorMessage: true });
|
||||
}, {
|
||||
successFeedback: `Alert for '${alertLabel}' set`,
|
||||
errorFeedback: `Failed to set alert for '${alertLabel}'`,
|
||||
appendErrorMessage: true,
|
||||
});
|
||||
|
||||
emit('alert', newAlert);
|
||||
emit('close', true);
|
||||
}
|
||||
|
||||
@@ -466,7 +491,6 @@ async function searchTags() {
|
||||
|
||||
function focusActorInput() {
|
||||
setTimeout(() => {
|
||||
console.log(actorInput.value);
|
||||
actorInput.value.focus();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="restriction"
|
||||
class="restricted"
|
||||
>
|
||||
<div>Traxxx is restricted in your region</div>
|
||||
<a
|
||||
href="/sfw"
|
||||
class="link"
|
||||
>Learn more</a>
|
||||
</div>
|
||||
|
||||
<iframe
|
||||
v-if="campaign?.banner?.type === 'html'"
|
||||
v-else-if="campaign?.banner?.type === 'html'"
|
||||
ref="iframe"
|
||||
:width="campaign.banner.width"
|
||||
:height="campaign.banner.height"
|
||||
@@ -18,27 +29,40 @@
|
||||
:href="campaign.url || campaign.affiliate?.url"
|
||||
target="_blank"
|
||||
class="campaign"
|
||||
:style="{ 'background-image': backdrop && `url(${bannerSrc})` }"
|
||||
:class="{ backdrop }"
|
||||
data-umami-event="campaign-click"
|
||||
:data-umami-event-campaign-id="`${campaign.entity.slug}-${campaign.id}`"
|
||||
>
|
||||
<img
|
||||
:src="bannerSrc"
|
||||
:width="campaign.banner.width"
|
||||
:height="campaign.banner.height"
|
||||
class="campaign-banner"
|
||||
>
|
||||
<div class="campaign-overlay">
|
||||
<img
|
||||
:src="bannerSrc"
|
||||
:width="campaign.banner.width"
|
||||
:height="campaign.banner.height"
|
||||
class="campaign-banner"
|
||||
>
|
||||
</div>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { inject } from 'vue';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const { restriction } = pageContext;
|
||||
|
||||
const props = defineProps({
|
||||
campaign: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
backdrop: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
// console.log(props.campaign?.banner);
|
||||
// console.log(props.campaign);
|
||||
|
||||
const bannerSrc = (() => {
|
||||
if (props.campaign.banner) {
|
||||
@@ -60,6 +84,10 @@ const bannerSrc = (() => {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border-radius: .25rem;
|
||||
overflow: hidden;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.frame {
|
||||
@@ -67,11 +95,45 @@ const bannerSrc = (() => {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.campaign-overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.campaign-banner {
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
.campaign-overlay {
|
||||
padding: 4px; /* margin for drop shadow */
|
||||
backdrop-filter: blur(1rem) saturate(70%) brightness(125%);
|
||||
}
|
||||
|
||||
.dark .campaign-overlay {
|
||||
backdrop-filter: blur(1rem) saturate(70%) brightness(75%);
|
||||
}
|
||||
|
||||
.campaign-banner {
|
||||
filter: drop-shadow(0 0 2px var(--shadow-weak-20));
|
||||
}
|
||||
}
|
||||
|
||||
.restricted {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: .5rem;
|
||||
font-weight: bold;
|
||||
padding: .5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Teleport to="#container">
|
||||
<div
|
||||
class="dialog-container"
|
||||
@click="emit('close')"
|
||||
@click="close"
|
||||
>
|
||||
<div
|
||||
class="dialog"
|
||||
@@ -14,11 +14,11 @@
|
||||
<Icon
|
||||
icon="cross2"
|
||||
class="dialog-close"
|
||||
@click="emit('close')"
|
||||
@click="close"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
<slot @event="({ type, data }) => emit('event', { type, data })" />
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
@@ -27,14 +27,24 @@
|
||||
<script setup>
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
defineProps({
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
confirmClose: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['open', 'close']);
|
||||
const emit = defineEmits(['open', 'close', 'event']);
|
||||
|
||||
function close() {
|
||||
if (!props.confirmClose || confirm('You have unchanged changes, are you sure you want to close the dialog?')) { // eslint-disable-line no-restricted-globals, no-alert
|
||||
emit('close');
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => emit('open'));
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<nav class="domains">
|
||||
<Link
|
||||
:href="getPath('scenes')"
|
||||
v-if="domains.includes('scenes')"
|
||||
:href="`${path}/scenes`"
|
||||
class="domain domain-scenes nolink"
|
||||
:active="domain === 'scenes'"
|
||||
>
|
||||
@@ -10,7 +11,8 @@
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
:href="getPath('actors')"
|
||||
v-if="domains.includes('actors')"
|
||||
:href="`${path}/actors`"
|
||||
class="domain domain-actors nolink"
|
||||
:active="domain === 'actors'"
|
||||
>
|
||||
@@ -19,7 +21,8 @@
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
:href="getPath('movies')"
|
||||
v-if="domains.includes('movies')"
|
||||
:href="`${path}/movies`"
|
||||
class="domain domain-movies nolink"
|
||||
:active="domain === 'movies'"
|
||||
>
|
||||
@@ -30,20 +33,24 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
defineProps({
|
||||
stash: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
path: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
domains: {
|
||||
type: Array,
|
||||
default: () => ['scenes', 'actors', 'movies'],
|
||||
},
|
||||
domain: {
|
||||
type: String,
|
||||
default: 'scenes',
|
||||
},
|
||||
});
|
||||
|
||||
function getPath(targetDomain) {
|
||||
return `/stash/${props.stash.user.username}/${props.stash.slug}/${targetDomain}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -52,10 +59,30 @@ function getPath(targetDomain) {
|
||||
justify-content: center;
|
||||
gap: .5rem;
|
||||
padding: 0 1rem;
|
||||
|
||||
&.light .domain,
|
||||
&.light .domain {
|
||||
color: var(--glass-strong-10);
|
||||
|
||||
.icon {
|
||||
fill: var(--glass-strong-10);
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
color: var(--primary);
|
||||
|
||||
.icon {
|
||||
fill: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.domain {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
padding: .75rem 1rem;
|
||||
color: var(--highlight-strong-10);
|
||||
@@ -82,7 +109,7 @@ function getPath(targetDomain) {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.domains-bar {
|
||||
.domains-bar:not(.light) {
|
||||
background: var(--grey-dark-50);
|
||||
box-shadow: inset 0 0 3px var(--shadow);
|
||||
}
|
||||
169
components/edit/actors.vue
Normal file
@@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<ul
|
||||
class="actors nolist"
|
||||
:class="{ disabled: !editing.has(item.key) }"
|
||||
>
|
||||
<li
|
||||
v-for="actor in [...item.value, ...newActors]"
|
||||
:key="`actor-${actor.id}`"
|
||||
class="actor"
|
||||
:class="{ deleted: edits.actors && !edits.actors.some((actorId) => actorId === actor.id) }"
|
||||
>
|
||||
<span class="actor-name">{{ actor.name }}</span>
|
||||
|
||||
<Icon
|
||||
v-if="edits.actors && !edits.actors.some((actorId) => actorId === actor.id)"
|
||||
icon="checkmark"
|
||||
class="add"
|
||||
@click="emit('actors', edits.actors.concat(actor.id))"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else
|
||||
icon="cross2"
|
||||
class="remove"
|
||||
@click="emit('actors', edits.actors.filter((actorId) => actorId !== actor.id))"
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="new">
|
||||
<ActorSearch
|
||||
:disabled="!editing.has(item.key)"
|
||||
@actor="addActor"
|
||||
>
|
||||
<Icon
|
||||
icon="plus3"
|
||||
class="add"
|
||||
/>
|
||||
</ActorSearch>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import ActorSearch from '#/components/actors/search.vue';
|
||||
|
||||
const newActors = ref([]);
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
scene: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
edits: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
editing: {
|
||||
type: Set,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['actors']);
|
||||
|
||||
function addActor(actor) {
|
||||
newActors.value = newActors.value.concat(actor);
|
||||
|
||||
emit('actors', props.edits.actors.concat(actor.id));
|
||||
}
|
||||
|
||||
watch(() => props.scene, () => { newActors.value = []; });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.actors {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .35rem .25rem;
|
||||
|
||||
&.disabled {
|
||||
.actor {
|
||||
background: var(--glass-weak-50);
|
||||
color: var(--glass-strong-10);
|
||||
|
||||
.remove,
|
||||
.add {
|
||||
fill: var(--shadow-weak-30);
|
||||
background: var(--shadow-weak-50);
|
||||
}
|
||||
}
|
||||
|
||||
.new .icon {
|
||||
background: var(--shadow-weak-40);
|
||||
}
|
||||
}
|
||||
|
||||
.new {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: .25rem;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 3px var(--shadow-weak-20);
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 100%;
|
||||
padding: 0 .5rem;
|
||||
background: var(--success);
|
||||
fill: var(--text-light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actor {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
border-radius: .25rem;
|
||||
background: var(--background);
|
||||
box-shadow: 0 0 3px var(--shadow-weak-30);
|
||||
|
||||
&.deleted {
|
||||
color: var(--glass);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.actor,
|
||||
.new {
|
||||
.remove,
|
||||
.add {
|
||||
height: auto;
|
||||
padding: .25rem .3rem;
|
||||
border-radius: .25rem;
|
||||
fill: var(--highlight-strong-10);
|
||||
|
||||
&:hover {
|
||||
fill: var(--text-light);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.remove {
|
||||
fill: var(--error);
|
||||
|
||||
&:hover {
|
||||
background: var(--error);
|
||||
}
|
||||
}
|
||||
|
||||
.add {
|
||||
fill: var(--success);
|
||||
|
||||
&:hover {
|
||||
background: var(--success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actor-name {
|
||||
padding: .25rem .5rem;
|
||||
}
|
||||
</style>
|
||||
230
components/edit/augmentation.vue
Normal file
@@ -0,0 +1,230 @@
|
||||
<template>
|
||||
<div
|
||||
class="figure augmentation"
|
||||
>
|
||||
<div class="value-section">
|
||||
<span class="value-label">Natural boobs</span>
|
||||
|
||||
<select
|
||||
v-model="augmentation.naturalBoobs"
|
||||
class="input"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option :value="true">Yes</option>
|
||||
<option :value="false">No</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="augmentation.naturalBoobs === false"
|
||||
class="value-section"
|
||||
>
|
||||
<span class="value-label">Implant CC</span>
|
||||
|
||||
<input
|
||||
v-model="augmentation.boobsVolume"
|
||||
type="number"
|
||||
class="volume input"
|
||||
placeholder="CC"
|
||||
min="50"
|
||||
max="10000"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="augmentation.naturalBoobs === false"
|
||||
class="value-section"
|
||||
>
|
||||
<span class="value-label">Implant type</span>
|
||||
|
||||
<select
|
||||
v-model="augmentation.boobsImplant"
|
||||
class="input"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option value="saline">Saline</option>
|
||||
<option value="silicone">Silicone</option>
|
||||
<option value="gummy">Gummy</option>
|
||||
<option value="fat">Fat transfer</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="augmentation.naturalBoobs === false"
|
||||
class="value-section"
|
||||
>
|
||||
<span class="value-label">Implant placement</span>
|
||||
|
||||
<select
|
||||
v-model="augmentation.boobsPlacement"
|
||||
class="input"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option value="over">Over muscle</option>
|
||||
<option value="under">Under muscle</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="augmentation.naturalBoobs === false"
|
||||
class="value-section"
|
||||
>
|
||||
<span class="value-label">Incision</span>
|
||||
|
||||
<select
|
||||
v-model="augmentation.boobsIncision"
|
||||
class="input"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option value="mammary">Under breast</option>
|
||||
<option value="areolar">Areola</option>
|
||||
<option value="crescent">Crescent</option>
|
||||
<option value="lollipop">Lollipop</option>
|
||||
<option value="anchor">Anchor</option>
|
||||
<option value="axillary">Armpit</option>
|
||||
<option value="umbilical">Navel</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="augmentation.naturalBoobs === false"
|
||||
class="value-section value-divide"
|
||||
>
|
||||
<span class="value-label">Surgeon</span>
|
||||
|
||||
<input
|
||||
v-model="augmentation.boobsSurgeon"
|
||||
class="volume input"
|
||||
placeholder="Surgeon"
|
||||
list="surgeons"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
|
||||
<datalist id="surgeons">
|
||||
<option value="Dr. Revis" />
|
||||
<option value="Dr. Lenny Roudner" />
|
||||
</datalist>
|
||||
</div>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Natural butt</span>
|
||||
|
||||
<select
|
||||
v-model="augmentation.naturalButt"
|
||||
class="input"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option :value="true">Yes</option>
|
||||
<option :value="false">No</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="augmentation.naturalButt === false"
|
||||
class="value-section"
|
||||
>
|
||||
<span class="value-label">Implant CC</span>
|
||||
|
||||
<input
|
||||
v-model="augmentation.buttVolume"
|
||||
type="number"
|
||||
class="volume input"
|
||||
placeholder="CC"
|
||||
min="50"
|
||||
max="10000"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="augmentation.naturalButt === false"
|
||||
class="value-section"
|
||||
>
|
||||
<span class="value-label">Implant type</span>
|
||||
|
||||
<select
|
||||
v-model="augmentation.buttImplant"
|
||||
class="input"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option value="bbl">BBL (fat transfer)</option>
|
||||
<option value="lift">Direct lift</option>
|
||||
<option value="filler">Filler (Sculptra)</option>
|
||||
<option value="mms">MMS (CoolTone)</option>
|
||||
<option value="lipo">Lipo without BBL</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Natural lips</span>
|
||||
|
||||
<select
|
||||
v-model="augmentation.naturalLips"
|
||||
class="input"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option :value="true">Yes</option>
|
||||
<option :value="false">No</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="augmentation.naturalLips === false"
|
||||
class="value-section"
|
||||
>
|
||||
<span class="value-label">Filler CC</span>
|
||||
|
||||
<input
|
||||
v-model="augmentation.lipsVolume"
|
||||
type="number"
|
||||
class="volume input"
|
||||
placeholder="CC"
|
||||
min="50"
|
||||
max="10000"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Natural labia</span>
|
||||
|
||||
<select
|
||||
v-model="augmentation.naturalLabia"
|
||||
class="input"
|
||||
:disabled="!editing.has('augmentation')"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option :value="true">Yes</option>
|
||||
<option :value="false">No</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
edits: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
editing: {
|
||||
type: Set,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['augmentation']);
|
||||
const augmentation = reactive(props.edits.augmentation);
|
||||
|
||||
watch(augmentation, () => emit('augmentation', augmentation));
|
||||
</script>
|
||||
115
components/edit/avatar.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div class="avatar noshrink">
|
||||
<img
|
||||
:src="getPath(avatar, 'thumbnail')"
|
||||
class="avatar-image"
|
||||
>
|
||||
|
||||
<span
|
||||
class="avatar-credit"
|
||||
title="Credit"
|
||||
>{{ avatar.credit }}</span>
|
||||
|
||||
<span class="avatar-meta">
|
||||
<span title="Dimensions">{{ avatar.width }}x{{ avatar.height }}</span>
|
||||
|
||||
<span
|
||||
v-if="avatar.sharpness"
|
||||
title="Sharpness"
|
||||
>{{ avatar.sharpness.toFixed(2) }}</span>
|
||||
</span>
|
||||
|
||||
<a
|
||||
:href="getPath(avatar)"
|
||||
target="_blank"
|
||||
class="avatar-zoom"
|
||||
>
|
||||
<Icon
|
||||
icon="search"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import getPath from '#/src/get-path.js';
|
||||
|
||||
defineProps({
|
||||
avatar: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
border: solid 2px transparent;
|
||||
border-radius: .35rem;
|
||||
box-shadow: 0 0 3px var(--shadow-weak-10);
|
||||
margin: 2px; /* clear outline */
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
|
||||
&.selected {
|
||||
border: solid 2px var(--primary);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
/*
|
||||
.avatar-meta,
|
||||
.avatar-credit {
|
||||
display: none;
|
||||
}
|
||||
*/
|
||||
|
||||
.icon {
|
||||
fill: var(--text-light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-image {
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
.avatar-zoom {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
padding: .25rem;
|
||||
|
||||
.icon {
|
||||
fill: var(--highlight-strong-20);
|
||||
filter: drop-shadow(0 0 1px var(--shadow));
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-meta,
|
||||
.avatar-credit {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
box-sizing: border-box;
|
||||
padding: .15rem .25rem;
|
||||
font-size: .7rem;
|
||||
color: var(--text-light);
|
||||
text-shadow: 1px 1px 0 var(--shadow-strong-30);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.avatar-meta {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.avatar-credit {
|
||||
bottom: .75rem;
|
||||
left: 0;
|
||||
}
|
||||
</style>
|
||||
147
components/edit/figure.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<div class="figure">
|
||||
<div class="value-section">
|
||||
<span class="value-label">Units</span>
|
||||
|
||||
<select
|
||||
:value="units"
|
||||
class="input"
|
||||
:disabled="!editing.has('figure')"
|
||||
@change="emit('units', $event.target.value)"
|
||||
>
|
||||
<option value="us">USA</option>
|
||||
<option value="uk">UK</option>
|
||||
<option value="eu">Europe/Asia</option>
|
||||
<option value="jp">Japan</option>
|
||||
<option value="au">Australia</option>
|
||||
<option value="it">Italy</option>
|
||||
<option value="fr">France</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<span class="figure-bust">
|
||||
<div class="value-section">
|
||||
<span class="value-label">Bust</span>
|
||||
|
||||
<select
|
||||
v-model="figure.bust"
|
||||
class="select input"
|
||||
placeholder="Bust"
|
||||
:disabled="!editing.has('figure')"
|
||||
>
|
||||
<option
|
||||
:key="`figure-bust-unknown`"
|
||||
:value="null"
|
||||
/>
|
||||
|
||||
<option
|
||||
v-for="bust in bustSizes[units]"
|
||||
:key="`figure-bust-${bust}`"
|
||||
:value="Array.isArray(bust) ? bust[0] : bust"
|
||||
>{{ Array.isArray(bust) ? bust.join('/') : bust }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Cup</span>
|
||||
|
||||
<select
|
||||
v-model="figure.cup"
|
||||
class="select input"
|
||||
placeholder="Cup"
|
||||
:disabled="!editing.has('figure')"
|
||||
>
|
||||
<option
|
||||
:key="`figure-cup-unknown`"
|
||||
:value="null"
|
||||
/>
|
||||
|
||||
<option
|
||||
v-for="cup in cupSizes[units]"
|
||||
:key="`figure-cup-${cup}`"
|
||||
:value="Array.isArray(cup) ? cup[0] : cup"
|
||||
>{{ Array.isArray(cup) ? cup.join('/') : cup }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Waist</span>
|
||||
|
||||
<span>
|
||||
<input
|
||||
v-model="figure.waist"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has('figure')"
|
||||
>
|
||||
|
||||
<template v-if="['us', 'uk'].includes(units)"> inch</template>
|
||||
<template v-else> cm</template>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Hip</span>
|
||||
|
||||
<span>
|
||||
<input
|
||||
v-model="figure.hip"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has('figure')"
|
||||
>
|
||||
|
||||
<template v-if="['us', 'uk'].includes(units)"> inch</template>
|
||||
<template v-else> cm</template>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
edits: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
editing: {
|
||||
type: Set,
|
||||
default: null,
|
||||
},
|
||||
units: {
|
||||
type: String,
|
||||
default: 'us',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['figure', 'units']);
|
||||
const figure = reactive(props.edits.figure);
|
||||
|
||||
watch(figure, () => emit('figure', figure));
|
||||
|
||||
const cupSizes = {
|
||||
us: ['AA', 'A', 'B', 'C', 'D', ['DD', 'E'], ['DDD', 'F'], 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'], // United States
|
||||
uk: ['AA', 'A', 'B', 'C', 'D', 'DD', 'E', 'F', 'FF', 'G', 'GG', 'H', 'HH', 'J', 'JJ', 'K', 'KK'], // United Kingdom
|
||||
eu: ['AA', 'A', 'B', 'C', 'D', 'E', 'F', 'G', ' H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'], // Europe
|
||||
jp: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'], // Japan
|
||||
};
|
||||
|
||||
cupSizes.fr = cupSizes.eu; // France
|
||||
cupSizes.it = cupSizes.uk; // Italy
|
||||
cupSizes.au = cupSizes.uk; // Australia
|
||||
|
||||
// bra band sizes
|
||||
const bustSizes = {
|
||||
us: [28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56],
|
||||
eu: [60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130],
|
||||
fr: [75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145],
|
||||
it: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
|
||||
au: [6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34],
|
||||
};
|
||||
|
||||
bustSizes.uk = bustSizes.us;
|
||||
bustSizes.jp = bustSizes.eu;
|
||||
</script>
|
||||
173
components/edit/movies.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<ul
|
||||
class="movies nolist"
|
||||
:class="{ disabled: !editing.has(item.key) }"
|
||||
>
|
||||
<li
|
||||
v-for="movie in [...item.value, ...newMovies]"
|
||||
:key="`movie-${movie.id}`"
|
||||
class="movie"
|
||||
:class="{ deleted: edits.movies && !edits.movies.some((movieId) => movieId === movie.id) }"
|
||||
>
|
||||
<span class="movie-name">{{ movie.title }}</span>
|
||||
|
||||
<Icon
|
||||
v-if="edits.movies && !edits.movies.some((movieId) => movieId === movie.id)"
|
||||
icon="checkmark"
|
||||
class="add"
|
||||
@click="emit('movies', edits.movies.concat(movie.id))"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else
|
||||
icon="cross2"
|
||||
class="remove"
|
||||
@click="emit('movies', edits.movies.filter((movieId) => movieId !== movie.id))"
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="new">
|
||||
<MovieSearch
|
||||
:disabled="!editing.has(item.key)"
|
||||
@movie="addMovie"
|
||||
>
|
||||
<Icon
|
||||
icon="plus3"
|
||||
class="add"
|
||||
/>
|
||||
</MovieSearch>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import MovieSearch from '#/components/movies/search.vue';
|
||||
|
||||
const newMovies = ref([]);
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
scene: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
edits: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
editing: {
|
||||
type: Set,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['movies']);
|
||||
|
||||
function addMovie(movie) {
|
||||
newMovies.value = newMovies.value.concat(movie);
|
||||
|
||||
console.log(movie);
|
||||
|
||||
emit('movies', props.edits.movies.concat(movie.id));
|
||||
|
||||
console.log(props.edits);
|
||||
}
|
||||
|
||||
watch(() => props.scene, () => { newMovies.value = []; });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.movies {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .35rem .25rem;
|
||||
|
||||
&.disabled {
|
||||
.movie {
|
||||
background: var(--glass-weak-50);
|
||||
color: var(--glass-strong-10);
|
||||
|
||||
.remove,
|
||||
.add {
|
||||
fill: var(--shadow-weak-30);
|
||||
background: var(--shadow-weak-50);
|
||||
}
|
||||
}
|
||||
|
||||
.new .icon {
|
||||
background: var(--shadow-weak-40);
|
||||
}
|
||||
}
|
||||
|
||||
.new {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: .25rem;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 3px var(--shadow-weak-20);
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 100%;
|
||||
padding: 0 .5rem;
|
||||
background: var(--success);
|
||||
fill: var(--text-light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.movie {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
border-radius: .25rem;
|
||||
background: var(--background);
|
||||
box-shadow: 0 0 3px var(--shadow-weak-30);
|
||||
|
||||
&.deleted {
|
||||
color: var(--glass);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.movie,
|
||||
.new {
|
||||
.remove,
|
||||
.add {
|
||||
height: auto;
|
||||
padding: .25rem .3rem;
|
||||
border-radius: .25rem;
|
||||
fill: var(--highlight-strong-10);
|
||||
|
||||
&:hover {
|
||||
fill: var(--text-light);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.remove {
|
||||
fill: var(--error);
|
||||
|
||||
&:hover {
|
||||
background: var(--error);
|
||||
}
|
||||
}
|
||||
|
||||
.add {
|
||||
fill: var(--success);
|
||||
|
||||
&:hover {
|
||||
background: var(--success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.movie-name {
|
||||
padding: .25rem .5rem;
|
||||
}
|
||||
</style>
|
||||
109
components/edit/penis.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<div
|
||||
class="figure penis"
|
||||
>
|
||||
<div class="value-section">
|
||||
<span class="value-label">Units</span>
|
||||
|
||||
<select
|
||||
:value="units"
|
||||
class="input"
|
||||
:disabled="!editing.has('penis')"
|
||||
@change="emit('units', $event.target.value)"
|
||||
>
|
||||
<option value="imperial">Imperial</option>
|
||||
<option value="metric">Metric</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Penis length</span>
|
||||
|
||||
<span v-if="units === 'metric'">
|
||||
<input
|
||||
v-model="penis.metricLength"
|
||||
type="number"
|
||||
class="volume input"
|
||||
min="1"
|
||||
max="30"
|
||||
:disabled="!editing.has('penis')"
|
||||
> cm
|
||||
</span>
|
||||
|
||||
<span v-if="units === 'imperial'">
|
||||
<input
|
||||
v-model="penis.imperialLength"
|
||||
type="number"
|
||||
class="volume input"
|
||||
min="1"
|
||||
max="30"
|
||||
:disabled="!editing.has('penis')"
|
||||
> inch
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Penis girth</span>
|
||||
|
||||
<span v-if="units === 'metric'">
|
||||
<input
|
||||
v-model="penis.metricGirth"
|
||||
type="number"
|
||||
class="volume input"
|
||||
min="1"
|
||||
max="30"
|
||||
:disabled="!editing.has('penis')"
|
||||
> cm
|
||||
</span>
|
||||
|
||||
<span v-if="units === 'imperial'">
|
||||
<input
|
||||
v-model="penis.imperialGirth"
|
||||
type="number"
|
||||
class="volume input"
|
||||
min="1"
|
||||
max="30"
|
||||
:disabled="!editing.has('penis')"
|
||||
> inch
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Circumcised</span>
|
||||
|
||||
<select
|
||||
v-model="penis.isCircumcised"
|
||||
class="input"
|
||||
:disabled="!editing.has('penis')"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option :value="true">Yes</option>
|
||||
<option :value="false">No</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
edits: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
editing: {
|
||||
type: Set,
|
||||
default: null,
|
||||
},
|
||||
units: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['penis', 'units']);
|
||||
const penis = reactive(props.edits.penis);
|
||||
|
||||
watch(penis, () => emit('penis', penis));
|
||||
</script>
|
||||
77
components/edit/place.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div
|
||||
class="place"
|
||||
>
|
||||
<div class="value-section">
|
||||
<span class="value-label">Country</span>
|
||||
|
||||
<select
|
||||
v-model="place.country"
|
||||
class="select input"
|
||||
placeholder="Country"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
<option
|
||||
:key="`${item.key}-country-unknown`"
|
||||
:value="null"
|
||||
/>
|
||||
|
||||
<option
|
||||
v-for="country in sortedCountries"
|
||||
:key="`${item.key}-country-${country.alpha2}`"
|
||||
:value="country.alpha2"
|
||||
>{{ country.alias || country.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="value-section">
|
||||
<span class="value-label">Place</span>
|
||||
|
||||
<input
|
||||
v-model="place.place"
|
||||
class="string input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, watch, inject } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
edits: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
editing: {
|
||||
type: Set,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const countries = pageContext.pageProps.countries;
|
||||
|
||||
const emit = defineEmits(['place']);
|
||||
const place = reactive(props.edits[props.item.key]);
|
||||
|
||||
watch(place, () => emit('place', place));
|
||||
|
||||
const topCountries = [
|
||||
'AU',
|
||||
'BR',
|
||||
'CZ',
|
||||
'DE',
|
||||
'JP',
|
||||
'RU',
|
||||
'GB',
|
||||
'US',
|
||||
];
|
||||
|
||||
const sortedCountries = countries.toSorted((countryA, countryB) => topCountries.indexOf(countryB.alpha2) - topCountries.indexOf(countryA.alpha2));
|
||||
</script>
|
||||
109
components/edit/revision-socials.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<ul class="socials nolist">
|
||||
<li
|
||||
v-for="social in socials"
|
||||
:key="`social-${rev.id}-${index}-${social.id}`"
|
||||
class="delta-item"
|
||||
:class="{ modified: social.modified }"
|
||||
>
|
||||
<a
|
||||
:href="getUrl(social)"
|
||||
target="_blank"
|
||||
class="link"
|
||||
>
|
||||
<Icon
|
||||
v-if="social.platform && env.socials.urls[social.platform]"
|
||||
:icon="iconMap[social.platform] || social.platform"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform}`"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="social.platform"
|
||||
icon="bubbles10"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform} icon-generic`"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="social.url"
|
||||
icon="sphere"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform} icon-generic`"
|
||||
/>
|
||||
|
||||
{{ social.handle || social.url }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { inject } from 'vue';
|
||||
|
||||
import formatTemplate from 'template-format';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const { env } = pageContext;
|
||||
|
||||
defineProps({
|
||||
rev: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
socials: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const iconMap = {
|
||||
twitter: 'twitter-x',
|
||||
};
|
||||
|
||||
function getUrl(social) {
|
||||
if (social.url) {
|
||||
return social.url;
|
||||
}
|
||||
|
||||
if (env.socials.urls[social.platform]) {
|
||||
return formatTemplate(env.socials.urls[social.platform], { handle: social.handle });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.socials {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.delta-item .link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: .25rem .5rem;
|
||||
border-radius: .25rem;
|
||||
box-shadow: 0 0 3px var(--shadow-weak-20);
|
||||
color: inherit;
|
||||
|
||||
.icon {
|
||||
margin-right: .5rem;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.icon-generic {
|
||||
fill: var(--glass-strong-10);
|
||||
}
|
||||
}
|
||||
|
||||
.delta-item.modified {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
686
components/edit/revisions.vue
Normal file
@@ -0,0 +1,686 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<div
|
||||
v-if="context === 'admin'"
|
||||
class="revs-header"
|
||||
>
|
||||
<Checkbox
|
||||
label="Show finalized"
|
||||
:checked="showReviewed"
|
||||
@change="(checked) => { showReviewed = checked; reloadRevisions(); }"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ul
|
||||
class="revs nolist"
|
||||
:class="{ [`revs-${context}`]: true }"
|
||||
>
|
||||
<li
|
||||
v-for="rev in curatedRevisions"
|
||||
:key="`rev-${rev.id}`"
|
||||
class="rev"
|
||||
:class="{
|
||||
reviewed: reviewedRevisions.has(rev.id),
|
||||
expanded: context === 'admin' || expanded.has(rev.id)
|
||||
}"
|
||||
>
|
||||
<template v-if="context === 'admin' || expanded.has(rev.id)">
|
||||
<div class="rev-header">
|
||||
<a
|
||||
:href="`/${domain.slice(0, -1)}/${rev.sceneId || rev.actorId}/${rev.base.slug}`"
|
||||
target="_blank"
|
||||
class="rev-link rev-scene nolink noshrink"
|
||||
>{{ rev.sceneId || rev.actorId }}@{{ rev.hash.slice(0, 6) }}</a>
|
||||
|
||||
<a
|
||||
:href="`/${domain.slice(0, -1)}/${rev.sceneId || rev.actorId}/${rev.base.slug}`"
|
||||
target="_blank"
|
||||
class="rev-link rev-title nolink ellipsis"
|
||||
>{{ rev.base.title || rev.base.name }}</a>
|
||||
|
||||
<div class="rev-details noshrink">
|
||||
<a
|
||||
v-if="rev.user"
|
||||
:href="`/user/${rev.user.username}`"
|
||||
target="_blank"
|
||||
class="rev-username nolink"
|
||||
>{{ rev.user.username }}</a>
|
||||
|
||||
<time
|
||||
:datetime="rev.createdAt"
|
||||
class="rev-created"
|
||||
>{{ format(rev.createdAt, 'yyyy-MM-dd hh:mm') }}</time>
|
||||
</div>
|
||||
|
||||
<div class="rev-actions noshrink">
|
||||
<span
|
||||
v-if="rev.review && context === 'admin'"
|
||||
class="approved"
|
||||
:class="{ rejected: !rev.review.isApproved }"
|
||||
>{{ rev.review.isApproved ? 'Approved' : 'Rejected' }} by <a
|
||||
:href="`/user/${rev.review.username}`"
|
||||
target="_blank"
|
||||
class="nolink"
|
||||
>{{ rev.review.username }}</a> {{ format(rev.review.reviewedAt, 'yyyy-MM-dd hh:mm') }}</span>
|
||||
|
||||
<template v-else-if="context === 'admin'">
|
||||
<Icon
|
||||
v-tooltip="`Ban user from submitting revisions`"
|
||||
icon="user-block"
|
||||
class="review-reject review-ban"
|
||||
@click="banEditor(rev)"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-tooltip="`Reject revision`"
|
||||
icon="blocked"
|
||||
class="review-reject"
|
||||
@click="reviewRevision(rev, false)"
|
||||
/>
|
||||
|
||||
<input
|
||||
v-model="feedbacks[rev.id]"
|
||||
placeholder="Feedback"
|
||||
class="input"
|
||||
>
|
||||
|
||||
<Icon
|
||||
v-tooltip="`Approve and apply revision`"
|
||||
icon="checkmark"
|
||||
class="review-approve"
|
||||
@click="reviewRevision(rev, true)"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="rev-deltas">
|
||||
<li
|
||||
v-for="(delta, index) in rev.deltas"
|
||||
:key="`delta-${rev.id}-${index}`"
|
||||
class="delta"
|
||||
>
|
||||
<span class="delta-key ellipsis">{{ delta.key }}</span>
|
||||
|
||||
<div class="delta-deltas">
|
||||
<span class="delta-from delta-value">
|
||||
<Socials
|
||||
v-if="delta.key === 'socials'"
|
||||
:rev="rev"
|
||||
:index="index"
|
||||
:socials="rev.base[delta.key]"
|
||||
/>
|
||||
|
||||
<ul
|
||||
v-else-if="Array.isArray(rev.base[delta.key])"
|
||||
class="nolist"
|
||||
>[
|
||||
<li
|
||||
v-for="item in rev.base[delta.key]"
|
||||
:key="`item-${rev.id}-${index}-${item.id}`"
|
||||
class="delta-item"
|
||||
:class="{ modified: item.modified }"
|
||||
>{{ item.name || item.id || item }}</li> ]
|
||||
</ul>
|
||||
|
||||
<Avatar
|
||||
v-else-if="delta.key === 'avatar'"
|
||||
:avatar="avatarsById[rev.base[delta.key]]"
|
||||
class="delta-avatar"
|
||||
/>
|
||||
|
||||
<template v-else-if="rev.base[delta.key] instanceof Date">{{ format(rev.base[delta.key], 'yyyy-MM-dd hh:mm') }}</template>
|
||||
<template v-else>{{ rev.base[delta.key] }}</template>
|
||||
</span>
|
||||
|
||||
<span class="delta-arrow">⇒</span>
|
||||
|
||||
<span class="delta-to delta-value">
|
||||
<Socials
|
||||
v-if="delta.key === 'socials'"
|
||||
:rev="rev"
|
||||
:index="index"
|
||||
:socials="delta.value"
|
||||
/>
|
||||
|
||||
<ul
|
||||
v-else-if="Array.isArray(delta.value)"
|
||||
class="nolist"
|
||||
>[
|
||||
<li
|
||||
v-for="item in delta.value"
|
||||
:key="`item-${rev.id}-${index}-${item.id}`"
|
||||
class="delta-item"
|
||||
:class="{ modified: item.modified }"
|
||||
>{{ item.name || item.id || item }}</li> ]
|
||||
</ul>
|
||||
|
||||
<Avatar
|
||||
v-else-if="delta.key === 'avatar'"
|
||||
:avatar="avatarsById[delta.value]"
|
||||
class="delta-avatar"
|
||||
/>
|
||||
|
||||
<template v-else-if="delta.value instanceof Date">{{ format(delta.value, 'yyyy-MM-dd hh:mm') }}</template>
|
||||
<template v-else>{{ delta.value }}</template>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div
|
||||
v-if="rev.comment"
|
||||
class="rev-comment"
|
||||
>
|
||||
{{ rev.comment }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="rev-compact"
|
||||
@click="expanded.add(rev.id)"
|
||||
>
|
||||
|
||||
<span class="rev-scene nolink noshrink"><template v-if="context !== 'scene' && context !== 'actor'">{{ rev.sceneId || rev.actorId }}</template>@{{ rev.hash.slice(0, 6) }}</span>
|
||||
|
||||
<span
|
||||
v-if="context !== 'scene'"
|
||||
class="rev-title nolink ellipsis"
|
||||
>{{ rev.base.title }}</span>
|
||||
|
||||
<span class="rev-summary">
|
||||
<span class="summary-deltas ellipsis">{{ rev.deltas.map((delta) => delta.key).join(', ') }}</span>
|
||||
|
||||
<span
|
||||
v-if="rev.comment"
|
||||
class="summary-comment ellipsis"
|
||||
>{{ rev.comment }}</span>
|
||||
</span>
|
||||
|
||||
<div class="rev-details noshrink">
|
||||
<a
|
||||
v-if="rev.user && context !== 'user'"
|
||||
:href="`/user/${rev.user.username}`"
|
||||
target="_blank"
|
||||
class="rev-username nolink ellipsis"
|
||||
@click.stop
|
||||
>{{ rev.user.username }}</a>
|
||||
|
||||
<a
|
||||
v-if="rev.user && context !== 'user'"
|
||||
v-tooltip="rev.user.username"
|
||||
:href="`/user/${rev.user.username}`"
|
||||
target="_blank"
|
||||
class="rev-avatar nolink ellipsis"
|
||||
@click.stop
|
||||
><Icon icon="user3-long" /></a>
|
||||
|
||||
<time
|
||||
:datetime="rev.createdAt"
|
||||
class="rev-created"
|
||||
>{{ format(rev.createdAt, 'yyyy-MM-dd hh:mm') }}</time>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, inject } from 'vue';
|
||||
import { format } from 'date-fns';
|
||||
|
||||
import Avatar from '#/components/edit/avatar.vue';
|
||||
import Socials from '#/components/edit/revision-socials.vue';
|
||||
import Checkbox from '#/components/form/checkbox.vue';
|
||||
|
||||
import { get, post } from '#/src/api.js';
|
||||
import { formatDuration } from '#/utils/format.js';
|
||||
|
||||
defineProps({
|
||||
context: {
|
||||
type: String,
|
||||
default: 'admin',
|
||||
},
|
||||
});
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const revisions = ref(pageContext.pageProps.revisions);
|
||||
const domain = pageContext.routeParams.domain;
|
||||
|
||||
const actors = ref(pageContext.pageProps.actors);
|
||||
const tags = ref(pageContext.pageProps.tags);
|
||||
const movies = ref(pageContext.pageProps.movies);
|
||||
const avatars = ref(pageContext.pageProps.avatars);
|
||||
|
||||
const actorsById = computed(() => Object.fromEntries(actors.value.map((actor) => [actor.id, actor])));
|
||||
const tagsById = computed(() => Object.fromEntries(tags.value.map((tag) => [tag.id, tag])));
|
||||
const moviesById = computed(() => Object.fromEntries(movies.value.map((movie) => [movie.id, movie])));
|
||||
const avatarsById = computed(() => Object.fromEntries(avatars.value.map((avatar) => [avatar.id, avatar])));
|
||||
|
||||
const feedbacks = ref({});
|
||||
const showReviewed = ref(false);
|
||||
const reviewedRevisions = ref(new Set());
|
||||
const expanded = ref(new Set());
|
||||
|
||||
const mappedKeys = {
|
||||
actors: actorsById,
|
||||
tags: tagsById,
|
||||
movies: moviesById,
|
||||
};
|
||||
|
||||
const dateKeys = [
|
||||
'date',
|
||||
'dateOfBirth',
|
||||
'dateOfDeath',
|
||||
'productionDate',
|
||||
'createdAt',
|
||||
];
|
||||
|
||||
const curatedKeys = {
|
||||
duration: (duration) => formatDuration(duration),
|
||||
};
|
||||
|
||||
const curatedRevisions = computed(() => revisions.value.map((revision) => {
|
||||
const curatedBase = Object.fromEntries(Object.entries(revision.base).map(([key, value]) => {
|
||||
if (Array.isArray(value) && mappedKeys[key]) {
|
||||
return [key, value.map((itemId) => ({
|
||||
id: itemId,
|
||||
name: mappedKeys[key].value[itemId]?.name || mappedKeys[key].value[itemId]?.title,
|
||||
modified: revision.deltas.some((delta) => delta.key === key && !delta.value.some((deltaItemId) => deltaItemId === itemId)),
|
||||
}))];
|
||||
}
|
||||
|
||||
if (key === 'socials') {
|
||||
// new socials don't have IDs yet, so we need to compare the values
|
||||
return [key, value.map((item) => ({
|
||||
...item,
|
||||
modified: revision.deltas.some((delta) => delta.key === key && !delta.value.some((deltaItem) => deltaItem.url === item.url || `${deltaItem.platform}:${deltaItem.handle}` === `${item.platform}:${item.handle}`)),
|
||||
}))];
|
||||
}
|
||||
|
||||
if (dateKeys.includes(key) && value) {
|
||||
return [key, new Date(value)];
|
||||
}
|
||||
|
||||
if (curatedKeys[key]) {
|
||||
return [key, curatedKeys[key](value)];
|
||||
}
|
||||
|
||||
return [key, value];
|
||||
}));
|
||||
|
||||
const curatedDeltas = revision.deltas.map((delta) => {
|
||||
if (Array.isArray(delta.value) && mappedKeys[delta.key]) {
|
||||
return {
|
||||
...delta,
|
||||
value: delta.value.map((itemId) => ({
|
||||
id: itemId,
|
||||
name: mappedKeys[delta.key].value[itemId]?.name || mappedKeys[delta.key].value[itemId]?.title,
|
||||
modified: !revision.base[delta.key].includes(itemId),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
if (delta.key === 'socials') {
|
||||
// new socials don't have IDs yet, so we need to compare the values
|
||||
return {
|
||||
...delta,
|
||||
value: delta.value.map((social) => ({
|
||||
...social,
|
||||
modified: !revision.base[delta.key].some((baseItem) => baseItem.url === social.url || `${baseItem.platform}:${baseItem.handle}` === `${social.platform}:${social.handle}`),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
if (dateKeys.includes(delta.key) && delta.value) {
|
||||
return {
|
||||
...delta,
|
||||
value: new Date(delta.value),
|
||||
};
|
||||
}
|
||||
|
||||
if (curatedKeys[delta.key]) {
|
||||
return {
|
||||
...delta,
|
||||
value: curatedKeys[delta.key](delta.value),
|
||||
};
|
||||
}
|
||||
|
||||
return delta;
|
||||
});
|
||||
|
||||
return {
|
||||
...revision,
|
||||
base: curatedBase,
|
||||
deltas: curatedDeltas,
|
||||
};
|
||||
}));
|
||||
|
||||
async function reloadRevisions() {
|
||||
const updatedRevisions = await get(`/revisions/${domain}`, {
|
||||
isFinalized: showReviewed.value ? undefined : false,
|
||||
limit: 50,
|
||||
});
|
||||
|
||||
actors.value = updatedRevisions.actors;
|
||||
tags.value = updatedRevisions.tags;
|
||||
movies.value = updatedRevisions.movies;
|
||||
avatars.value = updatedRevisions.avatars;
|
||||
revisions.value = updatedRevisions.revisions;
|
||||
}
|
||||
|
||||
async function reviewRevision(revision, isApproved) {
|
||||
reviewedRevisions.value.add(revision.id);
|
||||
|
||||
try {
|
||||
await post(`/revisions/${domain}/${revision.id}/reviews`, {
|
||||
isApproved,
|
||||
feedback: feedbacks.value[revision.id],
|
||||
});
|
||||
|
||||
const updatedRevision = await get(`/revisions/${domain}/${revision.id}`, {
|
||||
revisionId: revision.id,
|
||||
});
|
||||
|
||||
revisions.value = revisions.value.map((rev) => (rev.id === updatedRevision.revision.id ? updatedRevision.revision : rev));
|
||||
} catch (error) {
|
||||
reviewedRevisions.value.delete(revision.id);
|
||||
}
|
||||
}
|
||||
|
||||
async function banEditor(revision) {
|
||||
await post('/bans', {
|
||||
userId: revision.user.id,
|
||||
banIp: true,
|
||||
});
|
||||
|
||||
await reviewRevision(revision, false);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.revs-header {
|
||||
display: flex;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
.check-container {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
.revs {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
overflow-x: auto;
|
||||
padding: 3px; /* prevent shadow from getting cut off */
|
||||
}
|
||||
|
||||
.rev {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--background);
|
||||
border-radius: .25rem;
|
||||
box-shadow: 0 0 3px var(--shadow-weak-30);
|
||||
margin-bottom: .25rem;
|
||||
font-size: .9rem;
|
||||
|
||||
&.expanded {
|
||||
min-width: 1200px;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
&.reviewed {
|
||||
pointer-events: none;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 3px var(--primary-light-20);
|
||||
}
|
||||
}
|
||||
|
||||
.rev-link {
|
||||
&:hover {
|
||||
color: var(--primary);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.rev-header {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
border-bottom: solid 1px var(--glass-weak-30);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.rev-scene {
|
||||
width: 9rem;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
padding: .5rem .5rem;
|
||||
align-items: center;
|
||||
color: var(--glass-strong-10);
|
||||
|
||||
}
|
||||
|
||||
.rev-title {
|
||||
padding: .5rem 0;
|
||||
}
|
||||
|
||||
.rev-details {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
justify-content: flex-end;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
.rev-username {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.rev-actions {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
|
||||
.icon {
|
||||
height: 100%;
|
||||
padding: 0 1.5rem;
|
||||
fill: var(--glass);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
fill: var(--text-light);
|
||||
}
|
||||
}
|
||||
|
||||
.trigger {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.review-approve {
|
||||
fill: var(--success);
|
||||
|
||||
&:hover {
|
||||
background: var(--success);
|
||||
}
|
||||
}
|
||||
|
||||
.review-reject {
|
||||
fill: var(--error);
|
||||
|
||||
&:hover {
|
||||
background: var(--error);
|
||||
}
|
||||
}
|
||||
|
||||
.review-comment {
|
||||
&:hover {
|
||||
background: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
.approved {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--success);
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
.rejected {
|
||||
color: var(--error);
|
||||
}
|
||||
}
|
||||
|
||||
.rev-deltas {
|
||||
flex-grow: 1;
|
||||
padding: 0;
|
||||
margin: .25rem 0;
|
||||
}
|
||||
|
||||
.delta {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: .15rem .5rem;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: solid 1px var(--glass-weak-40);
|
||||
}
|
||||
}
|
||||
|
||||
.delta-key {
|
||||
width: 8.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.delta-deltas {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.delta-from {
|
||||
width: 40%;
|
||||
flex-shrink: 0;
|
||||
color: var(--reject);
|
||||
padding: .25rem 0;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.delta-arrow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
font-size: 1.2rem;
|
||||
color: var(--glass-weak-10);
|
||||
}
|
||||
|
||||
.delta-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.delta-to {
|
||||
flex-grow: 1;
|
||||
color: var(--approve);
|
||||
}
|
||||
|
||||
.delta-item {
|
||||
line-height: 1.5;
|
||||
|
||||
&:not(:last-child):after {
|
||||
content: ',\00a0';
|
||||
}
|
||||
|
||||
&.modified {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.rev-comment {
|
||||
padding: .5rem .5rem;
|
||||
border-top: solid 1px var(--glass-weak-30);
|
||||
}
|
||||
|
||||
.rev-compact {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
cursor: pointer;
|
||||
|
||||
.rev-title {
|
||||
width: 15rem;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.rev-details {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.rev-avatar {
|
||||
display: none;
|
||||
|
||||
.icon {
|
||||
fill: var(--glass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.revs-scene .rev-compact .rev-scene {
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
.rev-summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.summary-comment {
|
||||
padding-left: .5rem;
|
||||
border-left: solid 1px var(--glass-weak-20);
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.summary-deltas {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@media(--compact) {
|
||||
.rev-compact .rev-details {
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.rev-compact .rev-username {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rev-compact .rev-avatar {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media(--small) {
|
||||
.rev-compact .summary-comment {
|
||||
padding: 0;
|
||||
border: none;
|
||||
margin: 0;
|
||||
|
||||
& + .summary-deltas {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
285
components/edit/socials.vue
Normal file
@@ -0,0 +1,285 @@
|
||||
<template>
|
||||
<ul
|
||||
class="list nolist"
|
||||
:class="{ disabled: !editing.has('socials') }"
|
||||
>
|
||||
<li
|
||||
v-for="(social, index) in socials"
|
||||
:key="`socials-${social}`"
|
||||
class="list-item"
|
||||
:class="{ deleted: !socials.some((listItem) => listItem.social === social.social || listItem.url === social.url) }"
|
||||
>
|
||||
<a
|
||||
:href="getUrl(social)"
|
||||
target="_blank"
|
||||
class="link"
|
||||
>
|
||||
<Icon
|
||||
v-if="social.platform && env.socials.urls[social.platform]"
|
||||
:icon="iconMap[social.platform] || social.platform"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform}`"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="social.platform"
|
||||
icon="bubbles10"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform} icon-generic`"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else-if="social.url"
|
||||
icon="sphere"
|
||||
:title="social.platform"
|
||||
:class="`icon-social icon-${social.platform} icon-generic`"
|
||||
/>
|
||||
|
||||
{{ social.handle || social.url }}
|
||||
</a>
|
||||
|
||||
<Icon
|
||||
v-if="!socials.some((listItem) => listItem.social === social.social || listItem.url === social.url)"
|
||||
icon="checkmark"
|
||||
class="add noselect"
|
||||
@click="socials = socials.concat(social)"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else
|
||||
icon="cross2"
|
||||
class="remove noselect"
|
||||
@click="socials = socials.filter((listItem, listIndex) => listIndex !== index)"
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="list-new">
|
||||
<VDropdown>
|
||||
<Icon
|
||||
icon="plus2"
|
||||
class="add noselect"
|
||||
/>
|
||||
|
||||
<template #popper>
|
||||
<form
|
||||
class="new"
|
||||
@submit.prevent="addSocial"
|
||||
>
|
||||
<div class="new-section">
|
||||
<input
|
||||
v-model="platform"
|
||||
list="platforms"
|
||||
class="input"
|
||||
placeholder="Platform"
|
||||
pattern="[a-z]+"
|
||||
>
|
||||
|
||||
<datalist id="platforms">
|
||||
<option
|
||||
v-for="platformSlug in Object.keys(env.socials.urls)"
|
||||
:key="`platform-${platformSlug}`"
|
||||
:value="platformSlug"
|
||||
>{{ platformSlug }}</option>
|
||||
</datalist>
|
||||
|
||||
<input
|
||||
v-model="handle"
|
||||
class="input"
|
||||
placeholder="Handle"
|
||||
pattern="[\w-]+"
|
||||
:disabled="!!url"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="new-section">
|
||||
OR<input
|
||||
v-model="url"
|
||||
class="input"
|
||||
placeholder="Website URL"
|
||||
:disabled="!!handle"
|
||||
>
|
||||
|
||||
<button
|
||||
class="button"
|
||||
>Add</button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
</VDropdown>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
watch,
|
||||
inject,
|
||||
} from 'vue';
|
||||
|
||||
import formatTemplate from 'template-format';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const { env } = pageContext;
|
||||
|
||||
const props = defineProps({
|
||||
edits: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
editing: {
|
||||
type: Set,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['socials']);
|
||||
const socials = ref(props.edits.socials);
|
||||
|
||||
const platform = ref('');
|
||||
const handle = ref('');
|
||||
const url = ref('');
|
||||
|
||||
watch(socials, () => emit('socials', socials));
|
||||
|
||||
const iconMap = {
|
||||
twitter: 'twitter-x',
|
||||
};
|
||||
|
||||
function addSocial() {
|
||||
if (!handle.value && !url.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (handle.value && !platform.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
socials.value = socials.value.concat({
|
||||
platform: platform.value || null,
|
||||
handle: handle.value || null,
|
||||
url: url.value || null,
|
||||
});
|
||||
|
||||
emit('socials', socials.value);
|
||||
|
||||
platform.value = '';
|
||||
handle.value = '';
|
||||
url.value = '';
|
||||
}
|
||||
|
||||
function getUrl(social) {
|
||||
if (social.url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (env.socials.urls[social.platform]) {
|
||||
return formatTemplate(env.socials.urls[social.platform], { handle: social.handle });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.list {
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
|
||||
&.disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item {
|
||||
.icon-social {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
|
||||
.icon-generic {
|
||||
fill: var(--glass-strong-20);
|
||||
}
|
||||
|
||||
&.deleted {
|
||||
color: var(--glass);
|
||||
text-decoration: line-through;
|
||||
|
||||
.icon.icon-social {
|
||||
fill: var(--glass-weak-10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-item,
|
||||
.list-new {
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
border-radius: .25rem;
|
||||
box-shadow: 0 0 3px var(--shadow-weak-30);
|
||||
background: var(--background);
|
||||
|
||||
.link {
|
||||
padding: .25rem 0 .25rem .5rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.add,
|
||||
.remove {
|
||||
padding: 0 .3rem;
|
||||
margin-left: .5rem;
|
||||
border-radius: .25rem;
|
||||
|
||||
&:hover {
|
||||
fill: var(--text-light);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.add {
|
||||
fill: var(--success);
|
||||
|
||||
&:hover {
|
||||
background: var(--success);
|
||||
}
|
||||
}
|
||||
|
||||
.remove {
|
||||
fill: var(--error);
|
||||
|
||||
&:hover {
|
||||
background: var(--error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-new .add {
|
||||
padding: .25rem .5rem;
|
||||
background: var(--background);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.new {
|
||||
padding: .25rem;
|
||||
}
|
||||
|
||||
.new-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
padding: .25rem;
|
||||
|
||||
.input {
|
||||
flex-grow: 1;
|
||||
|
||||
&:disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
180
components/edit/tags.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<ul
|
||||
class="tags nolist"
|
||||
:class="{ disabled: !editing.has(item.key) }"
|
||||
>
|
||||
<li
|
||||
v-for="tag in [...item.value, ...newTags]"
|
||||
:key="`tag-${tag.id}`"
|
||||
class="tag"
|
||||
:class="{ deleted: edits.tags && !edits.tags.some((tagId) => tagId === tag.id) }"
|
||||
>
|
||||
<span class="tag-name">{{ tag.name }}</span>
|
||||
|
||||
<Icon
|
||||
v-if="edits.tags && !edits.tags.some((tagId) => tagId === tag.id)"
|
||||
icon="checkmark"
|
||||
class="add"
|
||||
@click="emit('tags', edits.tags.concat(tag.id))"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-else
|
||||
icon="cross2"
|
||||
class="remove"
|
||||
@click="emit('tags', edits.tags.filter((tagId) => tagId !== tag.id))"
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="new">
|
||||
<TagSearch
|
||||
:disabled="!editing.has(item.key)"
|
||||
@tag="addTag"
|
||||
>
|
||||
<Icon
|
||||
icon="plus3"
|
||||
class="add"
|
||||
/>
|
||||
</TagSearch>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import events from '#/src/events.js';
|
||||
|
||||
import TagSearch from '#/components/tags/search.vue';
|
||||
|
||||
const newTags = ref([]);
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
scene: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
edits: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
editing: {
|
||||
type: Set,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['tags']);
|
||||
|
||||
function addTag(tag) {
|
||||
if (props.edits.tags.some((tagId) => tagId === tag.id)) {
|
||||
events.emit('feedback', {
|
||||
type: 'error',
|
||||
message: 'Tag already added',
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
newTags.value = newTags.value.concat(tag);
|
||||
|
||||
emit('tags', props.edits.tags.concat(tag.id));
|
||||
}
|
||||
|
||||
watch(() => props.scene, () => { newTags.value = []; });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .35rem .25rem;
|
||||
|
||||
&.disabled {
|
||||
.tag {
|
||||
background: var(--glass-weak-50);
|
||||
color: var(--glass-strong-10);
|
||||
|
||||
.remove,
|
||||
.add {
|
||||
fill: var(--shadow-weak-30);
|
||||
background: var(--shadow-weak-50);
|
||||
}
|
||||
}
|
||||
|
||||
.new .icon {
|
||||
background: var(--shadow-weak-40);
|
||||
}
|
||||
}
|
||||
|
||||
.new {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: .25rem;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 3px var(--shadow-weak-20);
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 100%;
|
||||
padding: 0 .5rem;
|
||||
background: var(--success);
|
||||
fill: var(--text-light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
border-radius: .25rem;
|
||||
background: var(--background);
|
||||
box-shadow: 0 0 3px var(--shadow-weak-30);
|
||||
|
||||
&.deleted {
|
||||
color: var(--glass);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.tag,
|
||||
.new {
|
||||
.remove,
|
||||
.add {
|
||||
height: auto;
|
||||
padding: .25rem .3rem;
|
||||
border-radius: .25rem;
|
||||
fill: var(--highlight-strong-10);
|
||||
|
||||
&:hover {
|
||||
fill: var(--text-light);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.remove {
|
||||
fill: var(--error);
|
||||
|
||||
&:hover {
|
||||
background: var(--error);
|
||||
}
|
||||
}
|
||||
|
||||
.add {
|
||||
fill: var(--success);
|
||||
|
||||
&:hover {
|
||||
background: var(--success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag-name {
|
||||
padding: .25rem .5rem;
|
||||
}
|
||||
</style>
|
||||
@@ -5,12 +5,20 @@
|
||||
>
|
||||
<img
|
||||
v-if="entity.hasLogo"
|
||||
:src="entity.type === 'network' || entity.isIndependent ? `/logos/${entity.slug}/thumbs/network.png` : `/logos/${entity.parent?.slug}/thumbs/${entity.slug}.png`"
|
||||
:src="entity.type === 'network' || entity.isIndependent || !entity.parent
|
||||
? `/logos/${entity.slug}/thumbs/network.png`
|
||||
: `/logos/${entity.parent.slug}/thumbs/${entity.slug}.png`"
|
||||
:alt="entity.name"
|
||||
loading="lazy"
|
||||
class="logo"
|
||||
>
|
||||
|
||||
<span v-else>{{ entity.name }}</span>
|
||||
|
||||
<Icon
|
||||
v-if="showNetworkSymbol && entity.type === 'network'"
|
||||
icon="device_hub"
|
||||
/>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
@@ -20,6 +28,10 @@ defineProps({
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
showNetworkSymbol: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -33,10 +45,24 @@ defineProps({
|
||||
box-sizing: border-box;
|
||||
padding: 1rem;
|
||||
border-radius: .5rem;
|
||||
position: relative;
|
||||
background: var(--shadow-strong-30);
|
||||
text-align: center;
|
||||
line-height: 1.25;
|
||||
color: var(--text-light);
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
top: -.25rem;
|
||||
right: -.25rem;
|
||||
padding: .4rem .55rem .25rem .25rem;
|
||||
border-radius: .25rem;
|
||||
background: var(--highlight-weak-30);
|
||||
fill: var(--text-light);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 3px var(--shadow);
|
||||
|
||||
@@ -6,12 +6,16 @@
|
||||
>Some actors may not be listed, apply a filter or search to narrow down results.</div>
|
||||
|
||||
<div class="filters-sort">
|
||||
<input
|
||||
v-model="search"
|
||||
type="search"
|
||||
:placeholder="`Filter ${availableActors.length} actors`"
|
||||
class="input input-inline filters-search"
|
||||
>
|
||||
<label class="filter-search">
|
||||
<input
|
||||
v-model="search"
|
||||
type="search"
|
||||
:placeholder="`Filter ${availableActors.length} actors`"
|
||||
class="input input-inline filters-search"
|
||||
>
|
||||
|
||||
<Icon icon="search" />
|
||||
</label>
|
||||
|
||||
<div
|
||||
class="filter-sort noselect"
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
<template>
|
||||
<div class="filter channels-container">
|
||||
<div class="filters-sort">
|
||||
<input
|
||||
v-model="search"
|
||||
type="search"
|
||||
:placeholder="`Filter ${channels.length} channels`"
|
||||
class="input input-inline filters-search"
|
||||
>
|
||||
<label class="filter-search">
|
||||
<input
|
||||
v-model="search"
|
||||
type="search"
|
||||
:placeholder="`Filter ${channels.length} channels`"
|
||||
class="input input-inline filters-search"
|
||||
>
|
||||
|
||||
<Icon icon="search" />
|
||||
</label>
|
||||
|
||||
<div
|
||||
v-show="order === 'name'"
|
||||
@@ -47,7 +51,7 @@
|
||||
:title="entity.name"
|
||||
>
|
||||
<img
|
||||
v-if="entity.isIndependent || entity.type === 'network'"
|
||||
v-if="entity.isIndependent || entity.type === 'network' || !entity.parent"
|
||||
:src="`/logos/${entity.slug}/favicon_dark.png`"
|
||||
class="favicon"
|
||||
>
|
||||
@@ -131,14 +135,14 @@ const entities = computed(() => {
|
||||
return acc;
|
||||
}
|
||||
|
||||
if (channel.parent && !acc[channel.parent.id] && channel.type === 'channel') {
|
||||
if (!acc[channel.id] && channel.parent && !acc[channel.parent.id] && (channel.type === 'channel' || channel.type === 'studio')) {
|
||||
acc[channel.parent.id] = {
|
||||
...channel.parent,
|
||||
children: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (channel.parent && channel.type === 'channel') {
|
||||
if (!acc[channel.id] && channel.parent && (channel.type === 'channel' || channel.type === 'studio')) {
|
||||
acc[channel.parent.id].children.push(channel);
|
||||
}
|
||||
|
||||
|
||||