mirror of
https://github.com/NotAShelf/stash.git
synced 2026-04-13 14:33:47 +00:00
commands: prevent usize underflow when navigating empty entry list
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I0432dcc88b22226772f6bb6e05cc64d36a6a6964
This commit is contained in:
parent
20b6a12461
commit
3165543580
1 changed files with 85 additions and 83 deletions
|
|
@ -247,10 +247,13 @@ impl SqliteClipboardDb {
|
||||||
.map_err(|e| StashError::ListDecode(e.to_string().into()))?
|
.map_err(|e| StashError::ListDecode(e.to_string().into()))?
|
||||||
&& let Event::Key(key) = event::read()
|
&& let Event::Key(key) = event::read()
|
||||||
.map_err(|e| StashError::ListDecode(e.to_string().into()))?
|
.map_err(|e| StashError::ListDecode(e.to_string().into()))?
|
||||||
{
|
{
|
||||||
match (key.code, key.modifiers) {
|
match (key.code, key.modifiers) {
|
||||||
(KeyCode::Char('q') | KeyCode::Esc, _) => break,
|
(KeyCode::Char('q') | KeyCode::Esc, _) => break,
|
||||||
(KeyCode::Down | KeyCode::Char('j'), _) => {
|
(KeyCode::Down | KeyCode::Char('j'), _) => {
|
||||||
|
if entries.is_empty() {
|
||||||
|
state.select(None);
|
||||||
|
} else {
|
||||||
let i = match state.selected() {
|
let i = match state.selected() {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
if i >= entries.len() - 1 {
|
if i >= entries.len() - 1 {
|
||||||
|
|
@ -262,8 +265,12 @@ impl SqliteClipboardDb {
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
state.select(Some(i));
|
state.select(Some(i));
|
||||||
},
|
}
|
||||||
(KeyCode::Up | KeyCode::Char('k'), _) => {
|
},
|
||||||
|
(KeyCode::Up | KeyCode::Char('k'), _) => {
|
||||||
|
if entries.is_empty() {
|
||||||
|
state.select(None);
|
||||||
|
} else {
|
||||||
let i = match state.selected() {
|
let i = match state.selected() {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
|
@ -275,94 +282,89 @@ impl SqliteClipboardDb {
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
state.select(Some(i));
|
state.select(Some(i));
|
||||||
},
|
}
|
||||||
(KeyCode::Enter, _) => {
|
},
|
||||||
if let Some(idx) = state.selected()
|
(KeyCode::Enter, _) => {
|
||||||
&& let Some((id, ..)) = entries.get(idx) {
|
if let Some(idx) = state.selected()
|
||||||
match self.copy_entry(*id) {
|
&& let Some((id, ..)) = entries.get(idx)
|
||||||
Ok((new_id, contents, mime)) => {
|
{
|
||||||
if new_id != *id {
|
match self.copy_entry(*id) {
|
||||||
entries[idx] = (
|
Ok((new_id, contents, mime)) => {
|
||||||
new_id,
|
if new_id != *id {
|
||||||
entries[idx].1.clone(),
|
entries[idx] = (
|
||||||
entries[idx].2.clone(),
|
new_id,
|
||||||
);
|
entries[idx].1.clone(),
|
||||||
}
|
entries[idx].2.clone(),
|
||||||
let opts = Options::new();
|
);
|
||||||
let mime_type = match mime {
|
}
|
||||||
Some(ref m) if m == "text/plain" => MimeType::Text,
|
let opts = Options::new();
|
||||||
Some(ref m) => {
|
let mime_type = match mime {
|
||||||
MimeType::Specific(m.clone().to_owned())
|
Some(ref m) if m == "text/plain" => MimeType::Text,
|
||||||
},
|
Some(ref m) => MimeType::Specific(m.clone().to_owned()),
|
||||||
None => MimeType::Text,
|
None => MimeType::Text,
|
||||||
};
|
};
|
||||||
let copy_result = opts.copy(
|
let copy_result = opts
|
||||||
Source::Bytes(contents.clone().into()),
|
.copy(Source::Bytes(contents.clone().into()), mime_type);
|
||||||
mime_type,
|
match copy_result {
|
||||||
);
|
Ok(()) => {
|
||||||
match copy_result {
|
|
||||||
Ok(()) => {
|
|
||||||
let _ = Notification::new()
|
|
||||||
.summary("Stash")
|
|
||||||
.body("Copied entry to clipboard")
|
|
||||||
.show();
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
log::error!(
|
|
||||||
"Failed to copy entry to clipboard: {e}"
|
|
||||||
);
|
|
||||||
let _ = Notification::new()
|
|
||||||
.summary("Stash")
|
|
||||||
.body(&format!(
|
|
||||||
"Failed to copy to clipboard: {e}"
|
|
||||||
))
|
|
||||||
.show();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Failed to fetch entry {id}: {e}");
|
|
||||||
let _ = Notification::new()
|
let _ = Notification::new()
|
||||||
.summary("Stash")
|
.summary("Stash")
|
||||||
.body(&format!("Failed to fetch entry: {e}"))
|
.body("Copied entry to clipboard")
|
||||||
|
.show();
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Failed to copy entry to clipboard: {e}");
|
||||||
|
let _ = Notification::new()
|
||||||
|
.summary("Stash")
|
||||||
|
.body(&format!("Failed to copy to clipboard: {e}"))
|
||||||
.show();
|
.show();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
Err(e) => {
|
||||||
(KeyCode::Char('D'), KeyModifiers::SHIFT) => {
|
log::error!("Failed to fetch entry {id}: {e}");
|
||||||
if let Some(idx) = state.selected()
|
|
||||||
&& let Some((id, ..)) = entries.get(idx) {
|
|
||||||
// Delete entry from DB
|
|
||||||
self
|
|
||||||
.conn
|
|
||||||
.execute(
|
|
||||||
"DELETE FROM clipboard WHERE id = ?1",
|
|
||||||
rusqlite::params![id],
|
|
||||||
)
|
|
||||||
.map_err(|e| {
|
|
||||||
StashError::DeleteEntry(*id, e.to_string().into())
|
|
||||||
})?;
|
|
||||||
// Remove from entries and update selection
|
|
||||||
entries.remove(idx);
|
|
||||||
let new_len = entries.len();
|
|
||||||
if new_len == 0 {
|
|
||||||
state.select(None);
|
|
||||||
} else if idx >= new_len {
|
|
||||||
state.select(Some(new_len - 1));
|
|
||||||
} else {
|
|
||||||
state.select(Some(idx));
|
|
||||||
}
|
|
||||||
// Show notification
|
|
||||||
let _ = Notification::new()
|
let _ = Notification::new()
|
||||||
.summary("Stash")
|
.summary("Stash")
|
||||||
.body("Deleted entry")
|
.body(&format!("Failed to fetch entry: {e}"))
|
||||||
.show();
|
.show();
|
||||||
}
|
},
|
||||||
},
|
}
|
||||||
_ => {},
|
}
|
||||||
}
|
},
|
||||||
|
(KeyCode::Char('D'), KeyModifiers::SHIFT) => {
|
||||||
|
if let Some(idx) = state.selected()
|
||||||
|
&& let Some((id, ..)) = entries.get(idx)
|
||||||
|
{
|
||||||
|
// Delete entry from DB
|
||||||
|
self
|
||||||
|
.conn
|
||||||
|
.execute(
|
||||||
|
"DELETE FROM clipboard WHERE id = ?1",
|
||||||
|
rusqlite::params![id],
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
StashError::DeleteEntry(*id, e.to_string().into())
|
||||||
|
})?;
|
||||||
|
// Remove from entries and update selection
|
||||||
|
entries.remove(idx);
|
||||||
|
let new_len = entries.len();
|
||||||
|
if new_len == 0 {
|
||||||
|
state.select(None);
|
||||||
|
} else if idx >= new_len {
|
||||||
|
state.select(Some(new_len - 1));
|
||||||
|
} else {
|
||||||
|
state.select(Some(idx));
|
||||||
|
}
|
||||||
|
// Show notification
|
||||||
|
let _ = Notification::new()
|
||||||
|
.summary("Stash")
|
||||||
|
.body("Deleted entry")
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue