mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-01-11 20:00:29 +01:00
Open workspace pref (#44)
Ability to remember workspace window opening selection.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n SELECT\n id, model, created_at, updated_at, theme, appearance,\n theme_dark, theme_light, update_channel,\n interface_font_size, interface_scale, editor_font_size, editor_soft_wrap\n FROM settings\n WHERE id = 'default'\n ",
|
||||
"query": "\n SELECT\n id, model, created_at, updated_at, theme, appearance,\n theme_dark, theme_light, update_channel,\n interface_font_size, interface_scale, editor_font_size, editor_soft_wrap, \n open_workspace_new_window\n FROM settings\n WHERE id = 'default'\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -67,6 +67,11 @@
|
||||
"name": "editor_soft_wrap",
|
||||
"ordinal": 12,
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"name": "open_workspace_new_window",
|
||||
"ordinal": 13,
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -85,8 +90,9 @@
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "ca3485d87b060cd77c4114d2af544adf18f6f15341d9d5db40865e92a80da4e2"
|
||||
"hash": "05dca7fe15ab1bf03952e94498ef3130e16f752da72782783696eb2cca4736d5"
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n UPDATE settings SET (\n theme, appearance, theme_dark, theme_light, update_channel,\n interface_font_size, interface_scale, editor_font_size, editor_soft_wrap\n ) = (?, ?, ?, ?, ?, ?, ?, ?, ?) WHERE id = 'default';\n ",
|
||||
"query": "\n UPDATE settings SET (\n theme, appearance, theme_dark, theme_light, update_channel,\n interface_font_size, interface_scale, editor_font_size, editor_soft_wrap,\n open_workspace_new_window\n ) = (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) WHERE id = 'default';\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 9
|
||||
"Right": 10
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "efd8ba41ea909b18dd520c57c1d464c5ae057b720cbbedcaec1513d43535632c"
|
||||
"hash": "6b5edf45a6799cd7f87c23a3c7f818ad110d58c601f694a619d9345ae9e8e11d"
|
||||
}
|
||||
@@ -30,27 +30,27 @@ base64 = "0.22.0"
|
||||
boa_engine = { version = "0.18.0", features = ["annex-b"] }
|
||||
boa_runtime = { version = "0.18.0" }
|
||||
chrono = { version = "0.4.31", features = ["serde"] }
|
||||
datetime = "0.5.2"
|
||||
hex_color = "3.0.0"
|
||||
http = "0.2.10"
|
||||
log = "0.4.21"
|
||||
rand = "0.8.5"
|
||||
regex = "1.10.2"
|
||||
reqwest = { version = "0.11.23", features = ["multipart", "cookies", "gzip", "brotli", "deflate", "json"] }
|
||||
reqwest_cookie_store = "0.6.0"
|
||||
serde = { version = "1.0.198", features = ["derive"] }
|
||||
serde_json = { version = "1.0.116", features = ["raw_value"] }
|
||||
sqlx = { version = "0.7.4", features = ["sqlite", "runtime-tokio-rustls", "json", "chrono", "time"] }
|
||||
tauri = { version = "2.0.0-beta", features = ["config-toml", "devtools", "protocol-asset"] }
|
||||
tauri-plugin-clipboard-manager = "2.1.0-beta"
|
||||
tauri-plugin-deep-link = "2.0.0-beta"
|
||||
tauri-plugin-dialog = "2.0.0-beta"
|
||||
tauri-plugin-fs = "2.0.0-beta"
|
||||
tauri-plugin-log = { version = "2.0.0-beta", features = ["colored"] }
|
||||
tauri-plugin-shell = "2.0.0-beta"
|
||||
tauri-plugin-os = "2.0.0-beta"
|
||||
tauri-plugin-shell = "2.0.0-beta"
|
||||
tauri-plugin-updater = "2.0.0-beta"
|
||||
tauri-plugin-window-state = "2.0.0-beta"
|
||||
tauri-plugin-fs = "2.0.0-beta"
|
||||
tauri-plugin-deep-link = "2.0.0-beta"
|
||||
tokio = { version = "1.36.0", features = ["sync"] }
|
||||
uuid = "1.7.0"
|
||||
log = "0.4.21"
|
||||
datetime = "0.5.2"
|
||||
reqwest_cookie_store = "0.6.0"
|
||||
tokio-stream = "0.1.15"
|
||||
regex = "1.10.2"
|
||||
hex_color = "3.0.0"
|
||||
uuid = "1.7.0"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN open_workspace_new_window BOOLEAN NULL DEFAULT NULL;
|
||||
@@ -59,6 +59,7 @@ pub struct Settings {
|
||||
pub interface_scale: i64,
|
||||
pub editor_font_size: i64,
|
||||
pub editor_soft_wrap: bool,
|
||||
pub open_workspace_new_window: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(sqlx::FromRow, Debug, Clone, Serialize, Deserialize, Default)]
|
||||
@@ -891,7 +892,8 @@ async fn get_settings(mgr: &impl Manager<Wry>) -> Result<Settings, sqlx::Error>
|
||||
SELECT
|
||||
id, model, created_at, updated_at, theme, appearance,
|
||||
theme_dark, theme_light, update_channel,
|
||||
interface_font_size, interface_scale, editor_font_size, editor_soft_wrap
|
||||
interface_font_size, interface_scale, editor_font_size, editor_soft_wrap,
|
||||
open_workspace_new_window
|
||||
FROM settings
|
||||
WHERE id = 'default'
|
||||
"#,
|
||||
@@ -928,8 +930,9 @@ pub async fn update_settings(
|
||||
r#"
|
||||
UPDATE settings SET (
|
||||
theme, appearance, theme_dark, theme_light, update_channel,
|
||||
interface_font_size, interface_scale, editor_font_size, editor_soft_wrap
|
||||
) = (?, ?, ?, ?, ?, ?, ?, ?, ?) WHERE id = 'default';
|
||||
interface_font_size, interface_scale, editor_font_size, editor_soft_wrap,
|
||||
open_workspace_new_window
|
||||
) = (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) WHERE id = 'default';
|
||||
"#,
|
||||
settings.theme,
|
||||
settings.appearance,
|
||||
@@ -940,6 +943,7 @@ pub async fn update_settings(
|
||||
settings.interface_scale,
|
||||
settings.editor_font_size,
|
||||
settings.editor_soft_wrap,
|
||||
settings.open_workspace_new_window,
|
||||
)
|
||||
.execute(&db)
|
||||
.await?;
|
||||
|
||||
64
src-web/components/OpenWorkspaceDialog.tsx
Normal file
64
src-web/components/OpenWorkspaceDialog.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import { useState } from 'react';
|
||||
import { useOpenWorkspace } from '../hooks/useOpenWorkspace';
|
||||
import { useSettings } from '../hooks/useSettings';
|
||||
import { useUpdateSettings } from '../hooks/useUpdateSettings';
|
||||
import type { Workspace } from '../lib/models';
|
||||
import { Button } from './core/Button';
|
||||
import { Checkbox } from './core/Checkbox';
|
||||
import { Icon } from './core/Icon';
|
||||
import { InlineCode } from './core/InlineCode';
|
||||
import { HStack, VStack } from './core/Stacks';
|
||||
|
||||
interface Props {
|
||||
hide: () => void;
|
||||
workspace: Workspace;
|
||||
}
|
||||
|
||||
export function OpenWorkspaceDialog({ hide, workspace }: Props) {
|
||||
const openWorkspace = useOpenWorkspace();
|
||||
const settings = useSettings();
|
||||
const updateSettings = useUpdateSettings();
|
||||
const [remember, setRemember] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<VStack space={3}>
|
||||
<p>
|
||||
Where would you like to open <InlineCode>{workspace.name}</InlineCode>?
|
||||
</p>
|
||||
<HStack space={2} justifyContent="start" className="flex-row-reverse">
|
||||
<Button
|
||||
className="focus"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
hide();
|
||||
openWorkspace.mutate({ workspace, inNewWindow: false });
|
||||
if (remember) {
|
||||
updateSettings.mutate({ openWorkspaceNewWindow: false });
|
||||
}
|
||||
}}
|
||||
>
|
||||
This Window
|
||||
</Button>
|
||||
<Button
|
||||
className="focus"
|
||||
color="secondary"
|
||||
rightSlot={<Icon icon="externalLink" />}
|
||||
onClick={() => {
|
||||
hide();
|
||||
openWorkspace.mutate({ workspace, inNewWindow: true });
|
||||
if (remember) {
|
||||
updateSettings.mutate({ openWorkspaceNewWindow: true });
|
||||
}
|
||||
}}
|
||||
>
|
||||
New Window
|
||||
</Button>
|
||||
</HStack>
|
||||
{settings && (
|
||||
<HStack justifyContent="end">
|
||||
<Checkbox checked={remember} title="Remember my choice" onChange={setRemember} />
|
||||
</HStack>
|
||||
)}
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
@@ -50,6 +50,33 @@ export function SettingsGeneral() {
|
||||
onClick={() => checkForUpdates.mutateAsync()}
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
name="openWorkspace"
|
||||
label="Open Workspace"
|
||||
labelPosition="left"
|
||||
size="sm"
|
||||
value={
|
||||
settings.openWorkspaceNewWindow === true
|
||||
? 'new'
|
||||
: settings.openWorkspaceNewWindow === false
|
||||
? 'current'
|
||||
: 'ask'
|
||||
}
|
||||
onChange={(v) => {
|
||||
if (v === 'current') {
|
||||
updateSettings.mutate({ openWorkspaceNewWindow: false });
|
||||
} else if (v === 'new') {
|
||||
updateSettings.mutate({ openWorkspaceNewWindow: true });
|
||||
} else {
|
||||
updateSettings.mutate({ openWorkspaceNewWindow: null });
|
||||
}
|
||||
}}
|
||||
options={[
|
||||
{ label: 'Always Ask', value: 'ask' },
|
||||
{ label: 'Current Window', value: 'current' },
|
||||
{ label: 'New Window', value: 'new' },
|
||||
]}
|
||||
/>
|
||||
<Separator className="my-4" />
|
||||
|
||||
<Heading size={2}>
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import classNames from 'classnames';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
||||
import { useAppRoutes } from '../hooks/useAppRoutes';
|
||||
import { useCommand } from '../hooks/useCommands';
|
||||
import { useDeleteWorkspace } from '../hooks/useDeleteWorkspace';
|
||||
import { useOpenWorkspace } from '../hooks/useOpenWorkspace';
|
||||
import { usePrompt } from '../hooks/usePrompt';
|
||||
import { getRecentEnvironments } from '../hooks/useRecentEnvironments';
|
||||
import { getRecentRequests } from '../hooks/useRecentRequests';
|
||||
import { useSettings } from '../hooks/useSettings';
|
||||
import { useUpdateWorkspace } from '../hooks/useUpdateWorkspace';
|
||||
import { useWorkspaces } from '../hooks/useWorkspaces';
|
||||
import type { ButtonProps } from './core/Button';
|
||||
@@ -16,8 +14,8 @@ import type { DropdownItem } from './core/Dropdown';
|
||||
import { Dropdown } from './core/Dropdown';
|
||||
import { Icon } from './core/Icon';
|
||||
import { InlineCode } from './core/InlineCode';
|
||||
import { HStack } from './core/Stacks';
|
||||
import { useDialog } from './DialogContext';
|
||||
import { OpenWorkspaceDialog } from './OpenWorkspaceDialog';
|
||||
|
||||
type Props = Pick<ButtonProps, 'className' | 'justify' | 'forDropdown' | 'leftSlot'>;
|
||||
|
||||
@@ -33,7 +31,9 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
||||
const createWorkspace = useCommand('workspace.create');
|
||||
const dialog = useDialog();
|
||||
const prompt = usePrompt();
|
||||
const routes = useAppRoutes();
|
||||
const settings = useSettings();
|
||||
const openWorkspace = useOpenWorkspace();
|
||||
const openWorkspaceNewWindow = settings?.openWorkspaceNewWindow ?? null;
|
||||
|
||||
const items: DropdownItem[] = useMemo(() => {
|
||||
const workspaceItems: DropdownItem[] = workspaces.map((w) => ({
|
||||
@@ -41,58 +41,16 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
||||
label: w.name,
|
||||
leftSlot: w.id === activeWorkspaceId ? <Icon icon="check" /> : <Icon icon="empty" />,
|
||||
onSelect: async () => {
|
||||
if (typeof openWorkspaceNewWindow === 'boolean') {
|
||||
openWorkspace.mutate({ workspace: w, inNewWindow: openWorkspaceNewWindow });
|
||||
return;
|
||||
}
|
||||
|
||||
dialog.show({
|
||||
id: 'open-workspace',
|
||||
size: 'sm',
|
||||
title: 'Open Workspace',
|
||||
description: (
|
||||
<>
|
||||
Where would you like to open <InlineCode>{w.name}</InlineCode>?
|
||||
</>
|
||||
),
|
||||
render: ({ hide }) => {
|
||||
return (
|
||||
<HStack space={2} justifyContent="start" className="mt-4 mb-6 flex-row-reverse">
|
||||
<Button
|
||||
className="focus"
|
||||
color="primary"
|
||||
onClick={async () => {
|
||||
hide();
|
||||
const environmentId = (await getRecentEnvironments(w.id))[0];
|
||||
const requestId = (await getRecentRequests(w.id))[0];
|
||||
if (requestId != null) {
|
||||
routes.navigate('request', { workspaceId: w.id, environmentId, requestId });
|
||||
} else {
|
||||
routes.navigate('workspace', { workspaceId: w.id, environmentId });
|
||||
}
|
||||
}}
|
||||
>
|
||||
This Window
|
||||
</Button>
|
||||
<Button
|
||||
className="focus"
|
||||
color="secondary"
|
||||
rightSlot={<Icon icon="externalLink" />}
|
||||
onClick={async () => {
|
||||
hide();
|
||||
const environmentId = (await getRecentEnvironments(w.id))[0];
|
||||
const requestId = (await getRecentRequests(w.id))[0];
|
||||
const path =
|
||||
requestId != null
|
||||
? routes.paths.request({
|
||||
workspaceId: w.id,
|
||||
environmentId,
|
||||
requestId,
|
||||
})
|
||||
: routes.paths.workspace({ workspaceId: w.id, environmentId });
|
||||
await invoke('cmd_new_window', { url: path });
|
||||
}}
|
||||
>
|
||||
New Window
|
||||
</Button>
|
||||
</HStack>
|
||||
);
|
||||
},
|
||||
render: ({ hide }) => <OpenWorkspaceDialog workspace={w} hide={hide} />,
|
||||
});
|
||||
},
|
||||
}));
|
||||
@@ -152,8 +110,9 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
||||
createWorkspace,
|
||||
deleteWorkspace.mutate,
|
||||
dialog,
|
||||
openWorkspace,
|
||||
prompt,
|
||||
routes,
|
||||
openWorkspaceNewWindow,
|
||||
updateWorkspace,
|
||||
workspaces,
|
||||
]);
|
||||
|
||||
@@ -67,7 +67,7 @@ export function Dialog({
|
||||
'rounded-lg',
|
||||
'border border-background-highlight-secondary shadow-lg shadow-[rgba(0,0,0,0.1)]',
|
||||
'max-w-[calc(100vw-5rem)] max-h-[calc(100vh-6rem)]',
|
||||
size === 'sm' && 'w-[25rem] max-h-[80vh]',
|
||||
size === 'sm' && 'w-[28rem] max-h-[80vh]',
|
||||
size === 'md' && 'w-[45rem] max-h-[80vh]',
|
||||
size === 'lg' && 'w-[65rem] max-h-[80vh]',
|
||||
size === 'full' && 'w-[100vw] h-[100vh]',
|
||||
|
||||
50
src-web/hooks/useOpenWorkspace.ts
Normal file
50
src-web/hooks/useOpenWorkspace.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import type { Workspace } from '../lib/models';
|
||||
import { useAppRoutes } from './useAppRoutes';
|
||||
import { getRecentEnvironments } from './useRecentEnvironments';
|
||||
import { getRecentRequests } from './useRecentRequests';
|
||||
import { useSettings } from './useSettings';
|
||||
|
||||
export function useOpenWorkspace() {
|
||||
const settings = useSettings();
|
||||
const routes = useAppRoutes();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
workspace,
|
||||
inNewWindow,
|
||||
}: {
|
||||
workspace: Workspace;
|
||||
inNewWindow: boolean;
|
||||
}) => {
|
||||
if (settings == null || workspace == null) return;
|
||||
|
||||
if (inNewWindow) {
|
||||
const environmentId = (await getRecentEnvironments(workspace.id))[0];
|
||||
const requestId = (await getRecentRequests(workspace.id))[0];
|
||||
const path =
|
||||
requestId != null
|
||||
? routes.paths.request({
|
||||
workspaceId: workspace.id,
|
||||
environmentId,
|
||||
requestId,
|
||||
})
|
||||
: routes.paths.workspace({ workspaceId: workspace.id, environmentId });
|
||||
await invoke('cmd_new_window', { url: path });
|
||||
} else {
|
||||
const environmentId = (await getRecentEnvironments(workspace.id))[0];
|
||||
const requestId = (await getRecentRequests(workspace.id))[0];
|
||||
if (requestId != null) {
|
||||
routes.navigate('request', {
|
||||
workspaceId: workspace.id,
|
||||
environmentId,
|
||||
requestId,
|
||||
});
|
||||
} else {
|
||||
routes.navigate('workspace', { workspaceId: workspace.id, environmentId });
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -41,6 +41,7 @@ export interface Settings extends BaseModel {
|
||||
interfaceScale: number;
|
||||
editorFontSize: number;
|
||||
editorSoftWrap: boolean;
|
||||
openWorkspaceNewWindow: boolean | null;
|
||||
}
|
||||
|
||||
export interface Workspace extends BaseModel {
|
||||
|
||||
Reference in New Issue
Block a user