mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 09:18:30 +02:00
Compare commits
12 Commits
v2023.3.0-
...
v2023.4.0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
919465cdbb | ||
|
|
de3730fa4f | ||
|
|
aff26fdd46 | ||
|
|
3c0edf06af | ||
|
|
cb8939db88 | ||
|
|
bf4b3213c4 | ||
|
|
633d7c52c4 | ||
|
|
0401cb92aa | ||
|
|
bff6c668a0 | ||
|
|
ee87e65763 | ||
|
|
f165a0b827 | ||
|
|
f7426dc8ce |
13
.github/workflows/artifacts.yml
vendored
13
.github/workflows/artifacts.yml
vendored
@@ -13,12 +13,13 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- os: macos-12
|
- os: macos-12
|
||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
- os: macos-latest
|
# - os: macos-latest
|
||||||
target: x86_64-apple-darwin
|
# target: x86_64-apple-darwin
|
||||||
- os: windows-2022
|
# - os: windows-2022
|
||||||
target: x86_64-pc-windows-msvc
|
# target: x86_64-pc-windows-msvc
|
||||||
- os: ubuntu-20.04
|
# # Re-enable Linux when context menu is supported
|
||||||
target: x86_64-unknown-linux-gnu
|
# - os: ubuntu-20.04
|
||||||
|
# target: x86_64-unknown-linux-gnu
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
|||||||
20
.run/Build Desktop.run.xml
Normal file
20
.run/Build Desktop.run.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Build Desktop" type="ShConfigurationType">
|
||||||
|
<option name="SCRIPT_TEXT" value="npm run tauri build -- --target universal-apple-darwin" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||||
|
<option name="SCRIPT_PATH" value="" />
|
||||||
|
<option name="SCRIPT_OPTIONS" value="" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||||
|
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||||
|
<option name="INTERPRETER_PATH" value="/bin/zsh" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||||
|
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||||
|
<envs>
|
||||||
|
<env name="TAURI_KEY_PASSWORD" value="fishhook-upstream-wash-assured" />
|
||||||
|
<env name="TAURI_PRIVATE_KEY" value="dW50cnVzdGVkIGNvbW1lbnQ6IHJzaWduIGVuY3J5cHRlZCBzZWNyZXQga2V5ClJXUlRZMEl5OGxWaytTa3dIa2xXVUltQzRGUXIzd2lYQ2NpV0ZhQURSbWJWZ1NrK0tnY0FBQkFBQUFBQUFBQUFBQUlBQUFBQUV2M1VKdVRyVHpHSzhQdGc2ZVFtOVNsMU5tNEVSN280cFNrbXhncW9tdjNXaFJZUTJqUzQ5Q01zWTJWRVhaY1pGNHNjR1NFR3JmcWFRN09NdWdGMXpZVXhzejR4V3lDV1JpZHlnbW5LNS9vMFFtRlZjbUl4YjZSNzhlMmk3ait5SExYcG5QZUkxOFE9Cg==" />
|
||||||
|
</envs>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
12
.run/Dev Desktop.run.xml
Normal file
12
.run/Dev Desktop.run.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Dev Desktop" type="js.build_tools.npm">
|
||||||
|
<package-json value="$PROJECT_DIR$/package.json" />
|
||||||
|
<command value="run" />
|
||||||
|
<scripts>
|
||||||
|
<script value="start" />
|
||||||
|
</scripts>
|
||||||
|
<node-interpreter value="project" />
|
||||||
|
<envs />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -41,6 +41,7 @@
|
|||||||
"react-helmet-async": "^1.3.0",
|
"react-helmet-async": "^1.3.0",
|
||||||
"react-router-dom": "^6.8.1",
|
"react-router-dom": "^6.8.1",
|
||||||
"react-use": "^17.4.0",
|
"react-use": "^17.4.0",
|
||||||
|
"slugify": "^1.6.6",
|
||||||
"tauri-plugin-context-menu": "^0.5.0",
|
"tauri-plugin-context-menu": "^0.5.0",
|
||||||
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v1",
|
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v1",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
@@ -7312,6 +7313,14 @@
|
|||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/slugify": {
|
||||||
|
"version": "1.6.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz",
|
||||||
|
"integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
"react-helmet-async": "^1.3.0",
|
"react-helmet-async": "^1.3.0",
|
||||||
"react-router-dom": "^6.8.1",
|
"react-router-dom": "^6.8.1",
|
||||||
"react-use": "^17.4.0",
|
"react-use": "^17.4.0",
|
||||||
|
"slugify": "^1.6.6",
|
||||||
"tauri-plugin-context-menu": "^0.5.0",
|
"tauri-plugin-context-menu": "^0.5.0",
|
||||||
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v1",
|
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v1",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
|
|||||||
70
src-tauri/Cargo.lock
generated
70
src-tauri/Cargo.lock
generated
@@ -123,17 +123,6 @@ dependencies = [
|
|||||||
"critical-section",
|
"critical-section",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atty"
|
|
||||||
version = "0.2.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi 0.1.19",
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -535,30 +524,6 @@ dependencies = [
|
|||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "clap"
|
|
||||||
version = "3.2.25"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
|
|
||||||
dependencies = [
|
|
||||||
"atty",
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"clap_lex",
|
|
||||||
"indexmap 1.9.3",
|
|
||||||
"strsim",
|
|
||||||
"termcolor",
|
|
||||||
"textwrap",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "clap_lex"
|
|
||||||
version = "0.2.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
|
||||||
dependencies = [
|
|
||||||
"os_str_bytes",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cobs"
|
name = "cobs"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
@@ -1756,15 +1721,6 @@ dependencies = [
|
|||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.1.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@@ -2162,7 +2118,7 @@ version = "0.4.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi 0.3.3",
|
"hermit-abi",
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
@@ -2705,7 +2661,7 @@ version = "1.16.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi 0.3.3",
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2883,12 +2839,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "os_str_bytes"
|
|
||||||
version = "6.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -4523,7 +4473,6 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.21.5",
|
"base64 0.21.5",
|
||||||
"bytes",
|
"bytes",
|
||||||
"clap",
|
|
||||||
"cocoa 0.24.1",
|
"cocoa 0.24.1",
|
||||||
"dirs-next",
|
"dirs-next",
|
||||||
"embed_plist",
|
"embed_plist",
|
||||||
@@ -4782,21 +4731,6 @@ dependencies = [
|
|||||||
"utf-8",
|
"utf-8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "termcolor"
|
|
||||||
version = "1.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "textwrap"
|
|
||||||
version = "0.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thin-slice"
|
name = "thin-slice"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
serde_json = { version = "1.0", features = ["raw_value"] }
|
serde_json = { version = "1.0", features = ["raw_value"] }
|
||||||
sqlx = { version = "0.7.2", features = ["sqlite", "runtime-tokio-rustls", "json", "chrono", "time"] }
|
sqlx = { version = "0.7.2", features = ["sqlite", "runtime-tokio-rustls", "json", "chrono", "time"] }
|
||||||
tauri = { version = "1.3", features = [
|
tauri = { version = "1.3", features = [
|
||||||
"cli",
|
|
||||||
"config-toml",
|
"config-toml",
|
||||||
"devtools",
|
"devtools",
|
||||||
"fs-read-file",
|
"fs-read-file",
|
||||||
|
|||||||
@@ -2,7 +2,13 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>com.apple.security.files.user-selected.read-write</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -666,6 +666,8 @@ fn main() {
|
|||||||
|
|
||||||
create_dir_all(dir.clone()).expect("Problem creating App directory!");
|
create_dir_all(dir.clone()).expect("Problem creating App directory!");
|
||||||
let p = dir.join("db.sqlite");
|
let p = dir.join("db.sqlite");
|
||||||
|
File::options().write(true).create(true).open(&p).expect("Problem creating database file!");
|
||||||
|
|
||||||
let p_string = p.to_string_lossy().replace(' ', "%20");
|
let p_string = p.to_string_lossy().replace(' ', "%20");
|
||||||
let url = format!("sqlite://{}?mode=rwc", p_string);
|
let url = format!("sqlite://{}?mode=rwc", p_string);
|
||||||
println!("Connecting to database at {}", url);
|
println!("Connecting to database at {}", url);
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ use log::info;
|
|||||||
use tauri::{AppHandle, updater, Window, Wry};
|
use tauri::{AppHandle, updater, Window, Wry};
|
||||||
use tauri::api::dialog;
|
use tauri::api::dialog;
|
||||||
|
|
||||||
|
use crate::is_dev;
|
||||||
|
|
||||||
// Check for updates every 3 hours
|
// Check for updates every 3 hours
|
||||||
const MAX_UPDATE_CHECK_SECONDS: u64 = 60 * 60 * 3;
|
const MAX_UPDATE_CHECK_SECONDS: u64 = 60 * 60 * 3;
|
||||||
|
|
||||||
@@ -28,6 +30,10 @@ impl YaakUpdater {
|
|||||||
app_handle: &AppHandle<Wry>,
|
app_handle: &AppHandle<Wry>,
|
||||||
mode: UpdateMode,
|
mode: UpdateMode,
|
||||||
) -> Result<(), updater::Error> {
|
) -> Result<(), updater::Error> {
|
||||||
|
if is_dev() {
|
||||||
|
info!("Skipping update check because we are in dev mode");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
self.last_update_check = SystemTime::now();
|
self.last_update_check = SystemTime::now();
|
||||||
let update_mode = get_update_mode_str(mode);
|
let update_mode = get_update_mode_str(mode);
|
||||||
info!("Checking for updates mode={}", update_mode);
|
info!("Checking for updates mode={}", update_mode);
|
||||||
@@ -38,13 +44,40 @@ impl YaakUpdater {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(update) => {
|
Ok(update) => {
|
||||||
if dialog::blocking::ask(
|
let h = app_handle.clone();
|
||||||
|
dialog::ask(
|
||||||
None::<&Window>,
|
None::<&Window>,
|
||||||
"Update available",
|
"Update Available",
|
||||||
"An update is available. Would you like to download and install it now?",
|
format!(
|
||||||
) {
|
"{} is available. Would you like to download and install it now?",
|
||||||
_ = update.download_and_install().await;
|
update.latest_version()
|
||||||
}
|
),
|
||||||
|
|confirmed| {
|
||||||
|
if !confirmed {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tauri::async_runtime::spawn(async move {
|
||||||
|
match update.download_and_install().await {
|
||||||
|
Ok(_) => {
|
||||||
|
if dialog::blocking::ask(
|
||||||
|
None::<&Window>,
|
||||||
|
"Update Installed",
|
||||||
|
format!("Would you like to restart the app?",),
|
||||||
|
) {
|
||||||
|
h.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
dialog::message(
|
||||||
|
None::<&Window>,
|
||||||
|
"Update Failed",
|
||||||
|
format!("The update failed to install: {}", e),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(updater::Error::UpToDate) => Ok(()),
|
Err(updater::Error::UpToDate) => Ok(()),
|
||||||
|
|||||||
@@ -8,26 +8,10 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "Yaak",
|
"productName": "Yaak",
|
||||||
"version": "2023.3.0-beta.1"
|
"version": "2023.4.0-beta.2"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"windows": [],
|
"windows": [],
|
||||||
"cli": {
|
|
||||||
"description": "Yaak CLI",
|
|
||||||
"longDescription": "This is the Yaak CLI, yo",
|
|
||||||
"beforeHelp": "u can use it to build, develop and manage your Yaak application.",
|
|
||||||
"afterHelp": "Have fun!",
|
|
||||||
"args": [],
|
|
||||||
"subcommands": {
|
|
||||||
"import": {
|
|
||||||
"args": [{
|
|
||||||
"name": "file",
|
|
||||||
"short": "f",
|
|
||||||
"takesValue": true
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
"all": false,
|
"all": false,
|
||||||
"os": {
|
"os": {
|
||||||
@@ -72,7 +56,7 @@
|
|||||||
"icons/release/icon.icns",
|
"icons/release/icon.icns",
|
||||||
"icons/release/icon.ico"
|
"icons/release/icon.ico"
|
||||||
],
|
],
|
||||||
"identifier": "co.schier.yaak",
|
"identifier": "app.yaak.desktop",
|
||||||
"longDescription": "The best cross-platform visual API client",
|
"longDescription": "The best cross-platform visual API client",
|
||||||
"resources": [
|
"resources": [
|
||||||
"migrations/*",
|
"migrations/*",
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ import { responsesQueryKey } from '../hooks/useResponses';
|
|||||||
import { useSyncWindowTitle } from '../hooks/useSyncWindowTitle';
|
import { useSyncWindowTitle } from '../hooks/useSyncWindowTitle';
|
||||||
import { workspacesQueryKey } from '../hooks/useWorkspaces';
|
import { workspacesQueryKey } from '../hooks/useWorkspaces';
|
||||||
import { trackPage } from '../lib/analytics';
|
import { trackPage } from '../lib/analytics';
|
||||||
import { DEFAULT_FONT_SIZE } from '../lib/constants';
|
|
||||||
import { NAMESPACE_NO_SYNC } from '../lib/keyValueStore';
|
import { NAMESPACE_NO_SYNC } from '../lib/keyValueStore';
|
||||||
import type { HttpRequest, HttpResponse, Model, Workspace } from '../lib/models';
|
import type { HttpRequest, HttpResponse, Model, Workspace } from '../lib/models';
|
||||||
import { modelsEq } from '../lib/models';
|
import { modelsEq } from '../lib/models';
|
||||||
import { setPathname } from '../lib/persistPathname';
|
import { setPathname } from '../lib/persistPathname';
|
||||||
|
|
||||||
|
const DEFAULT_FONT_SIZE = 16;
|
||||||
|
|
||||||
export function GlobalHooks() {
|
export function GlobalHooks() {
|
||||||
// Include here so they always update, even
|
// Include here so they always update, even
|
||||||
// if no component references them
|
// if no component references them
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { updateSchema } from 'cm6-graphql';
|
|||||||
import type { EditorView } from 'codemirror';
|
import type { EditorView } from 'codemirror';
|
||||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
import { useIntrospectGraphQL } from '../hooks/useIntrospectGraphQL';
|
import { useIntrospectGraphQL } from '../hooks/useIntrospectGraphQL';
|
||||||
|
import { tryFormatJson } from '../lib/formatters';
|
||||||
import type { HttpRequest } from '../lib/models';
|
import type { HttpRequest } from '../lib/models';
|
||||||
import { Button } from './core/Button';
|
import { Button } from './core/Button';
|
||||||
import type { EditorProps } from './core/Editor';
|
import type { EditorProps } from './core/Editor';
|
||||||
@@ -89,10 +90,10 @@ export function GraphQLEditor({ defaultValue, onChange, baseRequest, ...extraEdi
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
dialog.show({
|
dialog.show({
|
||||||
title: 'Introspection Failed',
|
title: 'Introspection Failed',
|
||||||
size: 'sm',
|
size: 'dynamic',
|
||||||
id: 'introspection-failed',
|
id: 'introspection-failed',
|
||||||
render: () => (
|
render: () => (
|
||||||
<div className="whitespace-pre-wrap">
|
<>
|
||||||
<FormattedError>{error ?? 'unknown'}</FormattedError>
|
<FormattedError>{error ?? 'unknown'}</FormattedError>
|
||||||
<div className="w-full mt-3">
|
<div className="w-full mt-3">
|
||||||
<Button
|
<Button
|
||||||
@@ -107,7 +108,7 @@ export function GraphQLEditor({ defaultValue, onChange, baseRequest, ...extraEdi
|
|||||||
Try Again
|
Try Again
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -121,6 +122,7 @@ export function GraphQLEditor({ defaultValue, onChange, baseRequest, ...extraEdi
|
|||||||
<Separator variant="primary" />
|
<Separator variant="primary" />
|
||||||
<p className="pt-1 text-gray-500 text-sm">Variables</p>
|
<p className="pt-1 text-gray-500 text-sm">Variables</p>
|
||||||
<Editor
|
<Editor
|
||||||
|
format={tryFormatJson}
|
||||||
contentType="application/json"
|
contentType="application/json"
|
||||||
defaultValue={JSON.stringify(variables, null, 2)}
|
defaultValue={JSON.stringify(variables, null, 2)}
|
||||||
heightMode="auto"
|
heightMode="auto"
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export function Overlay({
|
|||||||
return (
|
return (
|
||||||
<Portal name={portalName}>
|
<Portal name={portalName}>
|
||||||
{open && (
|
{open && (
|
||||||
<FocusTrap>
|
<FocusTrap>
|
||||||
<motion.div
|
<motion.div
|
||||||
className={classNames('fixed inset-0', zIndexes[zIndex])}
|
className={classNames('fixed inset-0', zIndexes[zIndex])}
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ export const RequestPane = memo(function RequestPane({ style, fullHeight, classN
|
|||||||
defaultValue={`${activeRequest?.body?.text ?? ''}`}
|
defaultValue={`${activeRequest?.body?.text ?? ''}`}
|
||||||
contentType="application/json"
|
contentType="application/json"
|
||||||
onChange={handleBodyTextChange}
|
onChange={handleBodyTextChange}
|
||||||
format={(v) => tryFormatJson(v)}
|
format={tryFormatJson}
|
||||||
/>
|
/>
|
||||||
) : activeRequest.bodyType === BODY_TYPE_XML ? (
|
) : activeRequest.bodyType === BODY_TYPE_XML ? (
|
||||||
<Editor
|
<Editor
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const drag = { gridArea: 'drag' };
|
|||||||
const DEFAULT = 0.5;
|
const DEFAULT = 0.5;
|
||||||
const MIN_WIDTH_PX = 10;
|
const MIN_WIDTH_PX = 10;
|
||||||
const MIN_HEIGHT_PX = 30;
|
const MIN_HEIGHT_PX = 30;
|
||||||
const STACK_VERTICAL_WIDTH = 650;
|
const STACK_VERTICAL_WIDTH = 600;
|
||||||
|
|
||||||
export const RequestResponse = memo(function RequestResponse({ style }: Props) {
|
export const RequestResponse = memo(function RequestResponse({ style }: Props) {
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|||||||
@@ -78,6 +78,11 @@ export function Sidebar({ className }: Props) {
|
|||||||
namespace: NAMESPACE_NO_SYNC,
|
namespace: NAMESPACE_NO_SYNC,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isCollapsed = useCallback(
|
||||||
|
(id: string) => collapsed.value?.[id] ?? false,
|
||||||
|
[collapsed.value],
|
||||||
|
);
|
||||||
|
|
||||||
const { tree, treeParentMap, selectableRequests } = useMemo<{
|
const { tree, treeParentMap, selectableRequests } = useMemo<{
|
||||||
tree: TreeNode | null;
|
tree: TreeNode | null;
|
||||||
treeParentMap: Record<string, TreeNode>;
|
treeParentMap: Record<string, TreeNode>;
|
||||||
@@ -258,13 +263,21 @@ export function Sidebar({ className }: Props) {
|
|||||||
|
|
||||||
const handleMove = useCallback<DraggableSidebarItemProps['onMove']>(
|
const handleMove = useCallback<DraggableSidebarItemProps['onMove']>(
|
||||||
(id, side) => {
|
(id, side) => {
|
||||||
const hoveredTree = treeParentMap[id] ?? null;
|
let hoveredTree = treeParentMap[id] ?? null;
|
||||||
const dragIndex = hoveredTree?.children.findIndex((n) => n.item.id === id) ?? -99;
|
const dragIndex = hoveredTree?.children.findIndex((n) => n.item.id === id) ?? -99;
|
||||||
const hoveredIndex = dragIndex + (side === 'above' ? 0 : 1);
|
const hoveredItem = hoveredTree?.children[dragIndex]?.item ?? null;
|
||||||
|
let hoveredIndex = dragIndex + (side === 'above' ? 0 : 1);
|
||||||
|
|
||||||
|
if (hoveredItem?.model === 'folder' && side === 'below' && !isCollapsed(hoveredItem.id)) {
|
||||||
|
// Move into folder if it's open and we're moving below it
|
||||||
|
hoveredTree = hoveredTree?.children.find((n) => n.item.id === id) ?? null;
|
||||||
|
hoveredIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
setHoveredTree(hoveredTree);
|
setHoveredTree(hoveredTree);
|
||||||
setHoveredIndex(hoveredIndex);
|
setHoveredIndex(hoveredIndex);
|
||||||
},
|
},
|
||||||
[treeParentMap],
|
[isCollapsed, treeParentMap],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDragStart = useCallback<DraggableSidebarItemProps['onDragStart']>((id: string) => {
|
const handleDragStart = useCallback<DraggableSidebarItemProps['onDragStart']>((id: string) => {
|
||||||
@@ -340,11 +353,8 @@ export function Sidebar({ className }: Props) {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (tree == null) {
|
// Not ready to render yet
|
||||||
return null;
|
if (tree == null || collapsed.value == null) {
|
||||||
}
|
|
||||||
|
|
||||||
if (collapsed.value == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +374,7 @@ export function Sidebar({ className }: Props) {
|
|||||||
treeParentMap={treeParentMap}
|
treeParentMap={treeParentMap}
|
||||||
selectedId={selectedId}
|
selectedId={selectedId}
|
||||||
selectedTree={selectedTree}
|
selectedTree={selectedTree}
|
||||||
collapsed={collapsed.value}
|
isCollapsed={isCollapsed}
|
||||||
tree={tree}
|
tree={tree}
|
||||||
focused={hasFocus}
|
focused={hasFocus}
|
||||||
draggingId={draggingId}
|
draggingId={draggingId}
|
||||||
@@ -392,7 +402,7 @@ interface SidebarItemsProps {
|
|||||||
handleEnd: (id: string) => void;
|
handleEnd: (id: string) => void;
|
||||||
handleDragStart: (id: string) => void;
|
handleDragStart: (id: string) => void;
|
||||||
onSelect: (requestId: string) => void;
|
onSelect: (requestId: string) => void;
|
||||||
collapsed: Record<string, boolean>;
|
isCollapsed: (id: string) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarItems({
|
function SidebarItems({
|
||||||
@@ -403,7 +413,7 @@ function SidebarItems({
|
|||||||
draggingId,
|
draggingId,
|
||||||
onSelect,
|
onSelect,
|
||||||
treeParentMap,
|
treeParentMap,
|
||||||
collapsed,
|
isCollapsed,
|
||||||
hoveredTree,
|
hoveredTree,
|
||||||
hoveredIndex,
|
hoveredIndex,
|
||||||
handleEnd,
|
handleEnd,
|
||||||
@@ -438,16 +448,16 @@ function SidebarItems({
|
|||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
onDragStart={handleDragStart}
|
onDragStart={handleDragStart}
|
||||||
useProminentStyles={focused}
|
useProminentStyles={focused}
|
||||||
collapsed={collapsed}
|
isCollapsed={isCollapsed}
|
||||||
child={child}
|
child={child}
|
||||||
>
|
>
|
||||||
{child.item.model === 'folder' &&
|
{child.item.model === 'folder' &&
|
||||||
!collapsed[child.item.id] &&
|
!isCollapsed(child.item.id) &&
|
||||||
draggingId !== child.item.id && (
|
draggingId !== child.item.id && (
|
||||||
<SidebarItems
|
<SidebarItems
|
||||||
treeParentMap={treeParentMap}
|
treeParentMap={treeParentMap}
|
||||||
tree={child}
|
tree={child}
|
||||||
collapsed={collapsed}
|
isCollapsed={isCollapsed}
|
||||||
draggingId={draggingId}
|
draggingId={draggingId}
|
||||||
hoveredTree={hoveredTree}
|
hoveredTree={hoveredTree}
|
||||||
hoveredIndex={hoveredIndex}
|
hoveredIndex={hoveredIndex}
|
||||||
@@ -478,12 +488,10 @@ type SidebarItemProps = {
|
|||||||
itemModel: string;
|
itemModel: string;
|
||||||
useProminentStyles?: boolean;
|
useProminentStyles?: boolean;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
onSelect: (id: string) => void;
|
|
||||||
draggable?: boolean;
|
draggable?: boolean;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
collapsed: Record<string, boolean>;
|
|
||||||
child: TreeNode;
|
child: TreeNode;
|
||||||
};
|
} & Pick<SidebarItemsProps, 'isCollapsed' | 'onSelect'>;
|
||||||
|
|
||||||
const SidebarItem = forwardRef(function SidebarItem(
|
const SidebarItem = forwardRef(function SidebarItem(
|
||||||
{
|
{
|
||||||
@@ -496,7 +504,7 @@ const SidebarItem = forwardRef(function SidebarItem(
|
|||||||
useProminentStyles,
|
useProminentStyles,
|
||||||
selected,
|
selected,
|
||||||
onSelect,
|
onSelect,
|
||||||
collapsed,
|
isCollapsed,
|
||||||
child,
|
child,
|
||||||
}: SidebarItemProps,
|
}: SidebarItemProps,
|
||||||
ref: ForwardedRef<HTMLLIElement>,
|
ref: ForwardedRef<HTMLLIElement>,
|
||||||
@@ -679,7 +687,7 @@ const SidebarItem = forwardRef(function SidebarItem(
|
|||||||
icon="chevronRight"
|
icon="chevronRight"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'-ml-0.5 mr-2 transition-transform',
|
'-ml-0.5 mr-2 transition-transform',
|
||||||
!collapsed[itemId] && 'transform rotate-90',
|
!isCollapsed(itemId) && 'transform rotate-90',
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ import type {
|
|||||||
} from 'react';
|
} from 'react';
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useWindowSize } from 'react-use';
|
import { useWindowSize } from 'react-use';
|
||||||
|
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
|
||||||
import { useOsInfo } from '../hooks/useOsInfo';
|
import { useOsInfo } from '../hooks/useOsInfo';
|
||||||
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
||||||
import { useSidebarWidth } from '../hooks/useSidebarWidth';
|
import { useSidebarWidth } from '../hooks/useSidebarWidth';
|
||||||
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
|
|
||||||
import { WINDOW_FLOATING_SIDEBAR_WIDTH } from '../lib/constants';
|
|
||||||
import { Button } from './core/Button';
|
import { Button } from './core/Button';
|
||||||
import { HStack } from './core/Stacks';
|
import { HStack } from './core/Stacks';
|
||||||
import { Overlay } from './Overlay';
|
import { Overlay } from './Overlay';
|
||||||
@@ -27,6 +26,8 @@ const head = { gridArea: 'head' };
|
|||||||
const body = { gridArea: 'body' };
|
const body = { gridArea: 'body' };
|
||||||
const drag = { gridArea: 'drag' };
|
const drag = { gridArea: 'drag' };
|
||||||
|
|
||||||
|
const WINDOW_FLOATING_SIDEBAR_WIDTH = 600;
|
||||||
|
|
||||||
export default function Workspace() {
|
export default function Workspace() {
|
||||||
const { setWidth, width, resetWidth } = useSidebarWidth();
|
const { setWidth, width, resetWidth } = useSidebarWidth();
|
||||||
const { hide, show, hidden, toggle } = useSidebarHidden();
|
const { hide, show, hidden, toggle } = useSidebarHidden();
|
||||||
@@ -66,9 +67,9 @@ export default function Workspace() {
|
|||||||
e.preventDefault(); // Prevent text selection and things
|
e.preventDefault(); // Prevent text selection and things
|
||||||
const newWidth = startWidth + (e.clientX - mouseStartX);
|
const newWidth = startWidth + (e.clientX - mouseStartX);
|
||||||
if (newWidth < 100) {
|
if (newWidth < 100) {
|
||||||
hide();
|
hide();
|
||||||
resetWidth();
|
resetWidth();
|
||||||
} else {
|
} else {
|
||||||
show();
|
show();
|
||||||
setWidth(newWidth);
|
setWidth(newWidth);
|
||||||
}
|
}
|
||||||
@@ -121,9 +122,9 @@ export default function Workspace() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{floating ? (
|
{floating ? (
|
||||||
<Overlay open={!hidden} portalName="sidebar" onClose={hide} zIndex={10}>
|
<Overlay open={!hidden} portalName="sidebar" onClose={hide}>
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, x: -10 }}
|
initial={{ opacity: 0, x: -20 }}
|
||||||
animate={{ opacity: 1, x: 0 }}
|
animate={{ opacity: 1, x: 0 }}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'absolute top-0 left-0 bottom-0 bg-gray-100 border-r border-highlight w-[14rem]',
|
'absolute top-0 left-0 bottom-0 bg-gray-100 border-r border-highlight w-[14rem]',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import classNames from 'classnames';
|
|||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
||||||
import { useAppRoutes } from '../hooks/useAppRoutes';
|
import { useAppRoutes } from '../hooks/useAppRoutes';
|
||||||
|
import { useAppVersion } from '../hooks/useAppVersion';
|
||||||
import { useCreateWorkspace } from '../hooks/useCreateWorkspace';
|
import { useCreateWorkspace } from '../hooks/useCreateWorkspace';
|
||||||
import { useDeleteWorkspace } from '../hooks/useDeleteWorkspace';
|
import { useDeleteWorkspace } from '../hooks/useDeleteWorkspace';
|
||||||
import { useExportData } from '../hooks/useExportData';
|
import { useExportData } from '../hooks/useExportData';
|
||||||
@@ -40,6 +41,7 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
|||||||
const dialog = useDialog();
|
const dialog = useDialog();
|
||||||
const prompt = usePrompt();
|
const prompt = usePrompt();
|
||||||
const routes = useAppRoutes();
|
const routes = useAppRoutes();
|
||||||
|
const appVersion = useAppVersion();
|
||||||
const [updateMode, setUpdateMode] = useUpdateMode();
|
const [updateMode, setUpdateMode] = useUpdateMode();
|
||||||
|
|
||||||
const items: DropdownItem[] = useMemo(() => {
|
const items: DropdownItem[] = useMemo(() => {
|
||||||
@@ -159,7 +161,7 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
|||||||
leftSlot: <Icon icon="upload" />,
|
leftSlot: <Icon icon="upload" />,
|
||||||
onSelect: () => exportData.mutate(),
|
onSelect: () => exportData.mutate(),
|
||||||
},
|
},
|
||||||
{ type: 'separator' },
|
{ type: 'separator', label: `v${appVersion.data}` },
|
||||||
{
|
{
|
||||||
key: 'appearance',
|
key: 'appearance',
|
||||||
label: 'Toggle Theme',
|
label: 'Toggle Theme',
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
import { useActiveRequest } from '../hooks/useActiveRequest';
|
import { useActiveRequest } from '../hooks/useActiveRequest';
|
||||||
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
|
||||||
import { Icon } from './core/Icon';
|
import { Icon } from './core/Icon';
|
||||||
import { IconButton } from './core/IconButton';
|
import { IconButton } from './core/IconButton';
|
||||||
import { HStack } from './core/Stacks';
|
import { HStack } from './core/Stacks';
|
||||||
@@ -17,7 +16,6 @@ interface Props {
|
|||||||
|
|
||||||
export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Props) {
|
export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Props) {
|
||||||
const activeRequest = useActiveRequest();
|
const activeRequest = useActiveRequest();
|
||||||
const activeWorkspace = useActiveWorkspace();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HStack
|
<HStack
|
||||||
@@ -29,13 +27,7 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
|
|||||||
<HStack space={0.5} className="flex-1 pointer-events-none" alignItems="center">
|
<HStack space={0.5} className="flex-1 pointer-events-none" alignItems="center">
|
||||||
<SidebarActions />
|
<SidebarActions />
|
||||||
<HStack alignItems="center">
|
<HStack alignItems="center">
|
||||||
<WorkspaceActionsDropdown
|
<WorkspaceActionsDropdown />
|
||||||
leftSlot={
|
|
||||||
<div className="w-4 h-4 leading-4 rounded text-[0.8em] bg-[#1B88DE] bg-opacity-80 text-white mr-1">
|
|
||||||
{activeWorkspace?.name[0]?.toUpperCase()}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Icon icon="chevronRight" className="text-gray-900 text-opacity-disabled" />
|
<Icon icon="chevronRight" className="text-gray-900 text-opacity-disabled" />
|
||||||
<EnvironmentActionsDropdown className="w-auto pointer-events-auto" />
|
<EnvironmentActionsDropdown className="w-auto pointer-events-auto" />
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export function Dialog({
|
|||||||
<span />
|
<span />
|
||||||
)}
|
)}
|
||||||
{description && <p id={descriptionId}>{description}</p>}
|
{description && <p id={descriptionId}>{description}</p>}
|
||||||
<div className="h-full w-full">{children}</div>
|
<div className="h-full w-full grid grid-cols-[minmax(0,1fr)]">{children}</div>
|
||||||
{/*Put close at the end so that it's the last thing to be tabbed to*/}
|
{/*Put close at the end so that it's the last thing to be tabbed to*/}
|
||||||
{!hideX && (
|
{!hideX && (
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function FormattedError({ children }: Props) {
|
export function FormattedError({ children }: Props) {
|
||||||
|
console.log('ERROR', children);
|
||||||
return (
|
return (
|
||||||
<pre
|
<pre
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'text-sm select-auto cursor-text bg-gray-100 p-3 rounded',
|
'w-full text-sm select-auto cursor-text bg-gray-100 p-3 rounded',
|
||||||
'whitespace-normal border border-red-500 border-dashed',
|
'whitespace-pre border border-red-500 border-dashed overflow-x-auto',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -180,8 +180,8 @@ export const PairEditor = memo(function PairEditor({
|
|||||||
forceUpdateKey={forceUpdateKey}
|
forceUpdateKey={forceUpdateKey}
|
||||||
nameAutocomplete={nameAutocomplete}
|
nameAutocomplete={nameAutocomplete}
|
||||||
valueAutocomplete={valueAutocomplete}
|
valueAutocomplete={valueAutocomplete}
|
||||||
namePlaceholder={isLast ? namePlaceholder : ''}
|
namePlaceholder={namePlaceholder}
|
||||||
valuePlaceholder={isLast ? valuePlaceholder : ''}
|
valuePlaceholder={valuePlaceholder}
|
||||||
nameValidate={nameValidate}
|
nameValidate={nameValidate}
|
||||||
valueValidate={valueValidate}
|
valueValidate={valueValidate}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
|||||||
6
src-web/hooks/useAppVersion.ts
Normal file
6
src-web/hooks/useAppVersion.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { getVersion } from '@tauri-apps/api/app';
|
||||||
|
|
||||||
|
export function useAppVersion() {
|
||||||
|
return useQuery<string>(['appVersion'], getVersion);
|
||||||
|
}
|
||||||
@@ -1,17 +1,12 @@
|
|||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation } from '@tanstack/react-query';
|
||||||
import { invoke } from '@tauri-apps/api';
|
import { invoke } from '@tauri-apps/api';
|
||||||
import type { SaveDialogOptions } from '@tauri-apps/api/dialog';
|
|
||||||
import { save } from '@tauri-apps/api/dialog';
|
import { save } from '@tauri-apps/api/dialog';
|
||||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
import slugify from 'slugify';
|
||||||
|
import { useActiveWorkspace } from './useActiveWorkspace';
|
||||||
import { useAlert } from './useAlert';
|
import { useAlert } from './useAlert';
|
||||||
|
|
||||||
const saveArgs: SaveDialogOptions = {
|
|
||||||
title: 'Export Data',
|
|
||||||
defaultPath: 'yaak-export.json',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useExportData() {
|
export function useExportData() {
|
||||||
const workspaceId = useActiveWorkspaceId();
|
const workspace = useActiveWorkspace();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
@@ -19,12 +14,18 @@ export function useExportData() {
|
|||||||
alert({ title: 'Export Failed', body: err });
|
alert({ title: 'Export Failed', body: err });
|
||||||
},
|
},
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
const exportPath = await save(saveArgs);
|
if (workspace == null) return;
|
||||||
|
|
||||||
|
const workspaceSlug = slugify(workspace.name, { lower: true });
|
||||||
|
const exportPath = await save({
|
||||||
|
title: 'Export Data',
|
||||||
|
defaultPath: `yaak.${workspaceSlug}.json`,
|
||||||
|
});
|
||||||
if (exportPath == null) {
|
if (exportPath == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await invoke('export_data', { workspaceId, exportPath });
|
await invoke('export_data', { workspaceId: workspace.id, exportPath });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ export function useIntrospectGraphQL(baseRequest: HttpRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (response.status < 200 || response.status >= 300) {
|
if (response.status < 200 || response.status >= 300) {
|
||||||
|
const text = await getResponseBodyText(response);
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error(`Request failed with status ${response.status}.\n\n${response.body}`),
|
new Error(`Request failed with status ${response.status}.\n\n${text}`),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
export const DEFAULT_FONT_SIZE = 16;
|
|
||||||
export const WINDOW_FLOATING_SIDEBAR_WIDTH = 600;
|
|
||||||
Reference in New Issue
Block a user