mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-11-13 20:23:40 +01:00
Compare commits
40
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab785b18a4 | ||
|
|
dcfdf077e7 | ||
|
|
bde5a474cc | ||
|
|
21f1dad7a4 | ||
|
|
6dac1265f3 | ||
|
|
77ab293f87 | ||
|
|
471a099b9b | ||
|
|
b0b282535f | ||
|
|
19ed8c2f0d | ||
|
|
d7e67cf13c | ||
|
|
1b154ba550 | ||
|
|
947e3f2e97 | ||
|
|
10559c8f4f | ||
|
|
8b1f5e807f | ||
|
|
d2dc719cc6 | ||
|
|
50f33b45b9 | ||
|
|
41fe01adb9 | ||
|
|
a200410697 | ||
|
|
4c15a49f8f | ||
|
|
c901ad4cbd | ||
|
|
d73d38f418 | ||
|
|
b0740770df | ||
|
|
75d94da578 | ||
|
|
79c49d8398 | ||
|
|
7c51510616 | ||
|
|
0b36ee56d2 | ||
|
|
2c345fc2ca | ||
|
|
909580c4a4 | ||
|
|
e805b225f7 | ||
|
|
0def693b63 | ||
|
|
7109db911a | ||
|
|
980f26f2f0 | ||
|
|
6b56ec569f | ||
|
|
36fa7a52fe | ||
|
|
c95099588f | ||
|
|
929f6202a4 | ||
|
|
915af7e3de | ||
|
|
eb9b5b6bb6 | ||
|
|
b4a1c418bb | ||
|
|
45262edfbd |
No files matched your search
+7
-7
@@ -8,7 +8,7 @@ Make Yaak runnable as a standalone CLI without Tauri as a dependency. The core R
|
||||
|
||||
```
|
||||
crates/ # Core crates - should NOT depend on Tauri
|
||||
crates-tauri/ # Tauri-specific crates (yaak-app, yaak-tauri-utils, etc.)
|
||||
crates-tauri/ # Tauri-specific crates (yaak-app-client, yaak-tauri-utils, etc.)
|
||||
crates-cli/ # CLI crate (yaak-cli)
|
||||
```
|
||||
|
||||
@@ -16,7 +16,7 @@ crates-cli/ # CLI crate (yaak-cli)
|
||||
|
||||
### 1. Folder Restructure
|
||||
|
||||
- Moved Tauri-dependent app code to `crates-tauri/yaak-app/`
|
||||
- Moved Tauri-dependent app code to `crates-tauri/yaak-app-client/`
|
||||
- Created `crates-tauri/yaak-tauri-utils/` for shared Tauri utilities (window traits, api_client, error handling)
|
||||
- Created `crates-cli/yaak-cli/` for the standalone CLI
|
||||
|
||||
@@ -50,14 +50,14 @@ crates-cli/ # CLI crate (yaak-cli)
|
||||
3. Move extension traits (e.g., `SomethingManagerExt`) to yaak-app or yaak-tauri-utils
|
||||
4. Initialize managers in yaak-app's `.setup()` block
|
||||
5. Remove `tauri` from Cargo.toml dependencies
|
||||
6. Update `crates-tauri/yaak-app/capabilities/default.json` to remove the plugin permission
|
||||
6. Update `crates-tauri/yaak-app-client/capabilities/default.json` to remove the plugin permission
|
||||
7. Replace `tauri::async_runtime::block_on` with `tokio::runtime::Handle::current().block_on()`
|
||||
|
||||
## Key Files
|
||||
|
||||
- `crates-tauri/yaak-app/src/lib.rs` - Main Tauri app, setup block initializes managers
|
||||
- `crates-tauri/yaak-app/src/commands.rs` - Migrated Tauri commands
|
||||
- `crates-tauri/yaak-app/src/models_ext.rs` - Database plugin and extension traits
|
||||
- `crates-tauri/yaak-app-client/src/lib.rs` - Main Tauri app, setup block initializes managers
|
||||
- `crates-tauri/yaak-app-client/src/commands.rs` - Migrated Tauri commands
|
||||
- `crates-tauri/yaak-app-client/src/models_ext.rs` - Database plugin and extension traits
|
||||
- `crates-tauri/yaak-tauri-utils/src/window.rs` - WorkspaceWindowTrait for window state
|
||||
- `crates/yaak-models/src/lib.rs` - Contains `init_standalone()` for CLI usage
|
||||
|
||||
@@ -79,5 +79,5 @@ e718a5f1 Refactor models_ext to use init_standalone from yaak-models
|
||||
## Testing
|
||||
|
||||
- Run `cargo check -p <crate>` to verify a crate builds without Tauri
|
||||
- Run `npm run app-dev` to test the Tauri app still works
|
||||
- Run `npm run client:dev` to test the Tauri app still works
|
||||
- Run `cargo run -p yaak-cli -- --help` to test the CLI
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
crates-tauri/yaak-app/vendored/**/* linguist-generated=true
|
||||
crates-tauri/yaak-app/gen/schemas/**/* linguist-generated=true
|
||||
crates-tauri/yaak-app-client/vendored/**/* linguist-generated=true
|
||||
crates-tauri/yaak-app-client/gen/schemas/**/* linguist-generated=true
|
||||
**/bindings/* linguist-generated=true
|
||||
crates/yaak-templates/pkg/* linguist-generated=true
|
||||
|
||||
|
||||
@@ -125,8 +125,8 @@ jobs:
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
|
||||
# Sign vendored binaries with hardened runtime and their specific entitlements
|
||||
codesign --force --options runtime --entitlements crates-tauri/yaak-app/macos/entitlements.yaakprotoc.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app/vendored/protoc/yaakprotoc || true
|
||||
codesign --force --options runtime --entitlements crates-tauri/yaak-app/macos/entitlements.yaaknode.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app/vendored/node/yaaknode || true
|
||||
codesign --force --options runtime --entitlements crates-tauri/yaak-app-client/macos/entitlements.yaakprotoc.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/protoc/yaakprotoc || true
|
||||
codesign --force --options runtime --entitlements crates-tauri/yaak-app-client/macos/entitlements.yaaknode.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/node/yaaknode || true
|
||||
|
||||
- uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
@@ -155,7 +155,8 @@ jobs:
|
||||
releaseBody: "[Changelog __VERSION__](https://yaak.app/blog/__VERSION__)"
|
||||
releaseDraft: true
|
||||
prerelease: true
|
||||
args: "${{ matrix.args }} --config ./crates-tauri/yaak-app/tauri.release.conf.json"
|
||||
projectPath: ./crates-tauri/yaak-app-client
|
||||
args: "${{ matrix.args }} --config ./tauri.release.conf.json"
|
||||
|
||||
# Build a per-machine NSIS installer for enterprise deployment (PDQ, SCCM, Intune)
|
||||
- name: Build and upload machine-wide installer (Windows only)
|
||||
@@ -171,7 +172,9 @@ jobs:
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
run: |
|
||||
Get-ChildItem -Recurse -Path target -File -Filter "*.exe.sig" | Remove-Item -Force
|
||||
npx tauri bundle ${{ matrix.args }} --bundles nsis --config ./crates-tauri/yaak-app/tauri.release.conf.json --config '{"bundle":{"createUpdaterArtifacts":true,"windows":{"nsis":{"installMode":"perMachine"}}}}'
|
||||
Push-Location crates-tauri/yaak-app-client
|
||||
npx tauri bundle ${{ matrix.args }} --bundles nsis --config ./tauri.release.conf.json --config '{"bundle":{"createUpdaterArtifacts":true,"windows":{"nsis":{"installMode":"perMachine"}}}}'
|
||||
Pop-Location
|
||||
$setup = Get-ChildItem -Recurse -Path target -Filter "*setup*.exe" | Select-Object -First 1
|
||||
$setupSig = "$($setup.FullName).sig"
|
||||
$dest = $setup.FullName -replace '-setup\.exe$', '-setup-machine.exe'
|
||||
|
||||
@@ -45,8 +45,8 @@ jobs:
|
||||
with:
|
||||
name: vendored-assets
|
||||
path: |
|
||||
crates-tauri/yaak-app/vendored/plugin-runtime/index.cjs
|
||||
crates-tauri/yaak-app/vendored/plugins
|
||||
crates-tauri/yaak-app-client/vendored/plugin-runtime/index.cjs
|
||||
crates-tauri/yaak-app-client/vendored/plugins
|
||||
if-no-files-found: error
|
||||
|
||||
build-binaries:
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: vendored-assets
|
||||
path: crates-tauri/yaak-app/vendored
|
||||
path: crates-tauri/yaak-app-client/vendored
|
||||
|
||||
- name: Set CLI build version
|
||||
shell: bash
|
||||
|
||||
+2
-1
@@ -39,7 +39,8 @@ codebook.toml
|
||||
target
|
||||
|
||||
# Per-worktree Tauri config (generated by post-checkout hook)
|
||||
crates-tauri/yaak-app/tauri.worktree.conf.json
|
||||
crates-tauri/yaak-app-client/tauri.worktree.conf.json
|
||||
crates-tauri/yaak-app-proxy/tauri.worktree.conf.json
|
||||
|
||||
# Tauri auto-generated permission files
|
||||
**/permissions/autogenerated
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
**/bindings/**
|
||||
**/routeTree.gen.ts
|
||||
crates/yaak-templates/pkg/**
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"ignorePatterns": [
|
||||
"**/bindings/**",
|
||||
"crates/yaak-templates/pkg/**",
|
||||
"apps/yaak-client/routeTree.gen.ts"
|
||||
]
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
vp lint
|
||||
vp staged
|
||||
Generated
+548
-625
File diff suppressed because it is too large.
Load diff
+22
-5
@@ -2,6 +2,9 @@
|
||||
resolver = "2"
|
||||
members = [
|
||||
"crates/yaak",
|
||||
# Common/foundation crates
|
||||
"crates/common/yaak-database",
|
||||
"crates/common/yaak-rpc",
|
||||
# Shared crates (no Tauri dependency)
|
||||
"crates/yaak-core",
|
||||
"crates/yaak-common",
|
||||
@@ -17,14 +20,19 @@ members = [
|
||||
"crates/yaak-tls",
|
||||
"crates/yaak-ws",
|
||||
"crates/yaak-api",
|
||||
"crates/yaak-proxy",
|
||||
# Proxy-specific crates
|
||||
"crates-proxy/yaak-proxy-lib",
|
||||
# CLI crates
|
||||
"crates-cli/yaak-cli",
|
||||
# Tauri-specific crates
|
||||
"crates-tauri/yaak-app",
|
||||
"crates-tauri/yaak-app-client",
|
||||
"crates-tauri/yaak-app-proxy",
|
||||
"crates-tauri/yaak-fonts",
|
||||
"crates-tauri/yaak-license",
|
||||
"crates-tauri/yaak-mac-window",
|
||||
"crates-tauri/yaak-tauri-utils",
|
||||
"crates-tauri/yaak-window",
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
@@ -39,14 +47,18 @@ schemars = { version = "0.8.22", features = ["chrono"] }
|
||||
serde = "1.0.228"
|
||||
serde_json = "1.0.145"
|
||||
sha2 = "0.10.9"
|
||||
tauri = "2.9.5"
|
||||
tauri-plugin = "2.5.2"
|
||||
tauri-plugin-dialog = "2.4.2"
|
||||
tauri-plugin-shell = "2.3.3"
|
||||
tauri = "2.11.1"
|
||||
tauri-plugin = "2.6.1"
|
||||
tauri-plugin-dialog = "2.7.1"
|
||||
tauri-plugin-shell = "2.3.5"
|
||||
thiserror = "2.0.17"
|
||||
tokio = "1.48.0"
|
||||
ts-rs = "11.1.0"
|
||||
|
||||
# Internal crates - common/foundation
|
||||
yaak-database = { path = "crates/common/yaak-database" }
|
||||
yaak-rpc = { path = "crates/common/yaak-rpc" }
|
||||
|
||||
# Internal crates - shared
|
||||
yaak-core = { path = "crates/yaak-core" }
|
||||
yaak = { path = "crates/yaak" }
|
||||
@@ -63,12 +75,17 @@ yaak-templates = { path = "crates/yaak-templates" }
|
||||
yaak-tls = { path = "crates/yaak-tls" }
|
||||
yaak-ws = { path = "crates/yaak-ws" }
|
||||
yaak-api = { path = "crates/yaak-api" }
|
||||
yaak-proxy = { path = "crates/yaak-proxy" }
|
||||
|
||||
# Internal crates - proxy
|
||||
yaak-proxy-lib = { path = "crates-proxy/yaak-proxy-lib" }
|
||||
|
||||
# Internal crates - Tauri-specific
|
||||
yaak-fonts = { path = "crates-tauri/yaak-fonts" }
|
||||
yaak-license = { path = "crates-tauri/yaak-license" }
|
||||
yaak-mac-window = { path = "crates-tauri/yaak-mac-window" }
|
||||
yaak-tauri-utils = { path = "crates-tauri/yaak-tauri-utils" }
|
||||
yaak-window = { path = "crates-tauri/yaak-window" }
|
||||
|
||||
[profile.release]
|
||||
strip = false
|
||||
@@ -1,6 +1,6 @@
|
||||
<p align="center">
|
||||
<a href="https://github.com/JamesIves/github-sponsors-readme-action">
|
||||
<img width="200px" src="https://github.com/mountain-loop/yaak/raw/main/crates-tauri/yaak-app/icons/icon.png">
|
||||
<img width="200px" src="https://github.com/mountain-loop/yaak/raw/main/crates-tauri/yaak-app-client/icons/icon.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
File renamed without changes.
@@ -1,9 +1,9 @@
|
||||
import { createWorkspaceModel, type Folder, modelTypeLabel } from "@yaakapp-internal/models";
|
||||
import { applySync, calculateSync } from "@yaakapp-internal/sync";
|
||||
import { Banner } from "../components/core/Banner";
|
||||
import { Button } from "../components/core/Button";
|
||||
import { InlineCode } from "../components/core/InlineCode";
|
||||
import {
|
||||
Banner,
|
||||
InlineCode,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
TruncatedWideTableCell,
|
||||
} from "../components/core/Table";
|
||||
} from "@yaakapp-internal/ui";
|
||||
import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace";
|
||||
import { createFastMutation } from "../hooks/useFastMutation";
|
||||
import { showDialog } from "../lib/dialog";
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-3
@@ -1,10 +1,8 @@
|
||||
import type { HttpRequest } from "@yaakapp-internal/models";
|
||||
import { Banner, HStack, InlineCode, VStack } from "@yaakapp-internal/ui";
|
||||
import mime from "mime";
|
||||
import { useKeyValue } from "../hooks/useKeyValue";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Button } from "./core/Button";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { HStack, VStack } from "./core/Stacks";
|
||||
import { SelectFile } from "./SelectFile";
|
||||
|
||||
type Props = {
|
||||
File renamed without changes.
+1
-2
@@ -1,15 +1,14 @@
|
||||
import { open } from "@tauri-apps/plugin-dialog";
|
||||
import { gitClone } from "@yaakapp-internal/git";
|
||||
import { Banner, VStack } from "@yaakapp-internal/ui";
|
||||
import { useState } from "react";
|
||||
import { openWorkspaceFromSyncDir } from "../commands/openWorkspaceFromSyncDir";
|
||||
import { appInfo } from "../lib/appInfo";
|
||||
import { showErrorToast } from "../lib/toast";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Button } from "./core/Button";
|
||||
import { Checkbox } from "./core/Checkbox";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { PlainInput } from "./core/PlainInput";
|
||||
import { VStack } from "./core/Stacks";
|
||||
import { promptCredentials } from "./git/credentials";
|
||||
|
||||
interface Props {
|
||||
File renamed without changes.
+1
-3
@@ -1,4 +1,5 @@
|
||||
import { workspacesAtom } from "@yaakapp-internal/models";
|
||||
import { Heading, Icon, useDebouncedState } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import { fuzzyFilter } from "fuzzbunny";
|
||||
import { useAtomValue } from "jotai";
|
||||
@@ -21,7 +22,6 @@ import { useActiveRequest } from "../hooks/useActiveRequest";
|
||||
import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace";
|
||||
import { useAllRequests } from "../hooks/useAllRequests";
|
||||
import { useCreateWorkspace } from "../hooks/useCreateWorkspace";
|
||||
import { useDebouncedState } from "../hooks/useDebouncedState";
|
||||
import { useEnvironmentsBreakdown } from "../hooks/useEnvironmentsBreakdown";
|
||||
import { useGrpcRequestActions } from "../hooks/useGrpcRequestActions";
|
||||
import type { HotkeyAction } from "../hooks/useHotKey";
|
||||
@@ -47,10 +47,8 @@ import { router } from "../lib/router";
|
||||
import { setWorkspaceSearchParams } from "../lib/setWorkspaceSearchParams";
|
||||
import { CookieDialog } from "./CookieDialog";
|
||||
import { Button } from "./core/Button";
|
||||
import { Heading } from "./core/Heading";
|
||||
import { Hotkey } from "./core/Hotkey";
|
||||
import { HttpMethodTag } from "./core/HttpMethodTag";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { PlainInput } from "./core/PlainInput";
|
||||
|
||||
interface CommandPaletteGroup {
|
||||
+1
-3
@@ -1,14 +1,12 @@
|
||||
import type { HttpRequest } from "@yaakapp-internal/models";
|
||||
import { patchModel } from "@yaakapp-internal/models";
|
||||
import { Banner, HStack, InlineCode } from "@yaakapp-internal/ui";
|
||||
import type { ReactNode } from "react";
|
||||
import { useToggle } from "../hooks/useToggle";
|
||||
import { showConfirm } from "../lib/confirm";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Button } from "./core/Button";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { Link } from "./core/Link";
|
||||
import { SizeTag } from "./core/SizeTag";
|
||||
import { HStack } from "./core/Stacks";
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
+1
-3
@@ -1,4 +1,5 @@
|
||||
import type { HttpResponse } from "@yaakapp-internal/models";
|
||||
import { Banner, HStack, InlineCode } from "@yaakapp-internal/ui";
|
||||
import { type ReactNode, useMemo } from "react";
|
||||
import { useSaveResponse } from "../hooks/useSaveResponse";
|
||||
import { useToggle } from "../hooks/useToggle";
|
||||
@@ -6,11 +7,8 @@ import { isProbablyTextContentType } from "../lib/contentType";
|
||||
import { getContentTypeFromHeaders } from "../lib/model_util";
|
||||
import { getResponseBodyText } from "../lib/responseBody";
|
||||
import { CopyButton } from "./CopyButton";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Button } from "./core/Button";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { SizeTag } from "./core/SizeTag";
|
||||
import { HStack } from "./core/Stacks";
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
+1
-3
@@ -1,15 +1,13 @@
|
||||
import type { HttpResponse } from "@yaakapp-internal/models";
|
||||
import { Banner, HStack, InlineCode } from "@yaakapp-internal/ui";
|
||||
import { type ReactNode, useMemo } from "react";
|
||||
import { getRequestBodyText as getHttpResponseRequestBodyText } from "../hooks/useHttpRequestBody";
|
||||
import { useToggle } from "../hooks/useToggle";
|
||||
import { isProbablyTextContentType } from "../lib/contentType";
|
||||
import { getContentTypeFromHeaders } from "../lib/model_util";
|
||||
import { CopyButton } from "./CopyButton";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Button } from "./core/Button";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { SizeTag } from "./core/SizeTag";
|
||||
import { HStack } from "./core/Stacks";
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
@@ -0,0 +1,190 @@
|
||||
import type { Cookie, CookieDomain, CookieJar } from "@yaakapp-internal/models";
|
||||
import { cookieJarsAtom, patchModelById } from "@yaakapp-internal/models";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { cookieDomain } from "../lib/model_util";
|
||||
import { showPromptForm } from "../lib/prompt-form";
|
||||
import { Banner, InlineCode } from "@yaakapp-internal/ui";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
|
||||
interface Props {
|
||||
cookieJarId: string | null;
|
||||
}
|
||||
|
||||
async function showAddCookieForm(cookieJarId: string): Promise<void> {
|
||||
const result = await showPromptForm({
|
||||
id: "add-cookie",
|
||||
title: "Add Cookie",
|
||||
size: "md",
|
||||
inputs: [
|
||||
{
|
||||
name: "cookie_pairs",
|
||||
label: "Cookie Attributes",
|
||||
type: "key_value",
|
||||
description:
|
||||
"Add key-value pairs for the cookie. These will be combined into the cookie string.",
|
||||
},
|
||||
{
|
||||
name: "domain_value",
|
||||
label: "Domain",
|
||||
type: "text",
|
||||
placeholder: "example.com",
|
||||
},
|
||||
{
|
||||
name: "hostOnly",
|
||||
label: "Host Only",
|
||||
type: "checkbox",
|
||||
defaultValue: "true",
|
||||
description:
|
||||
"If enabled, cookie is restricted to the exact host. Otherwise, it applies to the domain and its subdomains.",
|
||||
},
|
||||
{
|
||||
name: "path",
|
||||
label: "Path",
|
||||
type: "text",
|
||||
placeholder: "/",
|
||||
defaultValue: "/",
|
||||
},
|
||||
{
|
||||
name: "secure",
|
||||
label: "Secure",
|
||||
type: "checkbox",
|
||||
defaultValue: "true",
|
||||
description: "If enabled, cookie will only be sent over HTTPS connections.",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (result == null) return;
|
||||
|
||||
// Parse the form results
|
||||
const cookie_pairs_raw = result.cookie_pairs;
|
||||
const domain_value = (result.domain_value as string) ?? "";
|
||||
const path = (result.path as string) ?? "/";
|
||||
const hostOnly = (result.hostOnly as string) === "true";
|
||||
const secure = (result.secure as string) === "true";
|
||||
|
||||
// Convert key-value pairs to raw_cookie string format: key1=value1;key2=value2
|
||||
// Parse cookie_pairs - it comes as a JSON string from the key_value input
|
||||
let parsedPairs: Array<{ name: string; value: string }> = [];
|
||||
try {
|
||||
// Handle null, undefined, or string value
|
||||
const pairsStr =
|
||||
typeof cookie_pairs_raw === "string"
|
||||
? cookie_pairs_raw
|
||||
: cookie_pairs_raw != null
|
||||
? JSON.stringify(cookie_pairs_raw)
|
||||
: "[]";
|
||||
if (pairsStr && pairsStr !== "") {
|
||||
parsedPairs = JSON.parse(pairsStr);
|
||||
}
|
||||
} catch {
|
||||
parsedPairs = [];
|
||||
}
|
||||
|
||||
const validPairs = parsedPairs.filter((p) => p?.name?.trim());
|
||||
// Ensure at least one valid pair exists
|
||||
if (validPairs.length === 0) {
|
||||
console.log("No valid cookie pairs provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const raw_cookie = validPairs.map((p) => `${p.name}=${p.value}`).join(";");
|
||||
|
||||
const domain: CookieDomain = hostOnly
|
||||
? { HostOnly: domain_value ?? "" }
|
||||
: { Suffix: domain_value ?? "" };
|
||||
|
||||
// Build the new cookie with explicit tuple type for path
|
||||
const newCookie: Cookie = {
|
||||
raw_cookie,
|
||||
domain,
|
||||
expires: "SessionEnd",
|
||||
path: [path, secure] as [string, boolean],
|
||||
};
|
||||
|
||||
try {
|
||||
await patchModelById<"cookie_jar", CookieJar>("cookie_jar", cookieJarId, (prev) => ({
|
||||
...prev,
|
||||
cookies: [...prev.cookies, newCookie],
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error("Failed to add cookie:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export const CookieDialog = ({ cookieJarId }: Props) => {
|
||||
const cookieJars = useAtomValue(cookieJarsAtom);
|
||||
const cookieJar = cookieJars?.find((c) => c.id === cookieJarId);
|
||||
|
||||
if (cookieJar == null) {
|
||||
return <div>No cookie jar selected</div>;
|
||||
}
|
||||
|
||||
const onAddCookie = () => showAddCookieForm(cookieJar.id);
|
||||
|
||||
let tableBody;
|
||||
if (cookieJar.cookies.length === 0) {
|
||||
tableBody = (
|
||||
<tr>
|
||||
<td colSpan={3}>
|
||||
<Banner>
|
||||
Cookies will appear when a response contains the <InlineCode>Set-Cookie</InlineCode>{" "}
|
||||
header
|
||||
</Banner>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
// );
|
||||
} else {
|
||||
tableBody = cookieJar?.cookies.map((c: Cookie) => (
|
||||
<tr key={JSON.stringify(c)}>
|
||||
<td className="py-2 select-text cursor-text font-mono font-semibold max-w-0">
|
||||
{cookieDomain(c)}
|
||||
</td>
|
||||
<td className="py-2 pl-4 select-text cursor-text font-mono text-text-subtle whitespace-nowrap overflow-x-auto max-w-[200px] hide-scrollbars">
|
||||
{c.raw_cookie}
|
||||
</td>
|
||||
<td className="max-w-0 w-10">
|
||||
<IconButton
|
||||
icon="trash"
|
||||
size="xs"
|
||||
iconSize="sm"
|
||||
title="Delete"
|
||||
className="ml-auto"
|
||||
onClick={async () =>
|
||||
await patchModelById<"cookie_jar", CookieJar>("cookie_jar", cookieJar.id, (prev) => ({
|
||||
...prev,
|
||||
cookies: prev.cookies.filter((c2: Cookie) => c2 !== c),
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
));
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pb-2">
|
||||
<table className="w-full text-sm mb-auto min-w-full max-w-full divide-y divide-surface-highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="py-2 text-left">Domain</th>
|
||||
<th className="py-2 text-left pl-4">Cookie</th>
|
||||
<th className="py-2 pl-4 w-10">
|
||||
<IconButton
|
||||
icon="plus"
|
||||
size="xs"
|
||||
iconSize="sm"
|
||||
title="Add Cookie"
|
||||
className="ml-auto"
|
||||
onClick={onAddCookie}
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-surface-highlight">{tableBody}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
+1
-2
@@ -9,9 +9,8 @@ import { showPrompt } from "../lib/prompt";
|
||||
import { setWorkspaceSearchParams } from "../lib/setWorkspaceSearchParams";
|
||||
import { CookieDialog } from "./CookieDialog";
|
||||
import { Dropdown, type DropdownItem } from "./core/Dropdown";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { Icon, InlineCode } from "@yaakapp-internal/ui";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
|
||||
export const CookieDropdown = memo(function CookieDropdown() {
|
||||
const activeCookieJar = useActiveCookieJar();
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useTimedBoolean } from "../hooks/useTimedBoolean";
|
||||
import { useTimedBoolean } from "@yaakapp-internal/ui";
|
||||
import { copyToClipboard } from "../lib/copy";
|
||||
import { showToast } from "../lib/toast";
|
||||
import type { ButtonProps } from "./core/Button";
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
import { useTimedBoolean } from "../hooks/useTimedBoolean";
|
||||
import { IconButton, type IconButtonProps, useTimedBoolean } from "@yaakapp-internal/ui";
|
||||
import { copyToClipboard } from "../lib/copy";
|
||||
import { showToast } from "../lib/toast";
|
||||
import type { IconButtonProps } from "./core/IconButton";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
|
||||
interface Props extends Omit<IconButtonProps, "onClick" | "icon"> {
|
||||
text: string | (() => Promise<string | null>);
|
||||
File renamed without changes.
File renamed without changes.
+1
-1
@@ -1,6 +1,7 @@
|
||||
import { gitMutations } from "@yaakapp-internal/git";
|
||||
import type { WorkspaceMeta } from "@yaakapp-internal/models";
|
||||
import { createGlobalModel, updateModel } from "@yaakapp-internal/models";
|
||||
import { VStack } from "@yaakapp-internal/ui";
|
||||
import { useState } from "react";
|
||||
import { router } from "../lib/router";
|
||||
import { setupOrConfigureEncryption } from "../lib/setupOrConfigureEncryption";
|
||||
@@ -10,7 +11,6 @@ import { Button } from "./core/Button";
|
||||
import { Checkbox } from "./core/Checkbox";
|
||||
import { Label } from "./core/Label";
|
||||
import { PlainInput } from "./core/PlainInput";
|
||||
import { VStack } from "./core/Stacks";
|
||||
import { EncryptionHelp } from "./EncryptionHelp";
|
||||
import { gitCallbacks } from "./git/callbacks";
|
||||
import { SyncToFilesystemSetting } from "./SyncToFilesystemSetting";
|
||||
File renamed without changes.
+11
-3
@@ -1,13 +1,21 @@
|
||||
import type { DnsOverride, Workspace } from "@yaakapp-internal/models";
|
||||
import { patchModel } from "@yaakapp-internal/models";
|
||||
import { useCallback, useId, useMemo } from "react";
|
||||
import { fireAndForget } from "../lib/fireAndForget";
|
||||
import {
|
||||
HStack,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
VStack,
|
||||
} from "@yaakapp-internal/ui";
|
||||
import { useCallback, useId, useMemo } from "react";
|
||||
import { Button } from "./core/Button";
|
||||
import { Checkbox } from "./core/Checkbox";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { PlainInput } from "./core/PlainInput";
|
||||
import { HStack, VStack } from "./core/Stacks";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "./core/Table";
|
||||
|
||||
interface Props {
|
||||
workspace: Workspace;
|
||||
File renamed without changes.
@@ -11,6 +11,7 @@ import type {
|
||||
FormInputText,
|
||||
JsonPrimitive,
|
||||
} from "@yaakapp-internal/plugins";
|
||||
import { Banner, VStack } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useCallback, useEffect, useMemo } from "react";
|
||||
@@ -19,7 +20,6 @@ import { useRandomKey } from "../hooks/useRandomKey";
|
||||
import { capitalize } from "../lib/capitalize";
|
||||
import { showDialog } from "../lib/dialog";
|
||||
import { resolvedModelName } from "../lib/resolvedModelName";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Checkbox } from "./core/Checkbox";
|
||||
import { DetailsBanner } from "./core/DetailsBanner";
|
||||
import { Editor } from "./core/Editor/LazyEditor";
|
||||
@@ -31,7 +31,6 @@ import type { Pair } from "./core/PairEditor";
|
||||
import { PairEditor } from "./core/PairEditor";
|
||||
import { PlainInput } from "./core/PlainInput";
|
||||
import { Select } from "./core/Select";
|
||||
import { VStack } from "./core/Stacks";
|
||||
import { Markdown } from "./Markdown";
|
||||
import { SelectFile } from "./SelectFile";
|
||||
|
||||
File renamed without changes.
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { VStack } from "./core/Stacks";
|
||||
import { VStack } from "@yaakapp-internal/ui";
|
||||
|
||||
export function EncryptionHelp() {
|
||||
return (
|
||||
+1
-1
@@ -8,7 +8,7 @@ import type { ButtonProps } from "./core/Button";
|
||||
import { Button } from "./core/Button";
|
||||
import type { DropdownItem } from "./core/Dropdown";
|
||||
import { Dropdown } from "./core/Dropdown";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { Icon } from "@yaakapp-internal/ui";
|
||||
import { EnvironmentColorIndicator } from "./EnvironmentColorIndicator";
|
||||
|
||||
type Props = {
|
||||
File renamed without changes.
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { ColorIndicator } from "./ColorIndicator";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Banner } from "@yaakapp-internal/ui";
|
||||
import { Button } from "./core/Button";
|
||||
import { ColorPickerWithThemeColors } from "./core/ColorPicker";
|
||||
|
||||
+84
-53
@@ -1,34 +1,38 @@
|
||||
import type { Environment, Workspace } from "@yaakapp-internal/models";
|
||||
import { duplicateModel, patchModel } from "@yaakapp-internal/models";
|
||||
import type { TreeHandle, TreeNode, TreeProps } from "@yaakapp-internal/ui";
|
||||
import { Banner, Icon, InlineCode, SplitLayout, Tree } from "@yaakapp-internal/ui";
|
||||
import { atom, useAtomValue } from "jotai";
|
||||
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||
import { atomFamily } from "jotai-family";
|
||||
import { useCallback, useLayoutEffect, useRef, useState } from "react";
|
||||
import { createSubEnvironmentAndActivate } from "../commands/createEnvironment";
|
||||
import { activeWorkspaceAtom, activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace";
|
||||
import {
|
||||
environmentsBreakdownAtom,
|
||||
useEnvironmentsBreakdown,
|
||||
} from "../hooks/useEnvironmentsBreakdown";
|
||||
import { useHotKey } from "../hooks/useHotKey";
|
||||
import { atomWithKVStorage } from "../lib/atoms/atomWithKVStorage";
|
||||
import { deleteModelWithConfirm } from "../lib/deleteModelWithConfirm";
|
||||
import { fireAndForget } from "../lib/fireAndForget";
|
||||
import { jotaiStore } from "../lib/jotai";
|
||||
import { isBaseEnvironment, isSubEnvironment } from "../lib/model_util";
|
||||
import { resolvedModelName } from "../lib/resolvedModelName";
|
||||
import { showColorPicker } from "../lib/showColorPicker";
|
||||
import { Banner } from "./core/Banner";
|
||||
import type { ContextMenuProps, DropdownItem } from "./core/Dropdown";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { ContextMenu } from "./core/Dropdown";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { IconTooltip } from "./core/IconTooltip";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import type { PairEditorHandle } from "./core/PairEditor";
|
||||
import { SplitLayout } from "./core/SplitLayout";
|
||||
import type { TreeNode } from "./core/tree/common";
|
||||
import type { TreeHandle, TreeProps } from "./core/tree/Tree";
|
||||
import { Tree } from "./core/tree/Tree";
|
||||
import { EnvironmentColorIndicator } from "./EnvironmentColorIndicator";
|
||||
import { EnvironmentEditor } from "./EnvironmentEditor";
|
||||
import { EnvironmentSharableTooltip } from "./EnvironmentSharableTooltip";
|
||||
|
||||
const collapsedFamily = atomFamily((treeId: string) => {
|
||||
const key = ["env_collapsed", treeId ?? "n/a"];
|
||||
return atomWithKVStorage<Record<string, boolean>>(key, {});
|
||||
});
|
||||
|
||||
interface Props {
|
||||
initialEnvironmentId: string | null;
|
||||
setRef?: (ref: PairEditorHandle | null) => void;
|
||||
@@ -49,7 +53,7 @@ export function EnvironmentEditDialog({ initialEnvironmentId, setRef }: Props) {
|
||||
|
||||
return (
|
||||
<SplitLayout
|
||||
name="env_editor"
|
||||
storageKey="env_editor"
|
||||
defaultRatio={0.75}
|
||||
layout="horizontal"
|
||||
className="gap-0"
|
||||
@@ -113,7 +117,7 @@ function EnvironmentEditDialogSidebar({
|
||||
const treeRef = useRef<TreeHandle>(null);
|
||||
const { baseEnvironment, baseEnvironments } = useEnvironmentsBreakdown();
|
||||
|
||||
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
||||
// oxlint-disable-next-line react-hooks/exhaustive-deps -- none
|
||||
useLayoutEffect(() => {
|
||||
if (selectedEnvironmentId == null) return;
|
||||
treeRef.current?.selectItem(selectedEnvironmentId);
|
||||
@@ -130,44 +134,60 @@ function EnvironmentEditDialogSidebar({
|
||||
[baseEnvironment?.id, selectedEnvironmentId, setSelectedEnvironmentId],
|
||||
);
|
||||
|
||||
const actions = useMemo(() => {
|
||||
const enable = () => treeRef.current?.hasFocus() ?? false;
|
||||
const treeHasFocus = useCallback(() => treeRef.current?.hasFocus() ?? false, []);
|
||||
|
||||
const actions = {
|
||||
"sidebar.selected.rename": {
|
||||
enable,
|
||||
allowDefault: true,
|
||||
priority: 100,
|
||||
cb: async (items: TreeModel[]) => {
|
||||
const item = items[0];
|
||||
if (items.length === 1 && item != null) {
|
||||
treeRef.current?.renameItem(item.id);
|
||||
}
|
||||
},
|
||||
},
|
||||
"sidebar.selected.delete": {
|
||||
priority: 100,
|
||||
enable,
|
||||
cb: (items: TreeModel[]) => deleteModelWithConfirm(items),
|
||||
},
|
||||
"sidebar.selected.duplicate": {
|
||||
priority: 100,
|
||||
enable,
|
||||
cb: async (items: TreeModel[]) => {
|
||||
if (items.length === 1 && items[0]) {
|
||||
const item = items[0];
|
||||
const newId = await duplicateModel(item);
|
||||
setSelectedEnvironmentId(newId);
|
||||
} else {
|
||||
await Promise.all(items.map(duplicateModel));
|
||||
}
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
return actions;
|
||||
}, [setSelectedEnvironmentId]);
|
||||
const getSelectedTreeModels = useCallback(
|
||||
() => treeRef.current?.getSelectedItems() as TreeModel[] | undefined,
|
||||
[],
|
||||
);
|
||||
|
||||
const hotkeys = useMemo<TreeProps<TreeModel>["hotkeys"]>(() => ({ actions }), [actions]);
|
||||
const handleRenameSelected = useCallback(() => {
|
||||
const items = getSelectedTreeModels();
|
||||
if (items?.length === 1 && items[0] != null) {
|
||||
treeRef.current?.renameItem(items[0].id);
|
||||
}
|
||||
}, [getSelectedTreeModels]);
|
||||
|
||||
const handleDeleteSelected = useCallback(
|
||||
(items: TreeModel[]) => deleteModelWithConfirm(items),
|
||||
[],
|
||||
);
|
||||
|
||||
const handleDuplicateSelected = useCallback(
|
||||
async (items: TreeModel[]) => {
|
||||
if (items.length === 1 && items[0]) {
|
||||
const newId = await duplicateModel(items[0]);
|
||||
setSelectedEnvironmentId(newId);
|
||||
} else {
|
||||
await Promise.all(items.map(duplicateModel));
|
||||
}
|
||||
},
|
||||
[setSelectedEnvironmentId],
|
||||
);
|
||||
|
||||
useHotKey("sidebar.selected.rename", handleRenameSelected, {
|
||||
enable: treeHasFocus,
|
||||
allowDefault: true,
|
||||
priority: 100,
|
||||
});
|
||||
useHotKey(
|
||||
"sidebar.selected.delete",
|
||||
useCallback(() => {
|
||||
const items = getSelectedTreeModels();
|
||||
if (items) {
|
||||
fireAndForget(handleDeleteSelected(items));
|
||||
}
|
||||
}, [getSelectedTreeModels, handleDeleteSelected]),
|
||||
{ enable: treeHasFocus, priority: 100 },
|
||||
);
|
||||
useHotKey(
|
||||
"sidebar.selected.duplicate",
|
||||
useCallback(async () => {
|
||||
const items = getSelectedTreeModels();
|
||||
if (items) await handleDuplicateSelected(items);
|
||||
}, [getSelectedTreeModels, handleDuplicateSelected]),
|
||||
{ enable: treeHasFocus, priority: 100 },
|
||||
);
|
||||
|
||||
const getContextMenu = useCallback(
|
||||
(items: TreeModel[]): ContextMenuProps["items"] => {
|
||||
@@ -196,12 +216,10 @@ function EnvironmentEditDialogSidebar({
|
||||
hidden: isBaseEnvironment(environment) || !singleEnvironment,
|
||||
hotKeyAction: "sidebar.selected.rename",
|
||||
hotKeyLabelOnly: true,
|
||||
onSelect: async () => {
|
||||
onSelect: () => {
|
||||
// Not sure why this is needed, but without it the
|
||||
// edit input blurs immediately after opening.
|
||||
requestAnimationFrame(() => {
|
||||
fireAndForget(actions["sidebar.selected.rename"].cb(items));
|
||||
});
|
||||
requestAnimationFrame(() => handleRenameSelected());
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -210,7 +228,7 @@ function EnvironmentEditDialogSidebar({
|
||||
hidden: isBaseEnvironment(environment),
|
||||
hotKeyAction: "sidebar.selected.duplicate",
|
||||
hotKeyLabelOnly: true,
|
||||
onSelect: () => actions["sidebar.selected.duplicate"].cb(items),
|
||||
onSelect: () => handleDuplicateSelected(items),
|
||||
},
|
||||
{
|
||||
label: environment.color ? "Change Color" : "Assign Color",
|
||||
@@ -246,7 +264,12 @@ function EnvironmentEditDialogSidebar({
|
||||
|
||||
return menuItems;
|
||||
},
|
||||
[actions, baseEnvironments.length, handleDeleteEnvironment],
|
||||
[
|
||||
baseEnvironments.length,
|
||||
handleDeleteEnvironment,
|
||||
handleDuplicateSelected,
|
||||
handleRenameSelected,
|
||||
],
|
||||
);
|
||||
|
||||
const handleDragEnd = useCallback(async function handleDragEnd({
|
||||
@@ -293,6 +316,13 @@ function EnvironmentEditDialogSidebar({
|
||||
[setSelectedEnvironmentId],
|
||||
);
|
||||
|
||||
const renderContextMenuFn = useCallback<NonNullable<TreeProps<TreeModel>["renderContextMenu"]>>(
|
||||
({ items, position, onClose }) => (
|
||||
<ContextMenu items={items as DropdownItem[]} triggerPosition={position} onClose={onClose} />
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
||||
const tree = useAtomValue(treeAtom);
|
||||
return (
|
||||
<aside className="x-theme-sidebar h-full w-full min-w-0 grid overflow-y-auto border-r border-border-subtle ">
|
||||
@@ -301,10 +331,11 @@ function EnvironmentEditDialogSidebar({
|
||||
<Tree
|
||||
ref={treeRef}
|
||||
treeId={treeId}
|
||||
collapsedAtom={collapsedFamily(treeId)}
|
||||
className="px-2 pb-10"
|
||||
hotkeys={hotkeys}
|
||||
root={tree}
|
||||
getContextMenu={getContextMenu}
|
||||
renderContextMenu={renderContextMenuFn}
|
||||
onDragEnd={handleDragEnd}
|
||||
getItemKey={(i) => `${i.id}::${i.name}`}
|
||||
ItemLeftSlotInner={ItemLeftSlotInner}
|
||||
+1
-1
@@ -1,6 +1,7 @@
|
||||
import type { Environment } from "@yaakapp-internal/models";
|
||||
import { patchModel } from "@yaakapp-internal/models";
|
||||
import type { GenericCompletionOption } from "@yaakapp-internal/plugins";
|
||||
import { Heading } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { useEnvironmentsBreakdown } from "../hooks/useEnvironmentsBreakdown";
|
||||
@@ -15,7 +16,6 @@ import {
|
||||
} from "../lib/setupOrConfigureEncryption";
|
||||
import { DismissibleBanner } from "./core/DismissibleBanner";
|
||||
import type { GenericCompletionConfig } from "./core/Editor/genericCompletion";
|
||||
import { Heading } from "./core/Heading";
|
||||
import type { PairEditorHandle, PairWithId } from "./core/PairEditor";
|
||||
import { ensurePairId } from "./core/PairEditor.util";
|
||||
import { PairOrBulkEditor } from "./core/PairOrBulkEditor";
|
||||
File renamed without changes.
+1
-3
@@ -1,9 +1,7 @@
|
||||
import { Banner, Button, InlineCode } from "@yaakapp-internal/ui";
|
||||
import type { ErrorInfo, ReactNode } from "react";
|
||||
import { Component, useEffect } from "react";
|
||||
import { showDialog } from "../lib/dialog";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Button } from "./core/Button";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import RouteError from "./RouteError";
|
||||
|
||||
interface ErrorBoundaryProps {
|
||||
+1
-1
@@ -1,6 +1,7 @@
|
||||
import { save } from "@tauri-apps/plugin-dialog";
|
||||
import type { Workspace } from "@yaakapp-internal/models";
|
||||
import { workspacesAtom } from "@yaakapp-internal/models";
|
||||
import { HStack, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import slugify from "slugify";
|
||||
@@ -11,7 +12,6 @@ import { Button } from "./core/Button";
|
||||
import { Checkbox } from "./core/Checkbox";
|
||||
import { DetailsBanner } from "./core/DetailsBanner";
|
||||
import { Link } from "./core/Link";
|
||||
import { HStack, VStack } from "./core/Stacks";
|
||||
|
||||
interface Props {
|
||||
onHide: () => void;
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Folder, GrpcRequest, HttpRequest, WebsocketRequest } from "@yaakapp-internal/models";
|
||||
import { foldersAtom } from "@yaakapp-internal/models";
|
||||
import { Heading, HStack, Icon, LoadingIcon } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import { useAtomValue } from "jotai";
|
||||
import type { CSSProperties, ReactNode } from "react";
|
||||
@@ -8,20 +9,15 @@ import { allRequestsAtom } from "../hooks/useAllRequests";
|
||||
import { useFolderActions } from "../hooks/useFolderActions";
|
||||
import { useLatestHttpResponse } from "../hooks/useLatestHttpResponse";
|
||||
import { sendAnyHttpRequest } from "../hooks/useSendAnyHttpRequest";
|
||||
import { fireAndForget } from "../lib/fireAndForget";
|
||||
import { showDialog } from "../lib/dialog";
|
||||
import { resolvedModelName } from "../lib/resolvedModelName";
|
||||
import { router } from "../lib/router";
|
||||
import { Button } from "./core/Button";
|
||||
import { Heading } from "./core/Heading";
|
||||
import { HttpResponseDurationTag } from "./core/HttpResponseDurationTag";
|
||||
import { HttpStatusTag } from "./core/HttpStatusTag";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { LoadingIcon } from "./core/LoadingIcon";
|
||||
import { Separator } from "./core/Separator";
|
||||
import { SizeTag } from "./core/SizeTag";
|
||||
import { HStack } from "./core/Stacks";
|
||||
import { HttpResponsePane } from "./HttpResponsePane";
|
||||
|
||||
interface Props {
|
||||
@@ -46,7 +42,7 @@ export function FolderLayout({ folder, style }: Props) {
|
||||
}, [folder.id, folders, requests]);
|
||||
|
||||
const handleSendAll = useCallback(() => {
|
||||
if (sendAllAction) fireAndForget(sendAllAction.call(folder));
|
||||
void sendAllAction?.call(folder);
|
||||
}, [sendAllAction, folder]);
|
||||
|
||||
return (
|
||||
+1
-3
@@ -1,4 +1,5 @@
|
||||
import { createWorkspaceModel, foldersAtom, patchModel } from "@yaakapp-internal/models";
|
||||
import { HStack, Icon, InlineCode, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { Fragment, useMemo } from "react";
|
||||
import { useAuthTab } from "../hooks/useAuthTab";
|
||||
@@ -11,11 +12,8 @@ import { hideDialog } from "../lib/dialog";
|
||||
import { CopyIconButton } from "./CopyIconButton";
|
||||
import { Button } from "./core/Button";
|
||||
import { CountBadge } from "./core/CountBadge";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { Input } from "./core/Input";
|
||||
import { Link } from "./core/Link";
|
||||
import { HStack, VStack } from "./core/Stacks";
|
||||
import type { TabItem } from "./core/Tabs/Tabs";
|
||||
import { TabContent, Tabs } from "./core/Tabs/Tabs";
|
||||
import { EmptyStateText } from "./EmptyStateText";
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+5
-3
@@ -7,10 +7,10 @@ import { useActiveRequest } from "../hooks/useActiveRequest";
|
||||
import { useGrpc } from "../hooks/useGrpc";
|
||||
import { useGrpcProtoFiles } from "../hooks/useGrpcProtoFiles";
|
||||
import { activeGrpcConnectionAtom, useGrpcEvents } from "../hooks/usePinnedGrpcConnection";
|
||||
import { Banner, SplitLayout } from "@yaakapp-internal/ui";
|
||||
import { activeWorkspaceAtom } from "../hooks/useActiveWorkspace";
|
||||
import { workspaceLayoutAtom } from "../lib/atoms";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { HotkeyList } from "./core/HotkeyList";
|
||||
import { SplitLayout } from "./core/SplitLayout";
|
||||
import { GrpcRequestPane } from "./GrpcRequestPane";
|
||||
import { GrpcResponsePane } from "./GrpcResponsePane";
|
||||
|
||||
@@ -22,6 +22,8 @@ const emptyArray: string[] = [];
|
||||
|
||||
export function GrpcConnectionLayout({ style }: Props) {
|
||||
const workspaceLayout = useAtomValue(workspaceLayoutAtom);
|
||||
const activeWorkspace = useAtomValue(activeWorkspaceAtom);
|
||||
const wsId = activeWorkspace?.id ?? "n/a";
|
||||
const activeRequest = useActiveRequest("grpc_request");
|
||||
const activeConnection = useAtomValue(activeGrpcConnectionAtom);
|
||||
const grpcEvents = useGrpcEvents(activeConnection?.id ?? null);
|
||||
@@ -79,7 +81,7 @@ export function GrpcConnectionLayout({ style }: Props) {
|
||||
|
||||
return (
|
||||
<SplitLayout
|
||||
name="grpc_layout"
|
||||
storageKey={`grpc_layout::${wsId}`}
|
||||
className="p-3 gap-1.5"
|
||||
style={style}
|
||||
layout={workspaceLayout}
|
||||
@@ -1,7 +1,8 @@
|
||||
import { jsoncLanguage } from "@shopify/lang-jsonc";
|
||||
import { linter } from "@codemirror/lint";
|
||||
import type { EditorView } from "@codemirror/view";
|
||||
import { jsoncLanguage } from "@shopify/lang-jsonc";
|
||||
import type { GrpcRequest } from "@yaakapp-internal/models";
|
||||
import { FormattedError, InlineCode, VStack } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import {
|
||||
handleRefresh,
|
||||
@@ -18,9 +19,6 @@ import { pluralizeCount } from "../lib/pluralize";
|
||||
import { Button } from "./core/Button";
|
||||
import type { EditorProps } from "./core/Editor/Editor";
|
||||
import { Editor } from "./core/Editor/LazyEditor";
|
||||
import { FormattedError } from "./core/FormattedError";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { VStack } from "./core/Stacks";
|
||||
import { GrpcProtoSelectionDialog } from "./GrpcProtoSelectionDialog";
|
||||
|
||||
type Props = Pick<EditorProps, "heightMode" | "onChange" | "className" | "forceUpdateKey"> & {
|
||||
+3
-6
@@ -1,16 +1,13 @@
|
||||
import { open } from "@tauri-apps/plugin-dialog";
|
||||
import type { GrpcRequest } from "@yaakapp-internal/models";
|
||||
import { Banner, HStack, Icon, InlineCode, VStack } from "@yaakapp-internal/ui";
|
||||
import { useActiveRequest } from "../hooks/useActiveRequest";
|
||||
import { useGrpc } from "../hooks/useGrpc";
|
||||
import { useGrpcProtoFiles } from "../hooks/useGrpcProtoFiles";
|
||||
import { pluralizeCount } from "../lib/pluralize";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Button } from "./core/Button";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { Link } from "./core/Link";
|
||||
import { HStack, VStack } from "./core/Stacks";
|
||||
|
||||
interface Props {
|
||||
onDone: () => void;
|
||||
@@ -30,7 +27,7 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
|
||||
const services = grpc.reflect.data;
|
||||
const serverReflection = protoFiles.length === 0 && services != null;
|
||||
let reflectError = grpc.reflect.error ?? null;
|
||||
const reflectionUnimplemented = `${reflectError}`.match(/unimplemented/i);
|
||||
const reflectionUnimplemented = String(reflectError).match(/unimplemented/i);
|
||||
|
||||
if (reflectionUnimplemented) {
|
||||
reflectError = null;
|
||||
@@ -143,8 +140,8 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
|
||||
<tbody className="divide-y divide-surface-highlight">
|
||||
{protoFiles.map((f, i) => {
|
||||
const parts = f.split("/");
|
||||
// oxlint-disable-next-line no-array-index-key -- none
|
||||
return (
|
||||
// oxlint-disable-next-line react/no-array-index-key
|
||||
<tr key={f + i} className="group">
|
||||
<td>
|
||||
<Icon icon={f.endsWith(".proto") ? "file_code" : "folder_code"} />
|
||||
+1
-3
@@ -1,9 +1,9 @@
|
||||
import { type GrpcRequest, type HttpRequestHeader, patchModel } from "@yaakapp-internal/models";
|
||||
import { HStack, Icon, useContainerSize, VStack } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import type { CSSProperties } from "react";
|
||||
import { useCallback, useMemo, useRef } from "react";
|
||||
import { useAuthTab } from "../hooks/useAuthTab";
|
||||
import { useContainerSize } from "../hooks/useContainerQuery";
|
||||
import type { ReflectResponseService } from "../hooks/useGrpc";
|
||||
import { useHeadersTab } from "../hooks/useHeadersTab";
|
||||
import { useInheritedHeaders } from "../hooks/useInheritedHeaders";
|
||||
@@ -11,11 +11,9 @@ import { useRequestUpdateKey } from "../hooks/useRequestUpdateKey";
|
||||
import { resolvedModelName } from "../lib/resolvedModelName";
|
||||
import { Button } from "./core/Button";
|
||||
import { CountBadge } from "./core/CountBadge";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { PlainInput } from "./core/PlainInput";
|
||||
import { RadioDropdown } from "./core/RadioDropdown";
|
||||
import { HStack, VStack } from "./core/Stacks";
|
||||
import type { TabItem } from "./core/Tabs/Tabs";
|
||||
import { TabContent, Tabs } from "./core/Tabs/Tabs";
|
||||
import { GrpcEditor } from "./GrpcEditor";
|
||||
+2
-4
@@ -1,4 +1,5 @@
|
||||
import type { GrpcEvent, GrpcRequest } from "@yaakapp-internal/models";
|
||||
import { HStack, Icon, type IconProps, LoadingIcon, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue, useSetAtom } from "jotai";
|
||||
import type { CSSProperties } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
@@ -14,10 +15,7 @@ import { Editor } from "./core/Editor/LazyEditor";
|
||||
import { EventDetailHeader, EventViewer } from "./core/EventViewer";
|
||||
import { EventViewerRow } from "./core/EventViewerRow";
|
||||
import { HotkeyList } from "./core/HotkeyList";
|
||||
import { Icon, type IconProps } from "./core/Icon";
|
||||
import { KeyValueRow, KeyValueRows } from "./core/KeyValueRow";
|
||||
import { LoadingIcon } from "./core/LoadingIcon";
|
||||
import { HStack, VStack } from "./core/Stacks";
|
||||
import { EmptyStateText } from "./EmptyStateText";
|
||||
import { ErrorBoundary } from "./ErrorBoundary";
|
||||
import { RecentGrpcConnectionsDropdown } from "./RecentGrpcConnectionsDropdown";
|
||||
@@ -93,7 +91,7 @@ export function GrpcResponsePane({ style, methodType, activeRequest }: Props) {
|
||||
getEventKey={(event) => event.id}
|
||||
error={activeConnection.error}
|
||||
header={header}
|
||||
splitLayoutName="grpc_events"
|
||||
splitLayoutStorageKey="grpc_events"
|
||||
defaultRatio={0.4}
|
||||
renderRow={({ event, isActive, onClick }) => (
|
||||
<GrpcEventRow event={event} isActive={isActive} onClick={onClick} />
|
||||
+1
-1
@@ -1,5 +1,6 @@
|
||||
import type { HttpRequestHeader } from "@yaakapp-internal/models";
|
||||
import type { GenericCompletionOption } from "@yaakapp-internal/plugins";
|
||||
import { HStack } from "@yaakapp-internal/ui";
|
||||
import { charsets } from "../lib/data/charsets";
|
||||
import { connections } from "../lib/data/connections";
|
||||
import { encodings } from "../lib/data/encodings";
|
||||
@@ -13,7 +14,6 @@ import type { Pair, PairEditorProps } from "./core/PairEditor";
|
||||
import { PairEditorRow } from "./core/PairEditor";
|
||||
import { ensurePairId } from "./core/PairEditor.util";
|
||||
import { PairOrBulkEditor } from "./core/PairOrBulkEditor";
|
||||
import { HStack } from "./core/Stacks";
|
||||
|
||||
type Props = {
|
||||
forceUpdateKey: string;
|
||||
+1
-3
@@ -6,6 +6,7 @@ import type {
|
||||
Workspace,
|
||||
} from "@yaakapp-internal/models";
|
||||
import { patchModel } from "@yaakapp-internal/models";
|
||||
import { HStack, Icon, InlineCode } from "@yaakapp-internal/ui";
|
||||
import { useCallback } from "react";
|
||||
import { openFolderSettings } from "../commands/openFolderSettings";
|
||||
import { openWorkspaceSettings } from "../commands/openWorkspaceSettings";
|
||||
@@ -14,13 +15,10 @@ import { useInheritedAuthentication } from "../hooks/useInheritedAuthentication"
|
||||
import { useRenderTemplate } from "../hooks/useRenderTemplate";
|
||||
import { resolvedModelName } from "../lib/resolvedModelName";
|
||||
import { Dropdown, type DropdownItem } from "./core/Dropdown";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { Input, type InputProps } from "./core/Input";
|
||||
import { Link } from "./core/Link";
|
||||
import { SegmentedControl } from "./core/SegmentedControl";
|
||||
import { HStack } from "./core/Stacks";
|
||||
import { DynamicForm } from "./DynamicForm";
|
||||
import { EmptyStateText } from "./EmptyStateText";
|
||||
|
||||
+7
-4
@@ -1,11 +1,12 @@
|
||||
import type { HttpRequest } from "@yaakapp-internal/models";
|
||||
import type { SlotProps } from "@yaakapp-internal/ui";
|
||||
import { SplitLayout } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import { useAtomValue } from "jotai";
|
||||
import type { CSSProperties } from "react";
|
||||
import { useCurrentGraphQLSchema } from "../hooks/useIntrospectGraphQL";
|
||||
import { activeWorkspaceAtom } from "../hooks/useActiveWorkspace";
|
||||
import { workspaceLayoutAtom } from "../lib/atoms";
|
||||
import type { SlotProps } from "./core/SplitLayout";
|
||||
import { SplitLayout } from "./core/SplitLayout";
|
||||
import { GraphQLDocsExplorer } from "./graphql/GraphQLDocsExplorer";
|
||||
import { showGraphQLDocExplorerAtom } from "./graphql/graphqlAtoms";
|
||||
import { HttpRequestPane } from "./HttpRequestPane";
|
||||
@@ -20,10 +21,12 @@ export function HttpRequestLayout({ activeRequest, style }: Props) {
|
||||
const showGraphQLDocExplorer = useAtomValue(showGraphQLDocExplorerAtom);
|
||||
const graphQLSchema = useCurrentGraphQLSchema(activeRequest);
|
||||
const workspaceLayout = useAtomValue(workspaceLayoutAtom);
|
||||
const activeWorkspace = useAtomValue(activeWorkspaceAtom);
|
||||
const wsId = activeWorkspace?.id ?? "n/a";
|
||||
|
||||
const requestResponseSplit = ({ style }: Pick<SlotProps, "style">) => (
|
||||
<SplitLayout
|
||||
name="http_layout"
|
||||
storageKey={`http_layout::${wsId}`}
|
||||
className="p-3 gap-1.5"
|
||||
style={style}
|
||||
layout={workspaceLayout}
|
||||
@@ -47,7 +50,7 @@ export function HttpRequestLayout({ activeRequest, style }: Props) {
|
||||
) {
|
||||
return (
|
||||
<SplitLayout
|
||||
name="graphql_layout"
|
||||
storageKey={`graphql_layout::${wsId}`}
|
||||
defaultRatio={1 / 3}
|
||||
firstSlot={requestResponseSplit}
|
||||
secondSlot={({ style, orientation }) => (
|
||||
+1
-1
@@ -38,7 +38,7 @@ import { ConfirmLargeRequestBody } from "./ConfirmLargeRequestBody";
|
||||
import { CountBadge } from "./core/CountBadge";
|
||||
import type { GenericCompletionConfig } from "./core/Editor/genericCompletion";
|
||||
import { Editor } from "./core/Editor/LazyEditor";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { InlineCode } from "@yaakapp-internal/ui";
|
||||
import type { Pair } from "./core/PairEditor";
|
||||
import { PlainInput } from "./core/PlainInput";
|
||||
import type { TabItem, TabsRef } from "./core/Tabs/Tabs";
|
||||
+1
-4
@@ -1,4 +1,5 @@
|
||||
import type { HttpResponse, HttpResponseEvent } from "@yaakapp-internal/models";
|
||||
import { Banner, HStack, Icon, LoadingIcon, VStack } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import type { ComponentType, CSSProperties } from "react";
|
||||
import { lazy, Suspense, useMemo } from "react";
|
||||
@@ -12,17 +13,13 @@ import { getMimeTypeFromContentType } from "../lib/contentType";
|
||||
import { getContentTypeFromHeaders, getCookieCounts } from "../lib/model_util";
|
||||
import { ConfirmLargeResponse } from "./ConfirmLargeResponse";
|
||||
import { ConfirmLargeResponseRequest } from "./ConfirmLargeResponseRequest";
|
||||
import { Banner } from "./core/Banner";
|
||||
import { Button } from "./core/Button";
|
||||
import { CountBadge } from "./core/CountBadge";
|
||||
import { HotkeyList } from "./core/HotkeyList";
|
||||
import { HttpResponseDurationTag } from "./core/HttpResponseDurationTag";
|
||||
import { HttpStatusTag } from "./core/HttpStatusTag";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { LoadingIcon } from "./core/LoadingIcon";
|
||||
import { PillButton } from "./core/PillButton";
|
||||
import { SizeTag } from "./core/SizeTag";
|
||||
import { HStack, VStack } from "./core/Stacks";
|
||||
import type { TabItem } from "./core/Tabs/Tabs";
|
||||
import { TabContent, Tabs } from "./core/Tabs/Tabs";
|
||||
import { Tooltip } from "./core/Tooltip";
|
||||
+2
-2
@@ -9,7 +9,7 @@ import { Editor } from "./core/Editor/LazyEditor";
|
||||
import { type EventDetailAction, EventDetailHeader, EventViewer } from "./core/EventViewer";
|
||||
import { EventViewerRow } from "./core/EventViewerRow";
|
||||
import { HttpStatusTagRaw } from "./core/HttpStatusTag";
|
||||
import { Icon, type IconProps } from "./core/Icon";
|
||||
import { Icon, type IconProps } from "@yaakapp-internal/ui";
|
||||
import { KeyValueRow, KeyValueRows } from "./core/KeyValueRow";
|
||||
import type { TimelineViewMode } from "./HttpResponsePane";
|
||||
|
||||
@@ -55,7 +55,7 @@ function Inner({ response, viewMode }: Props) {
|
||||
isLoading={isLoading}
|
||||
loadingMessage="Loading events..."
|
||||
emptyMessage="No events recorded"
|
||||
splitLayoutName="http_response_events"
|
||||
splitLayoutStorageKey="http_response_events"
|
||||
defaultRatio={0.25}
|
||||
renderRow={({ event, isActive, onClick }) => {
|
||||
const display = getEventDisplay(event.event);
|
||||
+3
-5
@@ -4,7 +4,7 @@ import { useEffect, useState } from "react";
|
||||
import { useImportCurl } from "../hooks/useImportCurl";
|
||||
import { useWindowFocus } from "../hooks/useWindowFocus";
|
||||
import { Button } from "./core/Button";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { Icon } from "@yaakapp-internal/ui";
|
||||
|
||||
export function ImportCurlButton() {
|
||||
const focused = useWindowFocus();
|
||||
@@ -13,11 +13,9 @@ export function ImportCurlButton() {
|
||||
const importCurl = useImportCurl();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
||||
// oxlint-disable-next-line react-hooks/exhaustive-deps -- none
|
||||
useEffect(() => {
|
||||
readText()
|
||||
.then(setClipboardText)
|
||||
.catch(() => {});
|
||||
void readText().then(setClipboardText);
|
||||
}, [focused]);
|
||||
|
||||
if (!clipboardText?.trim().startsWith("curl ")) {
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { VStack } from "@yaakapp-internal/ui";
|
||||
import { useState } from "react";
|
||||
import { useLocalStorage } from "react-use";
|
||||
import { Button } from "./core/Button";
|
||||
import { VStack } from "./core/Stacks";
|
||||
import { SelectFile } from "./SelectFile";
|
||||
|
||||
interface Props {
|
||||
File renamed without changes.
+2
-3
@@ -1,17 +1,16 @@
|
||||
import { linter } from "@codemirror/lint";
|
||||
import type { HttpRequest } from "@yaakapp-internal/models";
|
||||
import { patchModel } from "@yaakapp-internal/models";
|
||||
import { Banner, Icon } from "@yaakapp-internal/ui";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { fireAndForget } from "../lib/fireAndForget";
|
||||
import { useKeyValue } from "../hooks/useKeyValue";
|
||||
import { fireAndForget } from "../lib/fireAndForget";
|
||||
import { textLikelyContainsJsonComments } from "../lib/jsonComments";
|
||||
import { Banner } from "./core/Banner";
|
||||
import type { DropdownItem } from "./core/Dropdown";
|
||||
import { Dropdown } from "./core/Dropdown";
|
||||
import type { EditorProps } from "./core/Editor/Editor";
|
||||
import { jsonParseLinter } from "./core/Editor/json-lint";
|
||||
import { Editor } from "./core/Editor/LazyEditor";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { IconTooltip } from "./core/IconTooltip";
|
||||
|
||||
File renamed without changes.
@@ -12,7 +12,7 @@ import { jotaiStore } from "../lib/jotai";
|
||||
import { CargoFeature } from "./CargoFeature";
|
||||
import type { ButtonProps } from "./core/Button";
|
||||
import { Dropdown, type DropdownItem } from "./core/Dropdown";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { Icon } from "@yaakapp-internal/ui";
|
||||
import { PillButton } from "./core/PillButton";
|
||||
|
||||
const dismissedAtom = atomWithKVStorage<string | null>("dismissed_license_expired", null);
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-2
@@ -1,5 +1,6 @@
|
||||
import type { GrpcRequest, HttpRequest, WebsocketRequest } from "@yaakapp-internal/models";
|
||||
import { patchModel, workspacesAtom } from "@yaakapp-internal/models";
|
||||
import { InlineCode, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useState } from "react";
|
||||
import { pluralizeCount } from "../lib/pluralize";
|
||||
@@ -7,9 +8,7 @@ import { resolvedModelName } from "../lib/resolvedModelName";
|
||||
import { router } from "../lib/router";
|
||||
import { showToast } from "../lib/toast";
|
||||
import { Button } from "./core/Button";
|
||||
import { InlineCode } from "./core/InlineCode";
|
||||
import { Select } from "./core/Select";
|
||||
import { VStack } from "./core/Stacks";
|
||||
|
||||
interface Props {
|
||||
activeWorkspaceId: string;
|
||||
File renamed without changes.
File renamed without changes.
+1
-2
@@ -1,12 +1,11 @@
|
||||
import type { GrpcConnection } from "@yaakapp-internal/models";
|
||||
import { deleteModel } from "@yaakapp-internal/models";
|
||||
import { HStack, Icon } from "@yaakapp-internal/ui";
|
||||
import { formatDistanceToNowStrict } from "date-fns";
|
||||
import { useDeleteGrpcConnections } from "../hooks/useDeleteGrpcConnections";
|
||||
import { pluralizeCount } from "../lib/pluralize";
|
||||
import { Dropdown } from "./core/Dropdown";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { HStack } from "./core/Stacks";
|
||||
|
||||
interface Props {
|
||||
connections: GrpcConnection[];
|
||||
+1
-2
@@ -1,14 +1,13 @@
|
||||
import type { HttpResponse } from "@yaakapp-internal/models";
|
||||
import { deleteModel } from "@yaakapp-internal/models";
|
||||
import { HStack, Icon } from "@yaakapp-internal/ui";
|
||||
import { useCopyHttpResponse } from "../hooks/useCopyHttpResponse";
|
||||
import { useDeleteHttpResponses } from "../hooks/useDeleteHttpResponses";
|
||||
import { useSaveResponse } from "../hooks/useSaveResponse";
|
||||
import { pluralize } from "../lib/pluralize";
|
||||
import { Dropdown } from "./core/Dropdown";
|
||||
import { HttpStatusTag } from "./core/HttpStatusTag";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { HStack } from "./core/Stacks";
|
||||
|
||||
interface Props {
|
||||
responses: HttpResponse[];
|
||||
File renamed without changes.
+1
-2
@@ -1,12 +1,11 @@
|
||||
import type { WebsocketConnection } from "@yaakapp-internal/models";
|
||||
import { deleteModel, getModel } from "@yaakapp-internal/models";
|
||||
import { HStack, Icon } from "@yaakapp-internal/ui";
|
||||
import { formatDistanceToNowStrict } from "date-fns";
|
||||
import { deleteWebsocketConnections } from "../commands/deleteWebsocketConnections";
|
||||
import { pluralizeCount } from "../lib/pluralize";
|
||||
import { Dropdown } from "./core/Dropdown";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { HStack } from "./core/Stacks";
|
||||
|
||||
interface Props {
|
||||
connections: WebsocketConnection[];
|
||||
File renamed without changes.
+1
-1
@@ -2,7 +2,7 @@ import type { HttpResponse } from "@yaakapp-internal/models";
|
||||
import { lazy, Suspense } from "react";
|
||||
import { useHttpRequestBody } from "../hooks/useHttpRequestBody";
|
||||
import { getMimeTypeFromContentType, languageFromContentType } from "../lib/contentType";
|
||||
import { LoadingIcon } from "./core/LoadingIcon";
|
||||
import { LoadingIcon } from "@yaakapp-internal/ui";
|
||||
import { EmptyStateText } from "./EmptyStateText";
|
||||
import { AudioViewer } from "./responseViewers/AudioViewer";
|
||||
import { CsvViewer } from "./responseViewers/CsvViewer";
|
||||
+1
-1
@@ -6,7 +6,7 @@ import { showPrompt } from "../lib/prompt";
|
||||
import { Button } from "./core/Button";
|
||||
import type { DropdownItem } from "./core/Dropdown";
|
||||
import { HttpMethodTag, HttpMethodTagRaw } from "./core/HttpMethodTag";
|
||||
import { Icon } from "./core/Icon";
|
||||
import { Icon } from "@yaakapp-internal/ui";
|
||||
import type { RadioDropdownItem } from "./core/RadioDropdown";
|
||||
import { RadioDropdown } from "./core/RadioDropdown";
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,13 +1,10 @@
|
||||
import { Button } from "./core/Button";
|
||||
import { Button, FormattedError, Heading, VStack } from "@yaakapp-internal/ui";
|
||||
import { DetailsBanner } from "./core/DetailsBanner";
|
||||
import { FormattedError } from "./core/FormattedError";
|
||||
import { Heading } from "./core/Heading";
|
||||
import { VStack } from "./core/Stacks";
|
||||
|
||||
export default function RouteError({ error }: { error: unknown }) {
|
||||
console.log("Error", error);
|
||||
const stringified = JSON.stringify(error);
|
||||
// oxlint-disable-next-line no-explicit-any
|
||||
// oxlint-disable-next-line no-explicit-any -- none
|
||||
const message = (error as any).message ?? stringified;
|
||||
const stack =
|
||||
typeof error === "object" && error != null && "stack" in error ? String(error.stack) : null;
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import { open } from "@tauri-apps/plugin-dialog";
|
||||
import { HStack } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import mime from "mime";
|
||||
import type { ReactNode } from "react";
|
||||
@@ -9,7 +10,6 @@ import { Button } from "./core/Button";
|
||||
import { IconButton } from "./core/IconButton";
|
||||
import { IconTooltip } from "./core/IconTooltip";
|
||||
import { Label } from "./core/Label";
|
||||
import { HStack } from "./core/Stacks";
|
||||
|
||||
type Props = Omit<ButtonProps, "type"> & {
|
||||
onChange: (value: { filePath: string | null; contentType: string | null }) => void;
|
||||
+5
-3
@@ -3,16 +3,14 @@ import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import { type } from "@tauri-apps/plugin-os";
|
||||
import { useLicense } from "@yaakapp-internal/license";
|
||||
import { pluginsAtom, settingsAtom } from "@yaakapp-internal/models";
|
||||
import { HeaderSize, HStack, Icon } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useKeyPressEvent } from "react-use";
|
||||
import { appInfo } from "../../lib/appInfo";
|
||||
import { capitalize } from "../../lib/capitalize";
|
||||
import { CountBadge } from "../core/CountBadge";
|
||||
import { Icon } from "../core/Icon";
|
||||
import { HStack } from "../core/Stacks";
|
||||
import { TabContent, type TabItem, Tabs } from "../core/Tabs/Tabs";
|
||||
import { HeaderSize } from "../HeaderSize";
|
||||
import { SettingsCertificates } from "./SettingsCertificates";
|
||||
import { SettingsGeneral } from "./SettingsGeneral";
|
||||
import { SettingsHotkeys } from "./SettingsHotkeys";
|
||||
@@ -77,6 +75,10 @@ export default function Settings({ hide }: Props) {
|
||||
onlyXWindowControl
|
||||
size="md"
|
||||
className="x-theme-appHeader bg-surface text-text-subtle flex items-center justify-center border-b border-border-subtle text-sm font-semibold"
|
||||
osType={type()}
|
||||
hideWindowControls={settings.hideWindowControls}
|
||||
useNativeTitlebar={settings.useNativeTitlebar}
|
||||
interfaceScale={settings.interfaceScale}
|
||||
>
|
||||
<HStack
|
||||
space={2}
|
||||
+1
-3
@@ -1,17 +1,15 @@
|
||||
import type { ClientCertificate } from "@yaakapp-internal/models";
|
||||
import { patchModel, settingsAtom } from "@yaakapp-internal/models";
|
||||
import { Heading, HStack, InlineCode, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useRef } from "react";
|
||||
import { showConfirmDelete } from "../../lib/confirm";
|
||||
import { Button } from "../core/Button";
|
||||
import { Checkbox } from "../core/Checkbox";
|
||||
import { DetailsBanner } from "../core/DetailsBanner";
|
||||
import { Heading } from "../core/Heading";
|
||||
import { IconButton } from "../core/IconButton";
|
||||
import { InlineCode } from "../core/InlineCode";
|
||||
import { PlainInput } from "../core/PlainInput";
|
||||
import { Separator } from "../core/Separator";
|
||||
import { HStack, VStack } from "../core/Stacks";
|
||||
import { SelectFile } from "../SelectFile";
|
||||
|
||||
function createEmptyCertificate(): ClientCertificate {
|
||||
+1
-2
@@ -1,5 +1,6 @@
|
||||
import { revealItemInDir } from "@tauri-apps/plugin-opener";
|
||||
import { patchModel, settingsAtom } from "@yaakapp-internal/models";
|
||||
import { Heading, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { activeWorkspaceAtom } from "../../hooks/useActiveWorkspace";
|
||||
import { useCheckForUpdates } from "../../hooks/useCheckForUpdates";
|
||||
@@ -7,13 +8,11 @@ import { appInfo } from "../../lib/appInfo";
|
||||
import { revealInFinderText } from "../../lib/reveal";
|
||||
import { CargoFeature } from "../CargoFeature";
|
||||
import { Checkbox } from "../core/Checkbox";
|
||||
import { Heading } from "../core/Heading";
|
||||
import { IconButton } from "../core/IconButton";
|
||||
import { KeyValueRow, KeyValueRows } from "../core/KeyValueRow";
|
||||
import { PlainInput } from "../core/PlainInput";
|
||||
import { Select } from "../core/Select";
|
||||
import { Separator } from "../core/Separator";
|
||||
import { VStack } from "../core/Stacks";
|
||||
|
||||
export function SettingsGeneral() {
|
||||
const workspace = useAtomValue(activeWorkspaceAtom);
|
||||
+12
-4
@@ -1,4 +1,16 @@
|
||||
import { patchModel, settingsAtom } from "@yaakapp-internal/models";
|
||||
import {
|
||||
Heading,
|
||||
HStack,
|
||||
Icon,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
VStack,
|
||||
} from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import { fuzzyMatch } from "fuzzbunny";
|
||||
import { useAtomValue } from "jotai";
|
||||
@@ -16,13 +28,9 @@ import { capitalize } from "../../lib/capitalize";
|
||||
import { showDialog } from "../../lib/dialog";
|
||||
import { Button } from "../core/Button";
|
||||
import { Dropdown, type DropdownItem } from "../core/Dropdown";
|
||||
import { Heading } from "../core/Heading";
|
||||
import { HotkeyRaw } from "../core/Hotkey";
|
||||
import { Icon } from "../core/Icon";
|
||||
import { IconButton } from "../core/IconButton";
|
||||
import { PlainInput } from "../core/PlainInput";
|
||||
import { HStack, VStack } from "../core/Stacks";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../core/Table";
|
||||
|
||||
const HOLD_KEYS = ["Shift", "Control", "Alt", "Meta"];
|
||||
const LAYOUT_INSENSITIVE_KEYS = [
|
||||
+1
-5
@@ -3,21 +3,17 @@ import { useFonts } from "@yaakapp-internal/fonts";
|
||||
import { useLicense } from "@yaakapp-internal/license";
|
||||
import type { EditorKeymap, Settings } from "@yaakapp-internal/models";
|
||||
import { patchModel, settingsAtom } from "@yaakapp-internal/models";
|
||||
import { clamp, Heading, HStack, Icon, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useState } from "react";
|
||||
|
||||
import { activeWorkspaceAtom } from "../../hooks/useActiveWorkspace";
|
||||
import { clamp } from "../../lib/clamp";
|
||||
import { showConfirm } from "../../lib/confirm";
|
||||
import { invokeCmd } from "../../lib/tauri";
|
||||
import { CargoFeature } from "../CargoFeature";
|
||||
import { Button } from "../core/Button";
|
||||
import { Checkbox } from "../core/Checkbox";
|
||||
import { Heading } from "../core/Heading";
|
||||
import { Icon } from "../core/Icon";
|
||||
import { Link } from "../core/Link";
|
||||
import { Select } from "../core/Select";
|
||||
import { HStack, VStack } from "../core/Stacks";
|
||||
|
||||
const NULL_FONT_VALUE = "__NULL_FONT__";
|
||||
|
||||
+1
-3
@@ -1,18 +1,16 @@
|
||||
import { openUrl } from "@tauri-apps/plugin-opener";
|
||||
import { useLicense } from "@yaakapp-internal/license";
|
||||
import { Banner, HStack, Icon, VStack } from "@yaakapp-internal/ui";
|
||||
import { differenceInDays } from "date-fns";
|
||||
import { formatDate } from "date-fns/format";
|
||||
import { useState } from "react";
|
||||
import { useToggle } from "../../hooks/useToggle";
|
||||
import { pluralizeCount } from "../../lib/pluralize";
|
||||
import { CargoFeature } from "../CargoFeature";
|
||||
import { Banner } from "../core/Banner";
|
||||
import { Button } from "../core/Button";
|
||||
import { Icon } from "../core/Icon";
|
||||
import { Link } from "../core/Link";
|
||||
import { PlainInput } from "../core/PlainInput";
|
||||
import { Separator } from "../core/Separator";
|
||||
import { HStack, VStack } from "../core/Stacks";
|
||||
|
||||
export function SettingsLicense() {
|
||||
return (
|
||||
+13
-6
@@ -9,10 +9,22 @@ import {
|
||||
searchPlugins,
|
||||
uninstallPlugin,
|
||||
} from "@yaakapp-internal/plugins";
|
||||
import {
|
||||
HStack,
|
||||
Icon,
|
||||
InlineCode,
|
||||
LoadingIcon,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
useDebouncedValue,
|
||||
} from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useState } from "react";
|
||||
import { useDebouncedValue } from "../../hooks/useDebouncedValue";
|
||||
import { useInstallPlugin } from "../../hooks/useInstallPlugin";
|
||||
import { usePluginInfo } from "../../hooks/usePluginInfo";
|
||||
import { usePluginsKey, useRefreshPlugins } from "../../hooks/usePlugins";
|
||||
@@ -21,14 +33,9 @@ import { minPromiseMillis } from "../../lib/minPromiseMillis";
|
||||
import { Button } from "../core/Button";
|
||||
import { Checkbox } from "../core/Checkbox";
|
||||
import { CountBadge } from "../core/CountBadge";
|
||||
import { Icon } from "../core/Icon";
|
||||
import { IconButton } from "../core/IconButton";
|
||||
import { InlineCode } from "../core/InlineCode";
|
||||
import { Link } from "../core/Link";
|
||||
import { LoadingIcon } from "../core/LoadingIcon";
|
||||
import { PlainInput } from "../core/PlainInput";
|
||||
import { HStack } from "../core/Stacks";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "../core/Table";
|
||||
import { TabContent, Tabs } from "../core/Tabs/Tabs";
|
||||
import { EmptyStateText } from "../EmptyStateText";
|
||||
import { SelectFile } from "../SelectFile";
|
||||
+1
-4
@@ -1,13 +1,10 @@
|
||||
import { patchModel, settingsAtom } from "@yaakapp-internal/models";
|
||||
import { Heading, HStack, InlineCode, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
|
||||
import { Checkbox } from "../core/Checkbox";
|
||||
import { Heading } from "../core/Heading";
|
||||
import { InlineCode } from "../core/InlineCode";
|
||||
import { PlainInput } from "../core/PlainInput";
|
||||
import { Select } from "../core/Select";
|
||||
import { Separator } from "../core/Separator";
|
||||
import { HStack, VStack } from "../core/Stacks";
|
||||
|
||||
export function SettingsProxy() {
|
||||
const settings = useAtomValue(settingsAtom);
|
||||
+1
-4
@@ -1,18 +1,15 @@
|
||||
import { patchModel, settingsAtom } from "@yaakapp-internal/models";
|
||||
import { Heading, HStack, Icon, type IconProps, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { lazy, Suspense } from "react";
|
||||
import { activeWorkspaceAtom } from "../../hooks/useActiveWorkspace";
|
||||
import { useResolvedAppearance } from "../../hooks/useResolvedAppearance";
|
||||
import { useResolvedTheme } from "../../hooks/useResolvedTheme";
|
||||
import type { ButtonProps } from "../core/Button";
|
||||
import { Heading } from "../core/Heading";
|
||||
import type { IconProps } from "../core/Icon";
|
||||
import { Icon } from "../core/Icon";
|
||||
import { IconButton } from "../core/IconButton";
|
||||
import { Link } from "../core/Link";
|
||||
import type { SelectProps } from "../core/Select";
|
||||
import { Select } from "../core/Select";
|
||||
import { HStack, VStack } from "../core/Stacks";
|
||||
|
||||
const Editor = lazy(() => import("../core/Editor/Editor").then((m) => ({ default: m.Editor })));
|
||||
|
||||
Loaded 100 of 783 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user