summaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'frontend')
-rw-r--r--frontend/package.json11
-rw-r--r--frontend/pnpm-lock.yaml700
-rw-r--r--frontend/src/components/DeckyState.tsx13
-rw-r--r--frontend/src/components/modals/DropdownMultiselect.tsx121
-rw-r--r--frontend/src/components/modals/filepicker/FilePickerError.tsx51
-rw-r--r--frontend/src/components/modals/filepicker/i18n/TSortOptions.tsx46
-rw-r--r--frontend/src/components/modals/filepicker/iconCustomizations.ts2
-rw-r--r--frontend/src/components/modals/filepicker/index.tsx393
-rw-r--r--frontend/src/components/settings/pages/developer/index.tsx26
-rw-r--r--frontend/src/plugin-loader.tsx28
10 files changed, 925 insertions, 466 deletions
diff --git a/frontend/package.json b/frontend/package.json
index de0fd5a2..34c6fd2c 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -22,7 +22,7 @@
"@types/react-router": "5.1.18",
"@types/webpack": "^5.28.1",
"husky": "^8.0.3",
- "i18next-parser": "^7.9.0",
+ "i18next-parser": "^8.0.0",
"import-sort-style-module": "^6.0.0",
"inquirer": "^8.2.5",
"prettier": "^2.8.8",
@@ -33,8 +33,8 @@
"rollup-plugin-delete": "^2.0.0",
"rollup-plugin-external-globals": "^0.6.1",
"rollup-plugin-polyfill-node": "^0.10.2",
- "rollup-plugin-visualizer": "^5.9.0",
- "tslib": "^2.5.2",
+ "rollup-plugin-visualizer": "^5.9.2",
+ "tslib": "^2.5.3",
"typescript": "^4.9.5"
},
"importSort": {
@@ -45,11 +45,12 @@
},
"dependencies": {
"decky-frontend-lib": "3.21.1",
- "i18next": "^22.5.0",
+ "filesize": "^10.0.7",
+ "i18next": "^23.1.0",
"i18next-http-backend": "^2.2.1",
"react-file-icon": "^1.3.0",
"react-i18next": "^12.3.1",
- "react-icons": "^4.8.0",
+ "react-icons": "^4.9.0",
"react-markdown": "^8.0.7",
"remark-gfm": "^3.0.1"
}
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index ad7bb42c..3b1378e9 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -1,12 +1,19 @@
-lockfileVersion: '6.0'
+lockfileVersion: '6.1'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
dependencies:
decky-frontend-lib:
specifier: 3.21.1
version: 3.21.1
+ filesize:
+ specifier: ^10.0.7
+ version: 10.0.7
i18next:
- specifier: ^22.5.0
- version: 22.5.0
+ specifier: ^23.1.0
+ version: 23.1.0
i18next-http-backend:
specifier: ^2.2.1
version: 2.2.1
@@ -15,10 +22,10 @@ dependencies:
version: 1.3.0(react-dom@16.14.0)(react@16.14.0)
react-i18next:
specifier: ^12.3.1
- version: 12.3.1(i18next@22.5.0)(react-dom@16.14.0)(react@16.14.0)
+ version: 12.3.1(i18next@23.1.0)(react-dom@16.14.0)(react@16.14.0)
react-icons:
- specifier: ^4.8.0
- version: 4.8.0(react@16.14.0)
+ specifier: ^4.9.0
+ version: 4.9.0(react@16.14.0)
react-markdown:
specifier: ^8.0.7
version: 8.0.7(@types/react@16.14.0)(react@16.14.0)
@@ -44,7 +51,7 @@ devDependencies:
version: 4.0.0(rollup@2.79.1)
'@rollup/plugin-typescript':
specifier: ^8.5.0
- version: 8.5.0(rollup@2.79.1)(tslib@2.5.2)(typescript@4.9.5)
+ version: 8.5.0(rollup@2.79.1)(tslib@2.5.3)(typescript@4.9.5)
'@types/react':
specifier: 16.14.0
version: 16.14.0
@@ -61,8 +68,8 @@ devDependencies:
specifier: ^8.0.3
version: 8.0.3
i18next-parser:
- specifier: ^7.9.0
- version: 7.9.0
+ specifier: ^8.0.0
+ version: 8.0.0
import-sort-style-module:
specifier: ^6.0.0
version: 6.0.0
@@ -94,11 +101,11 @@ devDependencies:
specifier: ^0.10.2
version: 0.10.2(rollup@2.79.1)
rollup-plugin-visualizer:
- specifier: ^5.9.0
- version: 5.9.0(rollup@2.79.1)
+ specifier: ^5.9.2
+ version: 5.9.2(rollup@2.79.1)
tslib:
- specifier: ^2.5.2
- version: 2.5.2
+ specifier: ^2.5.3
+ version: 2.5.3
typescript:
specifier: ^4.9.5
version: 4.9.5
@@ -113,32 +120,32 @@ packages:
'@jridgewell/trace-mapping': 0.3.18
dev: true
- /@babel/code-frame@7.21.4:
- resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==}
+ /@babel/code-frame@7.22.5:
+ resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/highlight': 7.18.6
+ '@babel/highlight': 7.22.5
dev: true
- /@babel/compat-data@7.21.9:
- resolution: {integrity: sha512-FUGed8kfhyWvbYug/Un/VPJD41rDIgoVVcR+FuzhzOYyRz5uED+Gd3SLZml0Uw2l2aHFb7ZgdW5mGA3G2cCCnQ==}
+ /@babel/compat-data@7.22.5:
+ resolution: {integrity: sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==}
engines: {node: '>=6.9.0'}
dev: true
- /@babel/core@7.21.8:
- resolution: {integrity: sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==}
+ /@babel/core@7.22.5:
+ resolution: {integrity: sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==}
engines: {node: '>=6.9.0'}
dependencies:
'@ampproject/remapping': 2.2.1
- '@babel/code-frame': 7.21.4
- '@babel/generator': 7.21.9
- '@babel/helper-compilation-targets': 7.21.5(@babel/core@7.21.8)
- '@babel/helper-module-transforms': 7.21.5
- '@babel/helpers': 7.21.5
- '@babel/parser': 7.21.9
- '@babel/template': 7.21.9
- '@babel/traverse': 7.21.5
- '@babel/types': 7.21.5
+ '@babel/code-frame': 7.22.5
+ '@babel/generator': 7.22.5
+ '@babel/helper-compilation-targets': 7.22.5(@babel/core@7.22.5)
+ '@babel/helper-module-transforms': 7.22.5
+ '@babel/helpers': 7.22.5
+ '@babel/parser': 7.22.5
+ '@babel/template': 7.22.5
+ '@babel/traverse': 7.22.5
+ '@babel/types': 7.22.5
convert-source-map: 1.9.0
debug: 4.3.4
gensync: 1.0.0-beta.2
@@ -148,169 +155,169 @@ packages:
- supports-color
dev: true
- /@babel/generator@7.21.9:
- resolution: {integrity: sha512-F3fZga2uv09wFdEjEQIJxXALXfz0+JaOb7SabvVMmjHxeVTuGW8wgE8Vp1Hd7O+zMTYtcfEISGRzPkeiaPPsvg==}
+ /@babel/generator@7.22.5:
+ resolution: {integrity: sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/types': 7.21.5
+ '@babel/types': 7.22.5
'@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.18
jsesc: 2.5.2
dev: true
- /@babel/helper-compilation-targets@7.21.5(@babel/core@7.21.8):
- resolution: {integrity: sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==}
+ /@babel/helper-compilation-targets@7.22.5(@babel/core@7.22.5):
+ resolution: {integrity: sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
- '@babel/compat-data': 7.21.9
- '@babel/core': 7.21.8
- '@babel/helper-validator-option': 7.21.0
- browserslist: 4.21.5
+ '@babel/compat-data': 7.22.5
+ '@babel/core': 7.22.5
+ '@babel/helper-validator-option': 7.22.5
+ browserslist: 4.21.9
lru-cache: 5.1.1
semver: 6.3.0
dev: true
- /@babel/helper-environment-visitor@7.21.5:
- resolution: {integrity: sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==}
+ /@babel/helper-environment-visitor@7.22.5:
+ resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==}
engines: {node: '>=6.9.0'}
dev: true
- /@babel/helper-function-name@7.21.0:
- resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==}
+ /@babel/helper-function-name@7.22.5:
+ resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/template': 7.21.9
- '@babel/types': 7.21.5
+ '@babel/template': 7.22.5
+ '@babel/types': 7.22.5
dev: true
- /@babel/helper-hoist-variables@7.18.6:
- resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==}
+ /@babel/helper-hoist-variables@7.22.5:
+ resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/types': 7.21.5
+ '@babel/types': 7.22.5
dev: true
- /@babel/helper-module-imports@7.21.4:
- resolution: {integrity: sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==}
+ /@babel/helper-module-imports@7.22.5:
+ resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/types': 7.21.5
+ '@babel/types': 7.22.5
dev: true
- /@babel/helper-module-transforms@7.21.5:
- resolution: {integrity: sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==}
+ /@babel/helper-module-transforms@7.22.5:
+ resolution: {integrity: sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/helper-environment-visitor': 7.21.5
- '@babel/helper-module-imports': 7.21.4
- '@babel/helper-simple-access': 7.21.5
- '@babel/helper-split-export-declaration': 7.18.6
- '@babel/helper-validator-identifier': 7.19.1
- '@babel/template': 7.21.9
- '@babel/traverse': 7.21.5
- '@babel/types': 7.21.5
+ '@babel/helper-environment-visitor': 7.22.5
+ '@babel/helper-module-imports': 7.22.5
+ '@babel/helper-simple-access': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.5
+ '@babel/helper-validator-identifier': 7.22.5
+ '@babel/template': 7.22.5
+ '@babel/traverse': 7.22.5
+ '@babel/types': 7.22.5
transitivePeerDependencies:
- supports-color
dev: true
- /@babel/helper-simple-access@7.21.5:
- resolution: {integrity: sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==}
+ /@babel/helper-simple-access@7.22.5:
+ resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/types': 7.21.5
+ '@babel/types': 7.22.5
dev: true
- /@babel/helper-split-export-declaration@7.18.6:
- resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==}
+ /@babel/helper-split-export-declaration@7.22.5:
+ resolution: {integrity: sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/types': 7.21.5
+ '@babel/types': 7.22.5
dev: true
- /@babel/helper-string-parser@7.21.5:
- resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==}
+ /@babel/helper-string-parser@7.22.5:
+ resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==}
engines: {node: '>=6.9.0'}
dev: true
- /@babel/helper-validator-identifier@7.19.1:
- resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==}
+ /@babel/helper-validator-identifier@7.22.5:
+ resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==}
engines: {node: '>=6.9.0'}
dev: true
- /@babel/helper-validator-option@7.21.0:
- resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==}
+ /@babel/helper-validator-option@7.22.5:
+ resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==}
engines: {node: '>=6.9.0'}
dev: true
- /@babel/helpers@7.21.5:
- resolution: {integrity: sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==}
+ /@babel/helpers@7.22.5:
+ resolution: {integrity: sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/template': 7.21.9
- '@babel/traverse': 7.21.5
- '@babel/types': 7.21.5
+ '@babel/template': 7.22.5
+ '@babel/traverse': 7.22.5
+ '@babel/types': 7.22.5
transitivePeerDependencies:
- supports-color
dev: true
- /@babel/highlight@7.18.6:
- resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
+ /@babel/highlight@7.22.5:
+ resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/helper-validator-identifier': 7.19.1
+ '@babel/helper-validator-identifier': 7.22.5
chalk: 2.4.2
js-tokens: 4.0.0
dev: true
- /@babel/parser@7.21.9:
- resolution: {integrity: sha512-q5PNg/Bi1OpGgx5jYlvWZwAorZepEudDMCLtj967aeS7WMont7dUZI46M2XwcIQqvUlMxWfdLFu4S/qSxeUu5g==}
+ /@babel/parser@7.22.5:
+ resolution: {integrity: sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
- '@babel/types': 7.21.5
+ '@babel/types': 7.22.5
dev: true
- /@babel/runtime@7.21.5:
- resolution: {integrity: sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==}
+ /@babel/runtime@7.22.5:
+ resolution: {integrity: sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==}
engines: {node: '>=6.9.0'}
dependencies:
regenerator-runtime: 0.13.11
- /@babel/template@7.21.9:
- resolution: {integrity: sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==}
+ /@babel/template@7.22.5:
+ resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/code-frame': 7.21.4
- '@babel/parser': 7.21.9
- '@babel/types': 7.21.5
+ '@babel/code-frame': 7.22.5
+ '@babel/parser': 7.22.5
+ '@babel/types': 7.22.5
dev: true
- /@babel/traverse@7.21.5:
- resolution: {integrity: sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==}
+ /@babel/traverse@7.22.5:
+ resolution: {integrity: sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/code-frame': 7.21.4
- '@babel/generator': 7.21.9
- '@babel/helper-environment-visitor': 7.21.5
- '@babel/helper-function-name': 7.21.0
- '@babel/helper-hoist-variables': 7.18.6
- '@babel/helper-split-export-declaration': 7.18.6
- '@babel/parser': 7.21.9
- '@babel/types': 7.21.5
+ '@babel/code-frame': 7.22.5
+ '@babel/generator': 7.22.5
+ '@babel/helper-environment-visitor': 7.22.5
+ '@babel/helper-function-name': 7.22.5
+ '@babel/helper-hoist-variables': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.5
+ '@babel/parser': 7.22.5
+ '@babel/types': 7.22.5
debug: 4.3.4
globals: 11.12.0
transitivePeerDependencies:
- supports-color
dev: true
- /@babel/types@7.21.5:
- resolution: {integrity: sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==}
+ /@babel/types@7.22.5:
+ resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/helper-string-parser': 7.21.5
- '@babel/helper-validator-identifier': 7.19.1
+ '@babel/helper-string-parser': 7.22.5
+ '@babel/helper-validator-identifier': 7.22.5
to-fast-properties: 2.0.0
dev: true
@@ -649,7 +656,7 @@ packages:
rollup: 2.79.1
dev: true
- /@rollup/plugin-typescript@8.5.0(rollup@2.79.1)(tslib@2.5.2)(typescript@4.9.5):
+ /@rollup/plugin-typescript@8.5.0(rollup@2.79.1)(tslib@2.5.3)(typescript@4.9.5):
resolution: {integrity: sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ==}
engines: {node: '>=8.0.0'}
peerDependencies:
@@ -663,7 +670,7 @@ packages:
'@rollup/pluginutils': 3.1.0(rollup@2.79.1)
resolve: 1.22.2
rollup: 2.79.1
- tslib: 2.5.2
+ tslib: 2.5.3
typescript: 4.9.5
dev: true
@@ -711,12 +718,12 @@ packages:
/@types/eslint-scope@3.7.4:
resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==}
dependencies:
- '@types/eslint': 8.40.0
+ '@types/eslint': 8.40.2
'@types/estree': 1.0.1
dev: true
- /@types/eslint@8.40.0:
- resolution: {integrity: sha512-nbq2mvc/tBrK9zQQuItvjJl++GTN5j06DaPtp3hZCpngmG6Q3xoyEmd0TwZI0gAy/G1X0zhGBbr2imsGFdFV0g==}
+ /@types/eslint@8.40.2:
+ resolution: {integrity: sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ==}
dependencies:
'@types/estree': 1.0.1
'@types/json-schema': 7.0.12
@@ -734,7 +741,7 @@ packages:
resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
dependencies:
'@types/minimatch': 5.1.2
- '@types/node': 20.2.4
+ '@types/node': 20.3.1
dev: true
/@types/hast@2.3.4:
@@ -769,8 +776,8 @@ packages:
resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==}
dev: false
- /@types/node@20.2.4:
- resolution: {integrity: sha512-ni5f8Xlf4PwnT/Z3f0HURc3ZSw8UyrqMqmM3L5ysa7VjHu8c3FOmIo1nKCcLrV/OAmtf3N4kFna/aJqxsfEtnA==}
+ /@types/node@20.3.1:
+ resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==}
dev: true
/@types/prop-types@15.7.5:
@@ -798,7 +805,7 @@ packages:
/@types/resolve@1.17.1:
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
dependencies:
- '@types/node': 20.2.4
+ '@types/node': 20.3.1
dev: true
/@types/symlink-or-copy@1.2.0:
@@ -812,9 +819,9 @@ packages:
/@types/webpack@5.28.1:
resolution: {integrity: sha512-qw1MqGZclCoBrpiSe/hokSgQM/su8Ocpl3L/YHE0L6moyaypg4+5F7Uzq7NgaPKPxUxUbQ4fLPLpDWdR27bCZw==}
dependencies:
- '@types/node': 20.2.4
+ '@types/node': 20.3.1
tapable: 2.2.1
- webpack: 5.84.1
+ webpack: 5.87.0
transitivePeerDependencies:
- '@swc/core'
- esbuild
@@ -936,16 +943,16 @@ packages:
resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
dev: true
- /acorn-import-assertions@1.9.0(acorn@8.8.2):
+ /acorn-import-assertions@1.9.0(acorn@8.9.0):
resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==}
peerDependencies:
acorn: ^8
dependencies:
- acorn: 8.8.2
+ acorn: 8.9.0
dev: true
- /acorn@8.8.2:
- resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
+ /acorn@8.9.0:
+ resolution: {integrity: sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: true
@@ -1096,15 +1103,15 @@ packages:
- supports-color
dev: true
- /browserslist@4.21.5:
- resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==}
+ /browserslist@4.21.9:
+ resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
- caniuse-lite: 1.0.30001489
- electron-to-chromium: 1.4.408
+ caniuse-lite: 1.0.30001504
+ electron-to-chromium: 1.4.433
node-releases: 2.0.12
- update-browserslist-db: 1.0.11(browserslist@4.21.5)
+ update-browserslist-db: 1.0.11(browserslist@4.21.9)
dev: true
/buffer-equal@1.0.1:
@@ -1154,8 +1161,8 @@ packages:
engines: {node: '>=4'}
dev: true
- /caniuse-lite@1.0.30001489:
- resolution: {integrity: sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==}
+ /caniuse-lite@1.0.30001504:
+ resolution: {integrity: sha512-5uo7eoOp2mKbWyfMXnGO9rJWOGU8duvzEiYITW+wivukL7yHH4gX9yuRaobu6El4jPxo6jKZfG+N6fB621GD/Q==}
dev: true
/ccount@2.0.1:
@@ -1511,8 +1518,8 @@ packages:
stream-shift: 1.0.1
dev: true
- /electron-to-chromium@1.4.408:
- resolution: {integrity: sha512-vjeaj0u/UYnzA/CIdGXzzcxRLCqRwREYc9YfaWInjIEr7/XPttZ6ShpyqapchEy0S2r6LpLjDBTnNj7ZxnxJKg==}
+ /electron-to-chromium@1.4.433:
+ resolution: {integrity: sha512-MGO1k0w1RgrfdbLVwmXcDhHHuxCn2qRgR7dYsJvWFKDttvYPx6FNzCGG0c/fBBvzK2LDh3UV7Tt9awnHnvAAUQ==}
dev: true
/emoji-regex@8.0.0:
@@ -1525,8 +1532,8 @@ packages:
once: 1.4.0
dev: true
- /enhanced-resolve@5.14.1:
- resolution: {integrity: sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==}
+ /enhanced-resolve@5.15.0:
+ resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==}
engines: {node: '>=10.13.0'}
dependencies:
graceful-fs: 4.2.11
@@ -1552,8 +1559,8 @@ packages:
is-arrayish: 0.2.1
dev: true
- /es-module-lexer@1.2.1:
- resolution: {integrity: sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==}
+ /es-module-lexer@1.3.0:
+ resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==}
dev: true
/esbuild@0.17.19:
@@ -1693,6 +1700,11 @@ packages:
escape-string-regexp: 1.0.5
dev: true
+ /filesize@10.0.7:
+ resolution: {integrity: sha512-iMRG7Qo9nayLoU3PNCiLizYtsy4W1ClrapeCwEgtiQelOAOuRJiw4QaLI+sSr8xr901dgHv+EYP2bCusGZgoiA==}
+ engines: {node: '>= 10.4.0'}
+ dev: false
+
/fill-range@7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
@@ -1961,12 +1973,12 @@ packages:
- encoding
dev: false
- /i18next-parser@7.9.0:
- resolution: {integrity: sha512-yrPJhWGsDBx404T4KLMOTkTgAAEuHvjbxee3HnlqFHALWy/3BOY7or69CxsJOomN3wdrwgg8kWtfIUWR1BZ1nw==}
- engines: {node: ^14.13.1 || >=16.0.0 || >=18.0.0, npm: '>=6', yarn: '>=1'}
+ /i18next-parser@8.0.0:
+ resolution: {integrity: sha512-WnpIXJlwgUTwnlEFLJpL5E8Y7faWCV/GVqIJXJos15Zwoic5k3QXV3QodP4uYp8W1T1w4y5wXrSEGS1Y4obxCg==}
+ engines: {node: '>=16.0.0 || >=18.0.0 || >=20.0.0', npm: '>=6', yarn: '>=1'}
hasBin: true
dependencies:
- '@babel/runtime': 7.21.5
+ '@babel/runtime': 7.22.5
broccoli-plugin: 4.0.7
cheerio: 1.0.0-rc.12
colors: 1.4.0
@@ -1976,7 +1988,7 @@ packages:
esbuild: 0.17.19
fs-extra: 11.1.1
gulp-sort: 2.0.0
- i18next: 22.5.0
+ i18next: 22.5.1
js-yaml: 4.1.0
lilconfig: 2.1.0
rsvp: 4.8.5
@@ -1990,10 +2002,17 @@ packages:
- supports-color
dev: true
- /i18next@22.5.0:
- resolution: {integrity: sha512-sqWuJFj+wJAKQP2qBQ+b7STzxZNUmnSxrehBCCj9vDOW9RDYPfqCaK1Hbh2frNYQuPziz6O2CGoJPwtzY3vAYA==}
+ /i18next@22.5.1:
+ resolution: {integrity: sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==}
+ dependencies:
+ '@babel/runtime': 7.22.5
+ dev: true
+
+ /i18next@23.1.0:
+ resolution: {integrity: sha512-CObNPofJpw7zGVGYLd58mtMZUF+NZQl9czYMihbJkStjX+Nlu9kC3PHiC6uE1niP3qxP/3ocLXIBc2zqbAb1dg==}
dependencies:
- '@babel/runtime': 7.21.5
+ '@babel/runtime': 7.22.5
+ dev: false
/iconv-lite@0.4.24:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
@@ -2031,10 +2050,10 @@ packages:
/import-sort-parser-babylon@6.0.0:
resolution: {integrity: sha512-NyShTiNhTh4Vy7kJUVe6CuvOaQAzzfSIT72wtp3CzGjz8bHjNj59DCAjncuviicmDOgVAgmLuSh1WMcLYAMWGg==}
dependencies:
- '@babel/core': 7.21.8
- '@babel/parser': 7.21.9
- '@babel/traverse': 7.21.5
- '@babel/types': 7.21.5
+ '@babel/core': 7.22.5
+ '@babel/parser': 7.22.5
+ '@babel/traverse': 7.22.5
+ '@babel/types': 7.22.5
find-line-column: 0.5.2
transitivePeerDependencies:
- supports-color
@@ -2265,7 +2284,7 @@ packages:
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
engines: {node: '>= 10.13.0'}
dependencies:
- '@types/node': 20.2.4
+ '@types/node': 20.3.1
merge-stream: 2.0.0
supports-color: 8.1.1
dev: true
@@ -2426,19 +2445,19 @@ packages:
unist-util-visit-parents: 5.1.3
dev: false
- /mdast-util-from-markdown@1.3.0:
- resolution: {integrity: sha512-HN3W1gRIuN/ZW295c7zi7g9lVBllMgZE40RxCX37wrTPWXCWtpvOZdfnuK+1WNpvZje6XuJeI3Wnb4TJEUem+g==}
+ /mdast-util-from-markdown@1.3.1:
+ resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==}
dependencies:
'@types/mdast': 3.0.11
'@types/unist': 2.0.6
decode-named-character-reference: 1.0.2
mdast-util-to-string: 3.2.0
- micromark: 3.1.0
- micromark-util-decode-numeric-character-reference: 1.0.0
- micromark-util-decode-string: 1.0.2
- micromark-util-normalize-identifier: 1.0.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark: 3.2.0
+ micromark-util-decode-numeric-character-reference: 1.1.0
+ micromark-util-decode-string: 1.1.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
unist-util-stringify-position: 3.0.3
uvu: 0.5.6
transitivePeerDependencies:
@@ -2451,7 +2470,7 @@ packages:
'@types/mdast': 3.0.11
ccount: 2.0.1
mdast-util-find-and-replace: 2.2.2
- micromark-util-character: 1.1.0
+ micromark-util-character: 1.2.0
dev: false
/mdast-util-gfm-footnote@1.0.2:
@@ -2459,7 +2478,7 @@ packages:
dependencies:
'@types/mdast': 3.0.11
mdast-util-to-markdown: 1.5.0
- micromark-util-normalize-identifier: 1.0.0
+ micromark-util-normalize-identifier: 1.1.0
dev: false
/mdast-util-gfm-strikethrough@1.0.3:
@@ -2474,7 +2493,7 @@ packages:
dependencies:
'@types/mdast': 3.0.11
markdown-table: 3.0.3
- mdast-util-from-markdown: 1.3.0
+ mdast-util-from-markdown: 1.3.1
mdast-util-to-markdown: 1.5.0
transitivePeerDependencies:
- supports-color
@@ -2490,7 +2509,7 @@ packages:
/mdast-util-gfm@2.0.2:
resolution: {integrity: sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==}
dependencies:
- mdast-util-from-markdown: 1.3.0
+ mdast-util-from-markdown: 1.3.1
mdast-util-gfm-autolink-literal: 1.0.3
mdast-util-gfm-footnote: 1.0.2
mdast-util-gfm-strikethrough: 1.0.3
@@ -2514,7 +2533,7 @@ packages:
'@types/hast': 2.3.4
'@types/mdast': 3.0.11
mdast-util-definitions: 5.1.2
- micromark-util-sanitize-uri: 1.1.0
+ micromark-util-sanitize-uri: 1.2.0
trim-lines: 3.0.1
unist-util-generated: 2.0.1
unist-util-position: 4.0.4
@@ -2529,7 +2548,7 @@ packages:
longest-streak: 3.1.0
mdast-util-phrasing: 3.0.1
mdast-util-to-string: 3.2.0
- micromark-util-decode-string: 1.0.2
+ micromark-util-decode-string: 1.1.0
unist-util-visit: 4.1.2
zwitch: 2.0.4
dev: false
@@ -2549,249 +2568,248 @@ packages:
engines: {node: '>= 8'}
dev: true
- /micromark-core-commonmark@1.0.6:
- resolution: {integrity: sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==}
+ /micromark-core-commonmark@1.1.0:
+ resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==}
dependencies:
decode-named-character-reference: 1.0.2
- micromark-factory-destination: 1.0.0
- micromark-factory-label: 1.0.2
- micromark-factory-space: 1.0.0
- micromark-factory-title: 1.0.2
- micromark-factory-whitespace: 1.0.0
- micromark-util-character: 1.1.0
- micromark-util-chunked: 1.0.0
- micromark-util-classify-character: 1.0.0
- micromark-util-html-tag-name: 1.1.0
- micromark-util-normalize-identifier: 1.0.0
- micromark-util-resolve-all: 1.0.0
- micromark-util-subtokenize: 1.0.2
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-factory-destination: 1.1.0
+ micromark-factory-label: 1.1.0
+ micromark-factory-space: 1.1.0
+ micromark-factory-title: 1.1.0
+ micromark-factory-whitespace: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-chunked: 1.1.0
+ micromark-util-classify-character: 1.1.0
+ micromark-util-html-tag-name: 1.2.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-resolve-all: 1.1.0
+ micromark-util-subtokenize: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
uvu: 0.5.6
dev: false
- /micromark-extension-gfm-autolink-literal@1.0.4:
- resolution: {integrity: sha512-WCssN+M9rUyfHN5zPBn3/f0mIA7tqArHL/EKbv3CZK+LT2rG77FEikIQEqBkv46fOqXQK4NEW/Pc7Z27gshpeg==}
+ /micromark-extension-gfm-autolink-literal@1.0.5:
+ resolution: {integrity: sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==}
dependencies:
- micromark-util-character: 1.1.0
- micromark-util-sanitize-uri: 1.1.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-util-character: 1.2.0
+ micromark-util-sanitize-uri: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
dev: false
- /micromark-extension-gfm-footnote@1.1.0:
- resolution: {integrity: sha512-RWYce7j8+c0n7Djzv5NzGEGitNNYO3uj+h/XYMdS/JinH1Go+/Qkomg/rfxExFzYTiydaV6GLeffGO5qcJbMPA==}
+ /micromark-extension-gfm-footnote@1.1.2:
+ resolution: {integrity: sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==}
dependencies:
- micromark-core-commonmark: 1.0.6
- micromark-factory-space: 1.0.0
- micromark-util-character: 1.1.0
- micromark-util-normalize-identifier: 1.0.0
- micromark-util-sanitize-uri: 1.1.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-core-commonmark: 1.1.0
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-sanitize-uri: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
uvu: 0.5.6
dev: false
- /micromark-extension-gfm-strikethrough@1.0.5:
- resolution: {integrity: sha512-X0oI5eYYQVARhiNfbETy7BfLSmSilzN1eOuoRnrf9oUNsPRrWOAe9UqSizgw1vNxQBfOwL+n2610S3bYjVNi7w==}
+ /micromark-extension-gfm-strikethrough@1.0.7:
+ resolution: {integrity: sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==}
dependencies:
- micromark-util-chunked: 1.0.0
- micromark-util-classify-character: 1.0.0
- micromark-util-resolve-all: 1.0.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-util-chunked: 1.1.0
+ micromark-util-classify-character: 1.1.0
+ micromark-util-resolve-all: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
uvu: 0.5.6
dev: false
- /micromark-extension-gfm-table@1.0.6:
- resolution: {integrity: sha512-92pq7Q+T+4kXH4M6kL+pc8WU23Z9iuhcqmtYFWdFWjm73ZscFpH2xE28+XFpGWlvgq3LUwcN0XC0PGCicYFpgA==}
+ /micromark-extension-gfm-table@1.0.7:
+ resolution: {integrity: sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==}
dependencies:
- micromark-factory-space: 1.0.0
- micromark-util-character: 1.1.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
uvu: 0.5.6
dev: false
/micromark-extension-gfm-tagfilter@1.0.2:
resolution: {integrity: sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==}
dependencies:
- micromark-util-types: 1.0.2
+ micromark-util-types: 1.1.0
dev: false
- /micromark-extension-gfm-task-list-item@1.0.4:
- resolution: {integrity: sha512-9XlIUUVnYXHsFF2HZ9jby4h3npfX10S1coXTnV035QGPgrtNYQq3J6IfIvcCIUAJrrqBVi5BqA/LmaOMJqPwMQ==}
+ /micromark-extension-gfm-task-list-item@1.0.5:
+ resolution: {integrity: sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==}
dependencies:
- micromark-factory-space: 1.0.0
- micromark-util-character: 1.1.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
uvu: 0.5.6
dev: false
/micromark-extension-gfm@2.0.3:
resolution: {integrity: sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==}
dependencies:
- micromark-extension-gfm-autolink-literal: 1.0.4
- micromark-extension-gfm-footnote: 1.1.0
- micromark-extension-gfm-strikethrough: 1.0.5
- micromark-extension-gfm-table: 1.0.6
+ micromark-extension-gfm-autolink-literal: 1.0.5
+ micromark-extension-gfm-footnote: 1.1.2
+ micromark-extension-gfm-strikethrough: 1.0.7
+ micromark-extension-gfm-table: 1.0.7
micromark-extension-gfm-tagfilter: 1.0.2
- micromark-extension-gfm-task-list-item: 1.0.4
- micromark-util-combine-extensions: 1.0.0
- micromark-util-types: 1.0.2
+ micromark-extension-gfm-task-list-item: 1.0.5
+ micromark-util-combine-extensions: 1.1.0
+ micromark-util-types: 1.1.0
dev: false
- /micromark-factory-destination@1.0.0:
- resolution: {integrity: sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==}
+ /micromark-factory-destination@1.1.0:
+ resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==}
dependencies:
- micromark-util-character: 1.1.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
dev: false
- /micromark-factory-label@1.0.2:
- resolution: {integrity: sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==}
+ /micromark-factory-label@1.1.0:
+ resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==}
dependencies:
- micromark-util-character: 1.1.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
uvu: 0.5.6
dev: false
- /micromark-factory-space@1.0.0:
- resolution: {integrity: sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==}
+ /micromark-factory-space@1.1.0:
+ resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==}
dependencies:
- micromark-util-character: 1.1.0
- micromark-util-types: 1.0.2
+ micromark-util-character: 1.2.0
+ micromark-util-types: 1.1.0
dev: false
- /micromark-factory-title@1.0.2:
- resolution: {integrity: sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==}
+ /micromark-factory-title@1.1.0:
+ resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==}
dependencies:
- micromark-factory-space: 1.0.0
- micromark-util-character: 1.1.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
- uvu: 0.5.6
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
dev: false
- /micromark-factory-whitespace@1.0.0:
- resolution: {integrity: sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==}
+ /micromark-factory-whitespace@1.1.0:
+ resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==}
dependencies:
- micromark-factory-space: 1.0.0
- micromark-util-character: 1.1.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
dev: false
- /micromark-util-character@1.1.0:
- resolution: {integrity: sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==}
+ /micromark-util-character@1.2.0:
+ resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==}
dependencies:
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
dev: false
- /micromark-util-chunked@1.0.0:
- resolution: {integrity: sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==}
+ /micromark-util-chunked@1.1.0:
+ resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==}
dependencies:
- micromark-util-symbol: 1.0.1
+ micromark-util-symbol: 1.1.0
dev: false
- /micromark-util-classify-character@1.0.0:
- resolution: {integrity: sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==}
+ /micromark-util-classify-character@1.1.0:
+ resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==}
dependencies:
- micromark-util-character: 1.1.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
dev: false
- /micromark-util-combine-extensions@1.0.0:
- resolution: {integrity: sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==}
+ /micromark-util-combine-extensions@1.1.0:
+ resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==}
dependencies:
- micromark-util-chunked: 1.0.0
- micromark-util-types: 1.0.2
+ micromark-util-chunked: 1.1.0
+ micromark-util-types: 1.1.0
dev: false
- /micromark-util-decode-numeric-character-reference@1.0.0:
- resolution: {integrity: sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==}
+ /micromark-util-decode-numeric-character-reference@1.1.0:
+ resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==}
dependencies:
- micromark-util-symbol: 1.0.1
+ micromark-util-symbol: 1.1.0
dev: false
- /micromark-util-decode-string@1.0.2:
- resolution: {integrity: sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==}
+ /micromark-util-decode-string@1.1.0:
+ resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==}
dependencies:
decode-named-character-reference: 1.0.2
- micromark-util-character: 1.1.0
- micromark-util-decode-numeric-character-reference: 1.0.0
- micromark-util-symbol: 1.0.1
+ micromark-util-character: 1.2.0
+ micromark-util-decode-numeric-character-reference: 1.1.0
+ micromark-util-symbol: 1.1.0
dev: false
- /micromark-util-encode@1.0.1:
- resolution: {integrity: sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==}
+ /micromark-util-encode@1.1.0:
+ resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==}
dev: false
- /micromark-util-html-tag-name@1.1.0:
- resolution: {integrity: sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==}
+ /micromark-util-html-tag-name@1.2.0:
+ resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==}
dev: false
- /micromark-util-normalize-identifier@1.0.0:
- resolution: {integrity: sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==}
+ /micromark-util-normalize-identifier@1.1.0:
+ resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==}
dependencies:
- micromark-util-symbol: 1.0.1
+ micromark-util-symbol: 1.1.0
dev: false
- /micromark-util-resolve-all@1.0.0:
- resolution: {integrity: sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==}
+ /micromark-util-resolve-all@1.1.0:
+ resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==}
dependencies:
- micromark-util-types: 1.0.2
+ micromark-util-types: 1.1.0
dev: false
- /micromark-util-sanitize-uri@1.1.0:
- resolution: {integrity: sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==}
+ /micromark-util-sanitize-uri@1.2.0:
+ resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==}
dependencies:
- micromark-util-character: 1.1.0
- micromark-util-encode: 1.0.1
- micromark-util-symbol: 1.0.1
+ micromark-util-character: 1.2.0
+ micromark-util-encode: 1.1.0
+ micromark-util-symbol: 1.1.0
dev: false
- /micromark-util-subtokenize@1.0.2:
- resolution: {integrity: sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==}
+ /micromark-util-subtokenize@1.1.0:
+ resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==}
dependencies:
- micromark-util-chunked: 1.0.0
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-util-chunked: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
uvu: 0.5.6
dev: false
- /micromark-util-symbol@1.0.1:
- resolution: {integrity: sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==}
+ /micromark-util-symbol@1.1.0:
+ resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==}
dev: false
- /micromark-util-types@1.0.2:
- resolution: {integrity: sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==}
+ /micromark-util-types@1.1.0:
+ resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==}
dev: false
- /micromark@3.1.0:
- resolution: {integrity: sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==}
+ /micromark@3.2.0:
+ resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==}
dependencies:
'@types/debug': 4.1.8
debug: 4.3.4
decode-named-character-reference: 1.0.2
- micromark-core-commonmark: 1.0.6
- micromark-factory-space: 1.0.0
- micromark-util-character: 1.1.0
- micromark-util-chunked: 1.0.0
- micromark-util-combine-extensions: 1.0.0
- micromark-util-decode-numeric-character-reference: 1.0.0
- micromark-util-encode: 1.0.1
- micromark-util-normalize-identifier: 1.0.0
- micromark-util-resolve-all: 1.0.0
- micromark-util-sanitize-uri: 1.1.0
- micromark-util-subtokenize: 1.0.2
- micromark-util-symbol: 1.0.1
- micromark-util-types: 1.0.2
+ micromark-core-commonmark: 1.1.0
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-chunked: 1.1.0
+ micromark-util-combine-extensions: 1.1.0
+ micromark-util-decode-numeric-character-reference: 1.1.0
+ micromark-util-encode: 1.1.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-resolve-all: 1.1.0
+ micromark-util-sanitize-uri: 1.2.0
+ micromark-util-subtokenize: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
uvu: 0.5.6
transitivePeerDependencies:
- supports-color
@@ -3126,7 +3144,7 @@ packages:
react-dom: 16.14.0(react@16.14.0)
dev: false
- /react-i18next@12.3.1(i18next@22.5.0)(react-dom@16.14.0)(react@16.14.0):
+ /react-i18next@12.3.1(i18next@23.1.0)(react-dom@16.14.0)(react@16.14.0):
resolution: {integrity: sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==}
peerDependencies:
i18next: '>= 19.0.0'
@@ -3139,15 +3157,15 @@ packages:
react-native:
optional: true
dependencies:
- '@babel/runtime': 7.21.5
+ '@babel/runtime': 7.22.5
html-parse-stringify: 3.0.1
- i18next: 22.5.0
+ i18next: 23.1.0
react: 16.14.0
react-dom: 16.14.0(react@16.14.0)
dev: false
- /react-icons@4.8.0(react@16.14.0):
- resolution: {integrity: sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg==}
+ /react-icons@4.9.0(react@16.14.0):
+ resolution: {integrity: sha512-ijUnFr//ycebOqujtqtV9PFS7JjhWg0QU6ykURVHuL4cbofvRCf3f6GMn9+fBktEFQOIVZnuAYLZdiyadRQRFg==}
peerDependencies:
react: '*'
dependencies:
@@ -3235,7 +3253,7 @@ packages:
resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==}
dependencies:
'@types/mdast': 3.0.11
- mdast-util-from-markdown: 1.3.0
+ mdast-util-from-markdown: 1.3.1
unified: 10.1.2
transitivePeerDependencies:
- supports-color
@@ -3367,8 +3385,8 @@ packages:
rollup: 2.79.1
dev: true
- /rollup-plugin-visualizer@5.9.0(rollup@2.79.1):
- resolution: {integrity: sha512-bbDOv47+Bw4C/cgs0czZqfm8L82xOZssk4ayZjG40y9zbXclNk7YikrZTDao6p7+HDiGxrN0b65SgZiVm9k1Cg==}
+ /rollup-plugin-visualizer@5.9.2(rollup@2.79.1):
+ resolution: {integrity: sha512-waHktD5mlWrYFrhOLbti4YgQCn1uR24nYsNuXxg7LkPH8KdTXVWR9DNY1WU0QqokyMixVXJS4J04HNrVTMP01A==}
engines: {node: '>=14'}
hasBin: true
peerDependencies:
@@ -3415,7 +3433,7 @@ packages:
/rxjs@7.8.1:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
dependencies:
- tslib: 2.5.2
+ tslib: 2.5.3
dev: true
/sade@1.8.1:
@@ -3443,8 +3461,8 @@ packages:
loose-envify: 1.4.0
object-assign: 4.1.1
- /schema-utils@3.1.2:
- resolution: {integrity: sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==}
+ /schema-utils@3.3.0:
+ resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==}
engines: {node: '>= 10.13.0'}
dependencies:
'@types/json-schema': 7.0.12
@@ -3517,8 +3535,8 @@ packages:
resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==}
dev: true
- /streamx@2.13.2:
- resolution: {integrity: sha512-+TWqixPhGDXEG9L/XczSbhfkmwAtGs3BJX5QNU6cvno+pOLKeszByWcnaTu6dg8efsTYqR8ZZuXWHhZfgrxMvA==}
+ /streamx@2.15.0:
+ resolution: {integrity: sha512-HcxY6ncGjjklGs1xsP1aR71INYcsXFJet5CU1CHqihQ2J5nOsbd4OjgjHO42w/4QNv9gZb3BueV+Vxok5pLEXg==}
dependencies:
fast-fifo: 1.2.0
queue-tick: 1.0.1
@@ -3596,10 +3614,10 @@ packages:
/teex@1.0.1:
resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==}
dependencies:
- streamx: 2.13.2
+ streamx: 2.15.0
dev: true
- /terser-webpack-plugin@5.3.9(webpack@5.84.1):
+ /terser-webpack-plugin@5.3.9(webpack@5.87.0):
resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==}
engines: {node: '>= 10.13.0'}
peerDependencies:
@@ -3617,19 +3635,19 @@ packages:
dependencies:
'@jridgewell/trace-mapping': 0.3.18
jest-worker: 27.5.1
- schema-utils: 3.1.2
+ schema-utils: 3.3.0
serialize-javascript: 6.0.1
- terser: 5.17.6
- webpack: 5.84.1
+ terser: 5.18.0
+ webpack: 5.87.0
dev: true
- /terser@5.17.6:
- resolution: {integrity: sha512-V8QHcs8YuyLkLHsJO5ucyff1ykrLVsR4dNnS//L5Y3NiSXpbK1J+WMVUs67eI0KTxs9JtHhgEQpXQVHlHI92DQ==}
+ /terser@5.18.0:
+ resolution: {integrity: sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==}
engines: {node: '>=10'}
hasBin: true
dependencies:
'@jridgewell/source-map': 0.3.3
- acorn: 8.8.2
+ acorn: 8.9.0
commander: 2.20.3
source-map-support: 0.5.21
dev: true
@@ -3704,8 +3722,8 @@ packages:
resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==}
dev: false
- /tslib@2.5.2:
- resolution: {integrity: sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==}
+ /tslib@2.5.3:
+ resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==}
dev: true
/type-fest@0.21.3:
@@ -3807,13 +3825,13 @@ packages:
engines: {node: '>= 10.0.0'}
dev: true
- /update-browserslist-db@1.0.11(browserslist@4.21.5):
+ /update-browserslist-db@1.0.11(browserslist@4.21.9):
resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==}
hasBin: true
peerDependencies:
browserslist: '>= 4.21.0'
dependencies:
- browserslist: 4.21.5
+ browserslist: 4.21.9
escalade: 3.1.1
picocolors: 1.0.0
dev: true
@@ -3964,8 +3982,8 @@ packages:
engines: {node: '>=10.13.0'}
dev: true
- /webpack@5.84.1:
- resolution: {integrity: sha512-ZP4qaZ7vVn/K8WN/p990SGATmrL1qg4heP/MrVneczYtpDGJWlrgZv55vxaV2ul885Kz+25MP2kSXkPe3LZfmg==}
+ /webpack@5.87.0:
+ resolution: {integrity: sha512-GOu1tNbQ7p1bDEoFRs2YPcfyGs8xq52yyPBZ3m2VGnXGtV9MxjrkABHm4V9Ia280OefsSLzvbVoXcfLxjKY/Iw==}
engines: {node: '>=10.13.0'}
hasBin: true
peerDependencies:
@@ -3979,12 +3997,12 @@ packages:
'@webassemblyjs/ast': 1.11.6
'@webassemblyjs/wasm-edit': 1.11.6
'@webassemblyjs/wasm-parser': 1.11.6
- acorn: 8.8.2
- acorn-import-assertions: 1.9.0(acorn@8.8.2)
- browserslist: 4.21.5
+ acorn: 8.9.0
+ acorn-import-assertions: 1.9.0(acorn@8.9.0)
+ browserslist: 4.21.9
chrome-trace-event: 1.0.3
- enhanced-resolve: 5.14.1
- es-module-lexer: 1.2.1
+ enhanced-resolve: 5.15.0
+ es-module-lexer: 1.3.0
eslint-scope: 5.1.1
events: 3.3.0
glob-to-regexp: 0.4.1
@@ -3993,9 +4011,9 @@ packages:
loader-runner: 4.3.0
mime-types: 2.1.35
neo-async: 2.6.2
- schema-utils: 3.1.2
+ schema-utils: 3.3.0
tapable: 2.2.1
- terser-webpack-plugin: 5.3.9(webpack@5.84.1)
+ terser-webpack-plugin: 5.3.9(webpack@5.87.0)
watchpack: 2.4.0
webpack-sources: 3.2.3
transitivePeerDependencies:
diff --git a/frontend/src/components/DeckyState.tsx b/frontend/src/components/DeckyState.tsx
index 53ef6d2d..920985b3 100644
--- a/frontend/src/components/DeckyState.tsx
+++ b/frontend/src/components/DeckyState.tsx
@@ -13,6 +13,12 @@ interface PublicDeckyState {
hasLoaderUpdate?: boolean;
isLoaderUpdating: boolean;
versionInfo: VerInfo | null;
+ userInfo: UserInfo | null;
+}
+
+export interface UserInfo {
+ username: string;
+ path: string;
}
export class DeckyState {
@@ -24,6 +30,7 @@ export class DeckyState {
private _hasLoaderUpdate: boolean = false;
private _isLoaderUpdating: boolean = false;
private _versionInfo: VerInfo | null = null;
+ private _userInfo: UserInfo | null = null;
public eventBus = new EventTarget();
@@ -37,6 +44,7 @@ export class DeckyState {
hasLoaderUpdate: this._hasLoaderUpdate,
isLoaderUpdating: this._isLoaderUpdating,
versionInfo: this._versionInfo,
+ userInfo: this._userInfo,
};
}
@@ -85,6 +93,11 @@ export class DeckyState {
this.notifyUpdate();
}
+ setUserInfo(userInfo: UserInfo) {
+ this._userInfo = userInfo;
+ this.notifyUpdate();
+ }
+
private notifyUpdate() {
this.eventBus.dispatchEvent(new Event('update'));
}
diff --git a/frontend/src/components/modals/DropdownMultiselect.tsx b/frontend/src/components/modals/DropdownMultiselect.tsx
new file mode 100644
index 00000000..5defbfa4
--- /dev/null
+++ b/frontend/src/components/modals/DropdownMultiselect.tsx
@@ -0,0 +1,121 @@
+import {
+ DialogButton,
+ DialogCheckbox,
+ DialogCheckboxProps,
+ Marquee,
+ Menu,
+ MenuItem,
+ findModuleChild,
+ showContextMenu,
+} from 'decky-frontend-lib';
+import { FC, useCallback, useEffect, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { FaChevronDown } from 'react-icons/fa';
+
+const dropDownControlButtonClass = findModuleChild((m) => {
+ if (typeof m !== 'object') return undefined;
+ for (const prop in m) {
+ if (m[prop]?.toString()?.includes('gamepaddropdown_DropDownControlButton')) {
+ return m[prop];
+ }
+ }
+});
+
+const DropdownMultiselectItem: FC<
+ {
+ value: any;
+ onSelect: (checked: boolean, value: any) => void;
+ checked: boolean;
+ } & DialogCheckboxProps
+> = ({ value, onSelect, checked: defaultChecked, ...rest }) => {
+ const [checked, setChecked] = useState(defaultChecked);
+
+ useEffect(() => {
+ onSelect?.(checked, value);
+ }, [checked, onSelect, value]);
+
+ return (
+ <MenuItem bInteractableItem onClick={() => setChecked((x) => !x)}>
+ <DialogCheckbox
+ style={{ marginBottom: 0, padding: 0 }}
+ className="decky_DropdownMultiselectItem_DialogCheckbox"
+ bottomSeparator="none"
+ {...rest}
+ onClick={() => setChecked((x) => !x)}
+ onChange={(checked) => setChecked(checked)}
+ controlled
+ checked={checked}
+ />
+ </MenuItem>
+ );
+};
+
+const DropdownMultiselect: FC<{
+ items: {
+ label: string;
+ value: string;
+ }[];
+ selected: string[];
+ onSelect: (selected: any[]) => void;
+ label: string;
+}> = ({ label, items, selected, onSelect }) => {
+ const [itemsSelected, setItemsSelected] = useState<any>(selected);
+ const { t } = useTranslation();
+
+ const handleItemSelect = useCallback((checked, value) => {
+ setItemsSelected((x: any) =>
+ checked ? [...x.filter((y: any) => y !== value), value] : x.filter((y: any) => y !== value),
+ );
+ }, []);
+
+ useEffect(() => {
+ onSelect(itemsSelected);
+ }, [itemsSelected, onSelect]);
+
+ return (
+ <DialogButton
+ style={{
+ display: 'flex',
+ alignItems: 'center',
+ maxWidth: '100%',
+ }}
+ className={dropDownControlButtonClass}
+ onClick={(evt) => {
+ evt.preventDefault();
+ showContextMenu(
+ <Menu label={label} cancelText={t('DropdownMultiselect.button.back') as string}>
+ <style>
+ {`
+ /* Inherit color from ".basiccontextmenu" */
+ .decky_DropdownMultiselectItem_DialogCheckbox > .DialogToggle_Label {
+ color: inherit;
+ }
+ `}
+ </style>
+ <div style={{ marginTop: '10px' }}>{/*FIXME: Hack for missing padding under label menu*/}</div>
+ {items.map((x) => (
+ <DropdownMultiselectItem
+ key={x.value}
+ label={x.label}
+ value={x.value}
+ checked={itemsSelected.includes(x.value)}
+ onSelect={handleItemSelect}
+ />
+ ))}
+ </Menu>,
+ evt.currentTarget ?? window,
+ );
+ }}
+ >
+ <Marquee>
+ {selected.length > 0
+ ? selected.map((x: any) => items[items.findIndex((v) => v.value === x)].label).join(', ')
+ : '…'}
+ </Marquee>
+ <div style={{ flexGrow: 1, minWidth: '1ch' }} />
+ <FaChevronDown style={{ height: '1em', flex: '0 0 1em' }} />
+ </DialogButton>
+ );
+};
+
+export default DropdownMultiselect;
diff --git a/frontend/src/components/modals/filepicker/FilePickerError.tsx b/frontend/src/components/modals/filepicker/FilePickerError.tsx
new file mode 100644
index 00000000..bf75afae
--- /dev/null
+++ b/frontend/src/components/modals/filepicker/FilePickerError.tsx
@@ -0,0 +1,51 @@
+import { FC, useEffect, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { IconContext } from 'react-icons';
+import { FaExclamationTriangle, FaQuestionCircle } from 'react-icons/fa';
+
+export enum FileErrorTypes {
+ FileNotFound,
+ Unknown,
+ None,
+}
+
+interface FilePickerErrorProps {
+ error: FileErrorTypes;
+ rawError?: string;
+}
+
+const FilePickerError: FC<FilePickerErrorProps> = ({ error, rawError = null }) => {
+ const [icon, setIcon] = useState<JSX.Element>(<FaQuestionCircle />);
+ const [text, setText] = useState<string | null>(null);
+ const { t } = useTranslation();
+
+ useEffect(() => {
+ switch (error) {
+ case FileErrorTypes.FileNotFound:
+ setText(t('FilePickerError.errors.file_not_found'));
+ setIcon(<FaExclamationTriangle />);
+ break;
+ case FileErrorTypes.Unknown:
+ setText(t('FilePickerError.errors.unknown', { raw_error: rawError }));
+ setIcon(<FaQuestionCircle />);
+ break;
+ case FileErrorTypes.None:
+ setText(null);
+ setIcon(<div></div>);
+ break;
+ }
+ }, [error]);
+
+ return (
+ <>
+ <div style={{ paddingTop: '50px', textAlign: 'center', height: '100%' }}>
+ <IconContext.Provider value={{ className: 'fileError', size: '128px' }}>
+ <div style={{ alignSelf: 'center', alignContent: 'center' }}>{icon}</div>
+ </IconContext.Provider>
+ <p style={{ height: '32px', paddingTop: '25px', alignSelf: 'flex-start', textAlign: 'center' }}>{text}</p>
+ </div>
+ </>
+ );
+};
+
+export default FilePickerError;
diff --git a/frontend/src/components/modals/filepicker/i18n/TSortOptions.tsx b/frontend/src/components/modals/filepicker/i18n/TSortOptions.tsx
new file mode 100644
index 00000000..5d861d18
--- /dev/null
+++ b/frontend/src/components/modals/filepicker/i18n/TSortOptions.tsx
@@ -0,0 +1,46 @@
+import { FC } from 'react';
+import { Translation } from 'react-i18next';
+
+export enum SortOptions {
+ name_desc = 'name_desc',
+ name_asc = 'name_asc',
+ modified_desc = 'modified_desc',
+ modified_asc = 'modified_asc',
+ created_desc = 'created_desc',
+ created_asc = 'created_asc',
+ size_desc = 'size_desc',
+ size_asc = 'size_asc',
+}
+
+interface TSortOptionsProps {
+ trans_part: SortOptions;
+}
+
+const TSortOptions: FC<TSortOptionsProps> = ({ trans_part }) => {
+ return (
+ <Translation>
+ {(t, {}) => {
+ switch (trans_part) {
+ case SortOptions.name_desc:
+ return t('FilePickerIndex.filter.name_desc');
+ case SortOptions.name_asc:
+ return t('FilePickerIndex.filter.name_asce');
+ case SortOptions.modified_desc:
+ return t('FilePickerIndex.filter.modified_desc');
+ case SortOptions.modified_asc:
+ return t('FilePickerIndex.filter.modified_asce');
+ case SortOptions.created_desc:
+ return t('FilePickerIndex.filter.created_desc');
+ case SortOptions.created_asc:
+ return t('FilePickerIndex.filter.created_asce');
+ case SortOptions.size_desc:
+ return t('FilePickerIndex.filter.size_desc');
+ case SortOptions.size_asc:
+ return t('FilePickerIndex.filter.size_asce');
+ }
+ }}
+ </Translation>
+ );
+};
+
+export default TSortOptions;
diff --git a/frontend/src/components/modals/filepicker/iconCustomizations.ts b/frontend/src/components/modals/filepicker/iconCustomizations.ts
index e09c9e67..69e1652d 100644
--- a/frontend/src/components/modals/filepicker/iconCustomizations.ts
+++ b/frontend/src/components/modals/filepicker/iconCustomizations.ts
@@ -38,7 +38,7 @@ const imageStyle = {
color: '#d18f00',
};
-const imageExtList = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'tif', 'tiff'];
+const imageExtList = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'tif', 'tiff', 'apng', 'tga'];
styleDef.push([imageStyle, imageExtList]);
diff --git a/frontend/src/components/modals/filepicker/index.tsx b/frontend/src/components/modals/filepicker/index.tsx
index 629f4ec5..7aada5a5 100644
--- a/frontend/src/components/modals/filepicker/index.tsx
+++ b/frontend/src/components/modals/filepicker/index.tsx
@@ -1,11 +1,26 @@
-import { DialogButton, Focusable, SteamSpinner, TextField } from 'decky-frontend-lib';
-import { useEffect } from 'react';
-import { FunctionComponent, useState } from 'react';
+import {
+ ControlsList,
+ DialogBody,
+ DialogButton,
+ DialogControlsSection,
+ DialogFooter,
+ Dropdown,
+ Focusable,
+ Marquee,
+ SteamSpinner,
+ TextField,
+ ToggleField,
+} from 'decky-frontend-lib';
+import { filesize } from 'filesize';
+import { FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react';
import { FileIcon, defaultStyles } from 'react-file-icon';
import { useTranslation } from 'react-i18next';
import { FaArrowUp, FaFolder } from 'react-icons/fa';
import Logger from '../../../logger';
+import DropdownMultiselect from '../DropdownMultiselect';
+import FilePickerError, { FileErrorTypes } from './FilePickerError';
+import TSortOption, { SortOptions } from './i18n/TSortOptions';
import { styleDefObj } from './iconCustomizations';
const logger = new Logger('FilePicker');
@@ -13,27 +28,89 @@ const logger = new Logger('FilePicker');
export interface FilePickerProps {
startPath: string;
includeFiles?: boolean;
- regex?: RegExp;
+ includeFolders?: boolean;
+ filter?: RegExp | ((file: File) => boolean);
+ validFileExtensions?: string[];
+ allowAllFiles?: boolean;
+ defaultHidden?: boolean;
+ max?: number;
onSubmit: (val: { path: string; realpath: string }) => void;
closeModal?: () => void;
}
-interface File {
+export interface File {
isdir: boolean;
+ ishidden: boolean;
name: string;
realpath: string;
+ size: number;
+ modified: number;
+ created: number;
}
interface FileListing {
realpath: string;
files: File[];
+ total: number;
}
+const sortOptions = [
+ {
+ data: SortOptions.name_desc,
+ label: <TSortOption trans_part={SortOptions.name_desc} />,
+ },
+ {
+ data: SortOptions.name_asc,
+ label: <TSortOption trans_part={SortOptions.name_asc} />,
+ },
+ {
+ data: SortOptions.modified_desc,
+ label: <TSortOption trans_part={SortOptions.modified_desc} />,
+ },
+ {
+ data: SortOptions.modified_asc,
+ label: <TSortOption trans_part={SortOptions.modified_asc} />,
+ },
+ {
+ data: SortOptions.created_desc,
+ label: <TSortOption trans_part={SortOptions.created_desc} />,
+ },
+ {
+ data: SortOptions.created_asc,
+ label: <TSortOption trans_part={SortOptions.created_asc} />,
+ },
+ {
+ data: SortOptions.size_desc,
+ label: <TSortOption trans_part={SortOptions.size_desc} />,
+ },
+ {
+ data: SortOptions.size_asc,
+ label: <TSortOption trans_part={SortOptions.size_asc} />,
+ },
+];
+
function getList(
path: string,
- includeFiles: boolean = true,
+ includeFiles: boolean,
+ includeFolders: boolean = true,
+ includeExt: string[] | null = null,
+ includeHidden: boolean = false,
+ orderBy: SortOptions = SortOptions.name_desc,
+ filterFor: RegExp | ((file: File) => boolean) | null = null,
+ pageNumber: number = 1,
+ max: number = 1000,
): Promise<{ result: FileListing | string; success: boolean }> {
- return window.DeckyPluginLoader.callServerMethod('filepicker_ls', { path, include_files: includeFiles });
+ return window.DeckyPluginLoader.callServerMethod('filepicker_ls', {
+ path,
+ include_files: includeFiles,
+ include_folders: includeFolders,
+ include_ext: includeExt ? includeExt : [],
+ include_hidden: includeHidden,
+ order_by: orderBy,
+ filter_for: filterFor,
+ page: pageNumber,
+ max: max,
+ });
}
const iconStyles = {
@@ -44,126 +121,240 @@ const iconStyles = {
const FilePicker: FunctionComponent<FilePickerProps> = ({
startPath,
includeFiles = true,
- regex,
+ filter = undefined,
+ includeFolders = true,
+ validFileExtensions = undefined,
+ allowAllFiles = true,
+ defaultHidden = false, // false by default makes sense for most users
+ max = 1000,
onSubmit,
closeModal,
}) => {
const { t } = useTranslation();
- if (startPath.endsWith('/')) startPath = startPath.substring(0, startPath.length - 1); // remove trailing path
+
+ if (startPath !== '/' && startPath.endsWith('/')) startPath = startPath.substring(0, startPath.length - 1); // remove trailing path
const [path, setPath] = useState<string>(startPath);
- const [listing, setListing] = useState<FileListing>({ files: [], realpath: path });
- const [error, setError] = useState<string | null>(null);
+ const [listing, setListing] = useState<FileListing>({ files: [], realpath: path, total: 0 });
+ const [files, setFiles] = useState<File[]>([]);
+ const [error, setError] = useState<FileErrorTypes>(FileErrorTypes.None);
+ const [rawError, setRawError] = useState<string | null>(null);
+ const [page, setPage] = useState<number>(1);
const [loading, setLoading] = useState<boolean>(true);
+ const [showHidden, setShowHidden] = useState<boolean>(defaultHidden);
+ const [sort, setSort] = useState<SortOptions>(SortOptions.name_desc);
+ const [selectedExts, setSelectedExts] = useState<string[] | undefined>(validFileExtensions);
+
+ const validExtsOptions = useMemo(() => {
+ let validExt: { label: string; value: string }[] = [];
+ if (validFileExtensions) {
+ if (allowAllFiles) {
+ validExt.push({ label: t('FilePickerIndex.files.all_files'), value: 'all_files' });
+ }
+ validExt.push(...validFileExtensions.map((x) => ({ label: x, value: x })));
+ }
+ return validExt;
+ }, [validFileExtensions, allowAllFiles]);
+
+ function isSelectionValid(validExts: string[], selection: string[]) {
+ if (validExts.some((el) => selection.includes(el))) return true;
+ return false;
+ }
+
+ const handleExtsSelect = useCallback((val: any) => {
+ // unselect other options if "All Files" is checked
+ if (allowAllFiles && val.includes('all_files')) {
+ setSelectedExts(['all_files']);
+ } else if (validFileExtensions && isSelectionValid(validFileExtensions, val)) {
+ // If at least one extension is still selected, then assign this selection to the selected values
+ setSelectedExts(val);
+ } else {
+ // Else do nothing
+ setSelectedExts(selectedExts);
+ }
+ }, []);
useEffect(() => {
(async () => {
- if (error) setError(null);
setLoading(true);
- const listing = await getList(path, includeFiles);
+ const listing = await getList(
+ path,
+ includeFiles,
+ includeFolders,
+ selectedExts,
+ showHidden,
+ sort,
+ filter,
+ page,
+ max,
+ );
if (!listing.success) {
- setListing({ files: [], realpath: path });
+ setListing({ files: [], realpath: path, total: 0 });
setLoading(false);
- setError(listing.result as string);
- logger.error(listing.result);
+ const theError = listing.result as string;
+ switch (theError) {
+ case theError.match(/\[Errno\s2.*/i)?.input:
+ case theError.match(/\[WinError\s3.*/i)?.input:
+ setError(FileErrorTypes.FileNotFound);
+ break;
+ default:
+ setRawError(theError);
+ setError(FileErrorTypes.Unknown);
+ break;
+ }
+ logger.debug(theError);
return;
+ } else {
+ setRawError(null);
+ setError(FileErrorTypes.None);
+ setFiles((listing.result as FileListing).files);
}
setLoading(false);
setListing(listing.result as FileListing);
logger.log('reloaded', path, listing);
})();
- }, [path]);
+ }, [error, path, includeFiles, includeFolders, showHidden, sort, selectedExts, page]);
return (
- <div className="deckyFilePicker">
- <Focusable style={{ display: 'flex', flexDirection: 'row', paddingBottom: '10px' }}>
- <DialogButton
- style={{
- minWidth: 'unset',
- width: '40px',
- flexGrow: '0',
- borderRadius: 'unset',
- margin: '0',
- padding: '10px',
- }}
- onClick={() => {
- const newPathArr = path.split('/');
- newPathArr.pop();
- let newPath = newPathArr.join('/');
- if (newPath == '') newPath = '/';
- setPath(newPath);
- }}
- >
- <FaArrowUp />
- </DialogButton>
- <div style={{ flexGrow: '1', width: '100%' }}>
- <TextField
- value={path}
- onChange={(e) => {
- e.target.value && setPath(e.target.value);
- }}
- style={{ height: '100%' }}
- />
- </div>
- </Focusable>
- <Focusable style={{ display: 'flex', flexDirection: 'column', height: '60vh', overflow: 'scroll' }}>
- {loading && <SteamSpinner style={{ height: '100%' }} />}
- {!loading &&
- listing.files
- .filter((file) => (includeFiles || file.isdir) && (!regex || regex.test(file.name)))
- .map((file) => {
- let extension = file.realpath.split('.').pop() as string;
- return (
- <DialogButton
- style={{ borderRadius: 'unset', margin: '0', padding: '10px' }}
- onClick={() => {
- const fullPath = `${path}${path.endsWith('/') ? '' : '/'}${file.name}`;
- if (file.isdir) setPath(fullPath);
- else {
- onSubmit({ path: fullPath, realpath: file.realpath });
- closeModal?.();
- }
- }}
- >
- <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start' }}>
- {file.isdir ? (
- <FaFolder style={iconStyles} />
- ) : (
- <div style={iconStyles}>
- {file.realpath.includes('.') ? (
- <FileIcon {...defaultStyles[extension]} {...styleDefObj[extension]} extension={''} />
- ) : (
- <FileIcon />
- )}
- </div>
- )}
- <span
+ <>
+ <DialogBody className="deckyFilePicker">
+ <DialogControlsSection>
+ <Focusable flow-children="right" style={{ display: 'flex', marginBottom: '1em' }}>
+ <DialogButton
+ style={{
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ minWidth: 'unset',
+ width: '40px',
+ borderRadius: 'unset',
+ margin: '0',
+ padding: '10px',
+ }}
+ onClick={() => {
+ const newPathArr = path.split('/');
+ const lastPath = newPathArr.pop();
+ //If I have a single / with spaces, pop the array twice
+ if (lastPath?.match(/^\/\s*$/) != null) newPathArr.pop();
+ let newPath = newPathArr.join('/');
+ if (newPath == '') newPath = '/';
+ setPath(newPath);
+ }}
+ >
+ <FaArrowUp />
+ </DialogButton>
+ <div style={{ width: '100%' }}>
+ <TextField
+ value={path}
+ onChange={(e) => {
+ e.target.value && setPath(e.target.value);
+ }}
+ style={{ height: '100%' }}
+ />
+ </div>
+ </Focusable>
+ <ControlsList alignItems="center" spacing="standard">
+ <ToggleField
+ highlightOnFocus={false}
+ label={t('FilePickerIndex.files.show_hidden')}
+ bottomSeparator="none"
+ checked={showHidden}
+ onChange={() => setShowHidden((x) => !x)}
+ />
+ <Dropdown rgOptions={sortOptions} selectedOption={sort} onChange={(x) => setSort(x.data)} />
+ {validFileExtensions && (
+ <DropdownMultiselect
+ label={t('FilePickerIndex.files.file_type')}
+ items={validExtsOptions}
+ selected={selectedExts ? selectedExts : []}
+ onSelect={handleExtsSelect}
+ />
+ )}
+ </ControlsList>
+ </DialogControlsSection>
+ <DialogControlsSection style={{ marginTop: '1em' }}>
+ <Focusable
+ style={{ display: 'flex', gap: '.25em', flexDirection: 'column', height: '60vh', overflow: 'scroll' }}
+ >
+ {loading && error === FileErrorTypes.None && <SteamSpinner style={{ height: '100%' }} />}
+ {!loading &&
+ error === FileErrorTypes.None &&
+ files.map((file) => {
+ const extension = file.realpath.split('.').pop() as string;
+ return (
+ <DialogButton
+ key={`${file.realpath}${file.name}`}
+ style={{ borderRadius: 'unset', margin: '0', padding: '10px' }}
+ onClick={() => {
+ const fullPath = `${path}${path.endsWith('/') ? '' : '/'}${file.name}`;
+ if (file.isdir) setPath(fullPath);
+ else {
+ onSubmit({ path: fullPath, realpath: file.realpath });
+ closeModal?.();
+ }
+ }}
+ >
+ <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'flex-start' }}>
+ {file.isdir ? (
+ <FaFolder style={iconStyles} />
+ ) : (
+ <div style={iconStyles}>
+ {file.realpath.includes('.') ? (
+ <FileIcon {...defaultStyles[extension]} {...styleDefObj[extension]} extension={''} />
+ ) : (
+ <FileIcon />
+ )}
+ </div>
+ )}
+ <Marquee>{file.name}</Marquee>
+ </div>
+ <div
style={{
- textOverflow: 'ellipsis',
- overflow: 'hidden',
+ display: 'flex',
+ opacity: 0.5,
+ fontSize: '.6em',
textAlign: 'left',
+ lineHeight: 1,
+ marginTop: '.5em',
}}
>
- {file.name}
- </span>
- </div>
- </DialogButton>
- );
- })}
- {error}
- </Focusable>
+ {file.isdir ? t('FilePickerIndex.folder.label') : filesize(file.size, { standard: 'iec' })}
+ <span style={{ marginLeft: 'auto' }}>{new Date(file.modified * 1000).toLocaleString()}</span>
+ </div>
+ </DialogButton>
+ );
+ })}
+ {error !== FileErrorTypes.None && <FilePickerError error={error} rawError={rawError ? rawError : ''} />}
+ </Focusable>
+ </DialogControlsSection>
+ </DialogBody>
{!loading && !error && !includeFiles && (
- <DialogButton
- className="Primary"
- style={{ marginTop: '10px', alignSelf: 'flex-end' }}
- onClick={() => {
- onSubmit({ path, realpath: listing.realpath });
- closeModal?.();
- }}
- >
- {t('FilePickerIndex.folder.select')}
- </DialogButton>
+ <DialogFooter>
+ <DialogButton
+ className="Primary"
+ style={{ marginTop: '10px', alignSelf: 'flex-end' }}
+ onClick={() => {
+ onSubmit({ path, realpath: listing.realpath });
+ closeModal?.();
+ }}
+ >
+ {t('FilePickerIndex.folder.select')}
+ </DialogButton>
+ </DialogFooter>
+ )}
+ {page * max < listing.total && (
+ <DialogFooter>
+ <DialogButton
+ className="Primary"
+ style={{ marginTop: '10px', alignSelf: 'flex-end' }}
+ onClick={() => {
+ setPage(page + 1);
+ }}
+ >
+ {t('FilePickerIndex.folder.show_more')}
+ </DialogButton>
+ </DialogFooter>
)}
- </div>
+ </>
);
};
diff --git a/frontend/src/components/settings/pages/developer/index.tsx b/frontend/src/components/settings/pages/developer/index.tsx
index 200f13ab..3e6db2f7 100644
--- a/frontend/src/components/settings/pages/developer/index.tsx
+++ b/frontend/src/components/settings/pages/developer/index.tsx
@@ -13,26 +13,24 @@ import { useTranslation } from 'react-i18next';
import { FaFileArchive, FaLink, FaReact, FaSteamSymbol, FaTerminal } from 'react-icons/fa';
import { setShouldConnectToReactDevTools, setShowValveInternal } from '../../../../developer';
+import Logger from '../../../../logger';
import { installFromURL } from '../../../../store';
import { useSetting } from '../../../../utils/hooks/useSetting';
+import { getSetting } from '../../../../utils/settings';
import RemoteDebuggingSettings from '../general/RemoteDebugging';
-const installFromZip = () => {
- window.DeckyPluginLoader.openFilePicker('/home/deck', true).then((val) => {
+const logger = new Logger('DeveloperIndex');
+
+const installFromZip = async () => {
+ const path = await getSetting<string>('user_info.user_home', '');
+ if (path === '') {
+ logger.error('The default path has not been found!');
+ return;
+ }
+ window.DeckyPluginLoader.openFilePicker(path, true, undefined, true, ['zip', 'rar'], false, true).then((val) => {
const url = `file://${val.path}`;
console.log(`Installing plugin locally from ${url}`);
-
- if (url.endsWith('.zip')) {
- installFromURL(url);
- } else {
- window.DeckyPluginLoader.toaster.toast({
- //title: t('SettingsDeveloperIndex.toast_zip.title'),
- title: 'Decky',
- //body: t('SettingsDeveloperIndex.toast_zip.body'),
- body: 'Installation failed! Only ZIP files are supported.',
- onClick: installFromZip,
- });
- }
+ installFromURL(url);
});
};
diff --git a/frontend/src/plugin-loader.tsx b/frontend/src/plugin-loader.tsx
index 6d20c2f0..c4063557 100644
--- a/frontend/src/plugin-loader.tsx
+++ b/frontend/src/plugin-loader.tsx
@@ -12,8 +12,9 @@ import {
import { FC, lazy } from 'react';
import { FaExclamationCircle, FaPlug } from 'react-icons/fa';
-import { DeckyState, DeckyStateContextProvider, useDeckyState } from './components/DeckyState';
+import { DeckyState, DeckyStateContextProvider, UserInfo, useDeckyState } from './components/DeckyState';
import LegacyPlugin from './components/LegacyPlugin';
+import { File } from './components/modals/filepicker';
import { deinitFilepickerPatches, initFilepickerPatches } from './components/modals/filepicker/patches';
import MultiplePluginsInstallModal from './components/modals/MultiplePluginsInstallModal';
import PluginInstallModal from './components/modals/PluginInstallModal';
@@ -31,7 +32,7 @@ import TabsHook from './tabs-hook';
import OldTabsHook from './tabs-hook.old';
import Toaster from './toaster';
import { VerInfo, callUpdaterMethod } from './updater';
-import { getSetting } from './utils/settings';
+import { getSetting, setSetting } from './utils/settings';
import TranslationHelper, { TranslationClass } from './utils/TranslationHelper';
const StorePage = lazy(() => import('./components/store/Store'));
@@ -99,9 +100,17 @@ class PluginLoader extends Logger {
initFilepickerPatches();
+ this.getUserInfo();
+
this.updateVersion();
}
+ public async getUserInfo() {
+ const userInfo = (await this.callServerMethod('get_user_info')).result as UserInfo;
+ setSetting('user_info.user_name', userInfo.username);
+ setSetting('user_info.user_home', userInfo.path);
+ }
+
public async updateVersion() {
const versionInfo = (await callUpdaterMethod('get_version')).result as VerInfo;
this.deckyState.setVersionInfo(versionInfo);
@@ -268,6 +277,7 @@ class PluginLoader extends Logger {
Authentication: window.deckyAuthToken,
},
});
+
if (res.ok) {
try {
let plugin_export = await eval(await res.text());
@@ -352,7 +362,12 @@ class PluginLoader extends Logger {
openFilePicker(
startPath: string,
includeFiles?: boolean,
- regex?: RegExp,
+ filter?: RegExp | ((file: File) => boolean),
+ includeFolders?: boolean,
+ extensions?: string[],
+ showHiddenFiles?: boolean,
+ allowAllFiles?: boolean,
+ max?: number,
): Promise<{ path: string; realpath: string }> {
return new Promise((resolve, reject) => {
const Content = ({ closeModal }: { closeModal?: () => void }) => (
@@ -367,9 +382,14 @@ class PluginLoader extends Logger {
<FilePicker
startPath={startPath}
includeFiles={includeFiles}
- regex={regex}
+ includeFolders={includeFolders}
+ filter={filter}
+ validFileExtensions={extensions}
+ allowAllFiles={allowAllFiles}
+ defaultHidden={showHiddenFiles}
onSubmit={resolve}
closeModal={closeModal}
+ max={max}
/>
</WithSuspense>
</ModalRoot>