Skip to content

Commit fab94a3

Browse files
axpnetaeroftp[bot]claude
committed
fix(import): route a double-clicked .aeroftp export to the import flow
Only .aerovault and .aeroftp-keystore were forwarded from the single-instance and macOS first-launch argv handlers. A plain .aeroftp server-profiles export was a registered file association, so it opened the app, but no event was emitted and importAeroFtpProfileFile() was never called: the file dead-ended on a bare window (issue #214 pt.4a, plain .aeroftp). Emit servers-open-file from both handlers and add a frontend listener that drives the existing password-prompt import flow. ends_with(".aeroftp") does not match ".aeroftp-keystore", and the listener additionally guards !endsWith('.aeroftp-keystore'), so keystore files never reach the profiles importer. refs #214 Co-Authored-By: aeroftp[bot] <aeroftp[bot]@users.noreply.github.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 40388f0 commit fab94a3

2 files changed

Lines changed: 49 additions & 0 deletions

File tree

src-tauri/src/lib.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13863,6 +13863,24 @@ pub fn run() {
1386313863
}
1386413864
}
1386513865
}
13866+
// Forward a double-clicked plain .aeroftp server-profiles export
13867+
// so it lands on the import/password screen instead of just
13868+
// raising the window (issue #214 pt.4a, plain .aeroftp).
13869+
// ends_with(".aeroftp") does not match ".aeroftp-keystore", so
13870+
// there is no collision with the block above.
13871+
if let Some(sp_arg) = argv.iter().skip(1).find(|a| a.ends_with(".aeroftp")) {
13872+
if let Ok(canonical) = std::fs::canonicalize(sp_arg) {
13873+
let meta = std::fs::symlink_metadata(&canonical);
13874+
if meta.map(|m| m.is_file()).unwrap_or(false) {
13875+
if let Some(window) = app.get_webview_window("main") {
13876+
let _ = window.emit(
13877+
"servers-open-file",
13878+
canonical.to_string_lossy().to_string(),
13879+
);
13880+
}
13881+
}
13882+
}
13883+
}
1386613884
}))
1386713885
.plugin(
1386813886
tauri_plugin_window_state::Builder::new()
@@ -14516,6 +14534,25 @@ pub fn run() {
1451614534
}
1451714535
}
1451814536
}
14537+
// Same for a double-clicked plain .aeroftp server-profiles
14538+
// export on first launch so it routes to the import/password
14539+
// screen instead of a bare window (issue #214 pt.4a, plain
14540+
// .aeroftp). ends_with(".aeroftp") excludes ".aeroftp-keystore".
14541+
if let Some(sp_arg) = args.iter().skip(1).find(|a| a.ends_with(".aeroftp")) {
14542+
if let Ok(canonical) = std::fs::canonicalize(sp_arg) {
14543+
let meta = std::fs::symlink_metadata(&canonical);
14544+
if meta.map(|m| m.is_file()).unwrap_or(false) {
14545+
let sp_path = canonical.to_string_lossy().to_string();
14546+
let app_handle = app.handle().clone();
14547+
std::thread::spawn(move || {
14548+
std::thread::sleep(std::time::Duration::from_millis(1500));
14549+
if let Some(window) = app_handle.get_webview_window("main") {
14550+
let _ = window.emit("servers-open-file", sp_path);
14551+
}
14552+
});
14553+
}
14554+
}
14555+
}
1451914556
}
1452014557

1452114558
Ok(())

src/App.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3212,6 +3212,18 @@ interface UpdateVerificationInfo {
32123212
}
32133213
});
32143214

3215+
// OS file association: a double-clicked plain .aeroftp server-profiles
3216+
// export opens the import flow (password prompt -> import_server_profiles)
3217+
// instead of just raising the window (issue #214 pt.4a, plain .aeroftp).
3218+
// The explicit !endsWith('.aeroftp-keystore') guard keeps a keystore file
3219+
// from ever reaching the profiles importer, mirroring the backend filter.
3220+
useTauriListener<string>('servers-open-file', (event) => {
3221+
const p = event.payload;
3222+
if (p && p.endsWith('.aeroftp') && !p.endsWith('.aeroftp-keystore')) {
3223+
importAeroFtpProfileFile(p);
3224+
}
3225+
});
3226+
32153227
// Auto-enable debug mode when Cyber theme is active, disable when switching away
32163228
useEffect(() => {
32173229
const isCyber = getEffectiveTheme(theme, isDark) === 'cyber';

0 commit comments

Comments
 (0)