Compare commits
11 commits
1ed1e42225
...
4dd60b7365
Author | SHA1 | Date | |
---|---|---|---|
|
4dd60b7365 | ||
|
5c9a47c31e | ||
|
65a4c3441c | ||
|
77bc06545c | ||
|
11e64a2cc4 | ||
|
5433e4e119 | ||
|
c8dc32b884 | ||
|
1f29aee26e | ||
|
daae055f4d | ||
|
044f754d7e | ||
|
5ae2058c07 |
|
@ -244,6 +244,8 @@ And here I am. Building a Mastodon web client.
|
||||||
|
|
||||||
## Alternative web clients
|
## Alternative web clients
|
||||||
|
|
||||||
|
- Phanpy forks ↓
|
||||||
|
- [Agora](https://agorasocial.app/)
|
||||||
- [Pinafore](https://pinafore.social/) ([retired](https://nolanlawson.com/2023/01/09/retiring-pinafore/)) - forks ↓
|
- [Pinafore](https://pinafore.social/) ([retired](https://nolanlawson.com/2023/01/09/retiring-pinafore/)) - forks ↓
|
||||||
- [Semaphore](https://semaphore.social/)
|
- [Semaphore](https://semaphore.social/)
|
||||||
- [Enafore](https://enafore.social/)
|
- [Enafore](https://enafore.social/)
|
||||||
|
|
223
package-lock.json
generated
223
package-lock.json
generated
|
@ -10,7 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formatjs/intl-localematcher": "~0.5.4",
|
"@formatjs/intl-localematcher": "~0.5.4",
|
||||||
"@formatjs/intl-segmenter": "~11.5.5",
|
"@formatjs/intl-segmenter": "~11.5.5",
|
||||||
"@formkit/auto-animate": "~0.8.1",
|
"@formkit/auto-animate": "~0.8.2",
|
||||||
"@github/text-expander-element": "~2.6.1",
|
"@github/text-expander-element": "~2.6.1",
|
||||||
"@iconify-icons/mingcute": "~1.2.9",
|
"@iconify-icons/mingcute": "~1.2.9",
|
||||||
"@justinribeiro/lite-youtube": "~1.5.0",
|
"@justinribeiro/lite-youtube": "~1.5.0",
|
||||||
|
@ -21,18 +21,19 @@
|
||||||
"dayjs-twitter": "~0.5.0",
|
"dayjs-twitter": "~0.5.0",
|
||||||
"fast-blurhash": "~1.1.2",
|
"fast-blurhash": "~1.1.2",
|
||||||
"fast-equals": "~5.0.1",
|
"fast-equals": "~5.0.1",
|
||||||
|
"fuse.js": "~7.0.0",
|
||||||
"html-prettify": "^1.0.7",
|
"html-prettify": "^1.0.7",
|
||||||
"idb-keyval": "~6.2.1",
|
"idb-keyval": "~6.2.1",
|
||||||
"just-debounce-it": "~3.2.0",
|
"just-debounce-it": "~3.2.0",
|
||||||
"lz-string": "~1.5.0",
|
"lz-string": "~1.5.0",
|
||||||
"masto": "~6.7.0",
|
"masto": "~6.7.2",
|
||||||
"moize": "~6.1.6",
|
"moize": "~6.1.6",
|
||||||
"p-retry": "~6.2.0",
|
"p-retry": "~6.2.0",
|
||||||
"p-throttle": "~6.1.0",
|
"p-throttle": "~6.1.0",
|
||||||
"preact": "~10.20.1",
|
"preact": "~10.20.2",
|
||||||
"punycode": "~2.3.1",
|
"punycode": "~2.3.1",
|
||||||
"react-hotkeys-hook": "~4.5.0",
|
"react-hotkeys-hook": "~4.5.0",
|
||||||
"react-intersection-observer": "~9.8.1",
|
"react-intersection-observer": "~9.8.2",
|
||||||
"react-quick-pinch-zoom": "~5.1.0",
|
"react-quick-pinch-zoom": "~5.1.0",
|
||||||
"react-router-dom": "6.6.2",
|
"react-router-dom": "6.6.2",
|
||||||
"string-length": "6.0.0",
|
"string-length": "6.0.0",
|
||||||
|
@ -48,13 +49,13 @@
|
||||||
"@preact/preset-vite": "~2.8.2",
|
"@preact/preset-vite": "~2.8.2",
|
||||||
"@trivago/prettier-plugin-sort-imports": "~4.3.0",
|
"@trivago/prettier-plugin-sort-imports": "~4.3.0",
|
||||||
"postcss": "~8.4.38",
|
"postcss": "~8.4.38",
|
||||||
"postcss-dark-theme-class": "~1.2.1",
|
"postcss-dark-theme-class": "~1.2.3",
|
||||||
"postcss-preset-env": "~9.5.4",
|
"postcss-preset-env": "~9.5.8",
|
||||||
"twitter-text": "~3.1.0",
|
"twitter-text": "~3.1.0",
|
||||||
"vite": "~5.2.8",
|
"vite": "~5.2.10",
|
||||||
"vite-plugin-generate-file": "~0.1.1",
|
"vite-plugin-generate-file": "~0.1.1",
|
||||||
"vite-plugin-html-config": "~1.0.11",
|
"vite-plugin-html-config": "~1.0.11",
|
||||||
"vite-plugin-pwa": "~0.19.7",
|
"vite-plugin-pwa": "~0.19.8",
|
||||||
"vite-plugin-remove-console": "~2.2.0",
|
"vite-plugin-remove-console": "~2.2.0",
|
||||||
"workbox-cacheable-response": "~7.0.0",
|
"workbox-cacheable-response": "~7.0.0",
|
||||||
"workbox-expiration": "~7.0.0",
|
"workbox-expiration": "~7.0.0",
|
||||||
|
@ -1974,9 +1975,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/color-helpers": {
|
"node_modules/@csstools/color-helpers": {
|
||||||
"version": "4.1.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-4.2.0.tgz",
|
||||||
"integrity": "sha512-pWRKF6cDwget8HowIIf2MqEmqIca/cf8/jO4b3PRtUF5EfQXYMtBIKycXB4yXTCUmwLKOoRZAzh/hjnc7ywOIg==",
|
"integrity": "sha512-hJJrSBzbfGxUsaR6X4Bzd/FLx0F1ulKnR5ljY9AiXCtsR+H+zSWQDFWlKES1BRaVZTDHLpIIHS9K2o0h+JLlrg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2016,9 +2017,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/css-color-parser": {
|
"node_modules/@csstools/css-color-parser": {
|
||||||
"version": "1.6.3",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-1.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-2.0.0.tgz",
|
||||||
"integrity": "sha512-pQPUPo32HW3/NuZxrwr3VJHE+vGqSTVI5gK4jGbuJ7eOFUrsTmZikXcVdInCVWOvuxK5xbCzwDWoTlZUCAKN+A==",
|
"integrity": "sha512-0/v6OPpcg+b8TJT2N1Rcp0oH5xEvVOU5K2qDkaR3IMHNXuJ7XfVCQLINt3Cuj8mr54DbilEoZ9uvAmHBoZ//Fw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2031,7 +2032,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/color-helpers": "^4.1.0",
|
"@csstools/color-helpers": "^4.2.0",
|
||||||
"@csstools/css-calc": "^1.2.0"
|
"@csstools/css-calc": "^1.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2133,9 +2134,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-color-function": {
|
"node_modules/@csstools/postcss-color-function": {
|
||||||
"version": "3.0.13",
|
"version": "3.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-3.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-3.0.14.tgz",
|
||||||
"integrity": "sha512-gM24cIPU45HSPJ2zllz7VKjS1OKQS1sKOMI7Wsw8gFyXSGAGrxhYo++McylOqOXd8ecMaKxKQMUJqJVibvJYig==",
|
"integrity": "sha512-joGAf5bT3Jg1CpybupMJ4DwNg/VNjmLWZoWMDmX0MTy/ftHA1Qr4+CslqTT4AA1n6Dx4Wa+DSMGPrDLHtRP0jg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2148,7 +2149,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-color-parser": "^1.6.3",
|
"@csstools/css-color-parser": "^2.0.0",
|
||||||
"@csstools/css-parser-algorithms": "^2.6.1",
|
"@csstools/css-parser-algorithms": "^2.6.1",
|
||||||
"@csstools/css-tokenizer": "^2.2.4",
|
"@csstools/css-tokenizer": "^2.2.4",
|
||||||
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
||||||
|
@ -2162,9 +2163,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-color-mix-function": {
|
"node_modules/@csstools/postcss-color-mix-function": {
|
||||||
"version": "2.0.13",
|
"version": "2.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-2.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-2.0.14.tgz",
|
||||||
"integrity": "sha512-mD8IIfGVeWkN1H1wfCqYePOg4cDnVrOXm4P0OlYcvKriq6sImGCGShv/2D88q6s3iUlLXfUBES+DUjLVjDMhnw==",
|
"integrity": "sha512-ZLbgtdhyuOoWoRo/W8jFv68q+IMgTJHOAI+WunRbrRPqI+vJ0K2rud/lS9Se5urzM/imVKs/kz0Uobm5Yj4HUg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2177,7 +2178,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-color-parser": "^1.6.3",
|
"@csstools/css-color-parser": "^2.0.0",
|
||||||
"@csstools/css-parser-algorithms": "^2.6.1",
|
"@csstools/css-parser-algorithms": "^2.6.1",
|
||||||
"@csstools/css-tokenizer": "^2.2.4",
|
"@csstools/css-tokenizer": "^2.2.4",
|
||||||
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
||||||
|
@ -2244,9 +2245,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-gamut-mapping": {
|
"node_modules/@csstools/postcss-gamut-mapping": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-1.0.7.tgz",
|
||||||
"integrity": "sha512-qGFpHU9cRf9qqkbHh9cWMTlBtGi/ujPgP/znQdwkbB4TgDR1ddI5wRRrksBsx64sfoUSlIEd70bxXzD9FtfdLg==",
|
"integrity": "sha512-vrsHsl5TN6NB5CT0rPG6JE9V2GLFftcmPtF/k4cWT4gyVMCsDyS9wEVl82sgvh/JQ32TaUo6bh8Ndl+XRJqGQw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2259,7 +2260,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-color-parser": "^1.6.3",
|
"@csstools/css-color-parser": "^2.0.0",
|
||||||
"@csstools/css-parser-algorithms": "^2.6.1",
|
"@csstools/css-parser-algorithms": "^2.6.1",
|
||||||
"@csstools/css-tokenizer": "^2.2.4"
|
"@csstools/css-tokenizer": "^2.2.4"
|
||||||
},
|
},
|
||||||
|
@ -2271,9 +2272,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-gradients-interpolation-method": {
|
"node_modules/@csstools/postcss-gradients-interpolation-method": {
|
||||||
"version": "4.0.14",
|
"version": "4.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-4.0.14.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-4.0.15.tgz",
|
||||||
"integrity": "sha512-VMWC3xtpchHJoRBb/fs1gJR/5nHopX+0GwwmgdCI1DjROtfWUKIW0nv8occ922Gv0/Lk93XBtYBv8JttVBMZUQ==",
|
"integrity": "sha512-0xQ5r4WU/6W2lDmnOTx9liC1Cq6RSnrkEzqX7d0cRA3fz5hjC276pA0nLMoAiY3vtAp0u71nTk/3TRdnCx/OUw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2286,7 +2287,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-color-parser": "^1.6.3",
|
"@csstools/css-color-parser": "^2.0.0",
|
||||||
"@csstools/css-parser-algorithms": "^2.6.1",
|
"@csstools/css-parser-algorithms": "^2.6.1",
|
||||||
"@csstools/css-tokenizer": "^2.2.4",
|
"@csstools/css-tokenizer": "^2.2.4",
|
||||||
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
||||||
|
@ -2300,9 +2301,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-hwb-function": {
|
"node_modules/@csstools/postcss-hwb-function": {
|
||||||
"version": "3.0.12",
|
"version": "3.0.13",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-3.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-3.0.13.tgz",
|
||||||
"integrity": "sha512-90kIs+FsM6isAXLVoFHTTl4h0J6g1J1M6ahpIjAs6/k7a2A9FB/q+l0MHpLre0ZiPlBf2y3e1j4L+79vml7kJw==",
|
"integrity": "sha512-f44tgkFSxJBGm8UjlkAfBP7xE2x2XFFdvNdedHl8jpx2pQcW8a50OT3yeMnM3NB9Y2Ynd7Wn8iXARiV/IHoKvw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2315,7 +2316,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-color-parser": "^1.6.3",
|
"@csstools/css-color-parser": "^2.0.0",
|
||||||
"@csstools/css-parser-algorithms": "^2.6.1",
|
"@csstools/css-parser-algorithms": "^2.6.1",
|
||||||
"@csstools/css-tokenizer": "^2.2.4",
|
"@csstools/css-tokenizer": "^2.2.4",
|
||||||
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
||||||
|
@ -2655,9 +2656,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-oklab-function": {
|
"node_modules/@csstools/postcss-oklab-function": {
|
||||||
"version": "3.0.13",
|
"version": "3.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-3.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-3.0.14.tgz",
|
||||||
"integrity": "sha512-xbzMmukDFAwCt2+279io7ZiamZj87s6cnU3UgKB3G+NMpRX9A6uvN8xlnTLCe384hqg6hix5vlOmwkxqACb5pg==",
|
"integrity": "sha512-92xdpcfc2wB3z4+GftPA0PXMuGI/tRLw9Tc0+HzpaAHHxyLK6aCJtoQIcw0Ox/PthXtqXZn/3wWT/Idfe8I7Wg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2670,7 +2671,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-color-parser": "^1.6.3",
|
"@csstools/css-color-parser": "^2.0.0",
|
||||||
"@csstools/css-parser-algorithms": "^2.6.1",
|
"@csstools/css-parser-algorithms": "^2.6.1",
|
||||||
"@csstools/css-tokenizer": "^2.2.4",
|
"@csstools/css-tokenizer": "^2.2.4",
|
||||||
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
||||||
|
@ -2709,9 +2710,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-relative-color-syntax": {
|
"node_modules/@csstools/postcss-relative-color-syntax": {
|
||||||
"version": "2.0.13",
|
"version": "2.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-2.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-2.0.14.tgz",
|
||||||
"integrity": "sha512-mENWPNcHdiEYtjHFfZP9U1jNukQgFpSQ7wvTvwiadK3qgNBiSl0vMSinM9kKsGsJLTHQ0LEAqWLHurU52I4Jeg==",
|
"integrity": "sha512-NlxgLjAjVCTUVGiWk8WNj3dKvux9eC6O5aLM3BmdA8UXEwBHYI9r4IqlanxG9PlcXnzhTUX6eZsqgmxwt4FPow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2724,7 +2725,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-color-parser": "^1.6.3",
|
"@csstools/css-color-parser": "^2.0.0",
|
||||||
"@csstools/css-parser-algorithms": "^2.6.1",
|
"@csstools/css-parser-algorithms": "^2.6.1",
|
||||||
"@csstools/css-tokenizer": "^2.2.4",
|
"@csstools/css-tokenizer": "^2.2.4",
|
||||||
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
||||||
|
@ -2790,9 +2791,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-text-decoration-shorthand": {
|
"node_modules/@csstools/postcss-text-decoration-shorthand": {
|
||||||
"version": "3.0.5",
|
"version": "3.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-3.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-3.0.6.tgz",
|
||||||
"integrity": "sha512-qKxXpD0TYINkUtWDN1RHdeWKtZCzEv5j3UMT/ZGqyY27icwCFw7iKO0bUeLSHjYFBqhurCWvoOsa9REqLdrNDw==",
|
"integrity": "sha512-Q8HEu4AEiwNVZBD6+DpQ8M9SajpMow4+WtmndWIAv8qxDtDYL4JK1xXWkhOGk28PrcJawOvkrEZ8Ri59UN1TJw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -2805,7 +2806,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/color-helpers": "^4.1.0",
|
"@csstools/color-helpers": "^4.2.0",
|
||||||
"postcss-value-parser": "^4.2.0"
|
"postcss-value-parser": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3326,10 +3327,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@formkit/auto-animate": {
|
"node_modules/@formkit/auto-animate": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-0.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-0.8.2.tgz",
|
||||||
"integrity": "sha512-0/Z2cuNXWVVIG/l0SpcHAWFhGdvLJ8DRvEfRWvmojtmRWfEy+LWNwgDazbZqY0qQYtkHcoEK3jBLkhiZaB/4Ig==",
|
"integrity": "sha512-SwPWfeRa5veb1hOIBMdzI+73te5puUBHmqqaF1Bu7FjvxlYSz/kJcZKSa9Cg60zL0uRNeJL2SbRxV6Jp6Q1nFQ=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@github/combobox-nav": {
|
"node_modules/@github/combobox-nav": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
|
@ -4469,9 +4469,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/css-blank-pseudo": {
|
"node_modules/css-blank-pseudo": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-6.0.2.tgz",
|
||||||
"integrity": "sha512-goSnEITByxTzU4Oh5oJZrEWudxTqk7L6IXj1UW69pO6Hv0UdX+Vsrt02FFu5DweRh2bLu6WpX/+zsQCu5O1gKw==",
|
"integrity": "sha512-J/6m+lsqpKPqWHOifAFtKFeGLOzw3jR92rxQcwRUfA/eTuZzKfKlxOmYDx2+tqOPQAueNvBiY8WhAeHu5qNmTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -5131,6 +5131,14 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fuse.js": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/gensync": {
|
"node_modules/gensync": {
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.2",
|
||||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||||
|
@ -6031,9 +6039,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/masto": {
|
"node_modules/masto": {
|
||||||
"version": "6.7.0",
|
"version": "6.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/masto/-/masto-6.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/masto/-/masto-6.7.2.tgz",
|
||||||
"integrity": "sha512-R1UyuCdiyBuA9xuIEVIYa2187oIoHhpL1T0glIY+RICAo7JYOAEPdi4aAmROyPcWOYwMlaVDmRRb1zmNbvTnVg==",
|
"integrity": "sha512-MEX/XDWLJyOjCOedhGZaIsrTIH9yIA1k+z2ySJkClIfphtv8DTulBpcpi8CnBMCvgR/RjAF/wdu3QL5p6BVe2A==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"change-case": "^4.1.2",
|
"change-case": "^4.1.2",
|
||||||
"events-to-async": "^2.0.1",
|
"events-to-async": "^2.0.1",
|
||||||
|
@ -6424,9 +6432,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-color-functional-notation": {
|
"node_modules/postcss-color-functional-notation": {
|
||||||
"version": "6.0.8",
|
"version": "6.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-6.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-6.0.9.tgz",
|
||||||
"integrity": "sha512-BilFPTHcfWEnuQeqL83nbSPVK3tcU57S60aOrqgditarNDzOojyF0Gdc2Ur5L+zox366QjrCe0rOBLDO2pNvRQ==",
|
"integrity": "sha512-8i/ofOArZ4fljp+3g+HI6Pok01Kb8YaSqInrJt2vMimEKrI0ZDNRLpH+wLhXBNu/Bi8zeWDvxhvCqsGSpu8E6Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -6439,7 +6447,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-color-parser": "^1.6.3",
|
"@csstools/css-color-parser": "^2.0.0",
|
||||||
"@csstools/css-parser-algorithms": "^2.6.1",
|
"@csstools/css-parser-algorithms": "^2.6.1",
|
||||||
"@csstools/css-tokenizer": "^2.2.4",
|
"@csstools/css-tokenizer": "^2.2.4",
|
||||||
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
||||||
|
@ -6533,9 +6541,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-custom-properties": {
|
"node_modules/postcss-custom-properties": {
|
||||||
"version": "13.3.6",
|
"version": "13.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.3.7.tgz",
|
||||||
"integrity": "sha512-vVVIwQbJiIz+PBLMIWA6XMi53Zg66/f474KolA7x0Das6EwkATc/9ZvM6zZx2gs7ZhcgVHjmWBbHkK9FlCgLeA==",
|
"integrity": "sha512-0N9F/GUCr/D0IazjzHahyYW2bQVDT6qDtEudiGHAhMd3XqhfM3VmfYVlkc/40DOhsPtngSNb54/Ctu8msvFOvQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -6590,9 +6598,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-dark-theme-class": {
|
"node_modules/postcss-dark-theme-class": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-dark-theme-class/-/postcss-dark-theme-class-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-dark-theme-class/-/postcss-dark-theme-class-1.2.3.tgz",
|
||||||
"integrity": "sha512-EzQMGOcYnE0eMBjfgB+xnamlZ8O02Aiojyg/iv84cpRUdLKZW8ankZWxWUhhIid1OF7yl4G3BeYfE+7CGY2tdQ==",
|
"integrity": "sha512-Hr3pf9naYw0AJmIv6BcnkkpeWtIbXNc8OGqLbyYtHLqbuBpue5g7qK9g8fY7qvl3jig6tyu+Ga6N1FpMjIYqBQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -6604,6 +6612,9 @@
|
||||||
"url": "https://github.com/sponsors/ai"
|
"url": "https://github.com/sponsors/ai"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"postcss-value-parser": "^4.2.0"
|
||||||
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0"
|
"node": ">=18.0"
|
||||||
},
|
},
|
||||||
|
@ -6772,9 +6783,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-lab-function": {
|
"node_modules/postcss-lab-function": {
|
||||||
"version": "6.0.13",
|
"version": "6.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-6.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-6.0.14.tgz",
|
||||||
"integrity": "sha512-tzEThi3prSyomnVqaAU+k/YJib4rxeeTKVfMt+mPcEugFgp0t6xRjoc7fzaWCoEwYLC6GxGLD8/Ugx8COCqabw==",
|
"integrity": "sha512-ddQS9FRWT8sfl4wfW0ae8fpP2JdLIuhC9pYpHq1077avjrLzg73T9IEVu5QmFa72nJhYFlO9CbqjcoSdEzfY9A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -6787,7 +6798,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/css-color-parser": "^1.6.3",
|
"@csstools/css-color-parser": "^2.0.0",
|
||||||
"@csstools/css-parser-algorithms": "^2.6.1",
|
"@csstools/css-parser-algorithms": "^2.6.1",
|
||||||
"@csstools/css-tokenizer": "^2.2.4",
|
"@csstools/css-tokenizer": "^2.2.4",
|
||||||
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
||||||
|
@ -6826,9 +6837,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-nesting": {
|
"node_modules/postcss-nesting": {
|
||||||
"version": "12.1.1",
|
"version": "12.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.2.tgz",
|
||||||
"integrity": "sha512-qc74KvIAQNa5ujZKG1UV286dhaDW6basbUy2i9AzNU/T8C9hpvGu9NZzm1SfePe2yP7sPYgpA8d4sPVopn2Hhw==",
|
"integrity": "sha512-FUmTHGDNundodutB4PUBxt/EPuhgtpk8FJGRsBhOuy+6FnkR2A8RZWIsyyy6XmhvX2DZQQWIkvu+HB4IbJm+Ew==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -6936,9 +6947,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-preset-env": {
|
"node_modules/postcss-preset-env": {
|
||||||
"version": "9.5.4",
|
"version": "9.5.8",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.5.8.tgz",
|
||||||
"integrity": "sha512-o/jOlJjhm4f6rI5q1f+4Og3tz1cjaO50er9ndk7ZdcXHjWOH49kMAhqDC/nQifypQkOAiAmF46dPt3pZM+Cwbg==",
|
"integrity": "sha512-AjQ5ZgrVJVL8Ja7UxIlbyHUN5knkdk6L0JxxV7KDZU4S5WfJjRNgvWlU7Xq7CMyRZSjHZBmLDOsBKIL9WStPyw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -6952,13 +6963,13 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/postcss-cascade-layers": "^4.0.4",
|
"@csstools/postcss-cascade-layers": "^4.0.4",
|
||||||
"@csstools/postcss-color-function": "^3.0.13",
|
"@csstools/postcss-color-function": "^3.0.14",
|
||||||
"@csstools/postcss-color-mix-function": "^2.0.13",
|
"@csstools/postcss-color-mix-function": "^2.0.14",
|
||||||
"@csstools/postcss-exponential-functions": "^1.0.5",
|
"@csstools/postcss-exponential-functions": "^1.0.5",
|
||||||
"@csstools/postcss-font-format-keywords": "^3.0.2",
|
"@csstools/postcss-font-format-keywords": "^3.0.2",
|
||||||
"@csstools/postcss-gamut-mapping": "^1.0.6",
|
"@csstools/postcss-gamut-mapping": "^1.0.7",
|
||||||
"@csstools/postcss-gradients-interpolation-method": "^4.0.14",
|
"@csstools/postcss-gradients-interpolation-method": "^4.0.15",
|
||||||
"@csstools/postcss-hwb-function": "^3.0.12",
|
"@csstools/postcss-hwb-function": "^3.0.13",
|
||||||
"@csstools/postcss-ic-unit": "^3.0.6",
|
"@csstools/postcss-ic-unit": "^3.0.6",
|
||||||
"@csstools/postcss-initial": "^1.0.1",
|
"@csstools/postcss-initial": "^1.0.1",
|
||||||
"@csstools/postcss-is-pseudo-class": "^4.0.6",
|
"@csstools/postcss-is-pseudo-class": "^4.0.6",
|
||||||
|
@ -6972,27 +6983,27 @@
|
||||||
"@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.7",
|
"@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.7",
|
||||||
"@csstools/postcss-nested-calc": "^3.0.2",
|
"@csstools/postcss-nested-calc": "^3.0.2",
|
||||||
"@csstools/postcss-normalize-display-values": "^3.0.2",
|
"@csstools/postcss-normalize-display-values": "^3.0.2",
|
||||||
"@csstools/postcss-oklab-function": "^3.0.13",
|
"@csstools/postcss-oklab-function": "^3.0.14",
|
||||||
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
"@csstools/postcss-progressive-custom-properties": "^3.2.0",
|
||||||
"@csstools/postcss-relative-color-syntax": "^2.0.13",
|
"@csstools/postcss-relative-color-syntax": "^2.0.14",
|
||||||
"@csstools/postcss-scope-pseudo-class": "^3.0.1",
|
"@csstools/postcss-scope-pseudo-class": "^3.0.1",
|
||||||
"@csstools/postcss-stepped-value-functions": "^3.0.6",
|
"@csstools/postcss-stepped-value-functions": "^3.0.6",
|
||||||
"@csstools/postcss-text-decoration-shorthand": "^3.0.5",
|
"@csstools/postcss-text-decoration-shorthand": "^3.0.6",
|
||||||
"@csstools/postcss-trigonometric-functions": "^3.0.6",
|
"@csstools/postcss-trigonometric-functions": "^3.0.6",
|
||||||
"@csstools/postcss-unset-value": "^3.0.1",
|
"@csstools/postcss-unset-value": "^3.0.1",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"browserslist": "^4.22.3",
|
"browserslist": "^4.22.3",
|
||||||
"css-blank-pseudo": "^6.0.1",
|
"css-blank-pseudo": "^6.0.2",
|
||||||
"css-has-pseudo": "^6.0.3",
|
"css-has-pseudo": "^6.0.3",
|
||||||
"css-prefers-color-scheme": "^9.0.1",
|
"css-prefers-color-scheme": "^9.0.1",
|
||||||
"cssdb": "^8.0.0",
|
"cssdb": "^8.0.0",
|
||||||
"postcss-attribute-case-insensitive": "^6.0.3",
|
"postcss-attribute-case-insensitive": "^6.0.3",
|
||||||
"postcss-clamp": "^4.1.0",
|
"postcss-clamp": "^4.1.0",
|
||||||
"postcss-color-functional-notation": "^6.0.8",
|
"postcss-color-functional-notation": "^6.0.9",
|
||||||
"postcss-color-hex-alpha": "^9.0.4",
|
"postcss-color-hex-alpha": "^9.0.4",
|
||||||
"postcss-color-rebeccapurple": "^9.0.3",
|
"postcss-color-rebeccapurple": "^9.0.3",
|
||||||
"postcss-custom-media": "^10.0.4",
|
"postcss-custom-media": "^10.0.4",
|
||||||
"postcss-custom-properties": "^13.3.6",
|
"postcss-custom-properties": "^13.3.7",
|
||||||
"postcss-custom-selectors": "^7.1.8",
|
"postcss-custom-selectors": "^7.1.8",
|
||||||
"postcss-dir-pseudo-class": "^8.0.1",
|
"postcss-dir-pseudo-class": "^8.0.1",
|
||||||
"postcss-double-position-gradients": "^5.0.6",
|
"postcss-double-position-gradients": "^5.0.6",
|
||||||
|
@ -7001,14 +7012,14 @@
|
||||||
"postcss-font-variant": "^5.0.0",
|
"postcss-font-variant": "^5.0.0",
|
||||||
"postcss-gap-properties": "^5.0.1",
|
"postcss-gap-properties": "^5.0.1",
|
||||||
"postcss-image-set-function": "^6.0.3",
|
"postcss-image-set-function": "^6.0.3",
|
||||||
"postcss-lab-function": "^6.0.13",
|
"postcss-lab-function": "^6.0.14",
|
||||||
"postcss-logical": "^7.0.1",
|
"postcss-logical": "^7.0.1",
|
||||||
"postcss-nesting": "^12.1.1",
|
"postcss-nesting": "^12.1.2",
|
||||||
"postcss-opacity-percentage": "^2.0.0",
|
"postcss-opacity-percentage": "^2.0.0",
|
||||||
"postcss-overflow-shorthand": "^5.0.1",
|
"postcss-overflow-shorthand": "^5.0.1",
|
||||||
"postcss-page-break": "^3.0.4",
|
"postcss-page-break": "^3.0.4",
|
||||||
"postcss-place": "^9.0.1",
|
"postcss-place": "^9.0.1",
|
||||||
"postcss-pseudo-class-any-link": "^9.0.1",
|
"postcss-pseudo-class-any-link": "^9.0.2",
|
||||||
"postcss-replace-overflow-wrap": "^4.0.0",
|
"postcss-replace-overflow-wrap": "^4.0.0",
|
||||||
"postcss-selector-not": "^7.0.2"
|
"postcss-selector-not": "^7.0.2"
|
||||||
},
|
},
|
||||||
|
@ -7020,9 +7031,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-pseudo-class-any-link": {
|
"node_modules/postcss-pseudo-class-any-link": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-9.0.2.tgz",
|
||||||
"integrity": "sha512-cKYGGZ9yzUZi+dZd7XT2M8iSDfo+T2Ctbpiizf89uBTBfIpZpjvTavzIJXpCReMVXSKROqzpxClNu6fz4DHM0Q==",
|
"integrity": "sha512-HFSsxIqQ9nA27ahyfH37cRWGk3SYyQLpk0LiWw/UGMV4VKT5YG2ONee4Pz/oFesnK0dn2AjcyequDbIjKJgB0g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -7100,9 +7111,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/preact": {
|
"node_modules/preact": {
|
||||||
"version": "10.20.1",
|
"version": "10.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.20.1.tgz",
|
"resolved": "https://registry.npmjs.org/preact/-/preact-10.20.2.tgz",
|
||||||
"integrity": "sha512-JIFjgFg9B2qnOoGiYMVBtrcFxHqn+dNXbq76bVmcaHYJFYR4lW67AOcXgAYQQTDYXDOg/kTZrKPNCdRgJ2UJmw==",
|
"integrity": "sha512-S1d1ernz3KQ+Y2awUxKakpfOg2CEmJmwOP+6igPx6dgr6pgDvenqYviyokWso2rhHvGtTlWWnJDa7RaPbQerTg==",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/preact"
|
"url": "https://opencollective.com/preact"
|
||||||
|
@ -7230,9 +7241,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-intersection-observer": {
|
"node_modules/react-intersection-observer": {
|
||||||
"version": "9.8.1",
|
"version": "9.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.8.2.tgz",
|
||||||
"integrity": "sha512-QzOFdROX8D8MH3wE3OVKH0f3mLjKTtEN1VX/rkNuECCff+aKky0pIjulDhr3Ewqj5el/L+MhBkM3ef0Tbt+qUQ==",
|
"integrity": "sha512-901naEiiZmse3p+AmtbQ3NL9xx+gQ8TXLiGDc+8GiE3JKJkNV3vP737aGuWTAXBA+1QqxPrDDE+fIEgYpGDlrQ==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
|
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
|
||||||
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
@ -8207,9 +8218,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.2.8",
|
"version": "5.2.10",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz",
|
||||||
"integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==",
|
"integrity": "sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.20.1",
|
"esbuild": "^0.20.1",
|
||||||
|
@ -8288,9 +8299,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite-plugin-pwa": {
|
"node_modules/vite-plugin-pwa": {
|
||||||
"version": "0.19.7",
|
"version": "0.19.8",
|
||||||
"resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.19.7.tgz",
|
"resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.19.8.tgz",
|
||||||
"integrity": "sha512-18TECxoGPQE7tVZzKxbf5Icrl5688n1JGMPSgGotTsh89vLDxevY7ICfD3CFVfonZXh8ckuyJXg0NXE5+FAl2A==",
|
"integrity": "sha512-e1oK0dfhzhDhY3VBuML6c0h8Xfx6EkOVYqolj7g+u8eRfdauZe5RLteCIA/c5gH0CBQ0CNFAuv/AFTx4Z7IXTw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
|
|
17
package.json
17
package.json
|
@ -12,7 +12,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formatjs/intl-localematcher": "~0.5.4",
|
"@formatjs/intl-localematcher": "~0.5.4",
|
||||||
"@formatjs/intl-segmenter": "~11.5.5",
|
"@formatjs/intl-segmenter": "~11.5.5",
|
||||||
"@formkit/auto-animate": "~0.8.1",
|
"@formkit/auto-animate": "~0.8.2",
|
||||||
"@github/text-expander-element": "~2.6.1",
|
"@github/text-expander-element": "~2.6.1",
|
||||||
"@iconify-icons/mingcute": "~1.2.9",
|
"@iconify-icons/mingcute": "~1.2.9",
|
||||||
"@justinribeiro/lite-youtube": "~1.5.0",
|
"@justinribeiro/lite-youtube": "~1.5.0",
|
||||||
|
@ -23,18 +23,19 @@
|
||||||
"dayjs-twitter": "~0.5.0",
|
"dayjs-twitter": "~0.5.0",
|
||||||
"fast-blurhash": "~1.1.2",
|
"fast-blurhash": "~1.1.2",
|
||||||
"fast-equals": "~5.0.1",
|
"fast-equals": "~5.0.1",
|
||||||
|
"fuse.js": "~7.0.0",
|
||||||
"html-prettify": "^1.0.7",
|
"html-prettify": "^1.0.7",
|
||||||
"idb-keyval": "~6.2.1",
|
"idb-keyval": "~6.2.1",
|
||||||
"just-debounce-it": "~3.2.0",
|
"just-debounce-it": "~3.2.0",
|
||||||
"lz-string": "~1.5.0",
|
"lz-string": "~1.5.0",
|
||||||
"masto": "~6.7.0",
|
"masto": "~6.7.2",
|
||||||
"moize": "~6.1.6",
|
"moize": "~6.1.6",
|
||||||
"p-retry": "~6.2.0",
|
"p-retry": "~6.2.0",
|
||||||
"p-throttle": "~6.1.0",
|
"p-throttle": "~6.1.0",
|
||||||
"preact": "~10.20.1",
|
"preact": "~10.20.2",
|
||||||
"punycode": "~2.3.1",
|
"punycode": "~2.3.1",
|
||||||
"react-hotkeys-hook": "~4.5.0",
|
"react-hotkeys-hook": "~4.5.0",
|
||||||
"react-intersection-observer": "~9.8.1",
|
"react-intersection-observer": "~9.8.2",
|
||||||
"react-quick-pinch-zoom": "~5.1.0",
|
"react-quick-pinch-zoom": "~5.1.0",
|
||||||
"react-router-dom": "6.6.2",
|
"react-router-dom": "6.6.2",
|
||||||
"string-length": "6.0.0",
|
"string-length": "6.0.0",
|
||||||
|
@ -50,13 +51,13 @@
|
||||||
"@preact/preset-vite": "~2.8.2",
|
"@preact/preset-vite": "~2.8.2",
|
||||||
"@trivago/prettier-plugin-sort-imports": "~4.3.0",
|
"@trivago/prettier-plugin-sort-imports": "~4.3.0",
|
||||||
"postcss": "~8.4.38",
|
"postcss": "~8.4.38",
|
||||||
"postcss-dark-theme-class": "~1.2.1",
|
"postcss-dark-theme-class": "~1.2.3",
|
||||||
"postcss-preset-env": "~9.5.4",
|
"postcss-preset-env": "~9.5.8",
|
||||||
"twitter-text": "~3.1.0",
|
"twitter-text": "~3.1.0",
|
||||||
"vite": "~5.2.8",
|
"vite": "~5.2.10",
|
||||||
"vite-plugin-generate-file": "~0.1.1",
|
"vite-plugin-generate-file": "~0.1.1",
|
||||||
"vite-plugin-html-config": "~1.0.11",
|
"vite-plugin-html-config": "~1.0.11",
|
||||||
"vite-plugin-pwa": "~0.19.7",
|
"vite-plugin-pwa": "~0.19.8",
|
||||||
"vite-plugin-remove-console": "~2.2.0",
|
"vite-plugin-remove-console": "~2.2.0",
|
||||||
"workbox-cacheable-response": "~7.0.0",
|
"workbox-cacheable-response": "~7.0.0",
|
||||||
"workbox-expiration": "~7.0.0",
|
"workbox-expiration": "~7.0.0",
|
||||||
|
|
|
@ -597,41 +597,123 @@
|
||||||
#custom-emojis-sheet {
|
#custom-emojis-sheet {
|
||||||
max-height: 50vh;
|
max-height: 50vh;
|
||||||
max-height: 50dvh;
|
max-height: 50dvh;
|
||||||
}
|
|
||||||
#custom-emojis-sheet main {
|
header {
|
||||||
mask-image: none;
|
.loader-container {
|
||||||
}
|
margin: 0;
|
||||||
#custom-emojis-sheet .custom-emojis-list .section-header {
|
}
|
||||||
font-size: 80%;
|
|
||||||
text-transform: uppercase;
|
form {
|
||||||
color: var(--text-insignificant-color);
|
margin: 8px 0 0;
|
||||||
padding: 8px 0 4px;
|
|
||||||
position: sticky;
|
input {
|
||||||
top: 0;
|
width: 100%;
|
||||||
background-color: var(--bg-blur-color);
|
min-width: 0;
|
||||||
backdrop-filter: blur(1px);
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
#custom-emojis-sheet .custom-emojis-list section {
|
}
|
||||||
display: flex;
|
}
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
main {
|
||||||
#custom-emojis-sheet .custom-emojis-list button {
|
mask-image: none;
|
||||||
border-radius: 8px;
|
min-height: 40vh;
|
||||||
background-image: radial-gradient(
|
padding-bottom: 88px;
|
||||||
closest-side,
|
}
|
||||||
var(--img-bg-color),
|
|
||||||
transparent
|
.custom-emojis-matches {
|
||||||
);
|
margin: 0;
|
||||||
}
|
padding: 0;
|
||||||
#custom-emojis-sheet .custom-emojis-list button:is(:hover, :focus) {
|
list-style: none;
|
||||||
filter: none;
|
display: flex;
|
||||||
background-color: var(--bg-faded-color);
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
#custom-emojis-sheet .custom-emojis-list button img {
|
|
||||||
transition: transform 0.1s ease-out;
|
.custom-emojis-list {
|
||||||
}
|
.section-header {
|
||||||
#custom-emojis-sheet .custom-emojis-list button:is(:hover, :focus) img {
|
font-size: 80%;
|
||||||
transform: scale(1.5);
|
text-transform: uppercase;
|
||||||
|
color: var(--text-insignificant-color);
|
||||||
|
padding: 8px 0 4px;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
color: var(--text-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
background-image: radial-gradient(
|
||||||
|
closest-side,
|
||||||
|
var(--img-bg-color),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
text-shadow: 0 1px 0 var(--bg-color);
|
||||||
|
position: relative;
|
||||||
|
min-width: 44px;
|
||||||
|
min-height: 44px;
|
||||||
|
font-variant-numeric: slashed-zero;
|
||||||
|
font-feature-settings: 'ss01';
|
||||||
|
|
||||||
|
&[data-title]:after {
|
||||||
|
max-width: 50vw;
|
||||||
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
content: attr(data-title);
|
||||||
|
left: 50%;
|
||||||
|
top: 0;
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
padding: 2px 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
border: 1px solid var(--text-color);
|
||||||
|
transform: translate(-50%, -110%);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.1s ease-out 0.1s;
|
||||||
|
font-family: var(--monospace-font);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
&.edge-left[data-title]:after {
|
||||||
|
left: 0;
|
||||||
|
transform: translate(0, -110%);
|
||||||
|
}
|
||||||
|
&.edge-right[data-title]:after {
|
||||||
|
left: 100%;
|
||||||
|
transform: translate(-100%, -110%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:is(:hover, :focus) {
|
||||||
|
z-index: 1;
|
||||||
|
filter: none;
|
||||||
|
background-color: var(--bg-faded-color);
|
||||||
|
|
||||||
|
&[data-title]:after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
transition: transform 0.1s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:is(:hover, :focus) img {
|
||||||
|
transform: scale(2);
|
||||||
|
}
|
||||||
|
&.edge-left img {
|
||||||
|
transform-origin: left center;
|
||||||
|
}
|
||||||
|
&.edge-right img {
|
||||||
|
transform-origin: right center;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.compose-field-container {
|
.compose-field-container {
|
||||||
|
|
|
@ -3,8 +3,16 @@ import './compose.css';
|
||||||
import '@github/text-expander-element';
|
import '@github/text-expander-element';
|
||||||
import { MenuItem } from '@szhsin/react-menu';
|
import { MenuItem } from '@szhsin/react-menu';
|
||||||
import { deepEqual } from 'fast-equals';
|
import { deepEqual } from 'fast-equals';
|
||||||
|
import Fuse from 'fuse.js';
|
||||||
|
import { memo } from 'preact/compat';
|
||||||
import { forwardRef } from 'preact/compat';
|
import { forwardRef } from 'preact/compat';
|
||||||
import { useEffect, useMemo, useRef, useState } from 'preact/hooks';
|
import {
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'preact/hooks';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
import stringLength from 'string-length';
|
import stringLength from 'string-length';
|
||||||
import { uid } from 'uid/single';
|
import { uid } from 'uid/single';
|
||||||
|
@ -21,6 +29,7 @@ import db from '../utils/db';
|
||||||
import emojifyText from '../utils/emojify-text';
|
import emojifyText from '../utils/emojify-text';
|
||||||
import localeMatch from '../utils/locale-match';
|
import localeMatch from '../utils/locale-match';
|
||||||
import openCompose from '../utils/open-compose';
|
import openCompose from '../utils/open-compose';
|
||||||
|
import pmem from '../utils/pmem';
|
||||||
import shortenNumber from '../utils/shorten-number';
|
import shortenNumber from '../utils/shorten-number';
|
||||||
import showToast from '../utils/show-toast';
|
import showToast from '../utils/show-toast';
|
||||||
import states, { saveStatus } from '../utils/states';
|
import states, { saveStatus } from '../utils/states';
|
||||||
|
@ -181,6 +190,8 @@ function highlightText(text, { maxCharacters = Infinity }) {
|
||||||
|
|
||||||
const rtf = new Intl.RelativeTimeFormat();
|
const rtf = new Intl.RelativeTimeFormat();
|
||||||
|
|
||||||
|
const CUSTOM_EMOJIS_COUNT = 100;
|
||||||
|
|
||||||
function Compose({
|
function Compose({
|
||||||
onClose,
|
onClose,
|
||||||
replyToStatus,
|
replyToStatus,
|
||||||
|
@ -1423,25 +1434,40 @@ function autoResizeTextarea(textarea) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function _getCustomEmojis(instance, masto) {
|
||||||
|
const emojis = await masto.v1.customEmojis.list();
|
||||||
|
const visibleEmojis = emojis.filter((e) => e.visibleInPicker);
|
||||||
|
const searcher = new Fuse(visibleEmojis, {
|
||||||
|
keys: ['shortcode'],
|
||||||
|
findAllMatches: true,
|
||||||
|
});
|
||||||
|
return [visibleEmojis, searcher];
|
||||||
|
}
|
||||||
|
const getCustomEmojis = pmem(_getCustomEmojis, {
|
||||||
|
// Limit by time to reduce memory usage
|
||||||
|
// Cached by instance
|
||||||
|
matchesArg: (cacheKeyArg, keyArg) => cacheKeyArg.instance === keyArg.instance,
|
||||||
|
maxAge: 30 * 60 * 1000, // 30 minutes
|
||||||
|
});
|
||||||
|
|
||||||
const Textarea = forwardRef((props, ref) => {
|
const Textarea = forwardRef((props, ref) => {
|
||||||
const { masto } = api();
|
const { masto, instance } = api();
|
||||||
const [text, setText] = useState(ref.current?.value || '');
|
const [text, setText] = useState(ref.current?.value || '');
|
||||||
const { maxCharacters, performSearch = () => {}, ...textareaProps } = props;
|
const { maxCharacters, performSearch = () => {}, ...textareaProps } = props;
|
||||||
// const snapStates = useSnapshot(states);
|
// const snapStates = useSnapshot(states);
|
||||||
// const charCount = snapStates.composerCharacterCount;
|
// const charCount = snapStates.composerCharacterCount;
|
||||||
|
|
||||||
const customEmojis = useRef();
|
// const customEmojis = useRef();
|
||||||
|
const searcherRef = useRef();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
getCustomEmojis(instance, masto)
|
||||||
try {
|
.then((r) => {
|
||||||
const emojis = await masto.v1.customEmojis.list();
|
const [emojis, searcher] = r;
|
||||||
console.log({ emojis });
|
searcherRef.current = searcher;
|
||||||
customEmojis.current = emojis;
|
})
|
||||||
} catch (e) {
|
.catch((e) => {
|
||||||
// silent fail
|
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
});
|
||||||
})();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const textExpanderRef = useRef();
|
const textExpanderRef = useRef();
|
||||||
|
@ -1467,23 +1493,26 @@ const Textarea = forwardRef((props, ref) => {
|
||||||
// const emojis = customEmojis.current.filter((emoji) =>
|
// const emojis = customEmojis.current.filter((emoji) =>
|
||||||
// emoji.shortcode.startsWith(text),
|
// emoji.shortcode.startsWith(text),
|
||||||
// );
|
// );
|
||||||
const emojis = filterShortcodes(customEmojis.current, text);
|
// const emojis = filterShortcodes(customEmojis.current, text);
|
||||||
|
const results = searcherRef.current?.search(text, {
|
||||||
|
limit: 5,
|
||||||
|
});
|
||||||
let html = '';
|
let html = '';
|
||||||
emojis.forEach((emoji) => {
|
results.forEach(({ item: emoji }) => {
|
||||||
const { shortcode, url } = emoji;
|
const { shortcode, url } = emoji;
|
||||||
html += `
|
html += `
|
||||||
<li role="option" data-value="${encodeHTML(shortcode)}">
|
<li role="option" data-value="${encodeHTML(shortcode)}">
|
||||||
<img src="${encodeHTML(
|
<img src="${encodeHTML(
|
||||||
url,
|
url,
|
||||||
)}" width="16" height="16" alt="" loading="lazy" />
|
)}" width="16" height="16" alt="" loading="lazy" />
|
||||||
:${encodeHTML(shortcode)}:
|
${encodeHTML(shortcode)}
|
||||||
</li>`;
|
</li>`;
|
||||||
});
|
});
|
||||||
// console.log({ emojis, html });
|
// console.log({ emojis, html });
|
||||||
menu.innerHTML = html;
|
menu.innerHTML = html;
|
||||||
provide(
|
provide(
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
matched: emojis.length > 0,
|
matched: results.length > 0,
|
||||||
fragment: menu,
|
fragment: menu,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -2185,38 +2214,19 @@ function CustomEmojisModal({
|
||||||
}) {
|
}) {
|
||||||
const [uiState, setUIState] = useState('default');
|
const [uiState, setUIState] = useState('default');
|
||||||
const customEmojisList = useRef([]);
|
const customEmojisList = useRef([]);
|
||||||
const [customEmojis, setCustomEmojis] = useState({});
|
const [customEmojis, setCustomEmojis] = useState([]);
|
||||||
const recentlyUsedCustomEmojis = useMemo(
|
const recentlyUsedCustomEmojis = useMemo(
|
||||||
() => store.account.get('recentlyUsedCustomEmojis') || [],
|
() => store.account.get('recentlyUsedCustomEmojis') || [],
|
||||||
);
|
);
|
||||||
|
const searcherRef = useRef();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setUIState('loading');
|
setUIState('loading');
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const emojis = await masto.v1.customEmojis.list();
|
const [emojis, searcher] = await getCustomEmojis(instance, masto);
|
||||||
// Group emojis by category
|
console.log('emojis', emojis);
|
||||||
const emojisCat = {
|
searcherRef.current = searcher;
|
||||||
'--recent--': recentlyUsedCustomEmojis.filter((emoji) =>
|
setCustomEmojis(emojis);
|
||||||
emojis.find((e) => e.shortcode === emoji.shortcode),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
const othersCat = [];
|
|
||||||
emojis.forEach((emoji) => {
|
|
||||||
if (!emoji.visibleInPicker) return;
|
|
||||||
customEmojisList.current?.push?.(emoji);
|
|
||||||
if (!emoji.category) {
|
|
||||||
othersCat.push(emoji);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!emojisCat[emoji.category]) {
|
|
||||||
emojisCat[emoji.category] = [];
|
|
||||||
}
|
|
||||||
emojisCat[emoji.category].push(emoji);
|
|
||||||
});
|
|
||||||
if (othersCat.length) {
|
|
||||||
emojisCat['--others--'] = othersCat;
|
|
||||||
}
|
|
||||||
setCustomEmojis(emojisCat);
|
|
||||||
setUIState('default');
|
setUIState('default');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setUIState('error');
|
setUIState('error');
|
||||||
|
@ -2225,6 +2235,83 @@ function CustomEmojisModal({
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const customEmojisCatList = useMemo(() => {
|
||||||
|
// Group emojis by category
|
||||||
|
const emojisCat = {
|
||||||
|
'--recent--': recentlyUsedCustomEmojis.filter((emoji) =>
|
||||||
|
customEmojis.find((e) => e.shortcode === emoji.shortcode),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
const othersCat = [];
|
||||||
|
customEmojis.forEach((emoji) => {
|
||||||
|
customEmojisList.current?.push?.(emoji);
|
||||||
|
if (!emoji.category) {
|
||||||
|
othersCat.push(emoji);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!emojisCat[emoji.category]) {
|
||||||
|
emojisCat[emoji.category] = [];
|
||||||
|
}
|
||||||
|
emojisCat[emoji.category].push(emoji);
|
||||||
|
});
|
||||||
|
if (othersCat.length) {
|
||||||
|
emojisCat['--others--'] = othersCat;
|
||||||
|
}
|
||||||
|
return emojisCat;
|
||||||
|
}, [customEmojis]);
|
||||||
|
|
||||||
|
const scrollableRef = useRef();
|
||||||
|
const [matches, setMatches] = useState(null);
|
||||||
|
const onFind = useCallback(
|
||||||
|
(e) => {
|
||||||
|
const { value } = e.target;
|
||||||
|
if (value) {
|
||||||
|
const results = searcherRef.current?.search(value, {
|
||||||
|
limit: CUSTOM_EMOJIS_COUNT,
|
||||||
|
});
|
||||||
|
setMatches(results.map((r) => r.item));
|
||||||
|
scrollableRef.current?.scrollTo?.(0, 0);
|
||||||
|
} else {
|
||||||
|
setMatches(null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[customEmojis],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSelectEmoji = useCallback(
|
||||||
|
(emoji) => {
|
||||||
|
onSelect?.(emoji);
|
||||||
|
onClose?.();
|
||||||
|
|
||||||
|
queueMicrotask(() => {
|
||||||
|
let recentlyUsedCustomEmojis =
|
||||||
|
store.account.get('recentlyUsedCustomEmojis') || [];
|
||||||
|
const recentlyUsedEmojiIndex = recentlyUsedCustomEmojis.findIndex(
|
||||||
|
(e) => e.shortcode === emoji.shortcode,
|
||||||
|
);
|
||||||
|
if (recentlyUsedEmojiIndex !== -1) {
|
||||||
|
// Move emoji to index 0
|
||||||
|
recentlyUsedCustomEmojis.splice(recentlyUsedEmojiIndex, 1);
|
||||||
|
recentlyUsedCustomEmojis.unshift(emoji);
|
||||||
|
} else {
|
||||||
|
recentlyUsedCustomEmojis.unshift(emoji);
|
||||||
|
// Remove unavailable ones
|
||||||
|
recentlyUsedCustomEmojis = recentlyUsedCustomEmojis.filter((e) =>
|
||||||
|
customEmojisList.current?.find?.(
|
||||||
|
(emoji) => emoji.shortcode === e.shortcode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// Limit to 10
|
||||||
|
recentlyUsedCustomEmojis = recentlyUsedCustomEmojis.slice(0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store back
|
||||||
|
store.account.set('recentlyUsedCustomEmojis', recentlyUsedCustomEmojis);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[onSelect],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="custom-emojis-sheet" class="sheet">
|
<div id="custom-emojis-sheet" class="sheet">
|
||||||
{!!onClose && (
|
{!!onClose && (
|
||||||
|
@ -2233,107 +2320,167 @@ function CustomEmojisModal({
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<header>
|
<header>
|
||||||
<b>Custom emojis</b>{' '}
|
<div>
|
||||||
{uiState === 'loading' ? (
|
<b>Custom emojis</b>{' '}
|
||||||
<Loader />
|
{uiState === 'loading' ? (
|
||||||
) : (
|
<Loader />
|
||||||
<small class="insignificant"> • {instance}</small>
|
) : (
|
||||||
)}
|
<small class="insignificant"> • {instance}</small>
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
<div class="custom-emojis-list">
|
|
||||||
{uiState === 'error' && (
|
|
||||||
<div class="ui-state">
|
|
||||||
<p>Error loading custom emojis</p>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
{uiState === 'default' &&
|
|
||||||
Object.entries(customEmojis).map(
|
|
||||||
([category, emojis]) =>
|
|
||||||
!!emojis?.length && (
|
|
||||||
<>
|
|
||||||
<div class="section-header">
|
|
||||||
{{
|
|
||||||
'--recent--': 'Recently used',
|
|
||||||
'--others--': 'Others',
|
|
||||||
}[category] || category}
|
|
||||||
</div>
|
|
||||||
<section>
|
|
||||||
{emojis.map((emoji) => (
|
|
||||||
<button
|
|
||||||
key={emoji}
|
|
||||||
type="button"
|
|
||||||
class="plain4"
|
|
||||||
onClick={() => {
|
|
||||||
onClose();
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
onSelect(`:${emoji.shortcode}:`);
|
|
||||||
});
|
|
||||||
let recentlyUsedCustomEmojis =
|
|
||||||
store.account.get('recentlyUsedCustomEmojis') ||
|
|
||||||
[];
|
|
||||||
const recentlyUsedEmojiIndex =
|
|
||||||
recentlyUsedCustomEmojis.findIndex(
|
|
||||||
(e) => e.shortcode === emoji.shortcode,
|
|
||||||
);
|
|
||||||
if (recentlyUsedEmojiIndex !== -1) {
|
|
||||||
// Move emoji to index 0
|
|
||||||
recentlyUsedCustomEmojis.splice(
|
|
||||||
recentlyUsedEmojiIndex,
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
recentlyUsedCustomEmojis.unshift(emoji);
|
|
||||||
} else {
|
|
||||||
recentlyUsedCustomEmojis.unshift(emoji);
|
|
||||||
// Remove unavailable ones
|
|
||||||
recentlyUsedCustomEmojis =
|
|
||||||
recentlyUsedCustomEmojis.filter((e) =>
|
|
||||||
customEmojisList.current?.find?.(
|
|
||||||
(emoji) => emoji.shortcode === e.shortcode,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
// Limit to 10
|
|
||||||
recentlyUsedCustomEmojis =
|
|
||||||
recentlyUsedCustomEmojis.slice(0, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store back
|
|
||||||
store.account.set(
|
|
||||||
'recentlyUsedCustomEmojis',
|
|
||||||
recentlyUsedCustomEmojis,
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
title={`:${emoji.shortcode}:`}
|
|
||||||
>
|
|
||||||
<picture>
|
|
||||||
{!!emoji.staticUrl && (
|
|
||||||
<source
|
|
||||||
srcset={emoji.staticUrl}
|
|
||||||
media="(prefers-reduced-motion: reduce)"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<img
|
|
||||||
class="shortcode-emoji"
|
|
||||||
src={emoji.url || emoji.staticUrl}
|
|
||||||
alt={emoji.shortcode}
|
|
||||||
width="16"
|
|
||||||
height="16"
|
|
||||||
loading="lazy"
|
|
||||||
decoding="async"
|
|
||||||
/>
|
|
||||||
</picture>
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</section>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const emoji = matches[0];
|
||||||
|
if (emoji) {
|
||||||
|
onSelectEmoji(`:${emoji.shortcode}:`);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
placeholder="Search emoji"
|
||||||
|
onInput={onFind}
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
autocapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
dir="auto"
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</header>
|
||||||
|
<main ref={scrollableRef}>
|
||||||
|
{matches !== null ? (
|
||||||
|
<ul class="custom-emojis-matches custom-emojis-list">
|
||||||
|
{matches.map((emoji) => (
|
||||||
|
<li key={emoji.shortcode} class="custom-emojis-match">
|
||||||
|
<CustomEmojiButton
|
||||||
|
emoji={emoji}
|
||||||
|
onClick={() => {
|
||||||
|
onSelectEmoji(`:${emoji.shortcode}:`);
|
||||||
|
}}
|
||||||
|
showCode
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
) : (
|
||||||
|
<div class="custom-emojis-list">
|
||||||
|
{uiState === 'error' && (
|
||||||
|
<div class="ui-state">
|
||||||
|
<p>Error loading custom emojis</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{uiState === 'default' &&
|
||||||
|
Object.entries(customEmojisCatList).map(
|
||||||
|
([category, emojis]) =>
|
||||||
|
!!emojis?.length && (
|
||||||
|
<>
|
||||||
|
<div class="section-header">
|
||||||
|
{{
|
||||||
|
'--recent--': 'Recently used',
|
||||||
|
'--others--': 'Others',
|
||||||
|
}[category] || category}
|
||||||
|
</div>
|
||||||
|
<CustomEmojisList
|
||||||
|
emojis={emojis}
|
||||||
|
onSelect={onSelectEmoji}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CustomEmojisList = memo(({ emojis, onSelect }) => {
|
||||||
|
const [max, setMax] = useState(CUSTOM_EMOJIS_COUNT);
|
||||||
|
const showMore = emojis.length > max;
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
{emojis.slice(0, max).map((emoji) => (
|
||||||
|
<CustomEmojiButton
|
||||||
|
key={emoji.shortcode}
|
||||||
|
emoji={emoji}
|
||||||
|
onClick={() => {
|
||||||
|
onSelect(`:${emoji.shortcode}:`);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
{showMore && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="plain small"
|
||||||
|
onClick={() => setMax(max + CUSTOM_EMOJIS_COUNT)}
|
||||||
|
>
|
||||||
|
{(emojis.length - max).toLocaleString()} more…
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const CustomEmojiButton = memo(({ emoji, onClick, showCode }) => {
|
||||||
|
const addEdges = (e) => {
|
||||||
|
// Add edge-left or edge-right class based on self position relative to scrollable parent
|
||||||
|
// If near left edge, add edge-left, if near right edge, add edge-right
|
||||||
|
const buffer = 88;
|
||||||
|
const parent = e.currentTarget.closest('main');
|
||||||
|
if (parent) {
|
||||||
|
const rect = parent.getBoundingClientRect();
|
||||||
|
const selfRect = e.currentTarget.getBoundingClientRect();
|
||||||
|
const targetClassList = e.currentTarget.classList;
|
||||||
|
if (selfRect.left < rect.left + buffer) {
|
||||||
|
targetClassList.add('edge-left');
|
||||||
|
targetClassList.remove('edge-right');
|
||||||
|
} else if (selfRect.right > rect.right - buffer) {
|
||||||
|
targetClassList.add('edge-right');
|
||||||
|
targetClassList.remove('edge-left');
|
||||||
|
} else {
|
||||||
|
targetClassList.remove('edge-left', 'edge-right');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="plain4"
|
||||||
|
onClick={onClick}
|
||||||
|
data-title={showCode ? undefined : emoji.shortcode}
|
||||||
|
onPointerEnter={addEdges}
|
||||||
|
onFocus={addEdges}
|
||||||
|
>
|
||||||
|
<picture>
|
||||||
|
{!!emoji.staticUrl && (
|
||||||
|
<source
|
||||||
|
srcSet={emoji.staticUrl}
|
||||||
|
media="(prefers-reduced-motion: reduce)"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<img
|
||||||
|
className="shortcode-emoji"
|
||||||
|
src={emoji.url || emoji.staticUrl}
|
||||||
|
alt={emoji.shortcode}
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</picture>
|
||||||
|
{showCode && (
|
||||||
|
<>
|
||||||
|
{' '}
|
||||||
|
<code>{emoji.shortcode}</code>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const GIFS_PER_PAGE = 20;
|
const GIFS_PER_PAGE = 20;
|
||||||
function GIFPickerModal({ onClose = () => {}, onSelect = () => {} }) {
|
function GIFPickerModal({ onClose = () => {}, onSelect = () => {} }) {
|
||||||
const [uiState, setUIState] = useState('default');
|
const [uiState, setUIState] = useState('default');
|
||||||
|
|
|
@ -7,10 +7,13 @@ import { useInView } from 'react-intersection-observer';
|
||||||
// The sticky header, usually at the top
|
// The sticky header, usually at the top
|
||||||
const TOP = 48;
|
const TOP = 48;
|
||||||
|
|
||||||
export default function LazyShazam({ children }) {
|
const shazamIDs = {};
|
||||||
|
|
||||||
|
export default function LazyShazam({ id, children }) {
|
||||||
const containerRef = useRef();
|
const containerRef = useRef();
|
||||||
|
const hasID = !!shazamIDs[id];
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [visibleStart, setVisibleStart] = useState(false);
|
const [visibleStart, setVisibleStart] = useState(hasID || false);
|
||||||
|
|
||||||
const { ref } = useInView({
|
const { ref } = useInView({
|
||||||
root: null,
|
root: null,
|
||||||
|
@ -20,6 +23,7 @@ export default function LazyShazam({ children }) {
|
||||||
onChange: (inView) => {
|
onChange: (inView) => {
|
||||||
if (inView) {
|
if (inView) {
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
if (id) shazamIDs[id] = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
triggerOnce: true,
|
triggerOnce: true,
|
||||||
|
@ -35,6 +39,7 @@ export default function LazyShazam({ children }) {
|
||||||
} else {
|
} else {
|
||||||
setVisibleStart(true);
|
setVisibleStart(true);
|
||||||
}
|
}
|
||||||
|
if (id) shazamIDs[id] = true;
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
|
@ -825,6 +825,12 @@
|
||||||
.timeline-deck .status .content.truncated ~ .card {
|
.timeline-deck .status .content.truncated ~ .card {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
.status .content .inner-content {
|
||||||
|
> img[height] {
|
||||||
|
height: auto;
|
||||||
|
aspect-ratio: var(--original-aspect-ratio);
|
||||||
|
}
|
||||||
|
}
|
||||||
.status .content .inner-content a:not(.mention, .has-url-text) {
|
.status .content .inner-content a:not(.mention, .has-url-text) {
|
||||||
color: var(--link-text-color);
|
color: var(--link-text-color);
|
||||||
}
|
}
|
||||||
|
@ -2380,8 +2386,8 @@ a.card:is(:hover, :focus):visited {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: 1.2em;
|
height: 1.2em;
|
||||||
vertical-align: text-bottom;
|
vertical-align: text-bottom;
|
||||||
object-fit: cover;
|
object-fit: contain;
|
||||||
object-position: left;
|
/* object-position: left; */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EDIT HISTORY */
|
/* EDIT HISTORY */
|
||||||
|
|
|
@ -3337,7 +3337,7 @@ const QuoteStatuses = memo(({ id, instance, level = 0 }) => {
|
||||||
|
|
||||||
return uniqueQuotes.map((q) => {
|
return uniqueQuotes.map((q) => {
|
||||||
return (
|
return (
|
||||||
<LazyShazam>
|
<LazyShazam id={q.instance + q.id}>
|
||||||
<Link
|
<Link
|
||||||
key={q.instance + q.id}
|
key={q.instance + q.id}
|
||||||
to={`${q.instance ? `/${q.instance}` : ''}/s/${q.id}`}
|
to={`${q.instance ? `/${q.instance}` : ''}/s/${q.id}`}
|
||||||
|
|
|
@ -209,8 +209,8 @@ function Timeline({
|
||||||
|
|
||||||
const oRef = useHotkeys(['enter', 'o'], () => {
|
const oRef = useHotkeys(['enter', 'o'], () => {
|
||||||
// open active status
|
// open active status
|
||||||
const activeItem = document.activeElement.closest(itemsSelector);
|
const activeItem = document.activeElement;
|
||||||
if (activeItem) {
|
if (activeItem?.matches(itemsSelector)) {
|
||||||
activeItem.click();
|
activeItem.click();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { lazy } from 'preact/compat';
|
||||||
import { useEffect, useState } from 'preact/hooks';
|
import { useEffect, useState } from 'preact/hooks';
|
||||||
|
|
||||||
import IntlSegmenterSuspense from './components/intl-segmenter-suspense';
|
import IntlSegmenterSuspense from './components/intl-segmenter-suspense';
|
||||||
|
import { initStates } from './utils/states';
|
||||||
// import Compose from './components/compose';
|
// import Compose from './components/compose';
|
||||||
import useTitle from './utils/useTitle';
|
import useTitle from './utils/useTitle';
|
||||||
|
|
||||||
|
@ -31,6 +32,10 @@ function App() {
|
||||||
: 'Compose',
|
: 'Compose',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
initStates();
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (uiState === 'closed') {
|
if (uiState === 'closed') {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -286,7 +286,13 @@ function FiltersAddEdit({ filter, onClose }) {
|
||||||
// Preserve existing expiry if not specified
|
// Preserve existing expiry if not specified
|
||||||
// Seconds from now to expiresAtDate
|
// Seconds from now to expiresAtDate
|
||||||
// Other clients don't do this
|
// Other clients don't do this
|
||||||
expiresIn = Math.floor((expiresAtDate - new Date()) / 1000);
|
if (hasExpiry) {
|
||||||
|
expiresIn = Math.floor(
|
||||||
|
(expiresAtDate - new Date()) / 1000,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
expiresIn = null;
|
||||||
|
}
|
||||||
} else if (expiresIn === '0' || expiresIn === 0) {
|
} else if (expiresIn === '0' || expiresIn === 0) {
|
||||||
// 0 = Never
|
// 0 = Never
|
||||||
expiresIn = null;
|
expiresIn = null;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import './login.css';
|
import './login.css';
|
||||||
|
|
||||||
|
import Fuse from 'fuse.js';
|
||||||
import { useEffect, useRef, useState } from 'preact/hooks';
|
import { useEffect, useRef, useState } from 'preact/hooks';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
|
||||||
|
@ -27,12 +28,14 @@ function Login() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const [instancesList, setInstancesList] = useState([]);
|
const [instancesList, setInstancesList] = useState([]);
|
||||||
|
const searcher = useRef();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(instancesListURL);
|
const res = await fetch(instancesListURL);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
setInstancesList(data);
|
setInstancesList(data);
|
||||||
|
searcher.current = new Fuse(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Silently fail
|
// Silently fail
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
@ -90,21 +93,11 @@ function Login() {
|
||||||
!/[\s\/\\@]/.test(cleanInstanceText);
|
!/[\s\/\\@]/.test(cleanInstanceText);
|
||||||
|
|
||||||
const instancesSuggestions = cleanInstanceText
|
const instancesSuggestions = cleanInstanceText
|
||||||
? instancesList
|
? searcher.current
|
||||||
.filter((instance) => instance.includes(instanceText))
|
?.search(cleanInstanceText, {
|
||||||
.sort((a, b) => {
|
limit: 10,
|
||||||
// Move text that starts with instanceText to the start
|
|
||||||
const aStartsWith = a
|
|
||||||
.toLowerCase()
|
|
||||||
.startsWith(instanceText.toLowerCase());
|
|
||||||
const bStartsWith = b
|
|
||||||
.toLowerCase()
|
|
||||||
.startsWith(instanceText.toLowerCase());
|
|
||||||
if (aStartsWith && !bStartsWith) return -1;
|
|
||||||
if (!aStartsWith && bStartsWith) return 1;
|
|
||||||
return 0;
|
|
||||||
})
|
})
|
||||||
.slice(0, 10)
|
?.map((match) => match.item)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const selectedInstanceText = instanceTextLooksLikeDomain
|
const selectedInstanceText = instanceTextLooksLikeDomain
|
||||||
|
|
|
@ -242,6 +242,17 @@ function _enhanceContent(content, opts = {}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ADD ASPECT RATIO TO ALL IMAGES
|
||||||
|
if (enhancedContent.includes('<img')) {
|
||||||
|
dom.querySelectorAll('img').forEach((img) => {
|
||||||
|
const width = img.getAttribute('width') || img.naturalWidth;
|
||||||
|
const height = img.getAttribute('height') || img.naturalHeight;
|
||||||
|
if (width && height) {
|
||||||
|
img.style.setProperty('--original-aspect-ratio', `${width}/${height}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (postEnhanceDOM) {
|
if (postEnhanceDOM) {
|
||||||
queueMicrotask(() => postEnhanceDOM(dom));
|
queueMicrotask(() => postEnhanceDOM(dom));
|
||||||
// postEnhanceDOM(dom); // mutate dom
|
// postEnhanceDOM(dom); // mutate dom
|
||||||
|
|
Loading…
Reference in a new issue