open_file: file associations, default editor and 'Open with' dialog

- New open_file IPC message: resolves [open_with] extension mapping,
  falls back to default_editor for known text formats, otherwise opens
  an 'Öppna med' dialog where the user types a command (live preview
  of the full command line, path tail-truncated so the extension stays
  visible) and chooses open-once or save-as-default for the extension
  (persisted to [open_with] in config.toml)
- default_editor configurable in the settings dialog (new Editor row
  with inline text editing) and in config.toml; '{}' in commands is
  replaced with the shell-quoted path
- Documented in SOCKET_API.md; integration suite covers dialog →
  save-association → direct open (38/38)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 20:33:07 +02:00
parent 4cc33cf62c
commit 10ef87879a
7 changed files with 375 additions and 14 deletions

View File

@@ -597,6 +597,9 @@ fn handle_ipc_event(
format!("[Popup: {}]", &message[..message.len().min(20)])
}
WindowContent::Settings { .. } => "[Inställningar]".to_string(),
WindowContent::OpenWith { path, .. } => {
format!("[Öppna: {}]", path)
}
};
Some(WindowInfo {
id: w.id,
@@ -615,6 +618,14 @@ fn handle_ipc_event(
ClientMessage::CloseWindow { window_id, .. } => {
app.close_window_pub(window_id);
}
ClientMessage::OpenFile { path, request_id } => {
let window_id = app.open_file(&path);
app.ipc_out.push(AppIpcOut::WindowOpened {
client_id,
request_id,
window_id,
});
}
ClientMessage::SetBackground { path, save, request_id } => {
app.config.background_image = path.clone();
if save {