fix remote server keyboard and reconnect flows

This commit is contained in:
Shantur Rathore
2026-04-02 18:20:17 +01:00
parent 6eb3246d37
commit 92c029d744
2 changed files with 83 additions and 22 deletions

View File

@@ -174,6 +174,15 @@ fn open_remote_window(app: AppHandle, payload: RemoteWindowPayload) -> Result<()
let label = format!("remote-{}", payload.id); let label = format!("remote-{}", payload.id);
let title = format!("{} - {}", payload.name, parsed.host_str().unwrap_or(payload.base_url.as_str())); let title = format!("{} - {}", payload.name, parsed.host_str().unwrap_or(payload.base_url.as_str()));
if let Some(existing) = app.get_webview_window(&label) {
let _ = existing.navigate(parsed.clone());
let _ = existing.set_title(&title);
let _ = existing.show();
let _ = existing.unminimize();
let _ = existing.set_focus();
return Ok(());
}
app.state::<AppState>() app.state::<AppState>()
.remote_origins .remote_origins
.lock() .lock()

View File

@@ -74,8 +74,13 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
const selectedLanguageOption = () => languageOptions.find((opt) => opt.value === locale()) ?? languageOptions[0] const selectedLanguageOption = () => languageOptions.find((opt) => opt.value === locale()) ?? languageOptions[0]
const folders = () => recentFolders() const folders = () => recentFolders()
const serverList = () => remoteServers()
const isLoading = () => Boolean(props.isLoading) const isLoading = () => Boolean(props.isLoading)
function getActiveListLength() {
return activeTab() === "local" ? folders().length : serverList().length
}
// Update selected binary when preferences change // Update selected binary when preferences change
createEffect(() => { createEffect(() => {
const lastUsed = serverSettings().opencodeBinary const lastUsed = serverSettings().opencodeBinary
@@ -87,7 +92,7 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
function scrollToIndex(index: number) { function scrollToIndex(index: number) {
const container = recentListRef const container = recentListRef
if (!container) return if (!container) return
const element = container.querySelector(`[data-folder-index="${index}"]`) as HTMLElement | null const element = container.querySelector(`[data-list-index="${index}"]`) as HTMLElement | null
if (!element) return if (!element) return
const containerRect = container.getBoundingClientRect() const containerRect = container.getBoundingClientRect()
@@ -136,19 +141,18 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
return return
} }
const folderList = folders()
if (isBrowseShortcut) { if (isBrowseShortcut) {
e.preventDefault() e.preventDefault()
void handleBrowse() void handleBrowse()
return return
} }
if (folderList.length === 0) return const listLength = getActiveListLength()
if (listLength === 0) return
if (e.key === "ArrowDown") { if (e.key === "ArrowDown") {
e.preventDefault() e.preventDefault()
const newIndex = Math.min(selectedIndex() + 1, folderList.length - 1) const newIndex = Math.min(selectedIndex() + 1, listLength - 1)
setSelectedIndex(newIndex) setSelectedIndex(newIndex)
setFocusMode("recent") setFocusMode("recent")
scrollToIndex(newIndex) scrollToIndex(newIndex)
@@ -161,7 +165,7 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
} else if (e.key === "PageDown") { } else if (e.key === "PageDown") {
e.preventDefault() e.preventDefault()
const pageSize = 5 const pageSize = 5
const newIndex = Math.min(selectedIndex() + pageSize, folderList.length - 1) const newIndex = Math.min(selectedIndex() + pageSize, listLength - 1)
setSelectedIndex(newIndex) setSelectedIndex(newIndex)
setFocusMode("recent") setFocusMode("recent")
scrollToIndex(newIndex) scrollToIndex(newIndex)
@@ -179,7 +183,7 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
scrollToIndex(0) scrollToIndex(0)
} else if (e.key === "End") { } else if (e.key === "End") {
e.preventDefault() e.preventDefault()
const newIndex = folderList.length - 1 const newIndex = listLength - 1
setSelectedIndex(newIndex) setSelectedIndex(newIndex)
setFocusMode("recent") setFocusMode("recent")
scrollToIndex(newIndex) scrollToIndex(newIndex)
@@ -188,10 +192,17 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
handleEnterKey() handleEnterKey()
} else if (e.key === "Backspace" || e.key === "Delete") { } else if (e.key === "Backspace" || e.key === "Delete") {
e.preventDefault() e.preventDefault()
if (folderList.length > 0 && focusMode() === "recent") { if (listLength > 0 && focusMode() === "recent") {
const folder = folderList[selectedIndex()] if (activeTab() === "local") {
if (folder) { const folder = folders()[selectedIndex()]
handleRemove(folder.path) if (folder) {
handleRemove(folder.path)
}
} else {
const server = serverList()[selectedIndex()]
if (server) {
removeRemoteServerProfile(server.id)
}
} }
} }
} }
@@ -200,15 +211,40 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
function handleEnterKey() { function handleEnterKey() {
if (isLoading()) return if (isLoading()) return
const folderList = folders()
const index = selectedIndex() const index = selectedIndex()
const folder = folderList[index] if (activeTab() === "local") {
if (folder) { const folder = folders()[index]
handleFolderSelect(folder.path) if (folder) {
handleFolderSelect(folder.path)
}
return
}
const server = serverList()[index]
if (server) {
void handleConnectSavedServer(server.id)
} }
} }
createEffect(() => {
activeTab()
setSelectedIndex(0)
setFocusMode("recent")
})
createEffect(() => {
const length = getActiveListLength()
if (length === 0) {
setSelectedIndex(0)
return
}
if (selectedIndex() >= length) {
setSelectedIndex(length - 1)
}
})
onMount(() => { onMount(() => {
window.addEventListener("keydown", handleKeyDown) window.addEventListener("keydown", handleKeyDown)
@@ -672,12 +708,28 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
</div> </div>
} }
> >
<div class="panel-list panel-list--fill flex-1 min-h-0 overflow-auto"> <div
class="panel-list panel-list--fill flex-1 min-h-0 overflow-auto"
ref={(el) => (recentListRef = el)}
>
<For each={remoteServers()}> <For each={remoteServers()}>
{(server) => ( {(server, index) => (
<div class="panel-list-item"> <div
class="panel-list-item"
classList={{
"panel-list-item-highlight": focusMode() === "recent" && selectedIndex() === index(),
}}
>
<div class="flex items-center gap-2 w-full px-1"> <div class="flex items-center gap-2 w-full px-1">
<button class="panel-list-item-content flex-1" onClick={() => void handleConnectSavedServer(server.id)}> <button
data-list-index={index()}
class="panel-list-item-content flex-1"
onClick={() => void handleConnectSavedServer(server.id)}
onMouseEnter={() => {
setFocusMode("recent")
setSelectedIndex(index())
}}
>
<div class="flex items-center justify-between gap-3 w-full"> <div class="flex items-center justify-between gap-3 w-full">
<div class="flex-1 min-w-0 text-left"> <div class="flex-1 min-w-0 text-left">
<div class="flex items-center gap-2 mb-1"> <div class="flex items-center gap-2 mb-1">
@@ -688,7 +740,7 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
<span class="font-mono truncate-start flex-1 min-w-0">{server.baseUrl}</span> <span class="font-mono truncate-start flex-1 min-w-0">{server.baseUrl}</span>
</div> </div>
</div> </div>
<Show when={connectingServerId() === server.id} fallback={<kbd class="kbd"></kbd>}> <Show when={connectingServerId() === server.id} fallback={<Show when={focusMode() === "recent" && selectedIndex() === index()}><kbd class="kbd"></kbd></Show>}>
<Loader2 class="w-4 h-4 animate-spin icon-muted" /> <Loader2 class="w-4 h-4 animate-spin icon-muted" />
</Show> </Show>
</div> </div>
@@ -735,7 +787,7 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
> >
<div class="flex items-center gap-2 w-full px-1"> <div class="flex items-center gap-2 w-full px-1">
<button <button
data-folder-index={index()} data-list-index={index()}
class="panel-list-item-content flex-1" class="panel-list-item-content flex-1"
disabled={isLoading()} disabled={isLoading()}
onClick={() => handleFolderSelect(folder.path)} onClick={() => handleFolderSelect(folder.path)}