mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 09:08:32 +02:00
Hotkeys and view mode kvs
This commit is contained in:
148
package-lock.json
generated
148
package-lock.json
generated
@@ -26,6 +26,7 @@
|
|||||||
"@radix-ui/react-separator": "^1.0.1",
|
"@radix-ui/react-separator": "^1.0.1",
|
||||||
"@radix-ui/react-tabs": "^1.0.3",
|
"@radix-ui/react-tabs": "^1.0.3",
|
||||||
"@tanstack/react-query": "^4.24.10",
|
"@tanstack/react-query": "^4.24.10",
|
||||||
|
"@tanstack/react-query-devtools": "^4.26.1",
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@tauri-apps/api": "^1.2.0",
|
||||||
"@vitejs/plugin-react": "^3.1.0",
|
"@vitejs/plugin-react": "^3.1.0",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
@@ -1987,21 +1988,36 @@
|
|||||||
"postcss": "^8.2.14"
|
"postcss": "^8.2.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tanstack/match-sorter-utils": {
|
||||||
|
"version": "8.7.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.7.6.tgz",
|
||||||
|
"integrity": "sha512-2AMpRiA6QivHOUiBpQAVxjiHAA68Ei23ZUMNaRJrN6omWiSFLoYrxGcT6BXtuzp0Jw4h6HZCmGGIM/gbwebO2A==",
|
||||||
|
"dependencies": {
|
||||||
|
"remove-accents": "0.4.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/kentcdodds"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tanstack/query-core": {
|
"node_modules/@tanstack/query-core": {
|
||||||
"version": "4.24.10",
|
"version": "4.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.24.10.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.26.1.tgz",
|
||||||
"integrity": "sha512-2QywqXEAGBIUoTdgn1lAB4/C8QEqwXHj2jrCLeYTk2xVGtLiPEUD8jcMoeB2noclbiW2mMt4+Fq7fZStuz3wAQ==",
|
"integrity": "sha512-Zrx2pVQUP4ndnsu6+K/m8zerXSVY8QM+YSbxA1/jbBY21GeCd5oKfYl92oXPK0hPEUtoNuunIdiq0ZMqLos+Zg==",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/tannerlinsley"
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tanstack/react-query": {
|
"node_modules/@tanstack/react-query": {
|
||||||
"version": "4.24.10",
|
"version": "4.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.24.10.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.26.1.tgz",
|
||||||
"integrity": "sha512-FY1DixytOcNNCydPQXLxuKEV7VSST32CAuJ55BjhDNqASnMLZn+6c30yQBMrODjmWMNwzfjMZnq0Vw7C62Fwow==",
|
"integrity": "sha512-i3dnz4TOARGIXrXQ5P7S25Zfi4noii/bxhcwPurh2nrf5EUCcAt/95TB2HSmMweUBx206yIMWUMEQ7ptd6zwDg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/query-core": "4.24.10",
|
"@tanstack/query-core": "4.26.1",
|
||||||
"use-sync-external-store": "^1.2.0"
|
"use-sync-external-store": "^1.2.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
@@ -2022,6 +2038,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tanstack/react-query-devtools": {
|
||||||
|
"version": "4.26.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.26.1.tgz",
|
||||||
|
"integrity": "sha512-ts2mA+fyFYFRi3Cee4xBk8Fx6waSFOM+yCkFqwJfGQRGjjTIMYMZPJv4wkv7vy12IVi1SYhL8au22LRKlXS1Zg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/match-sorter-utils": "^8.7.0",
|
||||||
|
"superjson": "^1.10.0",
|
||||||
|
"use-sync-external-store": "^1.2.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tanstack/react-query": "4.26.1",
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tauri-apps/api": {
|
"node_modules/@tauri-apps/api": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.2.0.tgz",
|
||||||
@@ -3418,6 +3453,20 @@
|
|||||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
|
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/copy-anything": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-fpW2W/BqEzqPp29QS+MwwfisHCQZtiduTe/m8idFo0xbti9fIZ2WVhAsCv4ggFVH3AgCkVdpoOCtQC6gBrdhjw==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-what": "^4.1.8"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.13"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/mesqueeb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/copy-to-clipboard": {
|
"node_modules/copy-to-clipboard": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
|
||||||
@@ -5411,6 +5460,17 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-what": {
|
||||||
|
"version": "4.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.8.tgz",
|
||||||
|
"integrity": "sha512-yq8gMao5upkPoGEU9LsB2P+K3Kt8Q3fQFCGyNCWOAnJAMzEXVV9drYb0TXr42TTliLLhKIBvulgAXgtLLnwzGA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.13"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/mesqueeb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/isarray": {
|
"node_modules/isarray": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||||
@@ -6597,6 +6657,11 @@
|
|||||||
"url": "https://github.com/sponsors/mysticatea"
|
"url": "https://github.com/sponsors/mysticatea"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remove-accents": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
|
||||||
|
"integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA=="
|
||||||
|
},
|
||||||
"node_modules/require-directory": {
|
"node_modules/require-directory": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
@@ -7107,6 +7172,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz",
|
||||||
"integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA=="
|
"integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/superjson": {
|
||||||
|
"version": "1.12.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/superjson/-/superjson-1.12.2.tgz",
|
||||||
|
"integrity": "sha512-ugvUo9/WmvWOjstornQhsN/sR9mnGtWGYeTxFuqLb4AiT4QdUavjGFRALCPKWWnAiUJ4HTpytj5e0t5HoMRkXg==",
|
||||||
|
"dependencies": {
|
||||||
|
"copy-anything": "^3.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/supports-color": {
|
"node_modules/supports-color": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
@@ -9263,17 +9339,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@tanstack/match-sorter-utils": {
|
||||||
|
"version": "8.7.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.7.6.tgz",
|
||||||
|
"integrity": "sha512-2AMpRiA6QivHOUiBpQAVxjiHAA68Ei23ZUMNaRJrN6omWiSFLoYrxGcT6BXtuzp0Jw4h6HZCmGGIM/gbwebO2A==",
|
||||||
|
"requires": {
|
||||||
|
"remove-accents": "0.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@tanstack/query-core": {
|
"@tanstack/query-core": {
|
||||||
"version": "4.24.10",
|
"version": "4.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.24.10.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.26.1.tgz",
|
||||||
"integrity": "sha512-2QywqXEAGBIUoTdgn1lAB4/C8QEqwXHj2jrCLeYTk2xVGtLiPEUD8jcMoeB2noclbiW2mMt4+Fq7fZStuz3wAQ=="
|
"integrity": "sha512-Zrx2pVQUP4ndnsu6+K/m8zerXSVY8QM+YSbxA1/jbBY21GeCd5oKfYl92oXPK0hPEUtoNuunIdiq0ZMqLos+Zg=="
|
||||||
},
|
},
|
||||||
"@tanstack/react-query": {
|
"@tanstack/react-query": {
|
||||||
"version": "4.24.10",
|
"version": "4.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.24.10.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.26.1.tgz",
|
||||||
"integrity": "sha512-FY1DixytOcNNCydPQXLxuKEV7VSST32CAuJ55BjhDNqASnMLZn+6c30yQBMrODjmWMNwzfjMZnq0Vw7C62Fwow==",
|
"integrity": "sha512-i3dnz4TOARGIXrXQ5P7S25Zfi4noii/bxhcwPurh2nrf5EUCcAt/95TB2HSmMweUBx206yIMWUMEQ7ptd6zwDg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@tanstack/query-core": "4.24.10",
|
"@tanstack/query-core": "4.26.1",
|
||||||
|
"use-sync-external-store": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tanstack/react-query-devtools": {
|
||||||
|
"version": "4.26.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.26.1.tgz",
|
||||||
|
"integrity": "sha512-ts2mA+fyFYFRi3Cee4xBk8Fx6waSFOM+yCkFqwJfGQRGjjTIMYMZPJv4wkv7vy12IVi1SYhL8au22LRKlXS1Zg==",
|
||||||
|
"requires": {
|
||||||
|
"@tanstack/match-sorter-utils": "^8.7.0",
|
||||||
|
"superjson": "^1.10.0",
|
||||||
"use-sync-external-store": "^1.2.0"
|
"use-sync-external-store": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -10226,6 +10320,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
|
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
|
||||||
},
|
},
|
||||||
|
"copy-anything": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-fpW2W/BqEzqPp29QS+MwwfisHCQZtiduTe/m8idFo0xbti9fIZ2WVhAsCv4ggFVH3AgCkVdpoOCtQC6gBrdhjw==",
|
||||||
|
"requires": {
|
||||||
|
"is-what": "^4.1.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"copy-to-clipboard": {
|
"copy-to-clipboard": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
|
||||||
@@ -11711,6 +11813,11 @@
|
|||||||
"get-intrinsic": "^1.1.1"
|
"get-intrinsic": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-what": {
|
||||||
|
"version": "4.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.8.tgz",
|
||||||
|
"integrity": "sha512-yq8gMao5upkPoGEU9LsB2P+K3Kt8Q3fQFCGyNCWOAnJAMzEXVV9drYb0TXr42TTliLLhKIBvulgAXgtLLnwzGA=="
|
||||||
|
},
|
||||||
"isarray": {
|
"isarray": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||||
@@ -12545,6 +12652,11 @@
|
|||||||
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
|
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"remove-accents": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
|
||||||
|
"integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA=="
|
||||||
|
},
|
||||||
"require-directory": {
|
"require-directory": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
@@ -12928,6 +13040,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz",
|
||||||
"integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA=="
|
"integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA=="
|
||||||
},
|
},
|
||||||
|
"superjson": {
|
||||||
|
"version": "1.12.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/superjson/-/superjson-1.12.2.tgz",
|
||||||
|
"integrity": "sha512-ugvUo9/WmvWOjstornQhsN/sR9mnGtWGYeTxFuqLb4AiT4QdUavjGFRALCPKWWnAiUJ4HTpytj5e0t5HoMRkXg==",
|
||||||
|
"requires": {
|
||||||
|
"copy-anything": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
|||||||
@@ -33,18 +33,19 @@
|
|||||||
"@radix-ui/react-separator": "^1.0.1",
|
"@radix-ui/react-separator": "^1.0.1",
|
||||||
"@radix-ui/react-tabs": "^1.0.3",
|
"@radix-ui/react-tabs": "^1.0.3",
|
||||||
"@tanstack/react-query": "^4.24.10",
|
"@tanstack/react-query": "^4.24.10",
|
||||||
|
"@tanstack/react-query-devtools": "^4.26.1",
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@tauri-apps/api": "^1.2.0",
|
||||||
"@vitejs/plugin-react": "^3.1.0",
|
"@vitejs/plugin-react": "^3.1.0",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"react": "^18.2.0",
|
|
||||||
"react-dom": "^18.2.0",
|
|
||||||
"react-router-dom": "^6.8.1",
|
|
||||||
"cm6-graphql": "^0.0.4-canary-b30a2325.0",
|
"cm6-graphql": "^0.0.4-canary-b30a2325.0",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"format-graphql": "^1.4.0",
|
"format-graphql": "^1.4.0",
|
||||||
"framer-motion": "^9.0.4",
|
"framer-motion": "^9.0.4",
|
||||||
"parse-color": "^1.0.0",
|
"parse-color": "^1.0.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
"react-helmet-async": "^1.3.0",
|
"react-helmet-async": "^1.3.0",
|
||||||
|
"react-router-dom": "^6.8.1",
|
||||||
"react-use": "^17.4.0"
|
"react-use": "^17.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -375,6 +375,8 @@ fn main() {
|
|||||||
|
|
||||||
let default_menu = Menu::os_default("Yaak".to_string().as_str());
|
let default_menu = Menu::os_default("Yaak".to_string().as_str());
|
||||||
let submenu = Submenu::new("Test Menu", Menu::new()
|
let submenu = Submenu::new("Test Menu", Menu::new()
|
||||||
|
.add_item(CustomMenuItem::new("refresh".to_string(), "Refresh").accelerator("CmdOrCtrl+Shift+r"))
|
||||||
|
.add_item(CustomMenuItem::new("send_request".to_string(), "Send Request").accelerator("CmdOrCtrl+r"))
|
||||||
.add_item(CustomMenuItem::new("zoom_reset".to_string(), "Zoom to Actual Size").accelerator("CmdOrCtrl+0"))
|
.add_item(CustomMenuItem::new("zoom_reset".to_string(), "Zoom to Actual Size").accelerator("CmdOrCtrl+0"))
|
||||||
.add_item(CustomMenuItem::new("zoom_in".to_string(), "Zoom In").accelerator("CmdOrCtrl+Plus"))
|
.add_item(CustomMenuItem::new("zoom_in".to_string(), "Zoom In").accelerator("CmdOrCtrl+Plus"))
|
||||||
.add_item(CustomMenuItem::new("zoom_out".to_string(), "Zoom Out").accelerator("CmdOrCtrl+-")),
|
.add_item(CustomMenuItem::new("zoom_out".to_string(), "Zoom Out").accelerator("CmdOrCtrl+-")),
|
||||||
@@ -438,6 +440,8 @@ fn main() {
|
|||||||
"zoom_reset" => event.window().emit("zoom", 0).unwrap(),
|
"zoom_reset" => event.window().emit("zoom", 0).unwrap(),
|
||||||
"zoom_in" => event.window().emit("zoom", 1).unwrap(),
|
"zoom_in" => event.window().emit("zoom", 1).unwrap(),
|
||||||
"zoom_out" => event.window().emit("zoom", -1).unwrap(),
|
"zoom_out" => event.window().emit("zoom", -1).unwrap(),
|
||||||
|
"refresh" => event.window().emit("refresh", true).unwrap(),
|
||||||
|
"send_request" => event.window().emit("send_request", true).unwrap(),
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||||
|
import { invoke } from '@tauri-apps/api';
|
||||||
import { listen } from '@tauri-apps/api/event';
|
import { listen } from '@tauri-apps/api/event';
|
||||||
import { MotionConfig } from 'framer-motion';
|
import { MotionConfig } from 'framer-motion';
|
||||||
import { HelmetProvider } from 'react-helmet-async';
|
import { HelmetProvider } from 'react-helmet-async';
|
||||||
|
import { matchPath } from 'react-router-dom';
|
||||||
import { keyValueQueryKey } from '../hooks/useKeyValues';
|
import { keyValueQueryKey } from '../hooks/useKeyValues';
|
||||||
import { requestsQueryKey } from '../hooks/useRequests';
|
import { requestsQueryKey } from '../hooks/useRequests';
|
||||||
import { responsesQueryKey } from '../hooks/useResponses';
|
import { responsesQueryKey } from '../hooks/useResponses';
|
||||||
import { DEFAULT_FONT_SIZE } from '../lib/constants';
|
import { DEFAULT_FONT_SIZE } from '../lib/constants';
|
||||||
import type { HttpRequest, HttpResponse, KeyValue } from '../lib/models';
|
import type { HttpRequest, HttpResponse, KeyValue } from '../lib/models';
|
||||||
import { convertDates } from '../lib/models';
|
import { convertDates } from '../lib/models';
|
||||||
import { AppRouter } from './AppRouter';
|
import { AppRouter, WORKSPACE_REQUEST_PATH } from './AppRouter';
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
await listen('updated_key_value', ({ payload: keyValue }: { payload: KeyValue }) => {
|
await listen('updated_key_value', ({ payload: keyValue }: { payload: KeyValue }) => {
|
||||||
queryClient.setQueryData(keyValueQueryKey(keyValue.namespace, keyValue.key), keyValue);
|
queryClient.setQueryData(keyValueQueryKey(keyValue), keyValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
await listen('updated_request', ({ payload: request }: { payload: HttpRequest }) => {
|
await listen('updated_request', ({ payload: request }: { payload: HttpRequest }) => {
|
||||||
@@ -66,6 +69,19 @@ await listen('updated_response', ({ payload: response }: { payload: HttpResponse
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await listen('send_request', async () => {
|
||||||
|
const params = matchPath(WORKSPACE_REQUEST_PATH, window.location.pathname);
|
||||||
|
const requestId = params?.params.requestId;
|
||||||
|
if (typeof requestId !== 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await invoke('send_request', { requestId });
|
||||||
|
});
|
||||||
|
|
||||||
|
await listen('refresh', () => {
|
||||||
|
location.reload();
|
||||||
|
});
|
||||||
|
|
||||||
await listen('zoom', ({ payload: zoomDelta }: { payload: number }) => {
|
await listen('zoom', ({ payload: zoomDelta }: { payload: number }) => {
|
||||||
const fontSize = parseFloat(window.getComputedStyle(document.documentElement).fontSize);
|
const fontSize = parseFloat(window.getComputedStyle(document.documentElement).fontSize);
|
||||||
|
|
||||||
@@ -87,6 +103,7 @@ export function App() {
|
|||||||
<MotionConfig transition={{ duration: 0.1 }}>
|
<MotionConfig transition={{ duration: 0.1 }}>
|
||||||
<HelmetProvider>
|
<HelmetProvider>
|
||||||
<AppRouter />
|
<AppRouter />
|
||||||
|
<ReactQueryDevtools initialIsOpen={false} />
|
||||||
</HelmetProvider>
|
</HelmetProvider>
|
||||||
</MotionConfig>
|
</MotionConfig>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ const Workspaces = lazy(() => import('./Workspaces'));
|
|||||||
const Workspace = lazy(() => import('./Workspace'));
|
const Workspace = lazy(() => import('./Workspace'));
|
||||||
const RouteError = lazy(() => import('./RouteError'));
|
const RouteError = lazy(() => import('./RouteError'));
|
||||||
|
|
||||||
|
export const WORKSPACE_PATH = '/workspaces/:workspaceId';
|
||||||
|
export const WORKSPACE_REQUEST_PATH = '/workspaces/:workspaceId/requests/:requestId';
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
@@ -15,11 +18,11 @@ const router = createBrowserRouter([
|
|||||||
element: <Workspaces />,
|
element: <Workspaces />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/workspaces/:workspaceId',
|
path: WORKSPACE_PATH,
|
||||||
element: <Workspace />,
|
element: <Workspace />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/workspaces/:workspaceId/requests/:requestId',
|
path: WORKSPACE_REQUEST_PATH,
|
||||||
element: <Workspace />,
|
element: <Workspace />,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { useActiveRequest } from '../hooks/useActiveRequest';
|
import { useActiveRequest } from '../hooks/useActiveRequest';
|
||||||
|
import { useIsResponseLoading } from '../hooks/useIsResponseLoading';
|
||||||
import { useSendRequest } from '../hooks/useSendRequest';
|
import { useSendRequest } from '../hooks/useSendRequest';
|
||||||
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
||||||
import { tryFormatJson } from '../lib/formatters';
|
import { tryFormatJson } from '../lib/formatters';
|
||||||
import { Editor } from './core/Editor';
|
import { Editor } from './core/Editor';
|
||||||
|
import { PairEditor } from './core/PairEditor';
|
||||||
import { TabContent, Tabs } from './core/Tabs/Tabs';
|
import { TabContent, Tabs } from './core/Tabs/Tabs';
|
||||||
import { GraphQLEditor } from './editors/GraphQLEditor';
|
import { GraphQLEditor } from './editors/GraphQLEditor';
|
||||||
import { PairEditor } from './core/PairEditor';
|
|
||||||
import { UrlBar } from './UrlBar';
|
import { UrlBar } from './UrlBar';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -18,6 +19,7 @@ export function RequestPane({ fullHeight, className }: Props) {
|
|||||||
const activeRequest = useActiveRequest();
|
const activeRequest = useActiveRequest();
|
||||||
const updateRequest = useUpdateRequest(activeRequest);
|
const updateRequest = useUpdateRequest(activeRequest);
|
||||||
const sendRequest = useSendRequest(activeRequest);
|
const sendRequest = useSendRequest(activeRequest);
|
||||||
|
const responseLoading = useIsResponseLoading();
|
||||||
|
|
||||||
if (activeRequest === null) return null;
|
if (activeRequest === null) return null;
|
||||||
|
|
||||||
@@ -27,10 +29,10 @@ export function RequestPane({ fullHeight, className }: Props) {
|
|||||||
key={activeRequest.id}
|
key={activeRequest.id}
|
||||||
method={activeRequest.method}
|
method={activeRequest.method}
|
||||||
url={activeRequest.url}
|
url={activeRequest.url}
|
||||||
loading={sendRequest.isLoading}
|
|
||||||
onMethodChange={(method) => updateRequest.mutate({ method })}
|
onMethodChange={(method) => updateRequest.mutate({ method })}
|
||||||
onUrlChange={(url) => updateRequest.mutate({ url })}
|
onUrlChange={(url) => updateRequest.mutate({ url })}
|
||||||
sendRequest={sendRequest.mutate}
|
sendRequest={sendRequest}
|
||||||
|
loading={responseLoading}
|
||||||
/>
|
/>
|
||||||
<Tabs
|
<Tabs
|
||||||
tabs={[
|
tabs={[
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ import { memo, useEffect, useMemo, useState } from 'react';
|
|||||||
import { useDeleteResponses } from '../hooks/useDeleteResponses';
|
import { useDeleteResponses } from '../hooks/useDeleteResponses';
|
||||||
import { useDeleteResponse } from '../hooks/useResponseDelete';
|
import { useDeleteResponse } from '../hooks/useResponseDelete';
|
||||||
import { useResponses } from '../hooks/useResponses';
|
import { useResponses } from '../hooks/useResponses';
|
||||||
|
import { useResponseViewMode } from '../hooks/useResponseViewMode';
|
||||||
import { tryFormatJson } from '../lib/formatters';
|
import { tryFormatJson } from '../lib/formatters';
|
||||||
import type { HttpResponse } from '../lib/models';
|
import type { HttpResponse } from '../lib/models';
|
||||||
|
import { pluralize } from '../lib/pluralize';
|
||||||
import { Dropdown, DropdownMenuTrigger } from './core/Dropdown';
|
import { Dropdown, DropdownMenuTrigger } from './core/Dropdown';
|
||||||
import { Editor } from './core/Editor';
|
import { Editor } from './core/Editor';
|
||||||
import { Icon } from './core/Icon';
|
import { Icon } from './core/Icon';
|
||||||
@@ -19,11 +21,11 @@ interface Props {
|
|||||||
|
|
||||||
export const ResponsePane = memo(function ResponsePane({ className }: Props) {
|
export const ResponsePane = memo(function ResponsePane({ className }: Props) {
|
||||||
const [activeResponseId, setActiveResponseId] = useState<string | null>(null);
|
const [activeResponseId, setActiveResponseId] = useState<string | null>(null);
|
||||||
const [viewMode, setViewMode] = useState<'pretty' | 'raw'>('pretty');
|
|
||||||
const responses = useResponses();
|
const responses = useResponses();
|
||||||
const activeResponse: HttpResponse | null = activeResponseId
|
const activeResponse: HttpResponse | null = activeResponseId
|
||||||
? responses.find((r) => r.id === activeResponseId) ?? null
|
? responses.find((r) => r.id === activeResponseId) ?? null
|
||||||
: responses[responses.length - 1] ?? null;
|
: responses[responses.length - 1] ?? null;
|
||||||
|
const [viewMode, toggleViewMode] = useResponseViewMode(activeResponse?.requestId);
|
||||||
const deleteResponse = useDeleteResponse(activeResponse);
|
const deleteResponse = useDeleteResponse(activeResponse);
|
||||||
const deleteAllResponses = useDeleteResponses(activeResponse?.requestId);
|
const deleteAllResponses = useDeleteResponses(activeResponse?.requestId);
|
||||||
|
|
||||||
@@ -74,7 +76,7 @@ export const ResponsePane = memo(function ResponsePane({ className }: Props) {
|
|||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
label: viewMode === 'pretty' ? 'View Raw' : 'View Prettified',
|
label: viewMode === 'pretty' ? 'View Raw' : 'View Prettified',
|
||||||
onSelect: () => setViewMode((m) => (m === 'pretty' ? 'raw' : 'pretty')),
|
onSelect: toggleViewMode,
|
||||||
},
|
},
|
||||||
'-----',
|
'-----',
|
||||||
{
|
{
|
||||||
@@ -83,7 +85,7 @@ export const ResponsePane = memo(function ResponsePane({ className }: Props) {
|
|||||||
disabled: responses.length === 0,
|
disabled: responses.length === 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Clear All Responses',
|
label: `Clear ${responses.length} ${pluralize('Response', responses.length)}`,
|
||||||
onSelect: deleteAllResponses.mutate,
|
onSelect: deleteAllResponses.mutate,
|
||||||
disabled: responses.length === 0,
|
disabled: responses.length === 0,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useSendRequest } from '../hooks/useSendRequest';
|
||||||
import { Button } from './core/Button';
|
import { Button } from './core/Button';
|
||||||
import { DropdownMenuRadio, DropdownMenuTrigger } from './core/Dropdown';
|
import { DropdownMenuRadio, DropdownMenuTrigger } from './core/Dropdown';
|
||||||
import { IconButton } from './core/IconButton';
|
import { IconButton } from './core/IconButton';
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { invoke } from '@tauri-apps/api';
|
import { invoke } from '@tauri-apps/api';
|
||||||
|
import { responsesQueryKey } from './useResponses';
|
||||||
|
|
||||||
export function useDeleteResponses(requestId?: string) {
|
export function useDeleteResponses(requestId?: string) {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@@ -10,7 +11,7 @@ export function useDeleteResponses(requestId?: string) {
|
|||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
if (!requestId) return;
|
if (!requestId) return;
|
||||||
queryClient.setQueryData(['responses', { requestId: requestId }], []);
|
queryClient.setQueryData(responsesQueryKey(requestId), []);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
8
src-web/hooks/useIsResponseLoading.ts
Normal file
8
src-web/hooks/useIsResponseLoading.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { useResponses } from './useResponses';
|
||||||
|
|
||||||
|
export function useIsResponseLoading(): boolean {
|
||||||
|
const responses = useResponses();
|
||||||
|
const response = responses[responses.length - 1];
|
||||||
|
if (!response) return false;
|
||||||
|
return !(response.body || response.error);
|
||||||
|
}
|
||||||
@@ -2,25 +2,46 @@ import { useMutation, useQuery } from '@tanstack/react-query';
|
|||||||
import { invoke } from '@tauri-apps/api';
|
import { invoke } from '@tauri-apps/api';
|
||||||
import type { KeyValue } from '../lib/models';
|
import type { KeyValue } from '../lib/models';
|
||||||
|
|
||||||
export function keyValueQueryKey(namespace: string, key: string) {
|
const DEFAULT_NAMESPACE = 'app';
|
||||||
return ['key_value', { namespace, key }];
|
|
||||||
|
export function keyValueQueryKey({
|
||||||
|
namespace = DEFAULT_NAMESPACE,
|
||||||
|
key,
|
||||||
|
}: {
|
||||||
|
namespace: string;
|
||||||
|
key: string | string[];
|
||||||
|
}) {
|
||||||
|
return ['key_value', { namespace, key: buildKey(key) }];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useKeyValues(namespace: string, key: string) {
|
export function useKeyValues({
|
||||||
|
namespace = DEFAULT_NAMESPACE,
|
||||||
|
key,
|
||||||
|
initialValue,
|
||||||
|
}: {
|
||||||
|
namespace: string;
|
||||||
|
key: string | string[];
|
||||||
|
initialValue: string;
|
||||||
|
}) {
|
||||||
const query = useQuery<KeyValue | null>({
|
const query = useQuery<KeyValue | null>({
|
||||||
initialData: null,
|
initialData: null,
|
||||||
queryKey: keyValueQueryKey(namespace, key),
|
queryKey: keyValueQueryKey({ namespace, key }),
|
||||||
queryFn: async () => invoke('get_key_value', { namespace, key }),
|
queryFn: async () => invoke('get_key_value', { namespace, key: buildKey(key) }),
|
||||||
});
|
});
|
||||||
|
|
||||||
const mutate = useMutation<KeyValue, unknown, KeyValue['value']>({
|
const mutate = useMutation<KeyValue, unknown, string>({
|
||||||
mutationFn: (value) => {
|
mutationFn: (value) => {
|
||||||
return invoke('set_key_value', { namespace, key, value });
|
return invoke('set_key_value', { namespace, key: buildKey(key), value });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
value: query.data?.value ?? null,
|
value: query.data?.value ?? initialValue,
|
||||||
set: (value: KeyValue['value']) => mutate.mutate(value),
|
set: (value: string) => mutate.mutate(value),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildKey(key: string | string[]): string {
|
||||||
|
if (typeof key === 'string') return key;
|
||||||
|
return key.join('::');
|
||||||
|
}
|
||||||
|
|||||||
15
src-web/hooks/useResponseViewMode.ts
Normal file
15
src-web/hooks/useResponseViewMode.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { useKeyValues } from './useKeyValues';
|
||||||
|
|
||||||
|
export function useResponseViewMode(requestId?: string): [string, () => void] {
|
||||||
|
const v = useKeyValues({
|
||||||
|
namespace: 'app',
|
||||||
|
key: ['response_view_mode', requestId ?? 'n/a'],
|
||||||
|
initialValue: 'pretty',
|
||||||
|
});
|
||||||
|
|
||||||
|
const toggle = () => {
|
||||||
|
v.set(v.value === 'pretty' ? 'raw' : 'pretty');
|
||||||
|
};
|
||||||
|
|
||||||
|
return [v.value, toggle];
|
||||||
|
}
|
||||||
@@ -14,5 +14,5 @@ export function useSendRequest(request: HttpRequest | null) {
|
|||||||
if (request == null) return;
|
if (request == null) return;
|
||||||
await queryClient.invalidateQueries(responsesQueryKey(request.id));
|
await queryClient.invalidateQueries(responsesQueryKey(request.id));
|
||||||
},
|
},
|
||||||
});
|
}).mutate;
|
||||||
}
|
}
|
||||||
|
|||||||
6
src-web/lib/pluralize.ts
Normal file
6
src-web/lib/pluralize.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export function pluralize(word: string, count: number): string {
|
||||||
|
if (count === 1) {
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
return `${word}s`;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user