Compare commits

...

6 Commits

Author SHA1 Message Date
Gregory Schier
b9f397e04a Fix response filtering 2024-10-21 07:26:50 -07:00
Gregory Schier
57c3a86799 Animate up instead of down when dropdowns open up 2024-10-18 11:22:05 -07:00
Gregory Schier
52ac41b0c6 Move elapsed calculation 2024-10-18 10:53:04 -07:00
Gregory Schier
741ccbe741 Add labels to plugin event subscribers 2024-10-18 10:46:30 -07:00
Gregory Schier
2ecd86da78 Update README.md 2024-10-18 08:27:24 -07:00
Gregory Schier
30e4e7665a Remove ios config 2024-10-18 07:59:28 -07:00
8 changed files with 22 additions and 20 deletions

View File

@@ -1,4 +1,4 @@
# [Yaak API Client](https://yaak.app)
# Yaak API Client
Yaak is a desktop API client for organizing and executing REST, GraphQL, and gRPC
requests. It's built using [Tauri](https://tauri.app), Rust, and ReactJS.

View File

@@ -442,7 +442,6 @@ pub async fn send_http_request<R: Runtime>(
}
// Write body to FS
println!("BODYPATH {body_path:?}");
let mut f = File::options()
.create(true)
.truncate(true)
@@ -460,11 +459,11 @@ pub async fn send_http_request<R: Runtime>(
}
match chunk {
Ok(Some(bytes)) => {
let mut r = response.lock().await;
r.elapsed = start.elapsed().as_millis() as i32;
f.write_all(&bytes).await.expect("Failed to write to file");
f.flush().await.expect("Failed to flush file");
written_bytes += bytes.len();
let mut r = response.lock().await;
r.elapsed = start.elapsed().as_millis() as i32;
r.content_length = Some(written_bytes as i32);
update_response_if_id(&window, &r)
.await

View File

@@ -1969,7 +1969,7 @@ fn monitor_plugin_events<R: Runtime>(app_handle: &AppHandle<R>) {
let app_handle = app_handle.clone();
tauri::async_runtime::spawn(async move {
let plugin_manager: State<'_, PluginManager> = app_handle.state();
let (rx_id, mut rx) = plugin_manager.subscribe().await;
let (rx_id, mut rx) = plugin_manager.subscribe("app").await;
while let Some(event) = rx.recv().await {
let app_handle = app_handle.clone();

View File

@@ -72,9 +72,6 @@
"rpm"
],
"createUpdaterArtifacts": "v1Compatible",
"iOS": {
"developmentTeam": "7PU3P6ELJ8"
},
"macOS": {
"minimumSystemVersion": "13.0",
"exceptionDomain": "",

View File

@@ -273,9 +273,9 @@ impl PluginManager {
Ok(())
}
pub async fn subscribe(&self) -> (String, mpsc::Receiver<InternalEvent>) {
pub async fn subscribe(&self, label: &str) -> (String, mpsc::Receiver<InternalEvent>) {
let (tx, rx) = mpsc::channel(128);
let rx_id = generate_id();
let rx_id = format!("{label}_{}", generate_id());
self.subscribers.lock().await.insert(rx_id.clone(), tx);
(rx_id, rx)
}
@@ -362,7 +362,8 @@ impl PluginManager {
payload: &InternalEventPayload,
plugins: Vec<PluginHandle>,
) -> Result<Vec<InternalEvent>> {
let (rx_id, mut rx) = self.subscribe().await;
let label = format!("wait[{}]", plugins.len());
let (rx_id, mut rx) = self.subscribe(label.as_str()).await;
// 1. Build the events with IDs and everything
let events_to_send = plugins
@@ -557,9 +558,9 @@ impl PluginManager {
content_type: &str,
) -> Result<FilterResponse> {
let plugin_name = if content_type.to_lowercase().contains("json") {
"filter-jsonpath"
"@yaakapp/filter-jsonpath"
} else {
"filter-xpath"
"@yaakapp/filter-xpath"
};
let plugin = self

View File

@@ -350,8 +350,9 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
container: CSSProperties;
menu: CSSProperties;
triangle: CSSProperties;
upsideDown: boolean;
}>(() => {
if (triggerShape == null) return { container: {}, triangle: {}, menu: {} };
if (triggerShape == null) return { container: {}, triangle: {}, menu: {}, upsideDown: false };
const menuMarginY = 5;
const docRect = document.documentElement.getBoundingClientRect();
@@ -364,6 +365,7 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
const upsideDown = heightBelow < heightAbove && heightBelow < items.length * 25 + 20 + 200;
const triggerWidth = triggerShape.right - triggerShape.left;
return {
upsideDown,
container: {
top: !upsideDown ? top + menuMarginY : undefined,
bottom: upsideDown
@@ -426,7 +428,7 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
<motion.div
tabIndex={0}
onKeyDown={handleMenuKeyDown}
initial={{ opacity: 0, y: -5, scale: 0.98 }}
initial={{ opacity: 0, y: (styles.upsideDown ? 1 : -1) * 5, scale: 0.98 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
role="menu"
aria-orientation="vertical"

View File

@@ -41,6 +41,7 @@ export function HTMLOrTextViewer({ response, pretty, textViewerClassName }: Prop
className={textViewerClassName}
onSaveResponse={saveResponse.mutate}
responseId={response.id}
requestId={response.requestId}
/>
);
}

View File

@@ -28,6 +28,7 @@ interface Props {
text: string;
language: EditorProps['language'];
responseId: string;
requestId: string;
onSaveResponse: () => void;
}
@@ -37,20 +38,21 @@ export function TextViewer({
language,
text,
responseId,
requestId,
pretty,
className,
onSaveResponse,
}: Props) {
const [filterTextMap, setFilterTextMap] = useFilterText();
const [showLargeResponse, toggleShowLargeResponse] = useToggle();
const filterText = filterTextMap[responseId] ?? null;
const filterText = filterTextMap[requestId] ?? null;
const copy = useCopy();
const debouncedFilterText = useDebouncedValue(filterText, 200);
const setFilterText = useCallback(
(v: string | null) => {
setFilterTextMap((m) => ({ ...m, [responseId]: v }));
setFilterTextMap((m) => ({ ...m, [requestId]: v }));
},
[setFilterTextMap, responseId],
[setFilterTextMap, requestId],
);
const isSearching = filterText != null;
@@ -75,7 +77,7 @@ export function TextViewer({
nodes.push(
<div key="input" className="w-full !opacity-100">
<Input
key={responseId}
key={requestId}
validate={!filteredResponse.error}
hideLabel
autoFocus
@@ -110,7 +112,7 @@ export function TextViewer({
filteredResponse.error,
isSearching,
language,
responseId,
requestId,
setFilterText,
toggleSearch,
]);