mirror of
https://github.com/denoland/deno
synced 2024-10-12 11:02:29 +00:00
fix: hide progress bars when showing permission prompt (#17130)
Also adds download bytes progress when downloading remote specifiers. Closes #16860
This commit is contained in:
parent
5a8adc342b
commit
2ff27a1f93
|
@ -1,15 +1,17 @@
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use crate::args::CacheSetting;
|
use crate::args::CacheSetting;
|
||||||
|
use crate::auth_tokens::AuthToken;
|
||||||
use crate::auth_tokens::AuthTokens;
|
use crate::auth_tokens::AuthTokens;
|
||||||
use crate::cache::HttpCache;
|
use crate::cache::HttpCache;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
|
use crate::http_util;
|
||||||
use crate::http_util::resolve_redirect_from_response;
|
use crate::http_util::resolve_redirect_from_response;
|
||||||
use crate::http_util::CacheSemantics;
|
use crate::http_util::CacheSemantics;
|
||||||
use crate::http_util::FetchOnceArgs;
|
use crate::http_util::HeadersMap;
|
||||||
use crate::http_util::FetchOnceResult;
|
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
use crate::util::progress_bar::ProgressBar;
|
use crate::util::progress_bar::ProgressBar;
|
||||||
|
use crate::util::progress_bar::UpdateGuard;
|
||||||
use crate::util::text_encoding;
|
use crate::util::text_encoding;
|
||||||
|
|
||||||
use data_url::DataUrl;
|
use data_url::DataUrl;
|
||||||
|
@ -21,6 +23,7 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::futures;
|
use deno_core::futures;
|
||||||
use deno_core::futures::future::FutureExt;
|
use deno_core::futures::future::FutureExt;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
|
use deno_core::url::Url;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_runtime::deno_fetch::reqwest::header::HeaderValue;
|
use deno_runtime::deno_fetch::reqwest::header::HeaderValue;
|
||||||
use deno_runtime::deno_fetch::reqwest::header::ACCEPT;
|
use deno_runtime::deno_fetch::reqwest::header::ACCEPT;
|
||||||
|
@ -470,6 +473,7 @@ impl FileFetcher {
|
||||||
maybe_accept: maybe_accept.clone(),
|
maybe_accept: maybe_accept.clone(),
|
||||||
maybe_etag,
|
maybe_etag,
|
||||||
maybe_auth_token,
|
maybe_auth_token,
|
||||||
|
maybe_progress_guard: maybe_progress_guard.as_ref(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
|
@ -637,14 +641,30 @@ impl FileFetcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
enum FetchOnceResult {
|
||||||
|
Code(Vec<u8>, HeadersMap),
|
||||||
|
NotModified,
|
||||||
|
Redirect(Url, HeadersMap),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct FetchOnceArgs<'a> {
|
||||||
|
pub url: Url,
|
||||||
|
pub maybe_accept: Option<String>,
|
||||||
|
pub maybe_etag: Option<String>,
|
||||||
|
pub maybe_auth_token: Option<AuthToken>,
|
||||||
|
pub maybe_progress_guard: Option<&'a UpdateGuard>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Asynchronously fetches the given HTTP URL one pass only.
|
/// Asynchronously fetches the given HTTP URL one pass only.
|
||||||
/// If no redirect is present and no error occurs,
|
/// If no redirect is present and no error occurs,
|
||||||
/// yields Code(ResultPayload).
|
/// yields Code(ResultPayload).
|
||||||
/// If redirect occurs, does not follow and
|
/// If redirect occurs, does not follow and
|
||||||
/// yields Redirect(url).
|
/// yields Redirect(url).
|
||||||
async fn fetch_once(
|
async fn fetch_once<'a>(
|
||||||
http_client: &HttpClient,
|
http_client: &HttpClient,
|
||||||
args: FetchOnceArgs,
|
args: FetchOnceArgs<'a>,
|
||||||
) -> Result<FetchOnceResult, AnyError> {
|
) -> Result<FetchOnceResult, AnyError> {
|
||||||
let mut request = http_client.get_no_redirect(args.url.clone());
|
let mut request = http_client.get_no_redirect(args.url.clone());
|
||||||
|
|
||||||
|
@ -710,7 +730,11 @@ async fn fetch_once(
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = response.bytes().await?.to_vec();
|
let body = http_util::get_response_body_with_progress(
|
||||||
|
response,
|
||||||
|
args.maybe_progress_guard,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(FetchOnceResult::Code(body, result_headers))
|
Ok(FetchOnceResult::Code(body, result_headers))
|
||||||
}
|
}
|
||||||
|
@ -1760,6 +1784,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1787,6 +1812,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1815,6 +1841,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1837,6 +1864,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: Some("33a64df551425fcc55e".to_string()),
|
maybe_etag: Some("33a64df551425fcc55e".to_string()),
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1857,6 +1885,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1887,6 +1916,7 @@ mod tests {
|
||||||
maybe_accept: Some("application/json".to_string()),
|
maybe_accept: Some("application/json".to_string()),
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1913,6 +1943,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1953,6 +1984,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -1990,6 +2022,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -2025,6 +2058,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -2066,6 +2100,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -2110,6 +2145,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -2133,6 +2169,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: Some("33a64df551425fcc55e".to_string()),
|
maybe_etag: Some("33a64df551425fcc55e".to_string()),
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -2170,6 +2207,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -2200,6 +2238,7 @@ mod tests {
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_etag: None,
|
maybe_etag: None,
|
||||||
maybe_auth_token: None,
|
maybe_auth_token: None,
|
||||||
|
maybe_progress_guard: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
use crate::auth_tokens::AuthToken;
|
|
||||||
use crate::util::progress_bar::UpdateGuard;
|
use crate::util::progress_bar::UpdateGuard;
|
||||||
use crate::version::get_user_agent;
|
use crate::version::get_user_agent;
|
||||||
|
|
||||||
|
@ -218,21 +217,6 @@ impl CacheSemantics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
|
||||||
pub enum FetchOnceResult {
|
|
||||||
Code(Vec<u8>, HeadersMap),
|
|
||||||
NotModified,
|
|
||||||
Redirect(Url, HeadersMap),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct FetchOnceArgs {
|
|
||||||
pub url: Url,
|
|
||||||
pub maybe_accept: Option<String>,
|
|
||||||
pub maybe_etag: Option<String>,
|
|
||||||
pub maybe_auth_token: Option<AuthToken>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct HttpClient(reqwest::Client);
|
pub struct HttpClient(reqwest::Client);
|
||||||
|
|
||||||
|
@ -312,24 +296,9 @@ impl HttpClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(progress_guard) = progress_guard {
|
get_response_body_with_progress(response, progress_guard)
|
||||||
if let Some(total_size) = response.content_length() {
|
.await
|
||||||
progress_guard.set_total_size(total_size);
|
.map(Some)
|
||||||
let mut current_size = 0;
|
|
||||||
let mut data = Vec::with_capacity(total_size as usize);
|
|
||||||
let mut stream = response.bytes_stream();
|
|
||||||
while let Some(item) = stream.next().await {
|
|
||||||
let bytes = item?;
|
|
||||||
current_size += bytes.len() as u64;
|
|
||||||
progress_guard.set_position(current_size);
|
|
||||||
data.extend(bytes.into_iter());
|
|
||||||
}
|
|
||||||
return Ok(Some(data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let bytes = response.bytes().await?;
|
|
||||||
Ok(Some(bytes.into()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_redirected_response<U: reqwest::IntoUrl>(
|
async fn get_redirected_response<U: reqwest::IntoUrl>(
|
||||||
|
@ -358,6 +327,29 @@ impl HttpClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_response_body_with_progress(
|
||||||
|
response: reqwest::Response,
|
||||||
|
progress_guard: Option<&UpdateGuard>,
|
||||||
|
) -> Result<Vec<u8>, AnyError> {
|
||||||
|
if let Some(progress_guard) = progress_guard {
|
||||||
|
if let Some(total_size) = response.content_length() {
|
||||||
|
progress_guard.set_total_size(total_size);
|
||||||
|
let mut current_size = 0;
|
||||||
|
let mut data = Vec::with_capacity(total_size as usize);
|
||||||
|
let mut stream = response.bytes_stream();
|
||||||
|
while let Some(item) = stream.next().await {
|
||||||
|
let bytes = item?;
|
||||||
|
current_size += bytes.len() as u64;
|
||||||
|
progress_guard.set_position(current_size);
|
||||||
|
data.extend(bytes.into_iter());
|
||||||
|
}
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let bytes = response.bytes().await?;
|
||||||
|
Ok(bytes.into())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -260,6 +260,10 @@ pub fn main() {
|
||||||
util::windows::ensure_stdio_open();
|
util::windows::ensure_stdio_open();
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
colors::enable_ansi(); // For Windows 10
|
colors::enable_ansi(); // For Windows 10
|
||||||
|
deno_runtime::permissions::set_prompt_callbacks(
|
||||||
|
Box::new(util::draw_thread::DrawThread::hide),
|
||||||
|
Box::new(util::draw_thread::DrawThread::show),
|
||||||
|
);
|
||||||
|
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ impl Drop for DrawThreadGuard {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct InternalEntry {
|
struct InternalEntry {
|
||||||
priority: u8,
|
|
||||||
id: u16,
|
id: u16,
|
||||||
renderer: Arc<dyn DrawThreadRenderer>,
|
renderer: Arc<dyn DrawThreadRenderer>,
|
||||||
}
|
}
|
||||||
|
@ -69,6 +68,13 @@ static INTERNAL_STATE: Lazy<Arc<Mutex<InternalState>>> = Lazy::new(|| {
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static IS_TTY_WITH_CONSOLE_SIZE: Lazy<bool> = Lazy::new(|| {
|
||||||
|
atty::is(atty::Stream::Stderr)
|
||||||
|
&& console_size()
|
||||||
|
.map(|s| s.cols > 0 && s.rows > 0)
|
||||||
|
.unwrap_or(false)
|
||||||
|
});
|
||||||
|
|
||||||
/// The draw thread is responsible for rendering multiple active
|
/// The draw thread is responsible for rendering multiple active
|
||||||
/// `DrawThreadRenderer`s to stderr. It is global because the
|
/// `DrawThreadRenderer`s to stderr. It is global because the
|
||||||
/// concept of stderr in the process is also a global concept.
|
/// concept of stderr in the process is also a global concept.
|
||||||
|
@ -78,31 +84,17 @@ pub struct DrawThread;
|
||||||
impl DrawThread {
|
impl DrawThread {
|
||||||
/// Is using a draw thread supported.
|
/// Is using a draw thread supported.
|
||||||
pub fn is_supported() -> bool {
|
pub fn is_supported() -> bool {
|
||||||
atty::is(atty::Stream::Stderr)
|
// don't put the log level in the lazy because the
|
||||||
&& log::log_enabled!(log::Level::Info)
|
// log level may change as the application runs
|
||||||
&& console_size()
|
log::log_enabled!(log::Level::Info) && *IS_TTY_WITH_CONSOLE_SIZE
|
||||||
.map(|s| s.cols > 0 && s.rows > 0)
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a renderer to the draw thread with a given priority.
|
/// Adds a renderer to the draw thread.
|
||||||
/// Renderers are sorted by priority with higher priority
|
pub fn add_entry(renderer: Arc<dyn DrawThreadRenderer>) -> DrawThreadGuard {
|
||||||
/// entries appearing at the bottom of the screen.
|
|
||||||
pub fn add_entry(
|
|
||||||
priority: u8,
|
|
||||||
renderer: Arc<dyn DrawThreadRenderer>,
|
|
||||||
) -> DrawThreadGuard {
|
|
||||||
let internal_state = &*INTERNAL_STATE;
|
let internal_state = &*INTERNAL_STATE;
|
||||||
let mut internal_state = internal_state.lock();
|
let mut internal_state = internal_state.lock();
|
||||||
let id = internal_state.next_entry_id;
|
let id = internal_state.next_entry_id;
|
||||||
internal_state.entries.push(InternalEntry {
|
internal_state.entries.push(InternalEntry { id, renderer });
|
||||||
id,
|
|
||||||
priority,
|
|
||||||
renderer,
|
|
||||||
});
|
|
||||||
internal_state
|
|
||||||
.entries
|
|
||||||
.sort_by(|a, b| a.priority.cmp(&b.priority));
|
|
||||||
|
|
||||||
if internal_state.next_entry_id == u16::MAX {
|
if internal_state.next_entry_id == u16::MAX {
|
||||||
internal_state.next_entry_id = 0;
|
internal_state.next_entry_id = 0;
|
||||||
|
@ -116,16 +108,15 @@ impl DrawThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hides the draw thread.
|
/// Hides the draw thread.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn hide() {
|
pub fn hide() {
|
||||||
let internal_state = &*INTERNAL_STATE;
|
let internal_state = &*INTERNAL_STATE;
|
||||||
let mut internal_state = internal_state.lock();
|
let mut internal_state = internal_state.lock();
|
||||||
internal_state.hide = true;
|
internal_state.hide = true;
|
||||||
|
|
||||||
Self::clear_and_stop_draw_thread(&mut internal_state);
|
Self::clear_and_stop_draw_thread(&mut internal_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shows the draw thread if it was previously hidden.
|
/// Shows the draw thread if it was previously hidden.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn show() {
|
pub fn show() {
|
||||||
let internal_state = &*INTERNAL_STATE;
|
let internal_state = &*INTERNAL_STATE;
|
||||||
let mut internal_state = internal_state.lock();
|
let mut internal_state = internal_state.lock();
|
||||||
|
@ -159,7 +150,11 @@ impl DrawThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_start_draw_thread(internal_state: &mut InternalState) {
|
fn maybe_start_draw_thread(internal_state: &mut InternalState) {
|
||||||
if internal_state.has_draw_thread || internal_state.hide {
|
if internal_state.has_draw_thread
|
||||||
|
|| internal_state.hide
|
||||||
|
|| internal_state.entries.is_empty()
|
||||||
|
|| !DrawThread::is_supported()
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +163,7 @@ impl DrawThread {
|
||||||
|
|
||||||
let drawer_id = internal_state.drawer_id;
|
let drawer_id = internal_state.drawer_id;
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let mut previous_size = console_size().unwrap();
|
let mut previous_size = console_size();
|
||||||
loop {
|
loop {
|
||||||
let mut delay_ms = 120;
|
let mut delay_ms = 120;
|
||||||
{
|
{
|
||||||
|
@ -182,6 +177,10 @@ impl DrawThread {
|
||||||
internal_state.entries.clone()
|
internal_state.entries.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// this should always be set, but have the code handle
|
||||||
|
// it not being for some reason
|
||||||
|
let size = console_size();
|
||||||
|
|
||||||
// Call into the renderers outside the lock to prevent a potential
|
// Call into the renderers outside the lock to prevent a potential
|
||||||
// deadlock between our internal state lock and the renderers
|
// deadlock between our internal state lock and the renderers
|
||||||
// internal state lock.
|
// internal state lock.
|
||||||
|
@ -194,13 +193,12 @@ impl DrawThread {
|
||||||
// which attempts to acquire the other thread's Render's internal
|
// which attempts to acquire the other thread's Render's internal
|
||||||
// lock causing a deadlock
|
// lock causing a deadlock
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
let size = console_size().unwrap();
|
|
||||||
if size != previous_size {
|
if size != previous_size {
|
||||||
// means the user is actively resizing the console...
|
// means the user is actively resizing the console...
|
||||||
// wait a little bit until they stop resizing
|
// wait a little bit until they stop resizing
|
||||||
previous_size = size;
|
previous_size = size;
|
||||||
delay_ms = 200;
|
delay_ms = 200;
|
||||||
} else {
|
} else if let Some(size) = size {
|
||||||
let mut should_new_line_next = false;
|
let mut should_new_line_next = false;
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
let new_text = entry.renderer.render(&size);
|
let new_text = entry.renderer.render(&size);
|
||||||
|
@ -210,23 +208,23 @@ impl DrawThread {
|
||||||
should_new_line_next = !new_text.is_empty();
|
should_new_line_next = !new_text.is_empty();
|
||||||
text.push_str(&new_text);
|
text.push_str(&new_text);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// now reacquire the lock, ensure we should still be drawing, then
|
// now reacquire the lock, ensure we should still be drawing, then
|
||||||
// output the text
|
// output the text
|
||||||
{
|
{
|
||||||
let internal_state = &*INTERNAL_STATE;
|
let internal_state = &*INTERNAL_STATE;
|
||||||
let mut internal_state = internal_state.lock();
|
let mut internal_state = internal_state.lock();
|
||||||
if internal_state.should_exit_draw_thread(drawer_id) {
|
if internal_state.should_exit_draw_thread(drawer_id) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
internal_state.static_text.eprint_with_size(
|
||||||
|
&text,
|
||||||
|
console_static_text::ConsoleSize {
|
||||||
|
cols: Some(size.cols as u16),
|
||||||
|
rows: Some(size.rows as u16),
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
internal_state.static_text.eprint_with_size(
|
|
||||||
&text,
|
|
||||||
console_static_text::ConsoleSize {
|
|
||||||
cols: Some(size.cols as u16),
|
|
||||||
rows: Some(size.rows as u16),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ mod renderer;
|
||||||
// Inspired by Indicatif, but this custom implementation allows
|
// Inspired by Indicatif, but this custom implementation allows
|
||||||
// for more control over what's going on under the hood.
|
// for more control over what's going on under the hood.
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct UpdateGuard {
|
pub struct UpdateGuard {
|
||||||
maybe_entry: Option<ProgressBarEntry>,
|
maybe_entry: Option<ProgressBarEntry>,
|
||||||
}
|
}
|
||||||
|
@ -183,7 +184,7 @@ impl ProgressBarInner {
|
||||||
{
|
{
|
||||||
internal_state.start_time = SystemTime::now();
|
internal_state.start_time = SystemTime::now();
|
||||||
internal_state.draw_thread_guard =
|
internal_state.draw_thread_guard =
|
||||||
Some(DrawThread::add_entry(0, Arc::new(self.clone())));
|
Some(DrawThread::add_entry(Arc::new(self.clone())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,11 @@ pub fn permission_prompt(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_prompt_callbacks(
|
pub fn set_prompt_callbacks(
|
||||||
before_callback: Option<PromptCallback>,
|
before_callback: PromptCallback,
|
||||||
after_callback: Option<PromptCallback>,
|
after_callback: PromptCallback,
|
||||||
) {
|
) {
|
||||||
*MAYBE_BEFORE_PROMPT_CALLBACK.lock() = before_callback;
|
*MAYBE_BEFORE_PROMPT_CALLBACK.lock() = Some(before_callback);
|
||||||
*MAYBE_AFTER_PROMPT_CALLBACK.lock() = after_callback;
|
*MAYBE_AFTER_PROMPT_CALLBACK.lock() = Some(after_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PromptCallback = Box<dyn FnMut() + Send + Sync>;
|
pub type PromptCallback = Box<dyn FnMut() + Send + Sync>;
|
||||||
|
|
Loading…
Reference in a new issue