@@ -2,11 +2,13 @@ use std::{mem, time::{Duration, Instant}};
22
33use anyhow:: Result ;
44use futures:: { StreamExt , stream:: FuturesUnordered } ;
5+ use hashbrown:: HashSet ;
56use tokio:: sync:: oneshot;
6- use yazi_fs:: File ;
7- use yazi_macro:: { act, succ} ;
8- use yazi_parser:: mgr:: DownloadOpt ;
9- use yazi_shared:: data:: Data ;
7+ use yazi_fs:: { File , FsUrl , provider:: { Provider , local:: Local } } ;
8+ use yazi_macro:: succ;
9+ use yazi_parser:: mgr:: { DownloadOpt , OpenOpt } ;
10+ use yazi_proxy:: MgrProxy ;
11+ use yazi_shared:: { data:: Data , url:: UrlCow } ;
1012use yazi_vfs:: VfsFile ;
1113
1214use crate :: { Actor , Ctx } ;
@@ -19,26 +21,30 @@ impl Actor for Download {
1921 const NAME : & str = "download" ;
2022
2123 fn act ( cx : & mut Ctx , opt : Self :: Options ) -> Result < Data > {
22- act ! ( mgr: escape_visual, cx) ?;
23-
24- let mut wg1 = FuturesUnordered :: new ( ) ;
25- for url in opt. urls {
26- let ( tx, rx) = oneshot:: channel ( ) ;
27- cx. tasks . scheduler . file_download ( url. to_owned ( ) , Some ( tx) ) ;
28- wg1. push ( async move { ( rx. await == Ok ( true ) , url) } ) ;
29- }
30-
24+ let cwd = cx. cwd ( ) . clone ( ) ;
3125 let scheduler = cx. tasks . scheduler . clone ( ) ;
26+
3227 tokio:: spawn ( async move {
28+ Self :: prepare ( & opt. urls ) . await ;
29+
30+ let mut wg1 = FuturesUnordered :: new ( ) ;
31+ for url in opt. urls {
32+ let ( tx, rx) = oneshot:: channel ( ) ;
33+ scheduler. file_download ( url. to_owned ( ) , Some ( tx) ) ;
34+ wg1. push ( async move { ( rx. await == Ok ( false ) , url) } ) ;
35+ }
36+
3337 let mut wg2 = vec ! [ ] ;
38+ let mut urls = Vec :: with_capacity ( wg1. len ( ) ) ;
3439 let mut files = Vec :: with_capacity ( wg1. len ( ) ) ;
3540 let mut instant = Instant :: now ( ) ;
3641 while let Some ( ( success, url) ) = wg1. next ( ) . await {
3742 if !success {
3843 continue ;
3944 }
4045
41- let Ok ( f) = File :: new ( url) . await else { continue } ;
46+ let Ok ( f) = File :: new ( & url) . await else { continue } ;
47+ urls. push ( url) ;
4248 files. push ( f) ;
4349
4450 if instant. elapsed ( ) >= Duration :: from_secs ( 1 ) {
@@ -50,9 +56,29 @@ impl Actor for Download {
5056 if !files. is_empty ( ) {
5157 wg2. push ( scheduler. fetch_mimetype ( files) ) ;
5258 }
53- futures:: future:: join_all ( wg2) . await ;
59+ if futures:: future:: join_all ( wg2) . await . into_iter ( ) . any ( |b| !b) {
60+ return ;
61+ }
62+ if opt. open && !urls. is_empty ( ) {
63+ MgrProxy :: open ( OpenOpt {
64+ cwd : Some ( cwd. into ( ) ) ,
65+ targets : urls,
66+ interactive : false ,
67+ hovered : false ,
68+ } ) ;
69+ }
5470 } ) ;
5571
5672 succ ! ( ) ;
5773 }
5874}
75+
76+ impl Download {
77+ async fn prepare ( urls : & [ UrlCow < ' _ > ] ) {
78+ let roots: HashSet < _ > = urls. iter ( ) . filter_map ( |u| u. cache_root ( ) ) . collect ( ) ;
79+ for mut root in roots {
80+ root. push ( "%lock" ) ;
81+ Local . create_dir_all ( root) . await . ok ( ) ;
82+ }
83+ }
84+ }
0 commit comments