diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 28ac1ac9..b5550f3f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -7,7 +7,8 @@ license = "MIT" repository = "https://github.com/gschier/yaak-app" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[profile.release] +strip = true # Automatically strip symbols from the binary. [build-dependencies] tauri-build = { version = "1.2", features = [] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 30c71d88..4ea8dff2 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -491,8 +491,9 @@ fn main() { create_dir_all(dir.clone()).expect("Problem creating App directory!"); let p = dir.join("db.sqlite"); - 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); + println!("Connecting to database at {}", url); tauri::async_runtime::block_on(async move { let pool = SqlitePoolOptions::new() .connect(url.as_str()) diff --git a/src-web/assets/icons/Icons.afdesign b/src-web/assets/icons/Icons.afdesign new file mode 100644 index 00000000..5561d0fb Binary files /dev/null and b/src-web/assets/icons/Icons.afdesign differ diff --git a/src-web/components/Overlay.tsx b/src-web/components/Overlay.tsx new file mode 100644 index 00000000..1e1bfc32 --- /dev/null +++ b/src-web/components/Overlay.tsx @@ -0,0 +1,41 @@ +import classnames from 'classnames'; +import type { ReactNode } from 'react'; +import { motion } from 'framer-motion'; +import { Portal } from './Portal'; + +interface Props { + children: ReactNode; + onClick?: () => void; + portalName: string; + open: boolean; + zIndex?: keyof typeof zIndexes; +} + +const zIndexes: Record = { + 10: 'z-10', + 20: 'z-20', + 30: 'z-30', + 40: 'z-40', + 50: 'z-50', +}; + +export function Overlay({ zIndex = 30, open, children, onClick, portalName }: Props) { + return ( + + {open && ( + +
+ {children} + + )} + + ); +} diff --git a/src-web/components/Workspace.tsx b/src-web/components/Workspace.tsx index b5059642..322422c8 100644 --- a/src-web/components/Workspace.tsx +++ b/src-web/components/Workspace.tsx @@ -1,10 +1,20 @@ import classnames from 'classnames'; -import type { CSSProperties, MouseEvent as ReactMouseEvent } from 'react'; -import React, { useCallback, useMemo, useRef, useState } from 'react'; +import { motion } from 'framer-motion'; +import type { + CSSProperties, + HTMLAttributes, + MouseEvent as ReactMouseEvent, + ReactNode, +} from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useWindowSize } from 'react-use'; import { useSidebarDisplay } from '../hooks/useSidebarDisplay'; +import { WINDOW_FLOATING_SIDEBAR_WIDTH } from '../lib/constants'; +import { Overlay } from './Overlay'; import { RequestResponse } from './RequestResponse'; import { ResizeHandle } from './ResizeHandle'; import { Sidebar } from './Sidebar'; +import { SidebarDisplayToggle } from './SidebarDisplayToggle'; import { WorkspaceHeader } from './WorkspaceHeader'; const side = { gridArea: 'side' }; @@ -14,12 +24,23 @@ const drag = { gridArea: 'drag' }; export default function Workspace() { const sidebar = useSidebarDisplay(); - + const windowSize = useWindowSize(); + const [floating, setFloating] = useState(false); const [isResizing, setIsResizing] = useState(false); const moveState = useRef<{ move: (e: MouseEvent) => void; up: (e: MouseEvent) => void } | null>( null, ); + useEffect(() => { + if (windowSize.width <= WINDOW_FLOATING_SIDEBAR_WIDTH) { + setFloating(true); + sidebar.hide(); + } else { + setFloating(false); + sidebar.show(); + } + }, [windowSize.width]); + const unsub = () => { if (moveState.current !== null) { document.documentElement.removeEventListener('mousemove', moveState.current.move); @@ -55,46 +76,86 @@ export default function Workspace() { const sideWidth = sidebar.hidden ? 0 : sidebar.width; const styles = useMemo( () => ({ - gridTemplate: ` + gridTemplate: floating + ? ` + ' ${head.gridArea}' auto + ' ${body.gridArea}' minmax(0,1fr) + / 1fr` + : ` ' ${head.gridArea} ${head.gridArea} ${head.gridArea}' auto ' ${side.gridArea} ${drag.gridArea} ${body.gridArea}' minmax(0,1fr) / ${sideWidth}px 0 1fr`, }), - [sideWidth], + [sideWidth, floating], ); return (
-
-
-
- -
- + + {floating ? ( + + + + + + + + + ) : ( + <> +
+ +
+ + + )}
); } + +interface HeaderSizeProps extends HTMLAttributes { + children: ReactNode; +} + +function HeaderSize({ className, ...props }: HeaderSizeProps) { + return ( +
+ ); +} diff --git a/src-web/components/WorkspaceHeader.tsx b/src-web/components/WorkspaceHeader.tsx index 2d5a118a..404d2a8c 100644 --- a/src-web/components/WorkspaceHeader.tsx +++ b/src-web/components/WorkspaceHeader.tsx @@ -1,7 +1,6 @@ import classnames from 'classnames'; import { memo } from 'react'; import { useActiveRequest } from '../hooks/useActiveRequest'; -import { useSidebarDisplay } from '../hooks/useSidebarDisplay'; import { IconButton } from './core/IconButton'; import { HStack } from './core/Stacks'; import { RequestSettingsDropdown } from './RequestSettingsDropdown'; @@ -15,8 +14,12 @@ interface Props { export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Props) { const activeRequest = useActiveRequest(); return ( - - + + diff --git a/src-web/components/core/Dialog.tsx b/src-web/components/core/Dialog.tsx index f2712630..13e34d95 100644 --- a/src-web/components/core/Dialog.tsx +++ b/src-web/components/core/Dialog.tsx @@ -1,7 +1,7 @@ import classnames from 'classnames'; import { motion } from 'framer-motion'; import type { ReactNode } from 'react'; -import { Portal } from '../Portal'; +import { Overlay } from '../Overlay'; import { IconButton } from './IconButton'; import { HStack, VStack } from './Stacks'; @@ -25,43 +25,38 @@ export function Dialog({ description, }: Props) { return ( - - {open && ( - -
onOpenChange(false)} - className="fixed inset-0 bg-gray-600/60 dark:bg-black/50" - /> -
-
- onOpenChange(false)} - title="Close dialog" - aria-label="Close" - icon="x" - size="sm" - className="ml-auto absolute right-1 top-1" - /> - - -
{title}
-
- {description &&
{description}
} -
{children}
-
-
-
- - )} - + onOpenChange(false)} portalName="dialog"> +
+
+ + onOpenChange(false)} + title="Close dialog" + aria-label="Close" + icon="x" + size="sm" + className="ml-auto absolute right-1 top-1" + /> + + +
{title}
+
+ {description &&
{description}
} +
{children}
+
+
+
+
+
); } diff --git a/src-web/components/core/Dropdown.tsx b/src-web/components/core/Dropdown.tsx index 703b9b06..76b326db 100644 --- a/src-web/components/core/Dropdown.tsx +++ b/src-web/components/core/Dropdown.tsx @@ -161,8 +161,8 @@ function Menu({ className, items, onClose, triggerRect }: MenuProps) {