mirror of
https://github.com/cheeaun/phanpy.git
synced 2024-11-21 16:55:25 +03:00
Experimental Shortcuts settings import/export
This commit is contained in:
parent
4817eddc2a
commit
8790b20354
7 changed files with 551 additions and 144 deletions
280
package-lock.json
generated
280
package-lock.json
generated
|
@ -10,21 +10,22 @@
|
|||
"dependencies": {
|
||||
"@formatjs/intl-localematcher": "~0.4.0",
|
||||
"@github/text-expander-element": "~2.5.0",
|
||||
"@iconify-icons/mingcute": "~1.2.6",
|
||||
"@iconify-icons/mingcute": "~1.2.7",
|
||||
"@justinribeiro/lite-youtube": "~1.5.0",
|
||||
"@szhsin/react-menu": "~4.0.2",
|
||||
"@uidotdev/usehooks": "~2.0.1",
|
||||
"@szhsin/react-menu": "~4.0.3",
|
||||
"@uidotdev/usehooks": "~2.1.0",
|
||||
"dayjs": "~1.11.9",
|
||||
"dayjs-twitter": "~0.5.0",
|
||||
"fast-blurhash": "~1.1.2",
|
||||
"fast-deep-equal": "~3.1.3",
|
||||
"idb-keyval": "~6.2.1",
|
||||
"just-debounce-it": "~3.2.0",
|
||||
"lz-string": "^1.5.0",
|
||||
"masto": "~5.11.4",
|
||||
"mem": "~9.0.2",
|
||||
"p-retry": "~5.1.2",
|
||||
"p-throttle": "~5.1.0",
|
||||
"preact": "~10.16.0",
|
||||
"preact": "~10.17.0",
|
||||
"react-hotkeys-hook": "~4.4.1",
|
||||
"react-intersection-observer": "~9.5.2",
|
||||
"react-quick-pinch-zoom": "~4.9.0",
|
||||
|
@ -42,10 +43,10 @@
|
|||
"@preact/preset-vite": "~2.5.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "~4.2.0",
|
||||
"postcss": "~8.4.27",
|
||||
"postcss-dark-theme-class": "~0.7.3",
|
||||
"postcss-preset-env": "~9.1.0",
|
||||
"postcss-dark-theme-class": "~0.8.0",
|
||||
"postcss-preset-env": "~9.1.1",
|
||||
"twitter-text": "~3.1.0",
|
||||
"vite": "~4.4.7",
|
||||
"vite": "~4.4.9",
|
||||
"vite-plugin-generate-file": "~0.0.4",
|
||||
"vite-plugin-html-config": "~1.0.11",
|
||||
"vite-plugin-pwa": "~0.16.4",
|
||||
|
@ -1965,9 +1966,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@csstools/media-query-list-parser": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.3.tgz",
|
||||
"integrity": "sha512-ATul1u+pic4aVpstgueqxEv4MsObEbszAxfTXpx9LHaeD3LAh+wFqdCteyegWmjk0k5rkSCAvIOaJe9U3DD09w==",
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.4.tgz",
|
||||
"integrity": "sha512-V/OUXYX91tAC1CDsiY+HotIcJR+vPtzrX8pCplCpT++i8ThZZsq5F5dzZh/bDM3WUOjrvC1ljed1oSJxMfjqhw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2301,9 +2302,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@csstools/postcss-media-minmax": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.0.6.tgz",
|
||||
"integrity": "sha512-BmwKkqEzzQz6D+5ctoacsiGrq4kVgd1PMEPwkwdR0qFaL2C2nguGsWG87xEw+HIts/2yxhIPTm7Jp3DQq+wn3Q==",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.0.7.tgz",
|
||||
"integrity": "sha512-5LGLdu8cJgRPmvkjUNqOPKIKeHbyQmoGKooB5Rh0mp5mLaNI9bl+IjFZ2keY0cztZYsriJsGf6Lu8R5XetuwoQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2319,7 +2320,7 @@
|
|||
"@csstools/css-calc": "^1.1.3",
|
||||
"@csstools/css-parser-algorithms": "^2.3.1",
|
||||
"@csstools/css-tokenizer": "^2.2.0",
|
||||
"@csstools/media-query-list-parser": "^2.1.3"
|
||||
"@csstools/media-query-list-parser": "^2.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14 || ^16 || >=18"
|
||||
|
@ -2329,9 +2330,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-2.0.1.tgz",
|
||||
"integrity": "sha512-UvMYxXT3R011whbxzRwLx7d7eNGyVsnZo7waAmf10ZGnT34XidY+rsdFnk6OdFwuG6FYqw3/tptQEAZOmUgvLw==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-2.0.2.tgz",
|
||||
"integrity": "sha512-kQJR6NvTRidsaRjCdHGjra2+fLoFiDQOm5B2aZrhmXqng/hweXjruboKzB326rxQO2L0m0T+gCKbZgyuncyhLg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2346,7 +2347,7 @@
|
|||
"dependencies": {
|
||||
"@csstools/css-parser-algorithms": "^2.3.1",
|
||||
"@csstools/css-tokenizer": "^2.2.0",
|
||||
"@csstools/media-query-list-parser": "^2.1.3"
|
||||
"@csstools/media-query-list-parser": "^2.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14 || ^16 || >=18"
|
||||
|
@ -3009,9 +3010,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@iconify-icons/mingcute": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@iconify-icons/mingcute/-/mingcute-1.2.6.tgz",
|
||||
"integrity": "sha512-ToWyd3IuI+bU+q51T0GMEv7utgVksEAlzVoTSEK9GmxYG6qvUX0rKo2wMrRA4X+cv9WqDRJqJZN0pue9uUszDQ==",
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@iconify-icons/mingcute/-/mingcute-1.2.7.tgz",
|
||||
"integrity": "sha512-GObX5YACRhYunL6L8nJ3PGQ+vs9vzvsx8FBZSCs2S3awMwIPKpWPVnjIlx7urnyN5qJoHZGV0iiEVjOmdHDTuw==",
|
||||
"dependencies": {
|
||||
"@iconify/types": "*"
|
||||
}
|
||||
|
@ -3249,9 +3250,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@szhsin/react-menu": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-4.0.2.tgz",
|
||||
"integrity": "sha512-cYpktkWng7jCTPKog33w5iYldbaHQso5aJFd+7j3SkhInqYWjxiG0TtxUS0c5yFqLm6woGQEJHiBpiYHIaYMxg==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-4.0.3.tgz",
|
||||
"integrity": "sha512-TPsOKLEkesE79802evnLt2Mbv/+zwRJdX8776/vxK5ST9SK8SO0A8kRrus6JuxijLxZxFpmY/3VMdoyeCWQHKA==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.7.2",
|
||||
"react-transition-state": "^2.1.0"
|
||||
|
@ -3395,9 +3396,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@uidotdev/usehooks": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.0.1.tgz",
|
||||
"integrity": "sha512-rJXxE3Y8g9utRbOS9Pj9tIvrnOdaakHIhLbMxBlErV8HydnGD0DveD82aLBfVTh1hBp5IXqpeHpMrPE9WIT7vQ==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.1.0.tgz",
|
||||
"integrity": "sha512-D7SJiNQC1BOHgtE2dy2KvOtnRNaLWTFFHvcBLg7lZ8Jz7YcimxdUY3spqpvf/mVkGCuUHee8i/79p5vVkBgsYQ==",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
|
@ -3710,9 +3711,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.21.9",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
|
||||
"integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
|
||||
"version": "4.21.10",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
|
||||
"integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -3729,9 +3730,9 @@
|
|||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001503",
|
||||
"electron-to-chromium": "^1.4.431",
|
||||
"node-releases": "^2.0.12",
|
||||
"caniuse-lite": "^1.0.30001517",
|
||||
"electron-to-chromium": "^1.4.477",
|
||||
"node-releases": "^2.0.13",
|
||||
"update-browserslist-db": "^1.0.11"
|
||||
},
|
||||
"bin": {
|
||||
|
@ -3781,9 +3782,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001512",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz",
|
||||
"integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==",
|
||||
"version": "1.0.30001519",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz",
|
||||
"integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -4139,9 +4140,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.451",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.451.tgz",
|
||||
"integrity": "sha512-YYbXHIBxAHe3KWvGOJOuWa6f3tgow44rBW+QAuwVp2DvGqNZeE//K2MowNdWS7XE8li5cgQDrX1LdBr41LufkA==",
|
||||
"version": "1.4.490",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz",
|
||||
"integrity": "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
|
@ -5280,6 +5281,14 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/lz-string": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
|
||||
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
|
||||
"bin": {
|
||||
"lz-string": "bin/bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.25.9",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
|
||||
|
@ -5485,9 +5494,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.12",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
|
||||
"integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==",
|
||||
"version": "2.0.13",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
|
||||
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/normalize-range": {
|
||||
|
@ -5862,16 +5871,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss-dark-theme-class": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/postcss-dark-theme-class/-/postcss-dark-theme-class-0.7.3.tgz",
|
||||
"integrity": "sha512-M9vtfh8ORzQsVdT9BWb+xpEDAzC7nHBn7wVc988/JkEVLPupKcUnV0jw7RZ8sSj0ovpqN1POf6PLdt19JCHfhQ==",
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-dark-theme-class/-/postcss-dark-theme-class-0.8.0.tgz",
|
||||
"integrity": "sha512-/zyywenvSJVlG1Ie/MLkQBhoh0sTOKPQa+3exaBVAmeITuGscGZu1NuJc5qpv2+ywIkBujL9OU26bj0DdUgY2Q==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
"node": ">=18.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"postcss": "^8.2.14"
|
||||
|
@ -6097,9 +6112,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss-nesting": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.0.0.tgz",
|
||||
"integrity": "sha512-knqwW65kxssmyIFadRSimaiRyLVRd0MdwfabesKw6XvGLwSOCJ+4zfvNQQCOOYij5obwpZzDpODuGRv2PCyiUw==",
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.0.1.tgz",
|
||||
"integrity": "sha512-6LCqCWP9pqwXw/njMvNK0hGY44Fxc4B2EsGbn6xDcxbNRzP8GYoxT7yabVVMLrX3quqOJ9hg2jYMsnkedOf8pA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -6204,9 +6219,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss-preset-env": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.1.0.tgz",
|
||||
"integrity": "sha512-G+x9BD7jb9uHBB7o720emXV00CP+VdWeirJsHC5ERSpbTd2e6Xg7vHzT+a6UkxFyddALuV+Q8wJMgeTKaau+Pg==",
|
||||
"version": "9.1.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.1.1.tgz",
|
||||
"integrity": "sha512-rMPEqyTLm8JLbvaHnDAdQg6SN4Z/NDOsm+CRefg4HmSOiNpTcBXaw4RAaQbfTNe8BB75l4NpoQ6sMdrutdEpdQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -6231,8 +6246,8 @@
|
|||
"@csstools/postcss-logical-float-and-clear": "^2.0.0",
|
||||
"@csstools/postcss-logical-resize": "^2.0.0",
|
||||
"@csstools/postcss-logical-viewport-units": "^2.0.1",
|
||||
"@csstools/postcss-media-minmax": "^1.0.6",
|
||||
"@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.1",
|
||||
"@csstools/postcss-media-minmax": "^1.0.7",
|
||||
"@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.2",
|
||||
"@csstools/postcss-nested-calc": "^3.0.0",
|
||||
"@csstools/postcss-normalize-display-values": "^3.0.0",
|
||||
"@csstools/postcss-oklab-function": "^3.0.1",
|
||||
|
@ -6244,7 +6259,7 @@
|
|||
"@csstools/postcss-trigonometric-functions": "^3.0.1",
|
||||
"@csstools/postcss-unset-value": "^3.0.0",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"browserslist": "^4.21.9",
|
||||
"browserslist": "^4.21.10",
|
||||
"css-blank-pseudo": "^6.0.0",
|
||||
"css-has-pseudo": "^6.0.0",
|
||||
"css-prefers-color-scheme": "^9.0.0",
|
||||
|
@ -6267,7 +6282,7 @@
|
|||
"postcss-initial": "^4.0.1",
|
||||
"postcss-lab-function": "^6.0.1",
|
||||
"postcss-logical": "^7.0.0",
|
||||
"postcss-nesting": "^12.0.0",
|
||||
"postcss-nesting": "^12.0.1",
|
||||
"postcss-opacity-percentage": "^2.0.0",
|
||||
"postcss-overflow-shorthand": "^5.0.0",
|
||||
"postcss-page-break": "^3.0.4",
|
||||
|
@ -6357,9 +6372,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/preact": {
|
||||
"version": "10.16.0",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.16.0.tgz",
|
||||
"integrity": "sha512-XTSj3dJ4roKIC93pald6rWuB2qQJO9gO2iLLyTe87MrjQN+HklueLsmskbywEWqCHlclgz3/M4YLL2iBr9UmMA==",
|
||||
"version": "10.17.0",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.17.0.tgz",
|
||||
"integrity": "sha512-SNsI8cbaCcUS5tbv9nlXuCfIXnJ9ysBMWk0WnB6UWwcVA3qZ2O6FxqDFECMAMttvLQcW/HaNZUe2BLidyvrVYw==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/preact"
|
||||
|
@ -6699,9 +6714,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "3.26.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz",
|
||||
"integrity": "sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==",
|
||||
"version": "3.28.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz",
|
||||
"integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
|
@ -7362,14 +7377,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "4.4.7",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz",
|
||||
"integrity": "sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==",
|
||||
"version": "4.4.9",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
|
||||
"integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.18.10",
|
||||
"postcss": "^8.4.26",
|
||||
"rollup": "^3.25.2"
|
||||
"postcss": "^8.4.27",
|
||||
"rollup": "^3.27.1"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
|
@ -9230,9 +9245,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@csstools/media-query-list-parser": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.3.tgz",
|
||||
"integrity": "sha512-ATul1u+pic4aVpstgueqxEv4MsObEbszAxfTXpx9LHaeD3LAh+wFqdCteyegWmjk0k5rkSCAvIOaJe9U3DD09w==",
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.4.tgz",
|
||||
"integrity": "sha512-V/OUXYX91tAC1CDsiY+HotIcJR+vPtzrX8pCplCpT++i8ThZZsq5F5dzZh/bDM3WUOjrvC1ljed1oSJxMfjqhw==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
@ -9359,26 +9374,26 @@
|
|||
}
|
||||
},
|
||||
"@csstools/postcss-media-minmax": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.0.6.tgz",
|
||||
"integrity": "sha512-BmwKkqEzzQz6D+5ctoacsiGrq4kVgd1PMEPwkwdR0qFaL2C2nguGsWG87xEw+HIts/2yxhIPTm7Jp3DQq+wn3Q==",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.0.7.tgz",
|
||||
"integrity": "sha512-5LGLdu8cJgRPmvkjUNqOPKIKeHbyQmoGKooB5Rh0mp5mLaNI9bl+IjFZ2keY0cztZYsriJsGf6Lu8R5XetuwoQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@csstools/css-calc": "^1.1.3",
|
||||
"@csstools/css-parser-algorithms": "^2.3.1",
|
||||
"@csstools/css-tokenizer": "^2.2.0",
|
||||
"@csstools/media-query-list-parser": "^2.1.3"
|
||||
"@csstools/media-query-list-parser": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"@csstools/postcss-media-queries-aspect-ratio-number-values": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-2.0.1.tgz",
|
||||
"integrity": "sha512-UvMYxXT3R011whbxzRwLx7d7eNGyVsnZo7waAmf10ZGnT34XidY+rsdFnk6OdFwuG6FYqw3/tptQEAZOmUgvLw==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-2.0.2.tgz",
|
||||
"integrity": "sha512-kQJR6NvTRidsaRjCdHGjra2+fLoFiDQOm5B2aZrhmXqng/hweXjruboKzB326rxQO2L0m0T+gCKbZgyuncyhLg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@csstools/css-parser-algorithms": "^2.3.1",
|
||||
"@csstools/css-tokenizer": "^2.2.0",
|
||||
"@csstools/media-query-list-parser": "^2.1.3"
|
||||
"@csstools/media-query-list-parser": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"@csstools/postcss-nested-calc": {
|
||||
|
@ -9663,9 +9678,9 @@
|
|||
}
|
||||
},
|
||||
"@iconify-icons/mingcute": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@iconify-icons/mingcute/-/mingcute-1.2.6.tgz",
|
||||
"integrity": "sha512-ToWyd3IuI+bU+q51T0GMEv7utgVksEAlzVoTSEK9GmxYG6qvUX0rKo2wMrRA4X+cv9WqDRJqJZN0pue9uUszDQ==",
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@iconify-icons/mingcute/-/mingcute-1.2.7.tgz",
|
||||
"integrity": "sha512-GObX5YACRhYunL6L8nJ3PGQ+vs9vzvsx8FBZSCs2S3awMwIPKpWPVnjIlx7urnyN5qJoHZGV0iiEVjOmdHDTuw==",
|
||||
"requires": {
|
||||
"@iconify/types": "*"
|
||||
}
|
||||
|
@ -9865,9 +9880,9 @@
|
|||
}
|
||||
},
|
||||
"@szhsin/react-menu": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-4.0.2.tgz",
|
||||
"integrity": "sha512-cYpktkWng7jCTPKog33w5iYldbaHQso5aJFd+7j3SkhInqYWjxiG0TtxUS0c5yFqLm6woGQEJHiBpiYHIaYMxg==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-4.0.3.tgz",
|
||||
"integrity": "sha512-TPsOKLEkesE79802evnLt2Mbv/+zwRJdX8776/vxK5ST9SK8SO0A8kRrus6JuxijLxZxFpmY/3VMdoyeCWQHKA==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2",
|
||||
"react-transition-state": "^2.1.0"
|
||||
|
@ -9987,9 +10002,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@uidotdev/usehooks": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.0.1.tgz",
|
||||
"integrity": "sha512-rJXxE3Y8g9utRbOS9Pj9tIvrnOdaakHIhLbMxBlErV8HydnGD0DveD82aLBfVTh1hBp5IXqpeHpMrPE9WIT7vQ==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.1.0.tgz",
|
||||
"integrity": "sha512-D7SJiNQC1BOHgtE2dy2KvOtnRNaLWTFFHvcBLg7lZ8Jz7YcimxdUY3spqpvf/mVkGCuUHee8i/79p5vVkBgsYQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"@vue/compiler-core": {
|
||||
|
@ -10229,14 +10244,14 @@
|
|||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.21.9",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
|
||||
"integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
|
||||
"version": "4.21.10",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
|
||||
"integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001503",
|
||||
"electron-to-chromium": "^1.4.431",
|
||||
"node-releases": "^2.0.12",
|
||||
"caniuse-lite": "^1.0.30001517",
|
||||
"electron-to-chromium": "^1.4.477",
|
||||
"node-releases": "^2.0.13",
|
||||
"update-browserslist-db": "^1.0.11"
|
||||
}
|
||||
},
|
||||
|
@ -10271,9 +10286,9 @@
|
|||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001512",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz",
|
||||
"integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==",
|
||||
"version": "1.0.30001519",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz",
|
||||
"integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==",
|
||||
"dev": true
|
||||
},
|
||||
"capital-case": {
|
||||
|
@ -10505,9 +10520,9 @@
|
|||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.451",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.451.tgz",
|
||||
"integrity": "sha512-YYbXHIBxAHe3KWvGOJOuWa6f3tgow44rBW+QAuwVp2DvGqNZeE//K2MowNdWS7XE8li5cgQDrX1LdBr41LufkA==",
|
||||
"version": "1.4.490",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz",
|
||||
"integrity": "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==",
|
||||
"dev": true
|
||||
},
|
||||
"es-abstract": {
|
||||
|
@ -11357,6 +11372,11 @@
|
|||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"lz-string": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
|
||||
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="
|
||||
},
|
||||
"magic-string": {
|
||||
"version": "0.25.9",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
|
||||
|
@ -11507,9 +11527,9 @@
|
|||
}
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "2.0.12",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
|
||||
"integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==",
|
||||
"version": "2.0.13",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
|
||||
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-range": {
|
||||
|
@ -11719,9 +11739,9 @@
|
|||
}
|
||||
},
|
||||
"postcss-dark-theme-class": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/postcss-dark-theme-class/-/postcss-dark-theme-class-0.7.3.tgz",
|
||||
"integrity": "sha512-M9vtfh8ORzQsVdT9BWb+xpEDAzC7nHBn7wVc988/JkEVLPupKcUnV0jw7RZ8sSj0ovpqN1POf6PLdt19JCHfhQ==",
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-dark-theme-class/-/postcss-dark-theme-class-0.8.0.tgz",
|
||||
"integrity": "sha512-/zyywenvSJVlG1Ie/MLkQBhoh0sTOKPQa+3exaBVAmeITuGscGZu1NuJc5qpv2+ywIkBujL9OU26bj0DdUgY2Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
@ -11814,9 +11834,9 @@
|
|||
}
|
||||
},
|
||||
"postcss-nesting": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.0.0.tgz",
|
||||
"integrity": "sha512-knqwW65kxssmyIFadRSimaiRyLVRd0MdwfabesKw6XvGLwSOCJ+4zfvNQQCOOYij5obwpZzDpODuGRv2PCyiUw==",
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.0.1.tgz",
|
||||
"integrity": "sha512-6LCqCWP9pqwXw/njMvNK0hGY44Fxc4B2EsGbn6xDcxbNRzP8GYoxT7yabVVMLrX3quqOJ9hg2jYMsnkedOf8pA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@csstools/selector-specificity": "^3.0.0",
|
||||
|
@ -11856,9 +11876,9 @@
|
|||
}
|
||||
},
|
||||
"postcss-preset-env": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.1.0.tgz",
|
||||
"integrity": "sha512-G+x9BD7jb9uHBB7o720emXV00CP+VdWeirJsHC5ERSpbTd2e6Xg7vHzT+a6UkxFyddALuV+Q8wJMgeTKaau+Pg==",
|
||||
"version": "9.1.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.1.1.tgz",
|
||||
"integrity": "sha512-rMPEqyTLm8JLbvaHnDAdQg6SN4Z/NDOsm+CRefg4HmSOiNpTcBXaw4RAaQbfTNe8BB75l4NpoQ6sMdrutdEpdQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@csstools/postcss-cascade-layers": "^4.0.0",
|
||||
|
@ -11873,8 +11893,8 @@
|
|||
"@csstools/postcss-logical-float-and-clear": "^2.0.0",
|
||||
"@csstools/postcss-logical-resize": "^2.0.0",
|
||||
"@csstools/postcss-logical-viewport-units": "^2.0.1",
|
||||
"@csstools/postcss-media-minmax": "^1.0.6",
|
||||
"@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.1",
|
||||
"@csstools/postcss-media-minmax": "^1.0.7",
|
||||
"@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.2",
|
||||
"@csstools/postcss-nested-calc": "^3.0.0",
|
||||
"@csstools/postcss-normalize-display-values": "^3.0.0",
|
||||
"@csstools/postcss-oklab-function": "^3.0.1",
|
||||
|
@ -11886,7 +11906,7 @@
|
|||
"@csstools/postcss-trigonometric-functions": "^3.0.1",
|
||||
"@csstools/postcss-unset-value": "^3.0.0",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"browserslist": "^4.21.9",
|
||||
"browserslist": "^4.21.10",
|
||||
"css-blank-pseudo": "^6.0.0",
|
||||
"css-has-pseudo": "^6.0.0",
|
||||
"css-prefers-color-scheme": "^9.0.0",
|
||||
|
@ -11909,7 +11929,7 @@
|
|||
"postcss-initial": "^4.0.1",
|
||||
"postcss-lab-function": "^6.0.1",
|
||||
"postcss-logical": "^7.0.0",
|
||||
"postcss-nesting": "^12.0.0",
|
||||
"postcss-nesting": "^12.0.1",
|
||||
"postcss-opacity-percentage": "^2.0.0",
|
||||
"postcss-overflow-shorthand": "^5.0.0",
|
||||
"postcss-page-break": "^3.0.4",
|
||||
|
@ -11962,9 +11982,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"preact": {
|
||||
"version": "10.16.0",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.16.0.tgz",
|
||||
"integrity": "sha512-XTSj3dJ4roKIC93pald6rWuB2qQJO9gO2iLLyTe87MrjQN+HklueLsmskbywEWqCHlclgz3/M4YLL2iBr9UmMA=="
|
||||
"version": "10.17.0",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.17.0.tgz",
|
||||
"integrity": "sha512-SNsI8cbaCcUS5tbv9nlXuCfIXnJ9ysBMWk0WnB6UWwcVA3qZ2O6FxqDFECMAMttvLQcW/HaNZUe2BLidyvrVYw=="
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.8.0",
|
||||
|
@ -12191,9 +12211,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"rollup": {
|
||||
"version": "3.26.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz",
|
||||
"integrity": "sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==",
|
||||
"version": "3.28.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz",
|
||||
"integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.3.2"
|
||||
|
@ -12662,15 +12682,15 @@
|
|||
}
|
||||
},
|
||||
"vite": {
|
||||
"version": "4.4.7",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz",
|
||||
"integrity": "sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==",
|
||||
"version": "4.4.9",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
|
||||
"integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esbuild": "^0.18.10",
|
||||
"fsevents": "~2.3.2",
|
||||
"postcss": "^8.4.26",
|
||||
"rollup": "^3.25.2"
|
||||
"postcss": "^8.4.27",
|
||||
"rollup": "^3.27.1"
|
||||
}
|
||||
},
|
||||
"vite-plugin-generate-file": {
|
||||
|
|
15
package.json
15
package.json
|
@ -12,21 +12,22 @@
|
|||
"dependencies": {
|
||||
"@formatjs/intl-localematcher": "~0.4.0",
|
||||
"@github/text-expander-element": "~2.5.0",
|
||||
"@iconify-icons/mingcute": "~1.2.6",
|
||||
"@iconify-icons/mingcute": "~1.2.7",
|
||||
"@justinribeiro/lite-youtube": "~1.5.0",
|
||||
"@szhsin/react-menu": "~4.0.2",
|
||||
"@uidotdev/usehooks": "~2.0.1",
|
||||
"@szhsin/react-menu": "~4.0.3",
|
||||
"@uidotdev/usehooks": "~2.1.0",
|
||||
"dayjs": "~1.11.9",
|
||||
"dayjs-twitter": "~0.5.0",
|
||||
"fast-blurhash": "~1.1.2",
|
||||
"fast-deep-equal": "~3.1.3",
|
||||
"idb-keyval": "~6.2.1",
|
||||
"just-debounce-it": "~3.2.0",
|
||||
"lz-string": "^1.5.0",
|
||||
"masto": "~5.11.4",
|
||||
"mem": "~9.0.2",
|
||||
"p-retry": "~5.1.2",
|
||||
"p-throttle": "~5.1.0",
|
||||
"preact": "~10.16.0",
|
||||
"preact": "~10.17.0",
|
||||
"react-hotkeys-hook": "~4.4.1",
|
||||
"react-intersection-observer": "~9.5.2",
|
||||
"react-quick-pinch-zoom": "~4.9.0",
|
||||
|
@ -44,10 +45,10 @@
|
|||
"@preact/preset-vite": "~2.5.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "~4.2.0",
|
||||
"postcss": "~8.4.27",
|
||||
"postcss-dark-theme-class": "~0.7.3",
|
||||
"postcss-preset-env": "~9.1.0",
|
||||
"postcss-dark-theme-class": "~0.8.0",
|
||||
"postcss-preset-env": "~9.1.1",
|
||||
"twitter-text": "~3.1.0",
|
||||
"vite": "~4.4.7",
|
||||
"vite": "~4.4.9",
|
||||
"vite-plugin-generate-file": "~0.0.4",
|
||||
"vite-plugin-html-config": "~1.0.11",
|
||||
"vite-plugin-pwa": "~0.16.4",
|
||||
|
|
|
@ -1417,6 +1417,11 @@ body:has(.media-modal-container + .status-deck) .media-post-link {
|
|||
.tag.collapsed {
|
||||
margin: 0;
|
||||
}
|
||||
.tag.insignificant {
|
||||
border: 1px solid var(--outline-color);
|
||||
color: var(--text-insignificant-color);
|
||||
background-color: var(--bg-faded-color);
|
||||
}
|
||||
.tag.danger {
|
||||
background-color: var(--red-color);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,11 @@ export const ICONS = {
|
|||
announce: () => import('@iconify-icons/mingcute/announcement-line'),
|
||||
alert: () => import('@iconify-icons/mingcute/alert-line'),
|
||||
round: () => import('@iconify-icons/mingcute/round-fill'),
|
||||
'arrow-up-circle': () =>
|
||||
import('@iconify-icons/mingcute/arrow-up-circle-line'),
|
||||
'arrow-down-circle': () =>
|
||||
import('@iconify-icons/mingcute/arrow-down-circle-line'),
|
||||
clipboard: () => import('@iconify-icons/mingcute/clipboard-line'),
|
||||
};
|
||||
|
||||
function Icon({
|
||||
|
|
|
@ -126,3 +126,52 @@
|
|||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
/* Import/Export */
|
||||
|
||||
#import-export-container input[type='text'] {
|
||||
font-family: var(--monospace-font);
|
||||
}
|
||||
#import-export-container section {
|
||||
margin: 8px 0;
|
||||
background-color: var(--bg-faded-color);
|
||||
border-radius: 16px;
|
||||
padding: 8px;
|
||||
}
|
||||
#import-export-container section h3 {
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
#import-export-container section h3 * {
|
||||
vertical-align: middle;
|
||||
}
|
||||
#import-export-container section p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
#import-export-container section details > summary {
|
||||
cursor: pointer;
|
||||
}
|
||||
#import-export-container .import-settings-list {
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin: 8px 0 0;
|
||||
padding: 0;
|
||||
counter-reset: index;
|
||||
}
|
||||
#import-export-container .import-settings-list li {
|
||||
background-color: var(--bg-blur-color);
|
||||
margin: 0 0 2px;
|
||||
padding: 8px 4px;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
}
|
||||
#import-export-container .import-settings-list li::before {
|
||||
content: counter(index);
|
||||
counter-increment: index;
|
||||
display: inline-block;
|
||||
width: 1.2em;
|
||||
text-align: right;
|
||||
margin-right: 8px;
|
||||
color: var(--text-insignificant-color);
|
||||
font-size: 90%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
import './shortcuts-settings.css';
|
||||
|
||||
import {
|
||||
compressToEncodedURIComponent,
|
||||
decompressFromEncodedURIComponent,
|
||||
} from 'lz-string';
|
||||
import mem from 'mem';
|
||||
import { useEffect, useRef, useState } from 'preact/hooks';
|
||||
import { useEffect, useMemo, useRef, useState } from 'preact/hooks';
|
||||
import { useSnapshot } from 'valtio';
|
||||
|
||||
import floatingButtonUrl from '../assets/floating-button.svg';
|
||||
import multiColumnUrl from '../assets/multi-column.svg';
|
||||
import tabMenuBarUrl from '../assets/tab-menu-bar.svg';
|
||||
import { api } from '../utils/api';
|
||||
import showToast from '../utils/show-toast';
|
||||
import states from '../utils/states';
|
||||
|
||||
import AsyncText from './AsyncText';
|
||||
import Icon from './icon';
|
||||
import MenuConfirm from './menu-confirm';
|
||||
import Modal from './modal';
|
||||
|
||||
const SHORTCUTS_LIMIT = 9;
|
||||
|
@ -202,6 +208,7 @@ function ShortcutsSettings({ onClose }) {
|
|||
const [lists, setLists] = useState([]);
|
||||
const [followedHashtags, setFollowedHashtags] = useState([]);
|
||||
const [showForm, setShowForm] = useState(false);
|
||||
const [showImportExport, setShowImportExport] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
|
@ -432,6 +439,10 @@ function ShortcutsSettings({ onClose }) {
|
|||
</p>
|
||||
</div>
|
||||
)}
|
||||
<p class="insignificant">
|
||||
{shortcuts.length >= SHORTCUTS_LIMIT &&
|
||||
`Max ${SHORTCUTS_LIMIT} shortcuts`}
|
||||
</p>
|
||||
<p
|
||||
style={{
|
||||
display: 'flex',
|
||||
|
@ -439,10 +450,13 @@ function ShortcutsSettings({ onClose }) {
|
|||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<span class="insignificant">
|
||||
{shortcuts.length >= SHORTCUTS_LIMIT &&
|
||||
`Max ${SHORTCUTS_LIMIT} shortcuts`}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
class="light"
|
||||
onClick={() => setShowImportExport(true)}
|
||||
>
|
||||
Import/export
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
disabled={shortcuts.length >= SHORTCUTS_LIMIT}
|
||||
|
@ -478,6 +492,21 @@ function ShortcutsSettings({ onClose }) {
|
|||
/>
|
||||
</Modal>
|
||||
)}
|
||||
{showImportExport && (
|
||||
<Modal
|
||||
class="light"
|
||||
onClick={(e) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
setShowImportExport(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ImportExport
|
||||
shortcuts={shortcuts}
|
||||
onClose={() => setShowImportExport(false)}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -650,4 +679,296 @@ function ShortcutForm({
|
|||
);
|
||||
}
|
||||
|
||||
function ImportExport({ shortcuts, onClose }) {
|
||||
const shortcutsStr = useMemo(
|
||||
() =>
|
||||
compressToEncodedURIComponent(JSON.stringify(shortcuts.filter(Boolean))),
|
||||
[shortcuts],
|
||||
);
|
||||
const [importShortcutStr, setImportShortcutStr] = useState('');
|
||||
const [importUIState, setImportUIState] = useState('default');
|
||||
const parsedImportShortcutStr = useMemo(() => {
|
||||
if (!importShortcutStr) {
|
||||
setImportUIState('default');
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const parsed = JSON.parse(
|
||||
decompressFromEncodedURIComponent(importShortcutStr),
|
||||
);
|
||||
// Very basic validation, I know
|
||||
if (!Array.isArray(parsed)) throw new Error('Not an array');
|
||||
setImportUIState('default');
|
||||
return parsed;
|
||||
} catch (err) {
|
||||
// Fallback to JSON string parsing
|
||||
// There's a chance that someone might want to import a JSON string instead of the compressed version
|
||||
try {
|
||||
const parsed = JSON.parse(importShortcutStr);
|
||||
if (!Array.isArray(parsed)) throw new Error('Not an array');
|
||||
setImportUIState('default');
|
||||
return parsed;
|
||||
} catch (err) {
|
||||
setImportUIState('error');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}, [importShortcutStr]);
|
||||
const hasCurrentSettings = states.shortcuts.length > 0;
|
||||
|
||||
return (
|
||||
<div id="import-export-container" class="sheet">
|
||||
{!!onClose && (
|
||||
<button type="button" class="sheet-close" onClick={onClose}>
|
||||
<Icon icon="x" />
|
||||
</button>
|
||||
)}
|
||||
<header>
|
||||
<h2>
|
||||
Import/Export{' '}
|
||||
<small class="ib insignificant">Shortcuts settings</small>
|
||||
</h2>
|
||||
</header>
|
||||
<main tabindex="-1">
|
||||
<section>
|
||||
<h3>
|
||||
<Icon icon="arrow-down-circle" size="l" class="insignificant" />{' '}
|
||||
<span>Import</span>
|
||||
</h3>
|
||||
<p>
|
||||
<input
|
||||
type="text"
|
||||
name="import"
|
||||
placeholder="Paste settings here"
|
||||
class="block"
|
||||
onInput={(e) => {
|
||||
setImportShortcutStr(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
{!!parsedImportShortcutStr &&
|
||||
Array.isArray(parsedImportShortcutStr) && (
|
||||
<>
|
||||
<p>
|
||||
<b>{parsedImportShortcutStr.length}</b> shortcut
|
||||
{parsedImportShortcutStr.length > 1 ? 's' : ''}{' '}
|
||||
<small class="insignificant">
|
||||
({importShortcutStr.length} characters)
|
||||
</small>
|
||||
</p>
|
||||
<ol class="import-settings-list">
|
||||
{parsedImportShortcutStr.map((shortcut) => (
|
||||
<li>
|
||||
<span
|
||||
style={{
|
||||
opacity: shortcuts.some((s) =>
|
||||
// Compare all properties
|
||||
Object.keys(s).every(
|
||||
(key) => s[key] === shortcut[key],
|
||||
),
|
||||
)
|
||||
? 1
|
||||
: 0,
|
||||
}}
|
||||
>
|
||||
*
|
||||
</span>
|
||||
<span>
|
||||
{TYPE_TEXT[shortcut.type]}
|
||||
{shortcut.type === 'list' && ' ⚠️'}{' '}
|
||||
{TYPE_PARAMS[shortcut.type]?.map?.(
|
||||
({ text, name, type }) =>
|
||||
shortcut[name] ? (
|
||||
<>
|
||||
<span class="tag collapsed insignificant">
|
||||
{text}:{' '}
|
||||
{type === 'checkbox'
|
||||
? shortcut[name] === 'on'
|
||||
? '✅'
|
||||
: '❌'
|
||||
: shortcut[name]}
|
||||
</span>{' '}
|
||||
</>
|
||||
) : null,
|
||||
)}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
<p>
|
||||
<small>* Exists in current settings</small>
|
||||
<br />
|
||||
<small>
|
||||
⚠️ List may not work if it's from a different account.
|
||||
</small>
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
{importUIState === 'error' && (
|
||||
<p class="error">
|
||||
<small>⚠️ Invalid settings format</small>
|
||||
</p>
|
||||
)}
|
||||
<p>
|
||||
{hasCurrentSettings && (
|
||||
<>
|
||||
<MenuConfirm
|
||||
confirmLabel="Append these shortcuts to current settings?"
|
||||
menuFooter={
|
||||
<div class="footer">
|
||||
Only shortcuts that don’t exist in current settings will
|
||||
be appended.
|
||||
</div>
|
||||
}
|
||||
onClick={() => {
|
||||
// states.shortcuts = [
|
||||
// ...states.shortcuts,
|
||||
// ...parsedImportShortcutStr,
|
||||
// ];
|
||||
// Append non-unique shortcuts only
|
||||
const nonUniqueShortcuts = parsedImportShortcutStr.filter(
|
||||
(shortcut) =>
|
||||
!states.shortcuts.some((s) =>
|
||||
// Compare all properties
|
||||
Object.keys(s).every(
|
||||
(key) => s[key] === shortcut[key],
|
||||
),
|
||||
),
|
||||
);
|
||||
if (!nonUniqueShortcuts.length) {
|
||||
showToast('No new shortcuts to import');
|
||||
return;
|
||||
}
|
||||
let newShortcuts = [
|
||||
...states.shortcuts,
|
||||
...nonUniqueShortcuts,
|
||||
];
|
||||
const exceededLimit = newShortcuts.length > SHORTCUTS_LIMIT;
|
||||
if (exceededLimit) {
|
||||
// If exceeded, trim it
|
||||
newShortcuts = newShortcuts.slice(0, SHORTCUTS_LIMIT);
|
||||
}
|
||||
states.shortcuts = newShortcuts;
|
||||
showToast(
|
||||
exceededLimit
|
||||
? `Shortcuts settings imported. Exceeded max ${SHORTCUTS_LIMIT}, so the rest are not imported.`
|
||||
: 'Shortcuts settings imported',
|
||||
);
|
||||
onClose?.();
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="plain2"
|
||||
disabled={!parsedImportShortcutStr}
|
||||
>
|
||||
Import & append…
|
||||
</button>
|
||||
</MenuConfirm>{' '}
|
||||
</>
|
||||
)}
|
||||
<MenuConfirm
|
||||
confirmLabel={
|
||||
hasCurrentSettings
|
||||
? 'Override current settings?'
|
||||
: 'Import settings?'
|
||||
}
|
||||
menuItemClassName={hasCurrentSettings ? 'danger' : undefined}
|
||||
onClick={() => {
|
||||
states.shortcuts = parsedImportShortcutStr;
|
||||
showToast('Shortcuts settings imported');
|
||||
onClose?.();
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="plain2"
|
||||
disabled={!parsedImportShortcutStr}
|
||||
>
|
||||
{hasCurrentSettings ? 'or override…' : 'Import…'}
|
||||
</button>
|
||||
</MenuConfirm>
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<h3>
|
||||
<Icon icon="arrow-up-circle" size="l" class="insignificant" />{' '}
|
||||
<span>Export</span>
|
||||
</h3>
|
||||
<p>
|
||||
<input
|
||||
style={{ width: '100%' }}
|
||||
type="text"
|
||||
value={shortcutsStr}
|
||||
readOnly
|
||||
onClick={(e) => {
|
||||
e.target.select();
|
||||
// Copy url to clipboard
|
||||
try {
|
||||
navigator.clipboard.writeText(e.target.value);
|
||||
showToast('Shortcuts settings copied');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
showToast('Unable to copy shortcuts settings');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<button
|
||||
type="button"
|
||||
class="plain2"
|
||||
onClick={() => {
|
||||
try {
|
||||
navigator.clipboard.writeText(shortcutsStr);
|
||||
showToast('Shortcut settings copied');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
showToast('Unable to copy shortcut settings');
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon icon="clipboard" /> <span>Copy</span>
|
||||
</button>{' '}
|
||||
{navigator?.share &&
|
||||
navigator?.canShare?.({
|
||||
text: shortcutsStr,
|
||||
}) && (
|
||||
<button
|
||||
type="button"
|
||||
class="plain2"
|
||||
onClick={() => {
|
||||
try {
|
||||
navigator.share({
|
||||
text: shortcutsStr,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert("Sharing doesn't seem to work.");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon icon="share" /> <span>Share</span>
|
||||
</button>
|
||||
)}{' '}
|
||||
{shortcutsStr.length > 0 && (
|
||||
<small class="insignificant">
|
||||
{shortcutsStr.length} characters
|
||||
</small>
|
||||
)}
|
||||
</p>
|
||||
<details>
|
||||
<summary class="insignificant">
|
||||
<small>Raw Shortcuts settings JSON</small>
|
||||
</summary>
|
||||
<textarea style={{ width: '100%' }} rows={10} readOnly>
|
||||
{JSON.stringify(shortcuts.filter(Boolean), null, 2)}
|
||||
</textarea>
|
||||
</details>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ShortcutsSettings;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
--main-width: 40em;
|
||||
text-size-adjust: none;
|
||||
--hairline-width: 1px;
|
||||
--monospace-font: ui-monospace, 'SFMono-Regular', Consolas, 'Liberation Mono',
|
||||
Menlo, Courier, monospace;
|
||||
|
||||
--blue-color: royalblue;
|
||||
--purple-color: blueviolet;
|
||||
|
@ -288,6 +290,11 @@ button.large {
|
|||
padding: 12px;
|
||||
}
|
||||
|
||||
:is(input[type='text'], textarea, select).block {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button.small {
|
||||
font-size: 90%;
|
||||
padding: 4px 8px;
|
||||
|
@ -304,8 +311,7 @@ pre {
|
|||
pre code,
|
||||
code {
|
||||
font-size: 90%;
|
||||
font-family: ui-monospace, 'SFMono-Regular', Consolas, 'Liberation Mono',
|
||||
Menlo, Courier, monospace;
|
||||
font-family: var(--monospace-font);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
|
Loading…
Reference in a new issue