Key-file picker in the connection manager
Choose... button beside the private-key field opens the native file dialog starting in ~/.ssh (Utils.openFileDialog via a pickKeyFile RPC). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -203,6 +203,20 @@ export function createAppRPC({
|
||||
return { path };
|
||||
}),
|
||||
|
||||
pickKeyFile: () =>
|
||||
wrap(async () => {
|
||||
const { homedir } = await import("node:os");
|
||||
const picked = await Utils.openFileDialog({
|
||||
startingFolder: `${homedir()}/.ssh`,
|
||||
allowedFileTypes: "*",
|
||||
canChooseFiles: true,
|
||||
canChooseDirectory: false,
|
||||
allowsMultipleSelection: false,
|
||||
});
|
||||
const path = picked.find((p) => p.trim().length > 0) ?? null;
|
||||
return { path };
|
||||
}),
|
||||
|
||||
getEditLeftovers: () =>
|
||||
wrap(async () => ({ names: await edits.listLeftovers() })),
|
||||
|
||||
|
||||
@@ -91,6 +91,10 @@ export type AppRPC = {
|
||||
params: Record<string, never>;
|
||||
response: Result<{ path: string | null }>;
|
||||
};
|
||||
pickKeyFile: {
|
||||
params: Record<string, never>;
|
||||
response: Result<{ path: string | null }>;
|
||||
};
|
||||
getEditLeftovers: {
|
||||
params: Record<string, never>;
|
||||
response: Result<{ names: string[] }>;
|
||||
|
||||
@@ -196,13 +196,22 @@
|
||||
} @else {
|
||||
<label class="flex flex-col gap-1 text-xs">
|
||||
<span class="text-muted-foreground">Private key file</span>
|
||||
<div class="flex items-center gap-1">
|
||||
<input
|
||||
[value]="d.privateKeyPath"
|
||||
(input)="patch('privateKeyPath', $any($event.target).value)"
|
||||
placeholder="~/.ssh/id_ed25519"
|
||||
spellcheck="false"
|
||||
class="h-7 rounded-md border border-input bg-transparent px-2 font-mono outline-none focus:ring-2 focus:ring-ring"
|
||||
class="h-7 min-w-0 flex-1 rounded-md border border-input bg-transparent px-2 font-mono outline-none focus:ring-2 focus:ring-ring"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
(click)="pickKeyFile()"
|
||||
class="h-7 shrink-0 rounded-md border border-border px-2 text-[11px] hover:bg-accent"
|
||||
>
|
||||
Choose…
|
||||
</button>
|
||||
</div>
|
||||
</label>
|
||||
<label class="flex flex-col gap-1 text-xs">
|
||||
<span class="text-muted-foreground">Passphrase (optional)</span>
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { SavedConnection } from '@shared/types';
|
||||
import { ConnectionsService } from '../connections.service';
|
||||
import { DialogsService } from '../dialogs.service';
|
||||
import { PanelsService } from '../panels.service';
|
||||
import { RpcService } from '../rpc.service';
|
||||
|
||||
interface Draft {
|
||||
id: string;
|
||||
@@ -64,6 +65,7 @@ export class ConnectionManager {
|
||||
readonly store = inject(ConnectionsService);
|
||||
readonly dialogs = inject(DialogsService);
|
||||
readonly panels = inject(PanelsService);
|
||||
private readonly rpc = inject(RpcService);
|
||||
|
||||
readonly draft = signal<Draft | null>(null);
|
||||
readonly busy = signal(false);
|
||||
@@ -149,6 +151,11 @@ export class ConnectionManager {
|
||||
});
|
||||
}
|
||||
|
||||
async pickKeyFile(): Promise<void> {
|
||||
const res = await this.rpc.request.pickKeyFile({});
|
||||
if (res.ok && res.path) this.patch('privateKeyPath', res.path);
|
||||
}
|
||||
|
||||
openFolder(connections: SavedConnection[]): void {
|
||||
this.panels.openInNewTabs(connections);
|
||||
this.close();
|
||||
|
||||
Reference in New Issue
Block a user