feat: upgrade codemirror to 6.39.13 and enhance host switching
This commit is contained in:
@@ -23,7 +23,7 @@
|
|||||||
"@codemirror/lint": "^6.9.2",
|
"@codemirror/lint": "^6.9.2",
|
||||||
"@codemirror/search": "^6.6.0",
|
"@codemirror/search": "^6.6.0",
|
||||||
"@codemirror/state": "^6.5.4",
|
"@codemirror/state": "^6.5.4",
|
||||||
"@codemirror/view": "^6.39.11",
|
"@codemirror/view": "^6.39.13",
|
||||||
"@fontsource/ibm-plex-mono": "^5.2.7",
|
"@fontsource/ibm-plex-mono": "^5.2.7",
|
||||||
"@fontsource/ibm-plex-sans": "^5.1.1",
|
"@fontsource/ibm-plex-sans": "^5.1.1",
|
||||||
"@heroui/scroll-shadow": "^2.3.18",
|
"@heroui/scroll-shadow": "^2.3.18",
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
"@codemirror/lint": "^6.9.2",
|
"@codemirror/lint": "^6.9.2",
|
||||||
"@codemirror/search": "^6.6.0",
|
"@codemirror/search": "^6.6.0",
|
||||||
"@codemirror/state": "^6.5.4",
|
"@codemirror/state": "^6.5.4",
|
||||||
"@codemirror/view": "^6.39.11",
|
"@codemirror/view": "^6.39.13",
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
@@ -301,6 +301,9 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"overrides": {
|
||||||
|
"@codemirror/view": "6.39.13",
|
||||||
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"7zip-bin": ["7zip-bin@5.2.0", "", {}, "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A=="],
|
"7zip-bin": ["7zip-bin@5.2.0", "", {}, "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A=="],
|
||||||
|
|
||||||
@@ -3230,14 +3233,10 @@
|
|||||||
|
|
||||||
"@codemirror/highlight/@codemirror/state": ["@codemirror/state@0.19.9", "", { "dependencies": { "@codemirror/text": "^0.19.0" } }, "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw=="],
|
"@codemirror/highlight/@codemirror/state": ["@codemirror/state@0.19.9", "", { "dependencies": { "@codemirror/text": "^0.19.0" } }, "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw=="],
|
||||||
|
|
||||||
"@codemirror/highlight/@codemirror/view": ["@codemirror/view@0.19.48", "", { "dependencies": { "@codemirror/rangeset": "^0.19.5", "@codemirror/state": "^0.19.3", "@codemirror/text": "^0.19.0", "style-mod": "^4.0.0", "w3c-keyname": "^2.2.4" } }, "sha512-0eg7D2Nz4S8/caetCTz61rK0tkHI17V/d15Jy0kLOT8dTLGGNJUponDnW28h2B6bERmPlVHKh8MJIr5OCp1nGw=="],
|
|
||||||
|
|
||||||
"@codemirror/highlight/@lezer/common": ["@lezer/common@0.15.12", "", {}, "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig=="],
|
"@codemirror/highlight/@lezer/common": ["@lezer/common@0.15.12", "", {}, "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig=="],
|
||||||
|
|
||||||
"@codemirror/history/@codemirror/state": ["@codemirror/state@0.19.9", "", { "dependencies": { "@codemirror/text": "^0.19.0" } }, "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw=="],
|
"@codemirror/history/@codemirror/state": ["@codemirror/state@0.19.9", "", { "dependencies": { "@codemirror/text": "^0.19.0" } }, "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw=="],
|
||||||
|
|
||||||
"@codemirror/history/@codemirror/view": ["@codemirror/view@0.19.48", "", { "dependencies": { "@codemirror/rangeset": "^0.19.5", "@codemirror/state": "^0.19.3", "@codemirror/text": "^0.19.0", "style-mod": "^4.0.0", "w3c-keyname": "^2.2.4" } }, "sha512-0eg7D2Nz4S8/caetCTz61rK0tkHI17V/d15Jy0kLOT8dTLGGNJUponDnW28h2B6bERmPlVHKh8MJIr5OCp1nGw=="],
|
|
||||||
|
|
||||||
"@codemirror/rangeset/@codemirror/state": ["@codemirror/state@0.19.9", "", { "dependencies": { "@codemirror/text": "^0.19.0" } }, "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw=="],
|
"@codemirror/rangeset/@codemirror/state": ["@codemirror/state@0.19.9", "", { "dependencies": { "@codemirror/text": "^0.19.0" } }, "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw=="],
|
||||||
|
|
||||||
"@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="],
|
"@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="],
|
||||||
|
|||||||
+4
-1
@@ -76,7 +76,7 @@
|
|||||||
"@codemirror/lint": "^6.9.2",
|
"@codemirror/lint": "^6.9.2",
|
||||||
"@codemirror/search": "^6.6.0",
|
"@codemirror/search": "^6.6.0",
|
||||||
"@codemirror/state": "^6.5.4",
|
"@codemirror/state": "^6.5.4",
|
||||||
"@codemirror/view": "^6.39.11",
|
"@codemirror/view": "^6.39.13",
|
||||||
"@fontsource/ibm-plex-mono": "^5.2.7",
|
"@fontsource/ibm-plex-mono": "^5.2.7",
|
||||||
"@fontsource/ibm-plex-sans": "^5.1.1",
|
"@fontsource/ibm-plex-sans": "^5.1.1",
|
||||||
"@heroui/scroll-shadow": "^2.3.18",
|
"@heroui/scroll-shadow": "^2.3.18",
|
||||||
@@ -120,6 +120,9 @@
|
|||||||
"zod": "^4.3.6",
|
"zod": "^4.3.6",
|
||||||
"zustand": "^5.0.8"
|
"zustand": "^5.0.8"
|
||||||
},
|
},
|
||||||
|
"overrides": {
|
||||||
|
"@codemirror/view": "6.39.13"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.33.0",
|
"@eslint/js": "^9.33.0",
|
||||||
"@tailwindcss/postcss": "^4.0.0",
|
"@tailwindcss/postcss": "^4.0.0",
|
||||||
|
|||||||
@@ -1121,6 +1121,7 @@ async fn desktop_host_probe(url: String) -> Result<HostProbeResult, String> {
|
|||||||
.build()
|
.build()
|
||||||
.map_err(|err| err.to_string())?;
|
.map_err(|err| err.to_string())?;
|
||||||
let started = std::time::Instant::now();
|
let started = std::time::Instant::now();
|
||||||
|
|
||||||
match client.get(&health).send().await {
|
match client.get(&health).send().await {
|
||||||
Ok(resp) => {
|
Ok(resp) => {
|
||||||
let status = resp.status();
|
let status = resp.status();
|
||||||
@@ -2086,6 +2087,29 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if initial_url != local_ui_url {
|
||||||
|
match desktop_host_probe(initial_url.clone()).await {
|
||||||
|
Ok(probe) if probe.status != "unreachable" => {}
|
||||||
|
Ok(_) => {
|
||||||
|
log::warn!(
|
||||||
|
"[desktop] startup host unreachable ({}), falling back to local ({})",
|
||||||
|
initial_url,
|
||||||
|
local_ui_url
|
||||||
|
);
|
||||||
|
initial_url = local_ui_url.clone();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::warn!(
|
||||||
|
"[desktop] startup host probe failed ({}): {}, falling back to local ({})",
|
||||||
|
initial_url,
|
||||||
|
err,
|
||||||
|
local_ui_url
|
||||||
|
);
|
||||||
|
initial_url = local_ui_url.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(err) = create_main_window(&handle, &initial_url, &local_origin) {
|
if let Err(err) = create_main_window(&handle, &initial_url, &local_origin) {
|
||||||
log::error!("[desktop] failed to create window: {err}");
|
log::error!("[desktop] failed to create window: {err}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
"@codemirror/lint": "^6.9.2",
|
"@codemirror/lint": "^6.9.2",
|
||||||
"@codemirror/search": "^6.6.0",
|
"@codemirror/search": "^6.6.0",
|
||||||
"@codemirror/state": "^6.5.4",
|
"@codemirror/state": "^6.5.4",
|
||||||
"@codemirror/view": "^6.39.11",
|
"@codemirror/view": "^6.39.13",
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
@@ -102,4 +102,4 @@
|
|||||||
"typescript-eslint": "^8.39.1",
|
"typescript-eslint": "^8.39.1",
|
||||||
"vite": "^7.1.2"
|
"vite": "^7.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
RiDeleteBinLine,
|
RiDeleteBinLine,
|
||||||
} from '@remixicon/react';
|
} from '@remixicon/react';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import { toast } from '@/components/ui';
|
||||||
import { isTauriShell, isDesktopShell } from '@/lib/desktop';
|
import { isTauriShell, isDesktopShell } from '@/lib/desktop';
|
||||||
import {
|
import {
|
||||||
desktopHostProbe,
|
desktopHostProbe,
|
||||||
@@ -160,6 +161,7 @@ export function DesktopHostSwitcherDialog({
|
|||||||
const [isLoading, setIsLoading] = React.useState(false);
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
const [isProbing, setIsProbing] = React.useState(false);
|
const [isProbing, setIsProbing] = React.useState(false);
|
||||||
const [isSaving, setIsSaving] = React.useState(false);
|
const [isSaving, setIsSaving] = React.useState(false);
|
||||||
|
const [switchingHostId, setSwitchingHostId] = React.useState<string | null>(null);
|
||||||
const [error, setError] = React.useState<string>('');
|
const [error, setError] = React.useState<string>('');
|
||||||
|
|
||||||
const [editingId, setEditingId] = React.useState<string | null>(null);
|
const [editingId, setEditingId] = React.useState<string | null>(null);
|
||||||
@@ -262,9 +264,25 @@ export function DesktopHostSwitcherDialog({
|
|||||||
void probeAll(allHosts);
|
void probeAll(allHosts);
|
||||||
}, [open, allHosts, probeAll]);
|
}, [open, allHosts, probeAll]);
|
||||||
|
|
||||||
const handleSwitch = React.useCallback((host: DesktopHost) => {
|
const handleSwitch = React.useCallback(async (host: DesktopHost) => {
|
||||||
const origin = host.id === LOCAL_HOST_ID ? getLocalOrigin() : (normalizeHostUrl(host.url) || '');
|
const origin = host.id === LOCAL_HOST_ID ? getLocalOrigin() : (normalizeHostUrl(host.url) || '');
|
||||||
if (!origin) return;
|
if (!origin) return;
|
||||||
|
|
||||||
|
if (host.id !== LOCAL_HOST_ID && isTauriShell()) {
|
||||||
|
setSwitchingHostId(host.id);
|
||||||
|
const probe = await desktopHostProbe(origin).catch((): HostProbeResult => ({ status: 'unreachable', latencyMs: 0 }));
|
||||||
|
setStatusById((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[host.id]: { status: probe.status, latencyMs: probe.latencyMs },
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (probe.status === 'unreachable') {
|
||||||
|
toast.error(`Instance "${host.label}" is unreachable`);
|
||||||
|
setSwitchingHostId(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const target = toNavigationUrl(origin);
|
const target = toNavigationUrl(origin);
|
||||||
onHostSwitched?.();
|
onHostSwitched?.();
|
||||||
|
|
||||||
@@ -440,7 +458,8 @@ export function DesktopHostSwitcherDialog({
|
|||||||
'flex items-center gap-2 flex-1 min-w-0 text-left',
|
'flex items-center gap-2 flex-1 min-w-0 text-left',
|
||||||
isEditing && 'pointer-events-none opacity-70'
|
isEditing && 'pointer-events-none opacity-70'
|
||||||
)}
|
)}
|
||||||
onClick={() => handleSwitch(host)}
|
onClick={() => void handleSwitch(host)}
|
||||||
|
disabled={switchingHostId === host.id}
|
||||||
aria-label={`Switch to ${host.label}`}
|
aria-label={`Switch to ${host.label}`}
|
||||||
>
|
>
|
||||||
<span className={cn('h-2 w-2 rounded-full flex-shrink-0', statusDotClass(status?.status ?? null))} />
|
<span className={cn('h-2 w-2 rounded-full flex-shrink-0', statusDotClass(status?.status ?? null))} />
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import type { Extension } from '@codemirror/state';
|
import type { Extension } from '@codemirror/state';
|
||||||
import { Compartment, EditorState, RangeSetBuilder, StateField } from '@codemirror/state';
|
import { Compartment, EditorState, RangeSetBuilder, StateField } from '@codemirror/state';
|
||||||
import { Decoration, type DecorationSet, EditorView, ViewPlugin, WidgetType, gutters, keymap, lineNumbers } from '@codemirror/view';
|
import { Decoration, type DecorationSet, EditorView, type KeyBinding, ViewPlugin, WidgetType, gutters, keymap, lineNumbers } from '@codemirror/view';
|
||||||
import { defaultKeymap, indentWithTab, history, historyKeymap } from '@codemirror/commands';
|
import { defaultKeymap, indentWithTab, history, historyKeymap } from '@codemirror/commands';
|
||||||
import { indentUnit } from '@codemirror/language';
|
import { indentUnit } from '@codemirror/language';
|
||||||
import { search, searchKeymap, openSearchPanel, closeSearchPanel } from '@codemirror/search';
|
import { search, searchKeymap, openSearchPanel, closeSearchPanel } from '@codemirror/search';
|
||||||
@@ -39,6 +39,13 @@ const highlightLinesCompartment = new Compartment();
|
|||||||
const blockWidgetsCompartment = new Compartment();
|
const blockWidgetsCompartment = new Compartment();
|
||||||
const searchCompartment = new Compartment();
|
const searchCompartment = new Compartment();
|
||||||
|
|
||||||
|
const toViewKeyBindings = (bindings: readonly unknown[]): readonly KeyBinding[] => {
|
||||||
|
return bindings as readonly KeyBinding[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const openSearchPanelCompat = openSearchPanel as unknown as (view: EditorView) => void;
|
||||||
|
const closeSearchPanelCompat = closeSearchPanel as unknown as (view: EditorView) => void;
|
||||||
|
|
||||||
// BlockWidget class definition moved inside helper or adapted to take map
|
// BlockWidget class definition moved inside helper or adapted to take map
|
||||||
class BlockWidget extends WidgetType {
|
class BlockWidget extends WidgetType {
|
||||||
constructor(readonly id: string, readonly containerMap: Map<string, HTMLElement>) {
|
constructor(readonly id: string, readonly containerMap: Map<string, HTMLElement>) {
|
||||||
@@ -198,7 +205,7 @@ export function CodeMirrorEditor({
|
|||||||
externalExtensionsCompartment.of(extensions ?? []),
|
externalExtensionsCompartment.of(extensions ?? []),
|
||||||
highlightLinesCompartment.of(createHighlightLinesExtension(highlightLines)),
|
highlightLinesCompartment.of(createHighlightLinesExtension(highlightLines)),
|
||||||
blockWidgetsCompartment.of(createBlockWidgetsExtension(blockWidgets, widgetContainersRef.current)),
|
blockWidgetsCompartment.of(createBlockWidgetsExtension(blockWidgets, widgetContainersRef.current)),
|
||||||
searchCompartment.of(enableSearch ? [search({ top: true }), keymap.of(searchKeymap)] : []),
|
searchCompartment.of(enableSearch ? [search({ top: true }), keymap.of(toViewKeyBindings(searchKeymap))] : []),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -232,7 +239,7 @@ export function CodeMirrorEditor({
|
|||||||
externalExtensionsCompartment.reconfigure(extensions ?? []),
|
externalExtensionsCompartment.reconfigure(extensions ?? []),
|
||||||
highlightLinesCompartment.reconfigure(createHighlightLinesExtension(highlightLines)),
|
highlightLinesCompartment.reconfigure(createHighlightLinesExtension(highlightLines)),
|
||||||
blockWidgetsCompartment.reconfigure(createBlockWidgetsExtension(blockWidgets, widgetContainersRef.current)),
|
blockWidgetsCompartment.reconfigure(createBlockWidgetsExtension(blockWidgets, widgetContainersRef.current)),
|
||||||
searchCompartment.reconfigure(enableSearch ? [search({ top: true }), keymap.of(searchKeymap)] : []),
|
searchCompartment.reconfigure(enableSearch ? [search({ top: true }), keymap.of(toViewKeyBindings(searchKeymap))] : []),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -247,9 +254,9 @@ export function CodeMirrorEditor({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (searchOpen) {
|
if (searchOpen) {
|
||||||
openSearchPanel(view);
|
openSearchPanelCompat(view);
|
||||||
} else {
|
} else {
|
||||||
closeSearchPanel(view);
|
closeSearchPanelCompat(view);
|
||||||
}
|
}
|
||||||
}, [searchOpen, enableSearch]);
|
}, [searchOpen, enableSearch]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user