mirror of
https://github.com/localsend/localsend.git
synced 2026-08-07 07:14:52 +00:00
fix(cli): blink after selecting device
This commit is contained in:
+10
-4
@@ -80,11 +80,17 @@ impl App {
|
||||
return !self.preselected.is_empty();
|
||||
}
|
||||
DeviceListOutcome::Send { fingerprint } => {
|
||||
self.close_device_list();
|
||||
if !self.preselected.is_empty() {
|
||||
self.start_send(&fingerprint, self.preselected.clone());
|
||||
} else if let Some(device) = self.discovery.device_by_fingerprint(&fingerprint) {
|
||||
if self.preselected.is_empty()
|
||||
&& let Some(device) = self.discovery.device_by_fingerprint(&fingerprint)
|
||||
{
|
||||
// The list stays open until the picker takes over its
|
||||
// alternate screen, so the main screen never shows.
|
||||
self.open_picker(device);
|
||||
} else {
|
||||
self.close_device_list();
|
||||
if !self.preselected.is_empty() {
|
||||
self.start_send(&fingerprint, self.preselected.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
DeviceListOutcome::Pair { fingerprint } => self.pair(&fingerprint),
|
||||
|
||||
+25
-4
@@ -46,18 +46,39 @@ impl App {
|
||||
|
||||
pub(super) fn open_picker(&mut self, device: StatefulDevice) {
|
||||
if self.send.is_some() {
|
||||
self.close_device_list();
|
||||
self.ui.log(Category::Send, "A send is already in progress");
|
||||
return;
|
||||
}
|
||||
match Picker::open(
|
||||
device.device.fingerprint.clone(),
|
||||
device.device.alias.clone(),
|
||||
) {
|
||||
// When the device list is open, the picker takes over its alternate
|
||||
// screen — leaving and re-entering it would flash the main screen.
|
||||
let handoff = match self.device_list.take() {
|
||||
Some(list) => {
|
||||
list.close_keeping_screen();
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
};
|
||||
let opened = match handoff {
|
||||
true => Picker::open_on_alternate_screen(
|
||||
device.device.fingerprint.clone(),
|
||||
device.device.alias.clone(),
|
||||
),
|
||||
false => Picker::open(
|
||||
device.device.fingerprint.clone(),
|
||||
device.device.alias.clone(),
|
||||
),
|
||||
};
|
||||
match opened {
|
||||
Ok(picker) => {
|
||||
self.ui.suspend();
|
||||
self.picker = Some(picker);
|
||||
}
|
||||
Err(err) => {
|
||||
if handoff {
|
||||
crate::util::leave_alternate_screen();
|
||||
self.ui.resume();
|
||||
}
|
||||
self.ui.log(
|
||||
Category::Send,
|
||||
&format!(
|
||||
|
||||
@@ -86,6 +86,13 @@ impl DeviceList {
|
||||
util::leave_alternate_screen();
|
||||
}
|
||||
|
||||
/// Drops the list but stays on the (cleared) alternate screen, handing it
|
||||
/// over to the next modal (see [crate::picker::Picker::open_on_alternate_screen]).
|
||||
/// That modal's close leaves the screen.
|
||||
pub fn close_keeping_screen(self) {
|
||||
util::clear_alternate_screen();
|
||||
}
|
||||
|
||||
/// Replaces the rows (discovery goes on while the list is open), keeping
|
||||
/// the highlight on the same device where possible.
|
||||
pub fn set_rows(&mut self, rows: Vec<Row>) {
|
||||
|
||||
@@ -70,6 +70,19 @@ impl Picker {
|
||||
pub fn open(fingerprint: String, alias: String) -> anyhow::Result<Self> {
|
||||
let explorer = FileExplorer::new()?;
|
||||
util::enter_alternate_screen()?;
|
||||
Self::show(fingerprint, alias, explorer)
|
||||
}
|
||||
|
||||
/// Shows the picker on the blank alternate screen a previous modal left
|
||||
/// behind (see [crate::device_list::DeviceList::close_keeping_screen]);
|
||||
/// [Picker::close] leaves it as usual. When this fails, the caller must
|
||||
/// leave the alternate screen itself.
|
||||
pub fn open_on_alternate_screen(fingerprint: String, alias: String) -> anyhow::Result<Self> {
|
||||
let explorer = FileExplorer::new()?;
|
||||
Self::show(fingerprint, alias, explorer)
|
||||
}
|
||||
|
||||
fn show(fingerprint: String, alias: String, explorer: FileExplorer) -> anyhow::Result<Self> {
|
||||
let terminal = Terminal::new(CrosstermBackend::new(std::io::stdout()))?;
|
||||
let mut picker = Self {
|
||||
fingerprint,
|
||||
|
||||
@@ -32,6 +32,17 @@ pub fn leave_alternate_screen() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Clears the alternate screen without leaving it, for handing it over from
|
||||
/// one modal to the next — leaving and re-entering would flash the main
|
||||
/// screen in between.
|
||||
pub fn clear_alternate_screen() {
|
||||
let _ = execute!(
|
||||
std::io::stdout(),
|
||||
Clear(ClearType::All),
|
||||
cursor::MoveTo(0, 0)
|
||||
);
|
||||
}
|
||||
|
||||
pub fn format_bytes(bytes: u64) -> String {
|
||||
const UNITS: [&str; 5] = ["B", "KB", "MB", "GB", "TB"];
|
||||
let mut value = bytes as f64;
|
||||
|
||||
Reference in New Issue
Block a user