fix(macos/ios): prepend the Downloads dir to the suggested download path (#1599)

* fix(macos/ios): prepend the Downloads dir to the suggested download path

* typo

* numerate files
This commit is contained in:
Fabian-Lars
2025-08-13 20:10:15 +02:00
committed by GitHub
parent eb562ca993
commit af1cc1334a
5 changed files with 32 additions and 15 deletions

View File

@@ -2,4 +2,4 @@
"wry": "patch"
---
On Linux, the `download_started_handler` will now get the correct suggested destination path.
On Linux, macOS and iOS, the `download_started_handler` will now get the correct suggested destination path.

View File

@@ -94,6 +94,7 @@ features = [
[target.'cfg(target_vendor = "apple")'.dependencies]
url = "2.5"
dirs = "6"
block2 = "0.6"
objc2 = { version = "0.6", features = [
"exception",

View File

@@ -323,10 +323,10 @@ impl WebContextExt for super::WebContext {
let uri = uri.to_string();
if let Some(download_started_handler) = download_started_handler.borrow_mut().as_mut() {
let mut download_location =
let mut download_destination =
dirs::download_dir().unwrap_or_else(|| current_dir().unwrap_or_default());
let (mut suggested_filename, mut ext) = suggested_filename
let (mut suggested_filename, ext) = suggested_filename
.split_once('.')
.map(|(base, ext)| (base, format!(".{ext}")))
.unwrap_or((suggested_filename, "".to_string()));
@@ -337,17 +337,17 @@ impl WebContextExt for super::WebContext {
suggested_filename = "Unknown";
}
download_location.push(format!("{suggested_filename}{ext}"));
download_destination.push(format!("{suggested_filename}{ext}"));
// WebView2 does not overwrite files but appends numbers
let mut counter = 1;
while download_location.exists() {
download_location.set_file_name(format!("{suggested_filename} ({counter}){ext}"));
while download_destination.exists() {
download_destination.set_file_name(format!("{suggested_filename} ({counter}){ext}"));
counter += 1;
}
if download_started_handler(uri, &mut download_location) {
download.set_destination(&download_location.to_string_lossy());
if download_started_handler(uri, &mut download_destination) {
download.set_destination(&download_destination.to_string_lossy());
} else {
download.cancel();
}

View File

@@ -32,10 +32,10 @@ define_class!(
&self,
download: &WKDownload,
response: &NSURLResponse,
suggested_path: &NSString,
suggested_filename: &NSString,
handler: &block2::Block<dyn Fn(*const NSURL)>,
) {
download_policy(self, download, response, suggested_path, handler);
download_policy(self, download, response, suggested_filename, handler);
}
#[unsafe(method(downloadDidFinish:))]

View File

@@ -1,4 +1,4 @@
use std::{path::PathBuf, ptr::null_mut};
use std::{env::current_dir, ptr::null_mut};
use objc2::{rc::Retained, runtime::ProtocolObject, DeclaredClass};
use objc2_foundation::{NSData, NSError, NSString, NSURLResponse, NSURL};
@@ -47,20 +47,36 @@ pub(crate) fn download_policy(
this: &WryDownloadDelegate,
download: &WKDownload,
_response: &NSURLResponse,
suggested_path: &NSString,
suggested_filename: &NSString,
completion_handler: &block2::Block<dyn Fn(*const NSURL)>,
) {
unsafe {
let request = download.originalRequest().unwrap();
let url = request.URL().unwrap().absoluteString().unwrap();
let mut path = PathBuf::from(suggested_path.to_string());
let suggested_filename = suggested_filename.to_string();
let mut download_destination =
dirs::download_dir().unwrap_or_else(|| current_dir().unwrap_or_default());
download_destination.push(&suggested_filename);
let (suggested_filename, ext) = suggested_filename
.split_once('.')
.map(|(base, ext)| (base, format!(".{ext}")))
.unwrap_or((&suggested_filename, "".to_string()));
// WebView2 does not overwrite files but appends numbers
let mut counter = 1;
while download_destination.exists() {
download_destination.set_file_name(format!("{suggested_filename} ({counter}){ext}"));
counter += 1;
}
let started_fn = &this.ivars().started;
if let Some(started_fn) = started_fn {
let mut started_fn = started_fn.borrow_mut();
match started_fn(url.to_string().to_string(), &mut path) {
match started_fn(url.to_string().to_string(), &mut download_destination) {
true => {
let path = NSString::from_str(&path.display().to_string());
let path = NSString::from_str(&download_destination.display().to_string());
let ns_url = NSURL::fileURLWithPath_isDirectory(&path, false);
(*completion_handler).call((Retained::as_ptr(&ns_url),))
}