mirror of
https://seed.radicle.dev/rad:z39mP9rQAaGmERfUMPULfPUi473tY.git
synced 2026-11-16 00:10:38 +08:00
refactor: Simplify library ui and widget modules
This commit is contained in:
+12
-11
@@ -9,16 +9,17 @@ use radicle::identity::{Id, Project};
|
||||
use radicle::prelude::Signer;
|
||||
use radicle::profile::Profile;
|
||||
|
||||
use radicle_tui::ui::subscription;
|
||||
use radicle_tui::ui::widget;
|
||||
use tuirealm::application::PollStrategy;
|
||||
use tuirealm::{Application, Frame, NoUserEvent, Sub, SubClause};
|
||||
|
||||
use radicle_tui::cob;
|
||||
use radicle_tui::ui::context::Context;
|
||||
use radicle_tui::ui::theme::{self, Theme};
|
||||
use radicle_tui::PageStack;
|
||||
use radicle_tui::Tui;
|
||||
use radicle_tui as tui;
|
||||
|
||||
use tui::cob;
|
||||
use tui::ui::context::Context;
|
||||
use tui::ui::subscription;
|
||||
use tui::ui::theme::{self, Theme};
|
||||
use tui::PageStack;
|
||||
use tui::Tui;
|
||||
|
||||
use page::{IssuePage, ListPage};
|
||||
|
||||
@@ -235,7 +236,7 @@ impl App {
|
||||
theme: &Theme,
|
||||
message: &str,
|
||||
) -> Result<()> {
|
||||
let popup = widget::common::info(theme, message);
|
||||
let popup = tui::ui::info(theme, message);
|
||||
app.remount(Cid::Popup, popup.to_boxed(), vec![])?;
|
||||
app.active(&Cid::Popup)?;
|
||||
|
||||
@@ -248,7 +249,7 @@ impl App {
|
||||
theme: &Theme,
|
||||
message: &str,
|
||||
) -> Result<()> {
|
||||
let popup = widget::common::warning(theme, message);
|
||||
let popup = tui::ui::warning(theme, message);
|
||||
app.remount(Cid::Popup, popup.to_boxed(), vec![])?;
|
||||
app.active(&Cid::Popup)?;
|
||||
|
||||
@@ -261,7 +262,7 @@ impl App {
|
||||
theme: &Theme,
|
||||
message: &str,
|
||||
) -> Result<()> {
|
||||
let popup = widget::common::error(theme, message);
|
||||
let popup = tui::ui::error(theme, message);
|
||||
app.remount(Cid::Popup, popup.to_boxed(), vec![])?;
|
||||
app.active(&Cid::Popup)?;
|
||||
|
||||
@@ -304,7 +305,7 @@ impl Tui<Cid, Message> for App {
|
||||
self.view_list(app, &self.theme.clone())?;
|
||||
|
||||
// Add global key listener and subscribe to key events
|
||||
let global = widget::common::global_listener().to_boxed();
|
||||
let global = tui::ui::global_listener().to_boxed();
|
||||
app.mount(
|
||||
Cid::GlobalListener,
|
||||
global,
|
||||
|
||||
@@ -3,14 +3,14 @@ use tuirealm::command::{Cmd, CmdResult, Direction as MoveDirection, Position};
|
||||
use tuirealm::event::{Event, Key, KeyEvent, KeyModifiers};
|
||||
use tuirealm::{MockComponent, NoUserEvent, State, StateValue};
|
||||
|
||||
use radicle_tui::ui::widget::common::container::{
|
||||
AppHeader, GlobalListener, LabeledContainer, Popup,
|
||||
};
|
||||
use radicle_tui::ui::widget::common::context::{ContextBar, Shortcuts};
|
||||
use radicle_tui::ui::widget::common::form::Form;
|
||||
use radicle_tui::ui::widget::common::list::PropertyList;
|
||||
use radicle_tui as tui;
|
||||
|
||||
use radicle_tui::ui::widget::Widget;
|
||||
use tui::ui::widget::container::{AppHeader, GlobalListener, LabeledContainer, Popup};
|
||||
use tui::ui::widget::context::{ContextBar, Shortcuts};
|
||||
use tui::ui::widget::form::Form;
|
||||
use tui::ui::widget::list::PropertyList;
|
||||
|
||||
use tui::ui::widget::Widget;
|
||||
|
||||
use super::ui;
|
||||
use super::{IssueCid, IssueMessage, Message, PopupMessage};
|
||||
|
||||
+32
-29
@@ -3,15 +3,18 @@ use std::collections::HashMap;
|
||||
use anyhow::Result;
|
||||
|
||||
use radicle::cob::issue::{Issue, IssueId};
|
||||
use radicle_tui::cob;
|
||||
use radicle_tui::ui::widget::common::context::{Progress, Shortcuts};
|
||||
|
||||
use tuirealm::{AttrValue, Attribute, Frame, NoUserEvent, State, StateValue, Sub, SubClause};
|
||||
|
||||
use radicle_tui::ui::context::Context;
|
||||
use radicle_tui::ui::layout;
|
||||
use radicle_tui::ui::theme::Theme;
|
||||
use radicle_tui::ui::widget::{self, Widget};
|
||||
use radicle_tui::ViewPage;
|
||||
use radicle_tui as tui;
|
||||
|
||||
use tui::cob;
|
||||
use tui::ui::context::Context;
|
||||
use tui::ui::layout;
|
||||
use tui::ui::theme::Theme;
|
||||
use tui::ui::widget::context::{Progress, Shortcuts};
|
||||
use tui::ui::widget::Widget;
|
||||
use tui::ViewPage;
|
||||
|
||||
use super::{
|
||||
Application, Cid, IssueCid, IssueCobMessage, IssueMessage, ListCid, Message, PopupMessage,
|
||||
@@ -53,14 +56,14 @@ impl ListPage {
|
||||
fn build_shortcuts(theme: &Theme) -> HashMap<ListCid, Widget<Shortcuts>> {
|
||||
[(
|
||||
ListCid::IssueBrowser,
|
||||
widget::common::shortcuts(
|
||||
tui::ui::shortcuts(
|
||||
theme,
|
||||
vec![
|
||||
widget::common::shortcut(theme, "tab", "section"),
|
||||
widget::common::shortcut(theme, "↑/↓", "navigate"),
|
||||
widget::common::shortcut(theme, "enter", "show"),
|
||||
widget::common::shortcut(theme, "o", "open"),
|
||||
widget::common::shortcut(theme, "q", "quit"),
|
||||
tui::ui::shortcut(theme, "tab", "section"),
|
||||
tui::ui::shortcut(theme, "↑/↓", "navigate"),
|
||||
tui::ui::shortcut(theme, "enter", "show"),
|
||||
tui::ui::shortcut(theme, "o", "open"),
|
||||
tui::ui::shortcut(theme, "q", "quit"),
|
||||
],
|
||||
),
|
||||
)]
|
||||
@@ -112,7 +115,7 @@ impl ViewPage<Cid, Message> for ListPage {
|
||||
theme: &Theme,
|
||||
) -> Result<()> {
|
||||
let navigation = ui::list_navigation(theme);
|
||||
let header = widget::common::app_header(context, theme, Some(navigation)).to_boxed();
|
||||
let header = tui::ui::app_header(context, theme, Some(navigation)).to_boxed();
|
||||
let issue_browser = ui::issues(context, theme, None).to_boxed();
|
||||
|
||||
app.remount(Cid::List(ListCid::Header), header, vec![])?;
|
||||
@@ -229,36 +232,36 @@ impl IssuePage {
|
||||
[
|
||||
(
|
||||
IssueCid::List,
|
||||
widget::common::shortcuts(
|
||||
tui::ui::shortcuts(
|
||||
theme,
|
||||
vec![
|
||||
widget::common::shortcut(theme, "esc", "back"),
|
||||
widget::common::shortcut(theme, "↑/↓", "navigate"),
|
||||
widget::common::shortcut(theme, "enter", "show"),
|
||||
widget::common::shortcut(theme, "o", "open"),
|
||||
widget::common::shortcut(theme, "q", "quit"),
|
||||
tui::ui::shortcut(theme, "esc", "back"),
|
||||
tui::ui::shortcut(theme, "↑/↓", "navigate"),
|
||||
tui::ui::shortcut(theme, "enter", "show"),
|
||||
tui::ui::shortcut(theme, "o", "open"),
|
||||
tui::ui::shortcut(theme, "q", "quit"),
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
IssueCid::Details,
|
||||
widget::common::shortcuts(
|
||||
tui::ui::shortcuts(
|
||||
theme,
|
||||
vec![
|
||||
widget::common::shortcut(theme, "esc", "back"),
|
||||
widget::common::shortcut(theme, "↑/↓", "scroll"),
|
||||
widget::common::shortcut(theme, "q", "quit"),
|
||||
tui::ui::shortcut(theme, "esc", "back"),
|
||||
tui::ui::shortcut(theme, "↑/↓", "scroll"),
|
||||
tui::ui::shortcut(theme, "q", "quit"),
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
IssueCid::Form,
|
||||
widget::common::shortcuts(
|
||||
tui::ui::shortcuts(
|
||||
theme,
|
||||
vec![
|
||||
widget::common::shortcut(theme, "esc", "back"),
|
||||
widget::common::shortcut(theme, "shift + tab / tab", "navigate"),
|
||||
widget::common::shortcut(theme, "ctrl + s", "submit"),
|
||||
tui::ui::shortcut(theme, "esc", "back"),
|
||||
tui::ui::shortcut(theme, "shift + tab / tab", "navigate"),
|
||||
tui::ui::shortcut(theme, "ctrl + s", "submit"),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -334,7 +337,7 @@ impl ViewPage<Cid, Message> for IssuePage {
|
||||
theme: &Theme,
|
||||
) -> Result<()> {
|
||||
let navigation = ui::list_navigation(theme);
|
||||
let header = widget::common::app_header(context, theme, Some(navigation)).to_boxed();
|
||||
let header = tui::ui::app_header(context, theme, Some(navigation)).to_boxed();
|
||||
let list = ui::list(context, theme, self.issue.clone()).to_boxed();
|
||||
|
||||
app.remount(Cid::Issue(IssueCid::Header), header, vec![])?;
|
||||
|
||||
+40
-39
@@ -8,18 +8,19 @@ use tuirealm::command::{Cmd, CmdResult};
|
||||
use tuirealm::tui::layout::{Constraint, Direction, Layout, Rect};
|
||||
use tuirealm::{AttrValue, Attribute, Frame, MockComponent, Props, State};
|
||||
|
||||
use radicle_tui::ui::cob;
|
||||
use radicle_tui::ui::cob::IssueItem;
|
||||
use radicle_tui::ui::context::Context;
|
||||
use radicle_tui::ui::theme::Theme;
|
||||
use radicle_tui::ui::widget::common;
|
||||
use radicle_tui::ui::widget::{Widget, WidgetComponent};
|
||||
use radicle_tui as tui;
|
||||
|
||||
use common::container::{Container, Tabs};
|
||||
use common::context::{ContextBar, Progress};
|
||||
use common::form::{Form, TextArea, TextField};
|
||||
use common::label::Textarea;
|
||||
use common::list::{ColumnWidth, List, Property, Table};
|
||||
use tui::ui::cob;
|
||||
use tui::ui::cob::IssueItem;
|
||||
use tui::ui::context::Context;
|
||||
use tui::ui::theme::Theme;
|
||||
use tui::ui::widget::{Widget, WidgetComponent};
|
||||
|
||||
use tui::ui::widget::container::{Container, Tabs};
|
||||
use tui::ui::widget::context::{ContextBar, Progress};
|
||||
use tui::ui::widget::form::{Form, TextArea, TextField};
|
||||
use tui::ui::widget::label::Textarea;
|
||||
use tui::ui::widget::list::{ColumnWidth, List, Property, Table};
|
||||
|
||||
pub const FORM_ID_EDIT: &str = "edit-form";
|
||||
|
||||
@@ -31,13 +32,13 @@ pub struct IssueBrowser {
|
||||
impl IssueBrowser {
|
||||
pub fn new(context: &Context, theme: &Theme, selected: Option<(IssueId, Issue)>) -> Self {
|
||||
let header = [
|
||||
common::label(" ● "),
|
||||
common::label("ID"),
|
||||
common::label("Title"),
|
||||
common::label("Author"),
|
||||
common::label("Tags"),
|
||||
common::label("Assignees"),
|
||||
common::label("Opened"),
|
||||
tui::ui::label(" ● "),
|
||||
tui::ui::label("ID"),
|
||||
tui::ui::label("Title"),
|
||||
tui::ui::label("Author"),
|
||||
tui::ui::label("Tags"),
|
||||
tui::ui::label("Assignees"),
|
||||
tui::ui::label("Opened"),
|
||||
];
|
||||
|
||||
let widths = [
|
||||
@@ -121,7 +122,7 @@ impl LargeList {
|
||||
let list = Widget::new(List::new(&items, selected, theme.clone()))
|
||||
.highlight(theme.colors.item_list_highlighted_bg);
|
||||
|
||||
let container = common::container(theme, list.to_boxed());
|
||||
let container = tui::ui::container(theme, list.to_boxed());
|
||||
|
||||
Self {
|
||||
items,
|
||||
@@ -166,30 +167,30 @@ impl IssueHeader {
|
||||
let item = IssueItem::from((context.profile(), repo, id, issue.clone()));
|
||||
|
||||
let title = Property::new(
|
||||
common::label("Title").foreground(theme.colors.property_name_fg),
|
||||
common::label(item.title()).foreground(theme.colors.browser_list_title),
|
||||
tui::ui::label("Title").foreground(theme.colors.property_name_fg),
|
||||
tui::ui::label(item.title()).foreground(theme.colors.browser_list_title),
|
||||
);
|
||||
|
||||
let author = Property::new(
|
||||
common::label("Author").foreground(theme.colors.property_name_fg),
|
||||
common::label(&cob::format_author(issue.author().id(), by_you))
|
||||
tui::ui::label("Author").foreground(theme.colors.property_name_fg),
|
||||
tui::ui::label(&cob::format_author(issue.author().id(), by_you))
|
||||
.foreground(theme.colors.browser_list_author),
|
||||
);
|
||||
|
||||
let issue_id = Property::new(
|
||||
common::label("Issue").foreground(theme.colors.property_name_fg),
|
||||
common::label(&id.to_string()).foreground(theme.colors.browser_list_description),
|
||||
tui::ui::label("Issue").foreground(theme.colors.property_name_fg),
|
||||
tui::ui::label(&id.to_string()).foreground(theme.colors.browser_list_description),
|
||||
);
|
||||
|
||||
let labels = Property::new(
|
||||
common::label("Labels").foreground(theme.colors.property_name_fg),
|
||||
common::label(&cob::format_labels(item.labels()))
|
||||
tui::ui::label("Labels").foreground(theme.colors.property_name_fg),
|
||||
tui::ui::label(&cob::format_labels(item.labels()))
|
||||
.foreground(theme.colors.browser_list_labels),
|
||||
);
|
||||
|
||||
let assignees = Property::new(
|
||||
common::label("Assignees").foreground(theme.colors.property_name_fg),
|
||||
common::label(&cob::format_assignees(
|
||||
tui::ui::label("Assignees").foreground(theme.colors.property_name_fg),
|
||||
tui::ui::label(&cob::format_assignees(
|
||||
&item
|
||||
.assignees()
|
||||
.iter()
|
||||
@@ -200,11 +201,11 @@ impl IssueHeader {
|
||||
);
|
||||
|
||||
let state = Property::new(
|
||||
common::label("Status").foreground(theme.colors.property_name_fg),
|
||||
common::label(&item.state().to_string()).foreground(theme.colors.browser_list_title),
|
||||
tui::ui::label("Status").foreground(theme.colors.property_name_fg),
|
||||
tui::ui::label(&item.state().to_string()).foreground(theme.colors.browser_list_title),
|
||||
);
|
||||
|
||||
let table = common::property_table(
|
||||
let table = tui::ui::property_table(
|
||||
theme,
|
||||
vec![
|
||||
Widget::new(title),
|
||||
@@ -215,7 +216,7 @@ impl IssueHeader {
|
||||
Widget::new(state),
|
||||
],
|
||||
);
|
||||
let container = common::container(theme, table.to_boxed());
|
||||
let container = tui::ui::container(theme, table.to_boxed());
|
||||
|
||||
Self { container }
|
||||
}
|
||||
@@ -294,7 +295,7 @@ impl CommentBody {
|
||||
.content(AttrValue::String(content))
|
||||
.foreground(theme.colors.default_fg);
|
||||
|
||||
let textarea = common::container(theme, textarea.to_boxed());
|
||||
let textarea = tui::ui::container(theme, textarea.to_boxed());
|
||||
|
||||
Self { textarea }
|
||||
}
|
||||
@@ -320,9 +321,9 @@ impl WidgetComponent for CommentBody {
|
||||
}
|
||||
|
||||
pub fn list_navigation(theme: &Theme) -> Widget<Tabs> {
|
||||
common::tabs(
|
||||
tui::ui::tabs(
|
||||
theme,
|
||||
vec![common::reversable_label("Issues").foreground(theme.colors.tabs_highlighted_fg)],
|
||||
vec![tui::ui::reversable_label("Issues").foreground(theme.colors.tabs_highlighted_fg)],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -403,7 +404,7 @@ pub fn browse_context(context: &Context, theme: &Theme, progress: Progress) -> W
|
||||
.collect::<Vec<_>>()
|
||||
.len();
|
||||
|
||||
common::context::bar(
|
||||
tui::ui::widget::context::bar(
|
||||
theme,
|
||||
"Browse",
|
||||
"",
|
||||
@@ -418,11 +419,11 @@ pub fn description_context(
|
||||
theme: &Theme,
|
||||
progress: Progress,
|
||||
) -> Widget<ContextBar> {
|
||||
common::context::bar(theme, "Show", "", "", "", &progress.to_string())
|
||||
tui::ui::widget::context::bar(theme, "Show", "", "", "", &progress.to_string())
|
||||
}
|
||||
|
||||
pub fn form_context(_context: &Context, theme: &Theme, progress: Progress) -> Widget<ContextBar> {
|
||||
common::context::bar(theme, "Open", "", "", "", &progress.to_string())
|
||||
tui::ui::widget::context::bar(theme, "Open", "", "", "", &progress.to_string())
|
||||
.custom(ContextBar::PROP_EDIT_MODE, AttrValue::Flag(true))
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -11,10 +11,10 @@ use radicle::identity::{Id, Project};
|
||||
use radicle::prelude::Signer;
|
||||
use radicle::profile::Profile;
|
||||
|
||||
use radicle_tui::ui::widget;
|
||||
use tuirealm::application::PollStrategy;
|
||||
use tuirealm::{Application, Frame, NoUserEvent, Sub, SubClause};
|
||||
|
||||
use radicle_tui as tui;
|
||||
use radicle_tui::cob;
|
||||
use radicle_tui::ui::context::Context;
|
||||
use radicle_tui::ui::subscription;
|
||||
@@ -189,7 +189,7 @@ impl App {
|
||||
theme: &Theme,
|
||||
message: &str,
|
||||
) -> Result<()> {
|
||||
let popup = widget::common::info(theme, message);
|
||||
let popup = tui::ui::info(theme, message);
|
||||
app.remount(Cid::Popup, popup.to_boxed(), vec![])?;
|
||||
app.active(&Cid::Popup)?;
|
||||
|
||||
@@ -202,7 +202,7 @@ impl App {
|
||||
theme: &Theme,
|
||||
message: &str,
|
||||
) -> Result<()> {
|
||||
let popup = widget::common::warning(theme, message);
|
||||
let popup = tui::ui::warning(theme, message);
|
||||
app.remount(Cid::Popup, popup.to_boxed(), vec![])?;
|
||||
app.active(&Cid::Popup)?;
|
||||
|
||||
@@ -215,7 +215,7 @@ impl App {
|
||||
theme: &Theme,
|
||||
message: &str,
|
||||
) -> Result<()> {
|
||||
let popup = widget::common::error(theme, message);
|
||||
let popup = tui::ui::error(theme, message);
|
||||
app.remount(Cid::Popup, popup.to_boxed(), vec![])?;
|
||||
app.active(&Cid::Popup)?;
|
||||
|
||||
@@ -235,7 +235,7 @@ impl Tui<Cid, Message> for App {
|
||||
self.view_list(app, &self.theme.clone())?;
|
||||
|
||||
// Add global key listener and subscribe to key events
|
||||
let global = widget::common::global_listener().to_boxed();
|
||||
let global = tui::ui::global_listener().to_boxed();
|
||||
app.mount(
|
||||
Cid::GlobalListener,
|
||||
global,
|
||||
|
||||
@@ -2,11 +2,9 @@ use tuirealm::command::{Cmd, CmdResult, Direction as MoveDirection};
|
||||
use tuirealm::event::{Event, Key, KeyEvent};
|
||||
use tuirealm::{MockComponent, NoUserEvent, State, StateValue};
|
||||
|
||||
use radicle_tui::ui::widget::common::container::{
|
||||
AppHeader, GlobalListener, LabeledContainer, Popup,
|
||||
};
|
||||
use radicle_tui::ui::widget::common::context::{ContextBar, Shortcuts};
|
||||
use radicle_tui::ui::widget::common::list::PropertyList;
|
||||
use radicle_tui::ui::widget::container::{AppHeader, GlobalListener, LabeledContainer, Popup};
|
||||
use radicle_tui::ui::widget::context::{ContextBar, Shortcuts};
|
||||
use radicle_tui::ui::widget::list::PropertyList;
|
||||
|
||||
use radicle_tui::ui::widget::Widget;
|
||||
|
||||
|
||||
+23
-22
@@ -4,15 +4,16 @@ use anyhow::Result;
|
||||
|
||||
use radicle::cob::patch::{Patch, PatchId};
|
||||
|
||||
use radicle_tui::ui::widget::common::context::{Progress, Shortcuts};
|
||||
use tuirealm::{Frame, NoUserEvent, State, StateValue, Sub, SubClause};
|
||||
|
||||
use radicle_tui::ui::context::Context;
|
||||
use radicle_tui::ui::layout;
|
||||
use radicle_tui::ui::subscription;
|
||||
use radicle_tui::ui::theme::Theme;
|
||||
use radicle_tui::ui::widget::{self, Widget};
|
||||
use radicle_tui::ViewPage;
|
||||
use radicle_tui as tui;
|
||||
|
||||
use tui::ui::context::Context;
|
||||
use tui::ui::theme::Theme;
|
||||
use tui::ui::widget::context::{Progress, Shortcuts};
|
||||
use tui::ui::widget::Widget;
|
||||
use tui::ui::{layout, subscription};
|
||||
use tui::ViewPage;
|
||||
|
||||
use super::{ui, Application, Cid, ListCid, Message, PatchCid};
|
||||
|
||||
@@ -36,13 +37,13 @@ impl ListView {
|
||||
fn build_shortcuts(theme: &Theme) -> HashMap<ListCid, Widget<Shortcuts>> {
|
||||
[(
|
||||
ListCid::PatchBrowser,
|
||||
widget::common::shortcuts(
|
||||
tui::ui::shortcuts(
|
||||
theme,
|
||||
vec![
|
||||
widget::common::shortcut(theme, "tab", "section"),
|
||||
widget::common::shortcut(theme, "↑/↓", "navigate"),
|
||||
widget::common::shortcut(theme, "enter", "show"),
|
||||
widget::common::shortcut(theme, "q", "quit"),
|
||||
tui::ui::shortcut(theme, "tab", "section"),
|
||||
tui::ui::shortcut(theme, "↑/↓", "navigate"),
|
||||
tui::ui::shortcut(theme, "enter", "show"),
|
||||
tui::ui::shortcut(theme, "q", "quit"),
|
||||
],
|
||||
),
|
||||
)]
|
||||
@@ -95,7 +96,7 @@ impl ViewPage<Cid, Message> for ListView {
|
||||
theme: &Theme,
|
||||
) -> Result<()> {
|
||||
let navigation = ui::list_navigation(theme);
|
||||
let header = widget::common::app_header(context, theme, Some(navigation)).to_boxed();
|
||||
let header = tui::ui::app_header(context, theme, Some(navigation)).to_boxed();
|
||||
let patch_browser = ui::patches(context, theme, None).to_boxed();
|
||||
|
||||
app.remount(Cid::List(ListCid::Header), header, vec![])?;
|
||||
@@ -186,23 +187,23 @@ impl PatchView {
|
||||
[
|
||||
(
|
||||
PatchCid::Activity,
|
||||
widget::common::shortcuts(
|
||||
tui::ui::shortcuts(
|
||||
theme,
|
||||
vec![
|
||||
widget::common::shortcut(theme, "esc", "back"),
|
||||
widget::common::shortcut(theme, "tab", "section"),
|
||||
widget::common::shortcut(theme, "q", "quit"),
|
||||
tui::ui::shortcut(theme, "esc", "back"),
|
||||
tui::ui::shortcut(theme, "tab", "section"),
|
||||
tui::ui::shortcut(theme, "q", "quit"),
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
PatchCid::Files,
|
||||
widget::common::shortcuts(
|
||||
tui::ui::shortcuts(
|
||||
theme,
|
||||
vec![
|
||||
widget::common::shortcut(theme, "esc", "back"),
|
||||
widget::common::shortcut(theme, "tab", "section"),
|
||||
widget::common::shortcut(theme, "q", "quit"),
|
||||
tui::ui::shortcut(theme, "esc", "back"),
|
||||
tui::ui::shortcut(theme, "tab", "section"),
|
||||
tui::ui::shortcut(theme, "q", "quit"),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -236,7 +237,7 @@ impl ViewPage<Cid, Message> for PatchView {
|
||||
theme: &Theme,
|
||||
) -> Result<()> {
|
||||
let navigation = ui::navigation(theme);
|
||||
let header = widget::common::app_header(context, theme, Some(navigation)).to_boxed();
|
||||
let header = tui::ui::app_header(context, theme, Some(navigation)).to_boxed();
|
||||
let activity = ui::activity(theme).to_boxed();
|
||||
let files = ui::files(theme).to_boxed();
|
||||
let context = ui::context(context, theme, self.patch.clone()).to_boxed();
|
||||
|
||||
+29
-28
@@ -4,18 +4,19 @@ use tuirealm::command::{Cmd, CmdResult};
|
||||
use tuirealm::tui::layout::Rect;
|
||||
use tuirealm::{AttrValue, Attribute, Frame, MockComponent, Props, State};
|
||||
|
||||
use radicle_tui::ui::cob;
|
||||
use radicle_tui::ui::cob::PatchItem;
|
||||
use radicle_tui::ui::context::Context;
|
||||
use radicle_tui::ui::layout;
|
||||
use radicle_tui::ui::theme::Theme;
|
||||
use radicle_tui::ui::widget::common;
|
||||
use radicle_tui::ui::widget::{Widget, WidgetComponent};
|
||||
use radicle_tui as tui;
|
||||
|
||||
use common::container::Tabs;
|
||||
use common::context::{ContextBar, Progress};
|
||||
use common::label::Label;
|
||||
use common::list::{ColumnWidth, Table};
|
||||
use tui::ui::cob;
|
||||
use tui::ui::cob::PatchItem;
|
||||
use tui::ui::context::Context;
|
||||
use tui::ui::layout;
|
||||
use tui::ui::theme::Theme;
|
||||
use tui::ui::widget::{Widget, WidgetComponent};
|
||||
|
||||
use tui::ui::widget::container::Tabs;
|
||||
use tui::ui::widget::context::{ContextBar, Progress};
|
||||
use tui::ui::widget::label::Label;
|
||||
use tui::ui::widget::list::{ColumnWidth, Table};
|
||||
|
||||
pub struct PatchBrowser {
|
||||
items: Vec<PatchItem>,
|
||||
@@ -25,14 +26,14 @@ pub struct PatchBrowser {
|
||||
impl PatchBrowser {
|
||||
pub fn new(context: &Context, theme: &Theme, selected: Option<(PatchId, Patch)>) -> Self {
|
||||
let header = [
|
||||
common::label(" ● "),
|
||||
common::label("ID"),
|
||||
common::label("Title"),
|
||||
common::label("Author"),
|
||||
common::label("Head"),
|
||||
common::label("+"),
|
||||
common::label("-"),
|
||||
common::label("Updated"),
|
||||
tui::ui::label(" ● "),
|
||||
tui::ui::label("ID"),
|
||||
tui::ui::label("Title"),
|
||||
tui::ui::label("Author"),
|
||||
tui::ui::label("Head"),
|
||||
tui::ui::label("+"),
|
||||
tui::ui::label("-"),
|
||||
tui::ui::label("Updated"),
|
||||
];
|
||||
|
||||
let widths = [
|
||||
@@ -158,18 +159,18 @@ impl WidgetComponent for Files {
|
||||
}
|
||||
|
||||
pub fn list_navigation(theme: &Theme) -> Widget<Tabs> {
|
||||
common::tabs(
|
||||
tui::ui::tabs(
|
||||
theme,
|
||||
vec![common::reversable_label("Patches").foreground(theme.colors.tabs_highlighted_fg)],
|
||||
vec![tui::ui::reversable_label("Patches").foreground(theme.colors.tabs_highlighted_fg)],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn navigation(theme: &Theme) -> Widget<Tabs> {
|
||||
common::tabs(
|
||||
tui::ui::tabs(
|
||||
theme,
|
||||
vec![
|
||||
common::reversable_label("Activity").foreground(theme.colors.tabs_highlighted_fg),
|
||||
common::reversable_label("Files").foreground(theme.colors.tabs_highlighted_fg),
|
||||
tui::ui::reversable_label("Activity").foreground(theme.colors.tabs_highlighted_fg),
|
||||
tui::ui::reversable_label("Files").foreground(theme.colors.tabs_highlighted_fg),
|
||||
],
|
||||
)
|
||||
}
|
||||
@@ -183,14 +184,14 @@ pub fn patches(
|
||||
}
|
||||
|
||||
pub fn activity(theme: &Theme) -> Widget<Activity> {
|
||||
let not_implemented = common::label("not implemented").foreground(theme.colors.default_fg);
|
||||
let not_implemented = tui::ui::label("not implemented").foreground(theme.colors.default_fg);
|
||||
let activity = Activity::new(not_implemented);
|
||||
|
||||
Widget::new(activity)
|
||||
}
|
||||
|
||||
pub fn files(theme: &Theme) -> Widget<Files> {
|
||||
let not_implemented = common::label("not implemented").foreground(theme.colors.default_fg);
|
||||
let not_implemented = tui::ui::label("not implemented").foreground(theme.colors.default_fg);
|
||||
let files = Files::new(not_implemented);
|
||||
|
||||
Widget::new(files)
|
||||
@@ -206,7 +207,7 @@ pub fn context(context: &Context, theme: &Theme, patch: (PatchId, Patch)) -> Wid
|
||||
let author = cob::format_author(patch.author().id(), is_you);
|
||||
let comments = rev.discussion().len();
|
||||
|
||||
common::context::bar(theme, "Patch", &id, title, &author, &comments.to_string())
|
||||
tui::ui::widget::context::bar(theme, "Patch", &id, title, &author, &comments.to_string())
|
||||
}
|
||||
|
||||
pub fn browse_context(context: &Context, theme: &Theme, progress: Progress) -> Widget<ContextBar> {
|
||||
@@ -230,7 +231,7 @@ pub fn browse_context(context: &Context, theme: &Theme, progress: Progress) -> W
|
||||
}
|
||||
}
|
||||
|
||||
common::context::bar(
|
||||
tui::ui::widget::context::bar(
|
||||
theme,
|
||||
"Browse",
|
||||
"",
|
||||
|
||||
@@ -6,3 +6,183 @@ pub mod state;
|
||||
pub mod subscription;
|
||||
pub mod theme;
|
||||
pub mod widget;
|
||||
|
||||
use tuirealm::props::{AttrValue, Attribute};
|
||||
use tuirealm::MockComponent;
|
||||
|
||||
use widget::container::{
|
||||
AppHeader, AppInfo, Container, GlobalListener, Header, LabeledContainer, Popup, Tabs,
|
||||
VerticalLine,
|
||||
};
|
||||
use widget::context::{Shortcut, Shortcuts};
|
||||
use widget::label::{Label, Textarea};
|
||||
use widget::list::{ColumnWidth, Property, PropertyList, PropertyTable};
|
||||
|
||||
use widget::Widget;
|
||||
|
||||
use crate::ui::context::Context;
|
||||
use crate::ui::theme::Theme;
|
||||
|
||||
pub fn global_listener() -> Widget<GlobalListener> {
|
||||
Widget::new(GlobalListener::default())
|
||||
}
|
||||
|
||||
pub fn label(content: &str) -> Widget<Label> {
|
||||
// TODO: Remove when size constraints are implemented
|
||||
let width = content.chars().count() as u16;
|
||||
|
||||
Widget::new(Label)
|
||||
.content(AttrValue::String(content.to_string()))
|
||||
.height(1)
|
||||
.width(width)
|
||||
}
|
||||
|
||||
pub fn reversable_label(content: &str) -> Widget<Label> {
|
||||
let content = &format!(" {content} ");
|
||||
|
||||
label(content)
|
||||
}
|
||||
|
||||
pub fn container_header(theme: &Theme, label: Widget<Label>) -> Widget<Header<1>> {
|
||||
let header = Header::new([label], [ColumnWidth::Grow], theme.clone());
|
||||
|
||||
Widget::new(header)
|
||||
}
|
||||
|
||||
pub fn container(theme: &Theme, component: Box<dyn MockComponent>) -> Widget<Container> {
|
||||
let container = Container::new(component, theme.clone());
|
||||
Widget::new(container)
|
||||
}
|
||||
|
||||
pub fn labeled_container(
|
||||
theme: &Theme,
|
||||
title: &str,
|
||||
component: Box<dyn MockComponent>,
|
||||
) -> Widget<LabeledContainer> {
|
||||
let header = container_header(
|
||||
theme,
|
||||
label(&format!(" {title} ")).foreground(theme.colors.default_fg),
|
||||
);
|
||||
let container = LabeledContainer::new(header, component, theme.clone());
|
||||
|
||||
Widget::new(container)
|
||||
}
|
||||
|
||||
pub fn shortcut(theme: &Theme, short: &str, long: &str) -> Widget<Shortcut> {
|
||||
let short = label(short).foreground(theme.colors.shortcut_short_fg);
|
||||
let divider = label(&theme.icons.whitespace.to_string());
|
||||
let long = label(long).foreground(theme.colors.shortcut_long_fg);
|
||||
|
||||
// TODO: Remove when size constraints are implemented
|
||||
let short_w = short.query(Attribute::Width).unwrap().unwrap_size();
|
||||
let divider_w = divider.query(Attribute::Width).unwrap().unwrap_size();
|
||||
let long_w = long.query(Attribute::Width).unwrap().unwrap_size();
|
||||
let width = short_w.saturating_add(divider_w).saturating_add(long_w);
|
||||
|
||||
let shortcut = Shortcut::new(short, divider, long);
|
||||
|
||||
Widget::new(shortcut).height(1).width(width)
|
||||
}
|
||||
|
||||
pub fn shortcuts(theme: &Theme, shortcuts: Vec<Widget<Shortcut>>) -> Widget<Shortcuts> {
|
||||
let divider = label(&format!(" {} ", theme.icons.shortcutbar_divider))
|
||||
.foreground(theme.colors.shortcutbar_divider_fg);
|
||||
let shortcut_bar = Shortcuts::new(shortcuts, divider);
|
||||
|
||||
Widget::new(shortcut_bar).height(1)
|
||||
}
|
||||
|
||||
pub fn property(theme: &Theme, name: &str, value: &str) -> Widget<Property> {
|
||||
let name = label(name).foreground(theme.colors.property_name_fg);
|
||||
let divider = label(&format!(" {} ", theme.icons.property_divider));
|
||||
let value = label(value).foreground(theme.colors.default_fg);
|
||||
|
||||
// TODO: Remove when size constraints are implemented
|
||||
let name_w = name.query(Attribute::Width).unwrap().unwrap_size();
|
||||
let divider_w = divider.query(Attribute::Width).unwrap().unwrap_size();
|
||||
let value_w = value.query(Attribute::Width).unwrap().unwrap_size();
|
||||
let width = name_w.saturating_add(divider_w).saturating_add(value_w);
|
||||
|
||||
let property = Property::new(name, value).with_divider(divider);
|
||||
|
||||
Widget::new(property).height(1).width(width)
|
||||
}
|
||||
|
||||
pub fn property_list(_theme: &Theme, properties: Vec<Widget<Property>>) -> Widget<PropertyList> {
|
||||
let property_list = PropertyList::new(properties);
|
||||
|
||||
Widget::new(property_list)
|
||||
}
|
||||
|
||||
pub fn property_table(_theme: &Theme, properties: Vec<Widget<Property>>) -> Widget<PropertyTable> {
|
||||
let table = PropertyTable::new(properties);
|
||||
|
||||
Widget::new(table)
|
||||
}
|
||||
|
||||
pub fn tabs(_theme: &Theme, tabs: Vec<Widget<Label>>) -> Widget<Tabs> {
|
||||
let tabs = Tabs::new(tabs);
|
||||
|
||||
Widget::new(tabs).height(2)
|
||||
}
|
||||
|
||||
pub fn app_info(context: &Context, theme: &Theme) -> Widget<AppInfo> {
|
||||
let project = label(context.project().name()).foreground(theme.colors.app_header_project_fg);
|
||||
let rid = label(&format!(" ({})", context.id())).foreground(theme.colors.app_header_rid_fg);
|
||||
|
||||
let project_w = project
|
||||
.query(Attribute::Width)
|
||||
.unwrap_or(AttrValue::Size(0))
|
||||
.unwrap_size();
|
||||
let rid_w = rid
|
||||
.query(Attribute::Width)
|
||||
.unwrap_or(AttrValue::Size(0))
|
||||
.unwrap_size();
|
||||
|
||||
let info = AppInfo::new(project, rid);
|
||||
Widget::new(info).width(project_w.saturating_add(rid_w))
|
||||
}
|
||||
|
||||
pub fn app_header(
|
||||
context: &Context,
|
||||
theme: &Theme,
|
||||
nav: Option<Widget<Tabs>>,
|
||||
) -> Widget<AppHeader> {
|
||||
let line =
|
||||
label(&theme.icons.tab_overline.to_string()).foreground(theme.colors.tabs_highlighted_fg);
|
||||
let line = Widget::new(VerticalLine::new(line));
|
||||
let info = app_info(context, theme);
|
||||
let header = AppHeader::new(nav, info, line);
|
||||
|
||||
Widget::new(header)
|
||||
}
|
||||
|
||||
pub fn info(theme: &Theme, message: &str) -> Widget<Popup> {
|
||||
let textarea =
|
||||
Widget::new(Textarea::new(theme.clone())).content(AttrValue::String(message.to_owned()));
|
||||
let container = labeled_container(theme, "Info", textarea.to_boxed());
|
||||
|
||||
Widget::new(Popup::new(theme.clone(), container))
|
||||
.width(50)
|
||||
.height(20)
|
||||
}
|
||||
|
||||
pub fn warning(theme: &Theme, message: &str) -> Widget<Popup> {
|
||||
let textarea =
|
||||
Widget::new(Textarea::new(theme.clone())).content(AttrValue::String(message.to_owned()));
|
||||
let container = labeled_container(theme, "Warning", textarea.to_boxed());
|
||||
|
||||
Widget::new(Popup::new(theme.clone(), container))
|
||||
.width(50)
|
||||
.height(20)
|
||||
}
|
||||
|
||||
pub fn error(theme: &Theme, message: &str) -> Widget<Popup> {
|
||||
let textarea =
|
||||
Widget::new(Textarea::new(theme.clone())).content(AttrValue::String(message.to_owned()));
|
||||
let container = labeled_container(theme, "Error", textarea.to_boxed());
|
||||
|
||||
Widget::new(Popup::new(theme.clone(), container))
|
||||
.width(50)
|
||||
.height(20)
|
||||
}
|
||||
|
||||
+4
-9
@@ -2,8 +2,9 @@ pub mod format;
|
||||
|
||||
use radicle_surf;
|
||||
|
||||
// use cli::terminal::format;
|
||||
// use radicle_cli as cli;
|
||||
use tuirealm::props::{Color, Style};
|
||||
use tuirealm::tui::text::{Span, Spans};
|
||||
use tuirealm::tui::widgets::Cell;
|
||||
|
||||
use radicle::prelude::Did;
|
||||
use radicle::storage::git::Repository;
|
||||
@@ -14,14 +15,8 @@ use radicle::cob::issue::{Issue, IssueId, State as IssueState};
|
||||
use radicle::cob::patch::{Patch, PatchId, State as PatchState};
|
||||
use radicle::cob::{Label, Timestamp};
|
||||
|
||||
use tuirealm::props::{Color, Style};
|
||||
use tuirealm::tui::text::{Span, Spans};
|
||||
use tuirealm::tui::widgets::Cell;
|
||||
|
||||
use crate::ui::theme::Theme;
|
||||
use crate::ui::widget::common::list::TableItem;
|
||||
|
||||
use super::widget::common::list::ListItem;
|
||||
use crate::ui::widget::list::{ListItem, TableItem};
|
||||
|
||||
/// An author item that can be used in tables, list or trees.
|
||||
///
|
||||
|
||||
+5
-1
@@ -1,4 +1,8 @@
|
||||
pub mod common;
|
||||
pub mod container;
|
||||
pub mod context;
|
||||
pub mod form;
|
||||
pub mod label;
|
||||
pub mod list;
|
||||
mod utils;
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
@@ -218,19 +218,19 @@ pub fn bar(
|
||||
label_3: &str,
|
||||
label_4: &str,
|
||||
) -> Widget<ContextBar> {
|
||||
let context = super::label(&format!(" {label_0} "))
|
||||
let context = crate::ui::label(&format!(" {label_0} "))
|
||||
.foreground(theme.colors.context_bg)
|
||||
.background(theme.colors.context_badge_bg);
|
||||
let id = super::label(&format!(" {label_1} "))
|
||||
let id = crate::ui::label(&format!(" {label_1} "))
|
||||
.foreground(theme.colors.context_color_fg)
|
||||
.background(theme.colors.context_bg);
|
||||
let title = super::label(&format!(" {label_2} "))
|
||||
let title = crate::ui::label(&format!(" {label_2} "))
|
||||
.foreground(theme.colors.default_fg)
|
||||
.background(theme.colors.context_bg);
|
||||
let author = super::label(&format!(" {label_3} "))
|
||||
let author = crate::ui::label(&format!(" {label_3} "))
|
||||
.foreground(theme.colors.context_light)
|
||||
.background(theme.colors.context_bg);
|
||||
let comments = super::label(&format!(" {label_4} "))
|
||||
let comments = crate::ui::label(&format!(" {label_4} "))
|
||||
.foreground(theme.colors.context_light)
|
||||
.background(theme.colors.context_bg);
|
||||
|
||||
@@ -25,11 +25,11 @@ impl TextField {
|
||||
.single_line(true)
|
||||
.cursor_line_style(Style::reset())
|
||||
.style(Style::default().fg(theme.colors.default_fg));
|
||||
let container = super::container(&theme, Box::new(input));
|
||||
let container = crate::ui::container(&theme, Box::new(input));
|
||||
|
||||
Self {
|
||||
input: container,
|
||||
placeholder: super::label(title).foreground(theme.colors.input_placeholder_fg),
|
||||
placeholder: crate::ui::label(title).foreground(theme.colors.input_placeholder_fg),
|
||||
show_placeholder: true,
|
||||
}
|
||||
}
|
||||
@@ -99,11 +99,11 @@ impl TextArea {
|
||||
.single_line(false)
|
||||
.cursor_line_style(Style::reset())
|
||||
.style(Style::default().fg(theme.colors.default_fg));
|
||||
let container = super::container(&theme, Box::new(input));
|
||||
let container = crate::ui::container(&theme, Box::new(input));
|
||||
|
||||
Self {
|
||||
input: container,
|
||||
placeholder: super::label(title).foreground(theme.colors.input_placeholder_fg),
|
||||
placeholder: crate::ui::label(title).foreground(theme.colors.input_placeholder_fg),
|
||||
show_placeholder: true,
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ use crate::ui::widget::{utils, Widget, WidgetComponent};
|
||||
|
||||
use super::container::Header;
|
||||
use super::label::Label;
|
||||
use super::*;
|
||||
|
||||
/// A generic item that can be displayed in a table with [`const W: usize`] columns.
|
||||
pub trait TableItem<const W: usize> {
|
||||
@@ -48,7 +47,7 @@ pub struct Property {
|
||||
|
||||
impl Property {
|
||||
pub fn new(name: Widget<Label>, value: Widget<Label>) -> Self {
|
||||
let divider = label("");
|
||||
let divider = crate::ui::label("");
|
||||
Self {
|
||||
name,
|
||||
divider,
|
||||
@@ -1,6 +1,6 @@
|
||||
use tuirealm::tui::layout::{Constraint, Rect};
|
||||
|
||||
use super::common::list::ColumnWidth;
|
||||
use super::list::ColumnWidth;
|
||||
|
||||
/// Calculates `Constraint::Percentage` for each fixed column width in `widths`,
|
||||
/// taking into account the available width in `area` and the column spacing given by `spacing`.
|
||||
|
||||
Reference in New Issue
Block a user