mirror of
https://seed.radicle.dev/rad:z39mP9rQAaGmERfUMPULfPUi473tY.git
synced 2026-11-03 18:30:41 +08:00
Implement issue browser context on home page
This commit is contained in:
+25
-8
@@ -6,8 +6,8 @@ use radicle::cob::issue::{Issue, IssueId};
|
||||
use radicle::cob::patch::{Patch, PatchId};
|
||||
|
||||
use radicle_tui::cob;
|
||||
use radicle_tui::ui::widget::common::context::Shortcuts;
|
||||
use tuirealm::{Frame, NoUserEvent, Sub, SubClause};
|
||||
use radicle_tui::ui::widget::common::context::{Progress, Shortcuts};
|
||||
use tuirealm::{Frame, NoUserEvent, StateValue, Sub, SubClause};
|
||||
|
||||
use radicle_tui::ui::context::Context;
|
||||
use radicle_tui::ui::layout;
|
||||
@@ -119,16 +119,33 @@ impl HomeView {
|
||||
fn update_context(
|
||||
&self,
|
||||
app: &mut Application<Cid, Message, NoUserEvent>,
|
||||
context: &Context,
|
||||
theme: &Theme,
|
||||
cid: HomeCid,
|
||||
) -> Result<()> {
|
||||
use tuirealm::State;
|
||||
|
||||
let context = match cid {
|
||||
HomeCid::IssueBrowser => {
|
||||
let context = widget::issue::browse_context(theme);
|
||||
let state = app.state(&Cid::Home(HomeCid::IssueBrowser))?;
|
||||
let progress = match state {
|
||||
State::Tup2((StateValue::Usize(step), StateValue::Usize(total))) => {
|
||||
Progress::Step(step, total)
|
||||
}
|
||||
_ => Progress::None,
|
||||
};
|
||||
let context = widget::issue::browse_context(context, theme, progress);
|
||||
Some(context)
|
||||
}
|
||||
HomeCid::PatchBrowser => {
|
||||
let context = widget::patch::browse_context(theme);
|
||||
let state = app.state(&Cid::Home(HomeCid::PatchBrowser))?;
|
||||
let progress = match state {
|
||||
State::Tup2((StateValue::Usize(step), StateValue::Usize(total))) => {
|
||||
Progress::Step(step, total)
|
||||
}
|
||||
_ => Progress::None,
|
||||
};
|
||||
let context = widget::patch::browse_context(context, theme, progress);
|
||||
Some(context)
|
||||
}
|
||||
_ => None,
|
||||
@@ -180,7 +197,7 @@ impl ViewPage for HomeView {
|
||||
let active_component = Cid::Home(self.active_component.clone());
|
||||
app.active(&active_component)?;
|
||||
self.update_shortcuts(app, self.active_component.clone())?;
|
||||
self.update_context(app, theme, self.active_component.clone())?;
|
||||
self.update_context(app, context, theme, self.active_component.clone())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -198,7 +215,7 @@ impl ViewPage for HomeView {
|
||||
fn update(
|
||||
&mut self,
|
||||
app: &mut Application<Cid, Message, NoUserEvent>,
|
||||
_context: &Context,
|
||||
context: &Context,
|
||||
theme: &Theme,
|
||||
message: Message,
|
||||
) -> Result<Option<Message>> {
|
||||
@@ -209,9 +226,10 @@ impl ViewPage for HomeView {
|
||||
app.active(&active_component)?;
|
||||
|
||||
self.update_shortcuts(app, self.active_component.clone())?;
|
||||
self.update_context(app, theme, self.active_component.clone())?;
|
||||
}
|
||||
|
||||
self.update_context(app, context, theme, self.active_component.clone())?;
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@@ -476,7 +494,6 @@ impl ViewPage for PatchView {
|
||||
context: &Context,
|
||||
theme: &Theme,
|
||||
) -> Result<()> {
|
||||
let (id, patch) = &self.patch;
|
||||
let navigation = widget::patch::navigation(theme);
|
||||
let header = widget::common::app_header(context, theme, Some(navigation)).to_boxed();
|
||||
let activity = widget::patch::activity(theme).to_boxed();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use radicle::cob::issue::{Issue, IssueId};
|
||||
use radicle::prelude::{Id, Project};
|
||||
use radicle::Profile;
|
||||
|
||||
@@ -8,17 +9,20 @@ pub struct Context {
|
||||
id: Id,
|
||||
project: Project,
|
||||
repository: Repository,
|
||||
issues: Vec<(IssueId, Issue)>,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(profile: Profile, id: Id, project: Project) -> Self {
|
||||
let repository = profile.storage.repository(id).unwrap();
|
||||
let issues = crate::cob::issue::all(&repository).unwrap_or_default();
|
||||
|
||||
Self {
|
||||
id,
|
||||
profile,
|
||||
project,
|
||||
repository,
|
||||
issues,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,4 +41,8 @@ impl Context {
|
||||
pub fn repository(&self) -> &Repository {
|
||||
&self.repository
|
||||
}
|
||||
|
||||
pub fn issues(&self) -> &Vec<(IssueId, Issue)> {
|
||||
&self.issues
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -206,9 +206,9 @@ pub fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
|
||||
}
|
||||
|
||||
pub fn issue_page(area: Rect, shortcuts_h: u16) -> IssuePage {
|
||||
let content_h = area.height.saturating_sub(shortcuts_h);
|
||||
let header_h = 3u16;
|
||||
|
||||
let content_h = area.height.saturating_sub(header_h).saturating_sub(shortcuts_h);
|
||||
|
||||
let root = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.horizontal_margin(1)
|
||||
|
||||
@@ -9,6 +9,22 @@ use crate::ui::layout;
|
||||
use crate::ui::theme::Theme;
|
||||
use crate::ui::widget::{Widget, WidgetComponent};
|
||||
|
||||
pub enum Progress {
|
||||
Percentage(usize),
|
||||
Step(usize, usize),
|
||||
None,
|
||||
}
|
||||
|
||||
impl ToString for Progress {
|
||||
fn to_string(&self) -> std::string::String {
|
||||
match self {
|
||||
Progress::Percentage(value) => format!("{value} %"),
|
||||
Progress::Step(step, total) => format!("{step}/{total}"),
|
||||
_ => String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A shortcut that consists of a label displaying the "hotkey", a label that displays
|
||||
/// the action and a spacer between them.
|
||||
#[derive(Clone)]
|
||||
|
||||
@@ -271,7 +271,9 @@ where
|
||||
}
|
||||
|
||||
fn state(&self) -> State {
|
||||
State::None
|
||||
let selected = self.state.selected().unwrap_or_default();
|
||||
let len = self.items.len();
|
||||
State::Tup2((StateValue::Usize(selected), StateValue::Usize(len)))
|
||||
}
|
||||
|
||||
fn perform(&mut self, _properties: &Props, cmd: Cmd) -> CmdResult {
|
||||
|
||||
@@ -67,11 +67,9 @@ impl IssueBrowser {
|
||||
let repo = context.repository();
|
||||
let mut items = vec![];
|
||||
|
||||
if let Ok(issues) = cob::issue::all(repo) {
|
||||
for (id, issue) in issues {
|
||||
if let Ok(item) = IssueItem::try_from((context.profile(), repo, id, issue)) {
|
||||
items.push(item);
|
||||
}
|
||||
for (id, issue) in context.issues() {
|
||||
if let Ok(item) = IssueItem::try_from((context.profile(), repo, *id, issue.clone())) {
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-2
@@ -10,6 +10,7 @@ use tuirealm::tui::layout::Layout;
|
||||
use super::common::container::Container;
|
||||
use super::common::container::LabeledContainer;
|
||||
use super::common::context::ContextBar;
|
||||
use super::common::context::Progress;
|
||||
use super::common::label::Textarea;
|
||||
use super::common::list::List;
|
||||
use super::common::list::Property;
|
||||
@@ -273,6 +274,27 @@ pub fn details(
|
||||
Widget::new(discussion)
|
||||
}
|
||||
|
||||
pub fn browse_context(theme: &Theme) -> Widget<ContextBar> {
|
||||
common::context::bar(theme, "Browse", "", "", "", "")
|
||||
pub fn browse_context(context: &Context, theme: &Theme, progress: Progress) -> Widget<ContextBar> {
|
||||
use radicle::cob::issue::State;
|
||||
|
||||
let issues = context.issues();
|
||||
let open = issues
|
||||
.iter()
|
||||
.filter(|issue| *issue.1.state() == State::Open)
|
||||
.collect::<Vec<_>>()
|
||||
.len();
|
||||
let closed = issues
|
||||
.iter()
|
||||
.filter(|issue| *issue.1.state() != State::Open)
|
||||
.collect::<Vec<_>>()
|
||||
.len();
|
||||
|
||||
common::context::bar(
|
||||
theme,
|
||||
"Browse",
|
||||
"",
|
||||
"",
|
||||
&format!("{open} open | {closed} closed"),
|
||||
&progress.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use super::{Widget, WidgetComponent};
|
||||
|
||||
use super::common;
|
||||
use super::common::container::Tabs;
|
||||
use super::common::context::ContextBar;
|
||||
use super::common::context::{ContextBar, Progress};
|
||||
use super::common::label::Label;
|
||||
|
||||
use crate::ui::context::Context;
|
||||
@@ -116,6 +116,10 @@ pub fn context(context: &Context, theme: &Theme, patch: (PatchId, Patch)) -> Wid
|
||||
common::context::bar(theme, "Patch", &id, title, &author, &comments.to_string())
|
||||
}
|
||||
|
||||
pub fn browse_context(theme: &Theme) -> Widget<ContextBar> {
|
||||
pub fn browse_context(
|
||||
_context: &Context,
|
||||
theme: &Theme,
|
||||
_progress: Progress,
|
||||
) -> Widget<ContextBar> {
|
||||
common::context::bar(theme, "Browse", "", "", "", "")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user