It's not pretty but it works
This commit is contained in:
parent
c4cf867689
commit
4e507a01c6
16 changed files with 323 additions and 560 deletions
258
pnpm-lock.yaml
258
pnpm-lock.yaml
|
@ -61,8 +61,8 @@ importers:
|
|||
specifier: ^5.0.5
|
||||
version: 5.0.5
|
||||
svelte-check:
|
||||
specifier: ^3.8.6
|
||||
version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47))(postcss@8.4.47)(svelte@5.0.5)
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.5(picomatch@2.3.1)(svelte@5.0.5)(typescript@5.6.3)
|
||||
svelte-fa:
|
||||
specifier: ^4.0.3
|
||||
version: 4.0.3(svelte@5.0.5)
|
||||
|
@ -486,9 +486,6 @@ packages:
|
|||
'@types/estree@1.0.6':
|
||||
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
|
||||
|
||||
'@types/pug@2.0.10':
|
||||
resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==}
|
||||
|
||||
acorn-typescript@1.4.13:
|
||||
resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==}
|
||||
peerDependencies:
|
||||
|
@ -547,9 +544,6 @@ packages:
|
|||
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
brace-expansion@1.1.11:
|
||||
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
|
||||
|
||||
brace-expansion@2.0.1:
|
||||
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
|
||||
|
||||
|
@ -562,10 +556,6 @@ packages:
|
|||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
|
||||
buffer-crc32@1.0.0:
|
||||
resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
camelcase-css@2.0.1:
|
||||
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
@ -577,6 +567,10 @@ packages:
|
|||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
||||
chokidar@4.0.1:
|
||||
resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==}
|
||||
engines: {node: '>= 14.16.0'}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
|
@ -588,9 +582,6 @@ packages:
|
|||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
cookie@0.6.0:
|
||||
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
@ -617,10 +608,6 @@ packages:
|
|||
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
detect-indent@6.1.0:
|
||||
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
devalue@5.1.1:
|
||||
resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==}
|
||||
|
||||
|
@ -642,9 +629,6 @@ packages:
|
|||
emoji-regex@9.2.2:
|
||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
||||
|
||||
es6-promise@3.3.1:
|
||||
resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==}
|
||||
|
||||
esbuild@0.21.5:
|
||||
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -667,6 +651,14 @@ packages:
|
|||
fastq@1.17.1:
|
||||
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
|
||||
|
||||
fdir@6.4.2:
|
||||
resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==}
|
||||
peerDependencies:
|
||||
picomatch: ^3 || ^4
|
||||
peerDependenciesMeta:
|
||||
picomatch:
|
||||
optional: true
|
||||
|
||||
fill-range@7.1.1:
|
||||
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -678,9 +670,6 @@ packages:
|
|||
fraction.js@4.3.7:
|
||||
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
|
||||
|
||||
fs.realpath@1.0.0:
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||
|
||||
fsevents@2.3.3:
|
||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
|
@ -701,19 +690,12 @@ packages:
|
|||
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
|
||||
hasBin: true
|
||||
|
||||
glob@7.2.3:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
|
||||
globalyzer@0.1.0:
|
||||
resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==}
|
||||
|
||||
globrex@0.1.2:
|
||||
resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
|
||||
|
||||
graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
|
||||
hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
@ -721,13 +703,6 @@ packages:
|
|||
import-meta-resolve@4.1.0:
|
||||
resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==}
|
||||
|
||||
inflight@1.0.6:
|
||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
|
||||
|
||||
inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
|
||||
is-binary-path@2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -797,28 +772,14 @@ packages:
|
|||
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
min-indent@1.0.1:
|
||||
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
minimatch@3.1.2:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||
|
||||
minimatch@9.0.5:
|
||||
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
minimist@1.2.8:
|
||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||
|
||||
minipass@7.1.2:
|
||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
mkdirp@0.5.6:
|
||||
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
||||
hasBin: true
|
||||
|
||||
mri@1.2.0:
|
||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -857,16 +818,9 @@ packages:
|
|||
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
|
||||
package-json-from-dist@1.0.1:
|
||||
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
|
||||
|
||||
path-is-absolute@1.0.1:
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
path-key@3.1.1:
|
||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -959,6 +913,10 @@ packages:
|
|||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
||||
readdirp@4.0.2:
|
||||
resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
|
||||
engines: {node: '>= 14.16.0'}
|
||||
|
||||
resolve@1.22.8:
|
||||
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
|
||||
hasBin: true
|
||||
|
@ -967,11 +925,6 @@ packages:
|
|||
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
|
||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
|
||||
rimraf@2.7.1:
|
||||
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
|
||||
deprecated: Rimraf versions prior to v4 are no longer supported
|
||||
hasBin: true
|
||||
|
||||
rollup@4.24.0:
|
||||
resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
|
@ -984,9 +937,6 @@ packages:
|
|||
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
sander@0.5.1:
|
||||
resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==}
|
||||
|
||||
set-cookie-parser@2.7.1:
|
||||
resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
|
||||
|
||||
|
@ -1006,10 +956,6 @@ packages:
|
|||
resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
sorcery@0.11.1:
|
||||
resolution: {integrity: sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==}
|
||||
hasBin: true
|
||||
|
||||
source-map-js@1.2.1:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -1030,10 +976,6 @@ packages:
|
|||
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-indent@3.0.0:
|
||||
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
sucrase@3.35.0:
|
||||
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
@ -1043,54 +985,19 @@ packages:
|
|||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
svelte-check@3.8.6:
|
||||
resolution: {integrity: sha512-ij0u4Lw/sOTREP13BdWZjiXD/BlHE6/e2e34XzmVmsp5IN4kVa3PWP65NM32JAgwjZlwBg/+JtiNV1MM8khu0Q==}
|
||||
svelte-check@4.0.5:
|
||||
resolution: {integrity: sha512-icBTBZ3ibBaywbXUat3cK6hB5Du+Kq9Z8CRuyLmm64XIe2/r+lQcbuBx/IQgsbrC+kT2jQ0weVpZSSRIPwB6jQ==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0
|
||||
svelte: ^4.0.0 || ^5.0.0-next.0
|
||||
typescript: '>=5.0.0'
|
||||
|
||||
svelte-fa@4.0.3:
|
||||
resolution: {integrity: sha512-saZ8yACM0k9Aexey+2NXU1W0MBosU5lBsRgqFCJKM+Taw7d0HyimPaPAjmvY/Xkyi3UwEYL/Sdu1IZJv/p0Flw==}
|
||||
peerDependencies:
|
||||
svelte: ^4.0.0 || ^5.0.0
|
||||
|
||||
svelte-preprocess@5.1.4:
|
||||
resolution: {integrity: sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==}
|
||||
engines: {node: '>= 16.0.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.10.2
|
||||
coffeescript: ^2.5.1
|
||||
less: ^3.11.3 || ^4.0.0
|
||||
postcss: ^7 || ^8
|
||||
postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0
|
||||
pug: ^3.0.0
|
||||
sass: ^1.26.8
|
||||
stylus: ^0.55.0
|
||||
sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0
|
||||
svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0
|
||||
typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0'
|
||||
peerDependenciesMeta:
|
||||
'@babel/core':
|
||||
optional: true
|
||||
coffeescript:
|
||||
optional: true
|
||||
less:
|
||||
optional: true
|
||||
postcss:
|
||||
optional: true
|
||||
postcss-load-config:
|
||||
optional: true
|
||||
pug:
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
stylus:
|
||||
optional: true
|
||||
sugarss:
|
||||
optional: true
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
svelte@5.0.5:
|
||||
resolution: {integrity: sha512-f4WBlP5g8W6pEoDfx741lewMlemy+LIGpEqjGPWqnHVP92wqlQXl87U5O5Bi2tkSUrO95OxOoqwU8qlqiHmFKA==}
|
||||
engines: {node: '>=18'}
|
||||
|
@ -1187,9 +1094,6 @@ packages:
|
|||
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
yaml@2.6.0:
|
||||
resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==}
|
||||
engines: {node: '>= 14'}
|
||||
|
@ -1496,8 +1400,6 @@ snapshots:
|
|||
|
||||
'@types/estree@1.0.6': {}
|
||||
|
||||
'@types/pug@2.0.10': {}
|
||||
|
||||
acorn-typescript@1.4.13(acorn@8.13.0):
|
||||
dependencies:
|
||||
acorn: 8.13.0
|
||||
|
@ -1541,11 +1443,6 @@ snapshots:
|
|||
|
||||
binary-extensions@2.3.0: {}
|
||||
|
||||
brace-expansion@1.1.11:
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
concat-map: 0.0.1
|
||||
|
||||
brace-expansion@2.0.1:
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
|
@ -1561,8 +1458,6 @@ snapshots:
|
|||
node-releases: 2.0.18
|
||||
update-browserslist-db: 1.1.1(browserslist@4.24.2)
|
||||
|
||||
buffer-crc32@1.0.0: {}
|
||||
|
||||
camelcase-css@2.0.1: {}
|
||||
|
||||
caniuse-lite@1.0.30001669: {}
|
||||
|
@ -1579,6 +1474,10 @@ snapshots:
|
|||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
chokidar@4.0.1:
|
||||
dependencies:
|
||||
readdirp: 4.0.2
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
|
@ -1587,8 +1486,6 @@ snapshots:
|
|||
|
||||
commander@4.1.1: {}
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
||||
cookie@0.6.0: {}
|
||||
|
||||
cross-spawn@7.0.3:
|
||||
|
@ -1605,8 +1502,6 @@ snapshots:
|
|||
|
||||
deepmerge@4.3.1: {}
|
||||
|
||||
detect-indent@6.1.0: {}
|
||||
|
||||
devalue@5.1.1: {}
|
||||
|
||||
didyoumean@1.2.2: {}
|
||||
|
@ -1621,8 +1516,6 @@ snapshots:
|
|||
|
||||
emoji-regex@9.2.2: {}
|
||||
|
||||
es6-promise@3.3.1: {}
|
||||
|
||||
esbuild@0.21.5:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.21.5
|
||||
|
@ -1670,6 +1563,10 @@ snapshots:
|
|||
dependencies:
|
||||
reusify: 1.0.4
|
||||
|
||||
fdir@6.4.2(picomatch@2.3.1):
|
||||
optionalDependencies:
|
||||
picomatch: 2.3.1
|
||||
|
||||
fill-range@7.1.1:
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
|
@ -1681,8 +1578,6 @@ snapshots:
|
|||
|
||||
fraction.js@4.3.7: {}
|
||||
|
||||
fs.realpath@1.0.0: {}
|
||||
|
||||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
|
@ -1705,34 +1600,16 @@ snapshots:
|
|||
package-json-from-dist: 1.0.1
|
||||
path-scurry: 1.11.1
|
||||
|
||||
glob@7.2.3:
|
||||
dependencies:
|
||||
fs.realpath: 1.0.0
|
||||
inflight: 1.0.6
|
||||
inherits: 2.0.4
|
||||
minimatch: 3.1.2
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
|
||||
globalyzer@0.1.0: {}
|
||||
|
||||
globrex@0.1.2: {}
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
|
||||
hasown@2.0.2:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
import-meta-resolve@4.1.0: {}
|
||||
|
||||
inflight@1.0.6:
|
||||
dependencies:
|
||||
once: 1.4.0
|
||||
wrappy: 1.0.2
|
||||
|
||||
inherits@2.0.4: {}
|
||||
|
||||
is-binary-path@2.1.0:
|
||||
dependencies:
|
||||
binary-extensions: 2.3.0
|
||||
|
@ -1788,24 +1665,12 @@ snapshots:
|
|||
braces: 3.0.3
|
||||
picomatch: 2.3.1
|
||||
|
||||
min-indent@1.0.1: {}
|
||||
|
||||
minimatch@3.1.2:
|
||||
dependencies:
|
||||
brace-expansion: 1.1.11
|
||||
|
||||
minimatch@9.0.5:
|
||||
dependencies:
|
||||
brace-expansion: 2.0.1
|
||||
|
||||
minimist@1.2.8: {}
|
||||
|
||||
minipass@7.1.2: {}
|
||||
|
||||
mkdirp@0.5.6:
|
||||
dependencies:
|
||||
minimist: 1.2.8
|
||||
|
||||
mri@1.2.0: {}
|
||||
|
||||
mrmime@2.0.0: {}
|
||||
|
@ -1830,14 +1695,8 @@ snapshots:
|
|||
|
||||
object-hash@3.0.0: {}
|
||||
|
||||
once@1.4.0:
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
|
||||
package-json-from-dist@1.0.1: {}
|
||||
|
||||
path-is-absolute@1.0.1: {}
|
||||
|
||||
path-key@3.1.1: {}
|
||||
|
||||
path-parse@1.0.7: {}
|
||||
|
@ -1910,6 +1769,8 @@ snapshots:
|
|||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
|
||||
readdirp@4.0.2: {}
|
||||
|
||||
resolve@1.22.8:
|
||||
dependencies:
|
||||
is-core-module: 2.15.1
|
||||
|
@ -1918,10 +1779,6 @@ snapshots:
|
|||
|
||||
reusify@1.0.4: {}
|
||||
|
||||
rimraf@2.7.1:
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
|
||||
rollup@4.24.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.6
|
||||
|
@ -1952,13 +1809,6 @@ snapshots:
|
|||
dependencies:
|
||||
mri: 1.2.0
|
||||
|
||||
sander@0.5.1:
|
||||
dependencies:
|
||||
es6-promise: 3.3.1
|
||||
graceful-fs: 4.2.11
|
||||
mkdirp: 0.5.6
|
||||
rimraf: 2.7.1
|
||||
|
||||
set-cookie-parser@2.7.1: {}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
|
@ -1975,13 +1825,6 @@ snapshots:
|
|||
mrmime: 2.0.0
|
||||
totalist: 3.0.1
|
||||
|
||||
sorcery@0.11.1:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
buffer-crc32: 1.0.0
|
||||
minimist: 1.2.8
|
||||
sander: 0.5.1
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
|
@ -2004,10 +1847,6 @@ snapshots:
|
|||
dependencies:
|
||||
ansi-regex: 6.1.0
|
||||
|
||||
strip-indent@3.0.0:
|
||||
dependencies:
|
||||
min-indent: 1.0.1
|
||||
|
||||
sucrase@3.35.0:
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.5
|
||||
|
@ -2020,43 +1859,22 @@ snapshots:
|
|||
|
||||
supports-preserve-symlinks-flag@1.0.0: {}
|
||||
|
||||
svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47))(postcss@8.4.47)(svelte@5.0.5):
|
||||
svelte-check@4.0.5(picomatch@2.3.1)(svelte@5.0.5)(typescript@5.6.3):
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
chokidar: 3.6.0
|
||||
chokidar: 4.0.1
|
||||
fdir: 6.4.2(picomatch@2.3.1)
|
||||
picocolors: 1.1.1
|
||||
sade: 1.8.1
|
||||
svelte: 5.0.5
|
||||
svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47))(postcss@8.4.47)(svelte@5.0.5)(typescript@5.6.3)
|
||||
typescript: 5.6.3
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- coffeescript
|
||||
- less
|
||||
- postcss
|
||||
- postcss-load-config
|
||||
- pug
|
||||
- sass
|
||||
- stylus
|
||||
- sugarss
|
||||
- picomatch
|
||||
|
||||
svelte-fa@4.0.3(svelte@5.0.5):
|
||||
dependencies:
|
||||
svelte: 5.0.5
|
||||
|
||||
svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47))(postcss@8.4.47)(svelte@5.0.5)(typescript@5.6.3):
|
||||
dependencies:
|
||||
'@types/pug': 2.0.10
|
||||
detect-indent: 6.1.0
|
||||
magic-string: 0.30.12
|
||||
sorcery: 0.11.1
|
||||
strip-indent: 3.0.0
|
||||
svelte: 5.0.5
|
||||
optionalDependencies:
|
||||
postcss: 8.4.47
|
||||
postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.47)
|
||||
typescript: 5.6.3
|
||||
|
||||
svelte@5.0.5:
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.3.0
|
||||
|
@ -2159,8 +1977,6 @@ snapshots:
|
|||
string-width: 5.1.2
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
wrappy@1.0.2: {}
|
||||
|
||||
yaml@2.6.0: {}
|
||||
|
||||
zimmerframe@1.1.2: {}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"build": {
|
||||
"beforeDevCommand": "pnpm dev",
|
||||
"beforeBuildCommand": "pnpm build",
|
||||
"frontendDist": "../dist",
|
||||
"frontendDist": "../build",
|
||||
"devUrl": "http://localhost:1420"
|
||||
},
|
||||
"bundle": {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { RangeSlider, Tab, TabGroup, InputChip, SlideToggle } from '@skeletonlabs/skeleton';
|
||||
import { imageGridColumns, postGridPreviewQuality, blacklist, limitImageHeight } from '$lib/settings';
|
||||
import useSettings from '$lib/useSettings.svelte.js';
|
||||
const settings = useSettings();
|
||||
|
||||
let tabPos = $state(0);
|
||||
let showApikey = $state(false);
|
||||
|
@ -8,32 +9,31 @@
|
|||
</script>
|
||||
<div class="flex flex-col">
|
||||
<h2 class="h2 mb-2 text-dark-token">Settings</h2>
|
||||
<TabGroup>
|
||||
<!--<TabGroup>
|
||||
<Tab class="text-dark-token" bind:group={tabPos} name="tab1" value={0}>Display</Tab>
|
||||
<Tab class="text-dark-token" bind:group={tabPos} name="tab2" value={1}>API</Tab>
|
||||
<Tab class="text-dark-token" bind:group={tabPos} name="tab3" value={2}>User</Tab>
|
||||
<Tab class="text-dark-token" bind:group={tabPos} name="tab4" value={3}>Chats</Tab>
|
||||
|
||||
{#snippet panel()}
|
||||
|
||||
{#if tabPos === 0}
|
||||
<div class="flex flex-col gap-3">
|
||||
<h3 class="h3 text-dark-token font-bold">Image</h3>
|
||||
<SlideToggle name="image-limit-height" bind:checked={$limitImageHeight}><span class="text-dark-token">Limit image height</span></SlideToggle>
|
||||
<SlideToggle name="image-limit-height" bind:checked={settings.limitImageHeight}><span class="text-dark-token">Limit image height</span></SlideToggle>
|
||||
|
||||
<h3 class="h3 text-dark-token font-bold">Grid</h3>
|
||||
<div class="basis-1/2">
|
||||
<RangeSlider accent="text-dark-token" name="grid-columns" min={1} max={12} bind:value={$imageGridColumns} ticked={true}>
|
||||
<RangeSlider accent="text-dark-token" name="grid-columns" min={1} max={12} bind:value={settings.imageGridColumns} ticked={true}>
|
||||
<div class="flex flex-grow justify-between items-center dark">
|
||||
<div class="text-dark-token font-bold mb-1">Grid Columns</div>
|
||||
<div class="text-xs text-dark-token">{$imageGridColumns} / {12}</div>
|
||||
<div class="text-xs text-dark-token">{settings.imageGridColumns} / {12}</div>
|
||||
</div>
|
||||
</RangeSlider>
|
||||
</div>
|
||||
<div class="basis-1/2">
|
||||
<label class="label">
|
||||
<span class="text-dark-token font-bold">Preview type</span>
|
||||
<select class="select" bind:value={$postGridPreviewQuality}>
|
||||
<select class="select" bind:value={settings.postGridPreviewQuality}>
|
||||
<option value="preview">Preview</option>
|
||||
<option value="sample">Sample</option>
|
||||
</select>
|
||||
|
@ -71,7 +71,7 @@
|
|||
<div class="flex flex-col gap-3">
|
||||
<div class="">
|
||||
<p class="text-dark-token font-bold">Blacklist</p>
|
||||
<InputChip name="blacklist" label="Blacklist" bind:value={$blacklist} />
|
||||
<InputChip name="blacklist" label="Blacklist" bind:value={settings.blacklist} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -80,11 +80,10 @@
|
|||
<div class="flex flex-col gap-3">
|
||||
<div class="">
|
||||
<p class="text-dark-token font-bold">Chats</p>
|
||||
<InputChip name="blacklist" label="Blacklist" bind:value={$blacklist} />
|
||||
<InputChip name="blacklist" label="Blacklist" bind:value={settings.blacklist} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{/snippet}
|
||||
</TabGroup>
|
||||
</TabGroup>-->
|
||||
</div>
|
|
@ -1,18 +1,15 @@
|
|||
<script>
|
||||
import {faArrowLeft} from '@fortawesome/free-solid-svg-icons';
|
||||
import {Fa} from 'svelte-fa';
|
||||
import {AppRailAnchor} from '@skeletonlabs/skeleton';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Props
|
||||
* @property {number} [popCount]
|
||||
*/
|
||||
import {onMount} from "svelte";
|
||||
|
||||
/** @type {Props} */
|
||||
let { popCount = 1 } = $props();
|
||||
let href = $state();
|
||||
let pathnameParts = window.location.pathname.split('/');
|
||||
let pathnameParts = $state(null);
|
||||
|
||||
onMount(() => {
|
||||
pathnameParts = window.location.pathname.split('/')
|
||||
for(let i = 0; i < popCount; i++) {
|
||||
pathnameParts.pop();
|
||||
}
|
||||
|
@ -28,12 +25,13 @@ switch (pathnameParts.length) {
|
|||
href = '/' + pathnameParts.join('/')
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<AppRailAnchor {href} title="Back">
|
||||
<a {href} class="h-full aspect-square">
|
||||
<div class="flex flex-col gap-2 place-content-center">
|
||||
<Fa size={'2x'} icon={faArrowLeft} />
|
||||
<p>Back</p>
|
||||
</div>
|
||||
</AppRailAnchor>
|
||||
</a>
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
<script>
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
import useSettings from '$lib/useSettings.svelte.js';
|
||||
import {loading} from "$lib/stores.js";
|
||||
|
||||
import { showSearch, loading } from '$lib/stores';
|
||||
import { lastSearch } from '$lib/settings';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
let searchValue = $state($lastSearch);
|
||||
const settings = useSettings();
|
||||
let searchString = $state('');
|
||||
const {onsubmit = null} = $props();
|
||||
$effect(() => {
|
||||
searchString = settings.lastSearch
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if $showSearch}
|
||||
<form class="flex flex-row gap-2"
|
||||
onsubmit={preventDefault(() => {
|
||||
$loading = true;
|
||||
goto('/')
|
||||
lastSearch.set(searchValue);
|
||||
})}>
|
||||
<input class="input py-1 px-2 w-96" type="text" placeholder="Search" bind:value={searchValue} />
|
||||
onsubmit={(e) => {
|
||||
e.preventDefault();
|
||||
settings.lastSearch = searchString;
|
||||
loading.set(true);
|
||||
onsubmit?.(searchString, true);
|
||||
}}>
|
||||
<input class="input py-1 px-2 w-96" type="text" placeholder="Search" bind:value={searchString} />
|
||||
<button class="btn btn-md variant-filled" type="submit">Submit</button>
|
||||
</form>
|
||||
{/if}
|
13
src/lib/components/Header.svelte
Normal file
13
src/lib/components/Header.svelte
Normal file
|
@ -0,0 +1,13 @@
|
|||
<script>
|
||||
import {BackAppRailAnchor, GlobalSearch} from "$lib/components";
|
||||
let {onsubmit = null, back = null} = $props();
|
||||
</script>
|
||||
|
||||
<header class="top-0 fixed flex">
|
||||
{#if back}
|
||||
<BackAppRailAnchor popCount={back} />
|
||||
{/if}
|
||||
<GlobalSearch onsubmit={(val = '', explicitRefresh = false) => {
|
||||
onsubmit?.(val, explicitRefresh);
|
||||
}} />
|
||||
</header>
|
|
@ -1,27 +1,25 @@
|
|||
<script>
|
||||
import { showSearch, loading } from '$lib/stores';
|
||||
import { postGridPreviewQuality, imageGridColumns } from '$lib/settings';
|
||||
import useSettings from "$lib/useSettings.svelte.js";
|
||||
import { loading } from "$lib/stores.js";
|
||||
|
||||
let { posts = [] } = $props();
|
||||
const settings = useSettings();
|
||||
</script>
|
||||
|
||||
<div class="grid gap-3" style={`grid-template-columns: repeat(${$imageGridColumns}, minmax(0, 1fr))`}>
|
||||
<div class="grid gap-3" style={`grid-template-columns: repeat(${settings.imageGridColumns}, minmax(0, 1fr))`}>
|
||||
{#each posts as post}
|
||||
<a href={`/posts/${post.id}`} class="card p-3 flex flex-col justify-end items-center" onclick={() => {
|
||||
$loading = true;
|
||||
$showSearch = false
|
||||
loading.set(true);
|
||||
}}>
|
||||
<header class="card-header p-0"></header>
|
||||
<section class="flex flex-col">
|
||||
<img src={post[$postGridPreviewQuality].url}
|
||||
<img src={post[settings.postGridPreviewQuality].url}
|
||||
loading="lazy"
|
||||
alt={`Post ${post.id}`} />
|
||||
<div class="bg-black px-2 py-1">
|
||||
<p class="text-center text-dark-token">{post.id} {post.file.ext} {post.rating}</p>
|
||||
</div>
|
||||
</section>
|
||||
<footer >
|
||||
</footer>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { limitImageHeight } from '$lib/settings';
|
||||
import useSettings from '$lib/useSettings.svelte.js';
|
||||
const settings = useSettings();
|
||||
|
||||
/**
|
||||
* @typedef {Object} Props
|
||||
|
@ -11,13 +12,13 @@
|
|||
</script>
|
||||
|
||||
{#if post?.preview?.has}
|
||||
<img class:max-h-dvh={$limitImageHeight} src={post.preview.url} alt={`Post ${post.id}`} />
|
||||
<img class:max-h-dvh={settings.limitImageHeight} src={post.preview.url} alt={`Post ${post.id}`} />
|
||||
{:else}
|
||||
{#if ['webm', 'mp4'].includes(post.file.ext)}
|
||||
<video class:max-h-dvh={$limitImageHeight} controls playsinline>
|
||||
<video class:max-h-dvh={settings.limitImageHeight} controls playsinline>
|
||||
<source src={post.file.url} />
|
||||
</video>
|
||||
{:else}
|
||||
<img class:max-h-dvh={$limitImageHeight} src={post.file.url} alt={`Post ${post.id}`} />
|
||||
<img class:max-h-dvh={settings.limitImageHeight} src={post.file.url} alt={`Post ${post.id}`} />
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
@ -3,7 +3,7 @@ import BackAppRailAnchor from './BackAppRailAnchor.svelte';
|
|||
import GlobalSearch from './GlobalSearch.svelte';
|
||||
import ImageGrid from './ImageGrid.svelte';
|
||||
import PostMedia from './PostMedia.svelte';
|
||||
import SearchAppRailAnchor from './SearchAppRailAnchor.svelte';
|
||||
import Header from './Header.svelte';
|
||||
|
||||
export {
|
||||
AppSettings,
|
||||
|
@ -11,5 +11,5 @@ export {
|
|||
GlobalSearch,
|
||||
ImageGrid,
|
||||
PostMedia,
|
||||
SearchAppRailAnchor
|
||||
Header,
|
||||
}
|
|
@ -2,4 +2,3 @@ import { writable } from 'svelte/store';
|
|||
|
||||
export const postSearchResults = writable(null);
|
||||
export const loading = writable(false);
|
||||
export const showSearch = writable(true);
|
|
@ -1,8 +0,0 @@
|
|||
function useLoading() {
|
||||
let loading = $state(false);
|
||||
return {
|
||||
get loading() {return loading},
|
||||
setLoading: (val) => {loading = val},
|
||||
toggleLoading: () => {loading = !loading}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
import {onMount} from "svelte";
|
||||
|
||||
function initFromLocalStorage(storageKey, initalValue = null) {
|
||||
return window.localStorage.getItem(storageKey) ?? initalValue;
|
||||
}
|
||||
|
||||
export default function useSettings() {
|
||||
let lastSearch = $state(null),
|
||||
imageGridColumns = $state(6),
|
||||
limitImageHeight = $state(false),
|
||||
postGridPreviewQuality = $state('preview'),
|
||||
blacklist = $state([
|
||||
'gore',
|
||||
'scat',
|
||||
'watersports',
|
||||
'young',
|
||||
'loli',
|
||||
'shota',
|
||||
]);
|
||||
|
||||
onMount(() => {
|
||||
lastSearch = localStorage.getItem('lastSearch') ?? lastSearch;
|
||||
imageGridColumns = localStorage.getItem('gridColumns') ?? imageGridColumns;
|
||||
limitImageHeight = localStorage.getItem('limitImageHeight') ?? limitImageHeight;
|
||||
postGridPreviewQuality = localStorage.getItem('gridPreviewQuality') ?? postGridPreviewQuality;
|
||||
blacklist = localStorage.getItem('blacklist') ?? blacklist;
|
||||
})
|
||||
|
||||
return {
|
||||
get lastSearch() {return lastSearch},
|
||||
get imageGridColumns() {return imageGridColumns},
|
||||
get postGridPreviewQuality() {return postGridPreviewQuality},
|
||||
get blacklist() {return blacklist},
|
||||
get limitImageHeight() {return limitImageHeight},
|
||||
set lastSearch(val) {
|
||||
lastSearch = val;
|
||||
localStorage.setItem('lastSearch', val);
|
||||
},
|
||||
set imageGridColumns(val) {
|
||||
imageGridColumns = val;
|
||||
localStorage.setItem('gridColumns', val);
|
||||
},
|
||||
set postGridPreviewQuality(val) {
|
||||
postGridPreviewQuality = val
|
||||
localStorage.setItem('gridPreviewQuality', val);
|
||||
},
|
||||
set blacklist(val) {
|
||||
blacklist = val
|
||||
localStorage.setItem('blacklist', val);
|
||||
},
|
||||
set limitImageHeight(val) {
|
||||
limitImageHeight = val
|
||||
localStorage.setItem('limitImageHeight', val);
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
<script>
|
||||
import '../app.pcss';
|
||||
import { Drawer, initializeStores, Modal, ProgressRadial, Toast } from '@skeletonlabs/skeleton';
|
||||
import { loading } from '$lib/stores';
|
||||
import { AppSettings } from '$lib/components';
|
||||
import { loading } from "$lib/stores.js";
|
||||
/**
|
||||
* @typedef {Object} Props
|
||||
* @property {import('svelte').Snippet} [children]
|
||||
|
@ -10,22 +8,11 @@
|
|||
|
||||
/** @type {Props} */
|
||||
let { children } = $props();
|
||||
|
||||
initializeStores();
|
||||
</script>
|
||||
|
||||
<div class="relative h-dvh">
|
||||
<Modal />
|
||||
<Toast />
|
||||
<Drawer bgDrawer="bg-surface-500/90" width="w-6/12" height="h-dvh" position="left">
|
||||
<div class="h-full p-4">
|
||||
<AppSettings />
|
||||
</div>
|
||||
</Drawer>
|
||||
{#if $loading}
|
||||
<div class="fixed bottom-3 right-3 w-8 h-8">
|
||||
<ProgressRadial width="w-8" height="h-8" stroke={120} strokeLinecap="butt" />
|
||||
</div>
|
||||
<p class="absolute top-0 left-0">Loading</p>
|
||||
{/if}
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
|
|
@ -1,84 +1,41 @@
|
|||
<script>
|
||||
import { Fa } from 'svelte-fa';
|
||||
import { GlobalSearch, ImageGrid, SearchAppRailAnchor} from '$lib/components';
|
||||
import { faGear } from '@fortawesome/free-solid-svg-icons';
|
||||
import { Header, ImageGrid } from '$lib/components';
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { lastSearch, blacklist } from '$lib/settings';
|
||||
import { postSearchResults, loading, showSearch} from '$lib/stores';
|
||||
import {
|
||||
AppBar,
|
||||
AppRail,
|
||||
AppRailAnchor,
|
||||
AppShell,
|
||||
getDrawerStore, getToastStore
|
||||
} from '@skeletonlabs/skeleton';
|
||||
import PostList from '$lib/PostList';
|
||||
import useSettings from "$lib/useSettings.svelte.js";
|
||||
import {onMount} from "svelte";
|
||||
import {loading, postSearchResults} from "$lib/stores.js";
|
||||
|
||||
const drawerStore = getDrawerStore();
|
||||
let initalSearch = true;
|
||||
const settings = useSettings();
|
||||
|
||||
function onSearch() {
|
||||
$loading = true;
|
||||
/*invoke('get_posts', { query: $lastSearch }).then((resPosts) => {
|
||||
postSearchResults.set(new PostList(resPosts).filterPosts($blacklist).getPosts());
|
||||
requestAnimationFrame(() => $loading = false);
|
||||
});*/
|
||||
function onSearch(val = '', explicitRefresh = false) {
|
||||
loading.set(true);
|
||||
invoke('get_posts', { query: val }).then((resPosts) => {
|
||||
postSearchResults.set(new PostList(resPosts).filterPosts(settings.blacklist).getPosts())
|
||||
loading.set(false)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
lastSearch.subscribe(() => {
|
||||
if (initalSearch) {
|
||||
initalSearch = false;
|
||||
if ($postSearchResults === null) onSearch();
|
||||
return
|
||||
onMount(() => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.has('search')) {
|
||||
onSearch(urlParams.get('search'), false);
|
||||
return;
|
||||
}
|
||||
|
||||
onSearch();
|
||||
if ($postSearchResults === null) {
|
||||
onSearch(settings.lastSearch, true);
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<AppShell>
|
||||
{#snippet pageHeader()}
|
||||
|
||||
{#if $showSearch}
|
||||
<AppBar>
|
||||
<GlobalSearch />
|
||||
</AppBar>
|
||||
{/if}
|
||||
|
||||
{/snippet}
|
||||
|
||||
{#snippet sidebarLeft()}
|
||||
|
||||
<div class="h-dvh">
|
||||
<AppRail>
|
||||
{#snippet lead()}
|
||||
|
||||
<SearchAppRailAnchor />
|
||||
|
||||
{/snippet}
|
||||
{#snippet trail()}
|
||||
|
||||
<AppRailAnchor on:click={() => drawerStore.open()}>
|
||||
<div class="flex flex-col gap-2 place-content-center">
|
||||
<Fa size={'2x'} icon={faGear} />
|
||||
<p>Settings</p>
|
||||
</div>
|
||||
</AppRailAnchor>
|
||||
|
||||
{/snippet}
|
||||
</AppRail>
|
||||
</div>
|
||||
|
||||
{/snippet}
|
||||
|
||||
{#snippet children()}
|
||||
|
||||
<div>
|
||||
<Header onsubmit={(val = '', explicitRefresh = false) => {onSearch(val, explicitRefresh);}}></Header>
|
||||
<main>
|
||||
<div class="overflow-scroll p-2">
|
||||
{#if $postSearchResults}
|
||||
<ImageGrid posts={$postSearchResults} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{/snippet}
|
||||
</AppShell>
|
||||
</main>
|
||||
</div>
|
|
@ -1,100 +1,35 @@
|
|||
<script>
|
||||
import {
|
||||
AppBar,
|
||||
AppRail,
|
||||
AppRailAnchor,
|
||||
AppShell,
|
||||
getDrawerStore,
|
||||
clipboard,
|
||||
getToastStore
|
||||
} from '@skeletonlabs/skeleton';
|
||||
import {faGear, faCopy, faStar, faCaretUp, faCaretDown, faHeart} from '@fortawesome/free-solid-svg-icons';
|
||||
import { faStar, faCaretUp, faCaretDown, faHeart } from '@fortawesome/free-solid-svg-icons';
|
||||
import { Fa } from 'svelte-fa';
|
||||
import { BackAppRailAnchor, GlobalSearch, PostMedia, SearchAppRailAnchor } from '$lib/components';
|
||||
import { PostMedia } from '$lib/components';
|
||||
import { onMount } from 'svelte';
|
||||
import { loading, showSearch } from '$lib/stores';
|
||||
import { TAG_TYPES } from '$lib/Tags';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import Header from "$lib/components/Header.svelte";
|
||||
import {goto} from "$app/navigation";
|
||||
import {loading} from "$lib/stores.js";
|
||||
|
||||
let { data } = $props();
|
||||
const drawerStore = getDrawerStore();
|
||||
const tagTypes = Object.entries(TAG_TYPES);
|
||||
const toastStore = getToastStore();
|
||||
|
||||
/** @type any|null */
|
||||
let post = $state(null);
|
||||
|
||||
onMount(async () => {
|
||||
$loading = true;
|
||||
const postRequest = await invoke('get_post', {postId: +data.postId});
|
||||
$loading = false;
|
||||
post = postRequest;
|
||||
loading.set(true);
|
||||
post = await invoke('get_post', {postId: +data.postId});
|
||||
loading.set(false);
|
||||
});
|
||||
</script>
|
||||
|
||||
<AppShell>
|
||||
{#snippet pageHeader()}
|
||||
|
||||
{#if $showSearch}
|
||||
<AppBar>
|
||||
<GlobalSearch />
|
||||
</AppBar>
|
||||
{/if}
|
||||
|
||||
{/snippet}
|
||||
|
||||
{#snippet sidebarRight()}
|
||||
|
||||
{#if post}
|
||||
<div class="p-2 h-dvh">
|
||||
{#each tagTypes as [name, label]}
|
||||
<div class="mb-2">
|
||||
<p class="font-bold">{label}</p>
|
||||
{#each post.tags[name] as tag}
|
||||
<p>{tag}</p>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{/snippet}
|
||||
|
||||
{#snippet sidebarLeft()}
|
||||
|
||||
<div class="h-dvh">
|
||||
<AppRail>
|
||||
{#snippet lead()}
|
||||
|
||||
<BackAppRailAnchor popCount={2} />
|
||||
<SearchAppRailAnchor />
|
||||
|
||||
{/snippet}
|
||||
{#snippet trail()}
|
||||
|
||||
{#if post}
|
||||
<AppRailAnchor>
|
||||
<button class="w-full flex flex-col gap-2 place-content-center place-items-center" onclick={() => toastStore.trigger({message: 'Copied link'})} use:clipboard={`https://e621.net/posts/${post.id}`}>
|
||||
<Fa size={'2x'} icon={faCopy} />
|
||||
Copy link
|
||||
</button>
|
||||
</AppRailAnchor>
|
||||
{/if}
|
||||
<AppRailAnchor on:click={() => drawerStore.open()}>
|
||||
<button class="w-full flex flex-col gap-2 place-content-center place-items-center">
|
||||
<Fa size={'2x'} icon={faGear} />
|
||||
Settings
|
||||
</button>
|
||||
</AppRailAnchor>
|
||||
|
||||
{/snippet}
|
||||
</AppRail>
|
||||
</div>
|
||||
|
||||
{/snippet}
|
||||
|
||||
{#snippet default()}
|
||||
<div class="grid [grid-template-areas:'main_main_aside''footer_footer_footer']">
|
||||
<Header back={2} onsubmit={(val = '') => {
|
||||
const queryParams = new URLSearchParams();
|
||||
queryParams.set('search', val);
|
||||
goto("/?" + queryParams.toString())
|
||||
}}></Header>
|
||||
|
||||
<main clasS="h-screen [grid-area-main]">
|
||||
<div class="container mx-auto flex flex-col items-center justify-center">
|
||||
{#if post}
|
||||
<div class="card mb-4 flex flex-col">
|
||||
|
@ -135,15 +70,26 @@
|
|||
<footer class="card-footer pt-4">
|
||||
<h3 class="font-bold mb-2" class:line-through={post.description === ''} >Description</h3>
|
||||
<p>{post.description}</p>
|
||||
<!-- <pre class="break-all">
|
||||
{JSON.stringify(post, null, 2)}
|
||||
</pre> -->
|
||||
</footer>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{/snippet}
|
||||
</AppShell>
|
||||
<aside class="[grid-area-aside]">
|
||||
{#if post}
|
||||
<div class="p-2 h-dvh">
|
||||
{#each tagTypes as [name, label]}
|
||||
<div class="mb-2">
|
||||
<p class="font-bold">{label}</p>
|
||||
{#each post.tags[name] as tag}
|
||||
<p>{tag}</p>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<style lang="postcss"></style>
|
||||
|
|
Loading…
Reference in a new issue