mirror of
https://seed.radicle.dev/rad:z39mP9rQAaGmERfUMPULfPUi473tY.git
synced 2026-11-02 01:40:33 +08:00
inbox/list: Keep state between runs
This commit is contained in:
+21
-5
@@ -5,12 +5,13 @@ use std::ffi::OsString;
|
||||
|
||||
use anyhow::anyhow;
|
||||
|
||||
use radicle::node::notifications::NotificationId;
|
||||
use radicle::storage::{HasRepoId, ReadRepository};
|
||||
|
||||
use radicle_cli::terminal::{Args, Error, Help};
|
||||
|
||||
use crate::terminal;
|
||||
use crate::ui::items::notification::filter::{NotificationFilter, SortBy};
|
||||
use crate::ui::items::notification::filter::SortBy;
|
||||
|
||||
use self::list::{InboxOperation, RepositoryMode};
|
||||
|
||||
@@ -58,7 +59,6 @@ pub enum OperationName {
|
||||
#[derive(Debug, Default, Clone, PartialEq)]
|
||||
pub struct ListOptions {
|
||||
mode: RepositoryMode,
|
||||
filter: NotificationFilter,
|
||||
sort_by: SortBy,
|
||||
json: bool,
|
||||
}
|
||||
@@ -179,11 +179,18 @@ pub async fn run(options: Options, ctx: impl radicle_cli::terminal::Context) ->
|
||||
|
||||
match options.op {
|
||||
Operation::List { opts } => {
|
||||
#[derive(Default)]
|
||||
struct PreviousState {
|
||||
notif_id: Option<NotificationId>,
|
||||
search: Option<String>,
|
||||
}
|
||||
|
||||
if let Err(err) = crate::log::enable() {
|
||||
println!("{err}");
|
||||
}
|
||||
log::info!("Starting inbox listing interface in project {rid}..");
|
||||
|
||||
let mut state = PreviousState::default();
|
||||
loop {
|
||||
let profile = ctx.profile()?;
|
||||
let repository = profile.storage.repository(rid)?;
|
||||
@@ -193,8 +200,9 @@ pub async fn run(options: Options, ctx: impl radicle_cli::terminal::Context) ->
|
||||
project: repository.identity_doc()?.project()?,
|
||||
rid: repository.rid(),
|
||||
mode: opts.mode.clone(),
|
||||
filter: opts.filter.clone(),
|
||||
search: state.search.clone(),
|
||||
sort_by: opts.sort_by,
|
||||
_notif_id: state.notif_id,
|
||||
};
|
||||
|
||||
let app = list::Tui::new(context);
|
||||
@@ -212,13 +220,21 @@ pub async fn run(options: Options, ctx: impl radicle_cli::terminal::Context) ->
|
||||
} else if let Some(selection) = selection {
|
||||
if let Some(operation) = selection.operation.clone() {
|
||||
match operation {
|
||||
InboxOperation::Show { id } => {
|
||||
InboxOperation::Show { id, search } => {
|
||||
state = PreviousState {
|
||||
notif_id: Some(id),
|
||||
search: Some(search),
|
||||
};
|
||||
terminal::run_rad(
|
||||
Some("inbox"),
|
||||
&["show".into(), id.to_string().into()],
|
||||
)?;
|
||||
}
|
||||
InboxOperation::Clear { id } => {
|
||||
InboxOperation::Clear { id, search } => {
|
||||
state = PreviousState {
|
||||
notif_id: Some(id),
|
||||
search: Some(search),
|
||||
};
|
||||
terminal::run_rad(
|
||||
Some("inbox"),
|
||||
&["clear".into(), id.to_string().into()],
|
||||
|
||||
+20
-11
@@ -48,8 +48,8 @@ pub enum RepositoryMode {
|
||||
/// selection widget.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
pub enum InboxOperation {
|
||||
Show { id: NotificationId },
|
||||
Clear { id: NotificationId },
|
||||
Show { id: NotificationId, search: String },
|
||||
Clear { id: NotificationId, search: String },
|
||||
}
|
||||
|
||||
type Selection = tui::Selection<InboxOperation>;
|
||||
@@ -85,8 +85,9 @@ pub struct Context {
|
||||
pub project: Project,
|
||||
pub rid: RepoId,
|
||||
pub mode: RepositoryMode,
|
||||
pub filter: NotificationFilter,
|
||||
pub sort_by: SortBy,
|
||||
pub _notif_id: Option<NotificationId>,
|
||||
pub search: Option<String>,
|
||||
}
|
||||
|
||||
pub struct Tui {
|
||||
@@ -174,12 +175,17 @@ impl TryFrom<&Context> for App {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(context: &Context) -> Result<Self, Self::Error> {
|
||||
let search = {
|
||||
let raw = context.filter.to_string();
|
||||
raw.trim().to_string()
|
||||
let search = context.search.as_ref().map(|s| s.trim().to_string());
|
||||
let (search, filter) = match search {
|
||||
Some(search) => (
|
||||
search.clone(),
|
||||
NotificationFilter::from_str(search.trim()).unwrap_or(NotificationFilter::Invalid),
|
||||
),
|
||||
None => {
|
||||
let filter = NotificationFilter::default();
|
||||
(filter.to_string().trim().to_string(), filter)
|
||||
}
|
||||
};
|
||||
let filter = NotificationFilter::from_str(&context.filter.to_string())
|
||||
.unwrap_or(NotificationFilter::Invalid);
|
||||
|
||||
Ok(App {
|
||||
context: Arc::new(Mutex::new(context.clone())),
|
||||
@@ -189,8 +195,8 @@ impl TryFrom<&Context> for App {
|
||||
main_group: ContainerState::new(3, Some(0)),
|
||||
patches: TableState::new(Some(0)),
|
||||
search: BufferedValue::new(TextEditState {
|
||||
text: search.clone(),
|
||||
cursor: search.len(),
|
||||
text: search.to_string(),
|
||||
cursor: search.chars().count(),
|
||||
}),
|
||||
show_search: false,
|
||||
help: TextViewState::new(Position::default()),
|
||||
@@ -421,6 +427,7 @@ impl App {
|
||||
ui.send_message(Message::Exit {
|
||||
operation: Some(InboxOperation::Show {
|
||||
id: notification.id,
|
||||
search: self.state.search.read().text,
|
||||
}),
|
||||
});
|
||||
}
|
||||
@@ -428,6 +435,7 @@ impl App {
|
||||
ui.send_message(Message::Exit {
|
||||
operation: Some(InboxOperation::Clear {
|
||||
id: notification.id,
|
||||
search: self.state.search.read().text,
|
||||
}),
|
||||
});
|
||||
}
|
||||
@@ -554,7 +562,8 @@ impl App {
|
||||
Column::new(
|
||||
Span::raw(format!(" {search} "))
|
||||
.into_left_aligned_line()
|
||||
.style(ui.theme().bar_on_black_style),
|
||||
.style(ui.theme().bar_on_black_style)
|
||||
.cyan(),
|
||||
Constraint::Fill(1),
|
||||
),
|
||||
Column::new(
|
||||
|
||||
@@ -7,7 +7,7 @@ use serde::Serialize;
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
use ratatui::layout::{Alignment, Constraint, Layout, Position};
|
||||
use ratatui::style::{Style, Stylize};
|
||||
use ratatui::style::Stylize;
|
||||
use ratatui::text::{Line, Span, Text};
|
||||
use ratatui::{Frame, Viewport};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user