Skip to content

Commit 0964e69

Browse files
Faizanqalokedesai
andauthored
Open "Default App" files in the running Warp channel (#9285)
## Description Fixes #9189. When the user has multiple Warp channels installed (e.g. Stable + Preview), LaunchServices may register the Stable build as the default handler for common file types. The "Open File → Default App" path then resolves to that sibling channel and hands files to Stable even when the user is running Preview. The bug sits at `app/src/util/file/external_editor/mac.rs:336`: `default_app_to_open_path` returns the LaunchServices default, `Editor::new_from_identifier` has no `dev.warp.*` variants so the result is dropped, and we fall through to `ctx.open_file_path(full_path)` which is `[NSWorkspace openURL:]`. NSWorkspace then routes via the same default-app it just resolved, so the file lands in the other Warp. The fix detects this case after the existing editor-resolution path: if the system default is a Warp bundle other than the running channel's bundle (`ChannelState::app_id()`), open the file with the running channel's bundle directly via `/usr/bin/open -b`. Non-Warp defaults (VS Code, TextEdit, etc.) are unaffected, and when the system default already matches the running channel the override is skipped. ## Testing Added 2 unit tests in `app/src/util/file/external_editor/mac.rs` for the new `is_warp_bundle` helper: - `dev.warp.{Warp,WarpDev,WarpPreview,WarpOss}` → matches - `com.microsoft.VSCode`, `com.apple.TextEdit`, `dev.zed.Zed`, `invalid`, empty → does not match Both pass under `cargo test -p warp --lib util::file::external_editor::mac::tests`. The end-to-end behavior (file actually landing in the running channel) requires a multi-channel macOS install to verify; I didn't manually reproduce because the build I have access to is the OSS channel only. Logic is small enough that a Warp dev with Stable + Preview side-by-side should be able to confirm in seconds. ## Agent Mode - [ ] Warp Agent Mode - This PR was created via Warp's AI Agent Mode ## Changelog Entries for Stable CHANGELOG-BUG-FIX: `Open File → Default App` now opens files in the running Warp channel instead of routing to a different installed Warp. --------- Co-authored-by: Aloke Desai <aloke@warp.dev>
1 parent 0fca61d commit 0964e69

2 files changed

Lines changed: 54 additions & 0 deletions

File tree

‎app/src/util/file/external_editor/mac.rs‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use cocoa::{
99
foundation::{NSAutoreleasePool, NSString},
1010
};
1111
use command::r#async::Command;
12+
use warp_core::{channel::ChannelState, AppId};
1213
use warpui::{platform::mac::make_nsstring, ApplicationBundleInfo};
1314

1415
use super::*;
@@ -344,10 +345,41 @@ pub fn open_file_path_with_line_and_col(
344345
return;
345346
}
346347
}
348+
349+
// NSWorkspace's default-app routing can hand files to a sibling
350+
// Warp channel (e.g. Stable handling files while Preview is running).
351+
// When the resolved default is a different Warp, open with the
352+
// running channel's bundle directly.
353+
let bundle_id = unsafe { default_app_to_open_path(full_path) };
354+
if let Some(bundle_id) = bundle_id.as_deref() {
355+
let current = ChannelState::app_id().to_string();
356+
if bundle_id != current
357+
&& is_warp_bundle(bundle_id)
358+
&& open_with_bundle(&current, full_path)
359+
{
360+
return;
361+
}
362+
}
347363
}
348364
ctx.open_file_path(full_path);
349365
}
350366

367+
fn is_warp_bundle(bundle_id: &str) -> bool {
368+
AppId::parse(bundle_id)
369+
.map(|id| id.qualifier() == "dev" && id.organization() == "warp")
370+
.unwrap_or(false)
371+
}
372+
373+
fn open_with_bundle(bundle_id: &str, path: &Path) -> bool {
374+
// Wait for `open` to exit; a non-zero status needs to bubble up so
375+
// the caller's ctx.open_file_path fallback still runs.
376+
command::blocking::Command::new("/usr/bin/open")
377+
.args(["-b", bundle_id])
378+
.arg(path)
379+
.status()
380+
.is_ok_and(|s| s.success())
381+
}
382+
351383
// Get the Mac default app for opening the file path.
352384
//
353385
// The NSString returned by `-[NSBundle bundleIdentifier]` is autoreleased by
@@ -368,3 +400,7 @@ unsafe fn default_app_to_open_path(file_path: &Path) -> Option<String> {
368400
pool.drain();
369401
result
370402
}
403+
404+
#[cfg(test)]
405+
#[path = "mac_test.rs"]
406+
mod tests;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use super::is_warp_bundle;
2+
3+
#[test]
4+
fn is_warp_bundle_recognises_warp_channels() {
5+
assert!(is_warp_bundle("dev.warp.Warp"));
6+
assert!(is_warp_bundle("dev.warp.WarpDev"));
7+
assert!(is_warp_bundle("dev.warp.WarpPreview"));
8+
assert!(is_warp_bundle("dev.warp.WarpOss"));
9+
}
10+
11+
#[test]
12+
fn is_warp_bundle_rejects_other_apps() {
13+
assert!(!is_warp_bundle("com.microsoft.VSCode"));
14+
assert!(!is_warp_bundle("com.apple.TextEdit"));
15+
assert!(!is_warp_bundle("dev.zed.Zed"));
16+
assert!(!is_warp_bundle("invalid"));
17+
assert!(!is_warp_bundle(""));
18+
}

0 commit comments

Comments
 (0)