Update toss
This commit is contained in:
parent
b515ace906
commit
059ff94aef
41 changed files with 165 additions and 179 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
|
@ -1313,8 +1313,9 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toss"
|
name = "toss"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/Garmelon/toss.git?rev=0d59116012a51516a821991e2969b1cf4779770f#0d59116012a51516a821991e2969b1cf4779770f"
|
source = "git+https://github.com/Garmelon/toss.git?rev=59710c816269c434b97ece3ab1701d3fef2269cb#59710c816269c434b97ece3ab1701d3fef2269cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"unicode-linebreak",
|
"unicode-linebreak",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ features = ["bot"]
|
||||||
|
|
||||||
[dependencies.toss]
|
[dependencies.toss]
|
||||||
git = "https://github.com/Garmelon/toss.git"
|
git = "https://github.com/Garmelon/toss.git"
|
||||||
rev = "0d59116012a51516a821991e2969b1cf4779770f"
|
rev = "59710c816269c434b97ece3ab1701d3fef2269cb"
|
||||||
|
|
||||||
# [patch."https://github.com/Garmelon/toss.git"]
|
# [patch."https://github.com/Garmelon/toss.git"]
|
||||||
# toss = { path = "../toss/" }
|
# toss = { path = "../toss/" }
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use euphoxide::api::{MessageId, Snowflake, Time};
|
use euphoxide::api::{MessageId, Snowflake, Time};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled};
|
||||||
|
|
||||||
use crate::store::Msg;
|
use crate::store::Msg;
|
||||||
use crate::ui::ChatMsg;
|
use crate::ui::ChatMsg;
|
||||||
|
|
@ -35,7 +35,7 @@ enum Span {
|
||||||
|
|
||||||
struct Highlighter<'a> {
|
struct Highlighter<'a> {
|
||||||
content: &'a str,
|
content: &'a str,
|
||||||
base_style: ContentStyle,
|
base_style: Style,
|
||||||
exact: bool,
|
exact: bool,
|
||||||
|
|
||||||
span: Span,
|
span: Span,
|
||||||
|
|
@ -177,7 +177,7 @@ impl<'a> Highlighter<'a> {
|
||||||
self.room_or_mention_possible = !char.is_alphanumeric();
|
self.room_or_mention_possible = !char.is_alphanumeric();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight(content: &'a str, base_style: ContentStyle, exact: bool) -> Styled {
|
fn highlight(content: &'a str, base_style: Style, exact: bool) -> Styled {
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
content: if exact { content } else { content.trim() },
|
content: if exact { content } else { content.trim() },
|
||||||
base_style,
|
base_style,
|
||||||
|
|
@ -198,7 +198,7 @@ impl<'a> Highlighter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight_content(content: &str, base_style: ContentStyle, exact: bool) -> Styled {
|
fn highlight_content(content: &str, base_style: Style, exact: bool) -> Styled {
|
||||||
Highlighter::highlight(content, base_style, exact)
|
Highlighter::highlight(content, base_style, exact)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,13 +216,13 @@ fn as_me(content: &str) -> Option<&str> {
|
||||||
content.strip_prefix("/me")
|
content.strip_prefix("/me")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_me() -> ContentStyle {
|
fn style_me() -> Style {
|
||||||
ContentStyle::default().grey().italic()
|
Style::new().grey().italic()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn styled_nick(nick: &str) -> Styled {
|
fn styled_nick(nick: &str) -> Styled {
|
||||||
Styled::new_plain("[")
|
Styled::new_plain("[")
|
||||||
.and_then(util::style_nick(nick, ContentStyle::default()))
|
.and_then(util::style_nick(nick, Style::new()))
|
||||||
.then_plain("]")
|
.then_plain("]")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,7 +232,7 @@ fn styled_nick_me(nick: &str) -> Styled {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn styled_content(content: &str) -> Styled {
|
fn styled_content(content: &str) -> Styled {
|
||||||
highlight_content(content.trim(), ContentStyle::default(), false)
|
highlight_content(content.trim(), Style::new(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn styled_content_me(content: &str) -> Styled {
|
fn styled_content_me(content: &str) -> Styled {
|
||||||
|
|
@ -244,7 +244,7 @@ fn styled_editor_content(content: &str) -> Styled {
|
||||||
let style = if as_me(content).is_some() {
|
let style = if as_me(content).is_some() {
|
||||||
style_me()
|
style_me()
|
||||||
} else {
|
} else {
|
||||||
ContentStyle::default()
|
Style::new()
|
||||||
};
|
};
|
||||||
highlight_content(content, style, true)
|
highlight_content(content, style, true)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crossterm::style::{Color, ContentStyle, Stylize};
|
use crossterm::style::{Color, Stylize};
|
||||||
use euphoxide::Emoji;
|
use euphoxide::Emoji;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled};
|
||||||
|
|
||||||
pub static EMOJI: Lazy<Emoji> = Lazy::new(Emoji::load);
|
pub static EMOJI: Lazy<Emoji> = Lazy::new(Emoji::load);
|
||||||
|
|
||||||
|
|
@ -42,15 +42,15 @@ pub fn nick_color(nick: &str) -> (u8, u8, u8) {
|
||||||
hsl_to_rgb(hue, 1.0, 0.72)
|
hsl_to_rgb(hue, 1.0, 0.72)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nick_style(nick: &str, base: ContentStyle) -> ContentStyle {
|
pub fn nick_style(nick: &str, base: Style) -> Style {
|
||||||
let (r, g, b) = nick_color(nick);
|
let (r, g, b) = nick_color(nick);
|
||||||
base.bold().with(Color::Rgb { r, g, b })
|
base.bold().with(Color::Rgb { r, g, b })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn style_nick(nick: &str, base: ContentStyle) -> Styled {
|
pub fn style_nick(nick: &str, base: Style) -> Styled {
|
||||||
Styled::new(EMOJI.replace(nick), nick_style(nick, base))
|
Styled::new(EMOJI.replace(nick), nick_style(nick, base))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn style_nick_exact(nick: &str, base: ContentStyle) -> Styled {
|
pub fn style_nick_exact(nick: &str, base: Style) -> Styled {
|
||||||
Styled::new(nick, nick_style(nick, base))
|
Styled::new(nick, nick_style(nick, base))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@ use std::sync::Arc;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use log::{Level, LevelFilter, Log};
|
use log::{Level, LevelFilter, Log};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled};
|
||||||
|
|
||||||
use crate::store::{Msg, MsgStore, Path, Tree};
|
use crate::store::{Msg, MsgStore, Path, Tree};
|
||||||
use crate::ui::ChatMsg;
|
use crate::ui::ChatMsg;
|
||||||
|
|
@ -48,11 +48,11 @@ impl ChatMsg for LogMsg {
|
||||||
|
|
||||||
fn styled(&self) -> (Styled, Styled) {
|
fn styled(&self) -> (Styled, Styled) {
|
||||||
let nick_style = match self.level {
|
let nick_style = match self.level {
|
||||||
Level::Error => ContentStyle::default().bold().red(),
|
Level::Error => Style::new().bold().red(),
|
||||||
Level::Warn => ContentStyle::default().bold().yellow(),
|
Level::Warn => Style::new().bold().yellow(),
|
||||||
Level::Info => ContentStyle::default().bold().green(),
|
Level::Info => Style::new().bold().green(),
|
||||||
Level::Debug => ContentStyle::default().bold().blue(),
|
Level::Debug => Style::new().bold().blue(),
|
||||||
Level::Trace => ContentStyle::default().bold().magenta(),
|
Level::Trace => Style::new().bold().magenta(),
|
||||||
};
|
};
|
||||||
let nick = Styled::new(format!("{}", self.level), nick_style);
|
let nick = Styled::new(format!("{}", self.level), nick_style);
|
||||||
let content = Styled::new_plain(&self.content);
|
let content = Styled::new_plain(&self.content);
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ use cookie::CookieJar;
|
||||||
use directories::{BaseDirs, ProjectDirs};
|
use directories::{BaseDirs, ProjectDirs};
|
||||||
use log::info;
|
use log::info;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use toss::terminal::Terminal;
|
use toss::Terminal;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::logger::Logger;
|
use crate::logger::Logger;
|
||||||
|
|
|
||||||
21
src/ui.rs
21
src/ui.rs
|
|
@ -14,7 +14,7 @@ use parking_lot::FairMutex;
|
||||||
use tokio::sync::mpsc::error::TryRecvError;
|
use tokio::sync::mpsc::error::TryRecvError;
|
||||||
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
use toss::terminal::Terminal;
|
use toss::Terminal;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::logger::{LogMsg, Logger};
|
use crate::logger::{LogMsg, Logger};
|
||||||
|
|
@ -144,14 +144,7 @@ impl Ui {
|
||||||
terminal.present()?;
|
terminal.present()?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// 1. Measure grapheme widths if required
|
// 1. Handle events (in batches)
|
||||||
if terminal.measuring_required() {
|
|
||||||
let _guard = crossterm_lock.lock();
|
|
||||||
terminal.measure_widths()?;
|
|
||||||
ok_or_return!(self.event_tx.send(UiEvent::GraphemeWidthsChanged), Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Handle events (in batches)
|
|
||||||
let mut event = match event_rx.recv().await {
|
let mut event = match event_rx.recv().await {
|
||||||
Some(event) => event,
|
Some(event) => event,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
|
|
@ -174,12 +167,18 @@ impl Ui {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Render and present final state
|
|
||||||
if redraw {
|
if redraw {
|
||||||
|
// 2. Draw and present resulting state
|
||||||
terminal.autoresize()?;
|
terminal.autoresize()?;
|
||||||
terminal.frame().reset();
|
|
||||||
self.widget().await.render(terminal.frame()).await;
|
self.widget().await.render(terminal.frame()).await;
|
||||||
terminal.present()?;
|
terminal.present()?;
|
||||||
|
|
||||||
|
// 3. Measure grapheme widths
|
||||||
|
if terminal.measuring_required() {
|
||||||
|
let _guard = crossterm_lock.lock();
|
||||||
|
terminal.measure_widths()?;
|
||||||
|
ok_or_return!(self.event_tx.send(UiEvent::GraphemeWidthsChanged), Ok(()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,7 @@ use std::{fmt, io};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use parking_lot::FairMutex;
|
use parking_lot::FairMutex;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use toss::frame::{Frame, Size};
|
use toss::{Frame, Size, Styled, Terminal};
|
||||||
use toss::styled::Styled;
|
|
||||||
use toss::terminal::Terminal;
|
|
||||||
|
|
||||||
use crate::store::{Msg, MsgStore};
|
use crate::store::{Msg, MsgStore};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::collections::{vec_deque, VecDeque};
|
use std::collections::{vec_deque, VecDeque};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use toss::frame::Frame;
|
use toss::Frame;
|
||||||
|
|
||||||
use crate::macros::some_or_return;
|
use crate::macros::some_or_return;
|
||||||
use crate::ui::widgets::BoxedWidget;
|
use crate::ui::widgets::BoxedWidget;
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,7 @@ use std::sync::Arc;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use parking_lot::FairMutex;
|
use parking_lot::FairMutex;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use toss::frame::{Frame, Pos, Size};
|
use toss::{Frame, Pos, Size, Terminal};
|
||||||
use toss::terminal::Terminal;
|
|
||||||
|
|
||||||
use crate::macros::logging_unwrap;
|
use crate::macros::logging_unwrap;
|
||||||
use crate::store::{Msg, MsgStore};
|
use crate::store::{Msg, MsgStore};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use toss::frame::Frame;
|
use toss::Frame;
|
||||||
|
|
||||||
use crate::store::{Msg, MsgStore, Path, Tree};
|
use crate::store::{Msg, MsgStore, Path, Tree};
|
||||||
use crate::ui::chat::blocks::Block;
|
use crate::ui::chat::blocks::Block;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,8 @@ mod indent;
|
||||||
mod seen;
|
mod seen;
|
||||||
mod time;
|
mod time;
|
||||||
|
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled, WidthDb};
|
||||||
use toss::widthdb::WidthDb;
|
|
||||||
|
|
||||||
use super::super::ChatMsg;
|
use super::super::ChatMsg;
|
||||||
use crate::store::Msg;
|
use crate::store::Msg;
|
||||||
|
|
@ -19,36 +18,36 @@ use self::indent::Indent;
|
||||||
|
|
||||||
pub const PLACEHOLDER: &str = "[...]";
|
pub const PLACEHOLDER: &str = "[...]";
|
||||||
|
|
||||||
pub fn style_placeholder() -> ContentStyle {
|
pub fn style_placeholder() -> Style {
|
||||||
ContentStyle::default().dark_grey()
|
Style::new().dark_grey()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_time(highlighted: bool) -> ContentStyle {
|
fn style_time(highlighted: bool) -> Style {
|
||||||
if highlighted {
|
if highlighted {
|
||||||
ContentStyle::default().black().on_white()
|
Style::new().black().on_white()
|
||||||
} else {
|
} else {
|
||||||
ContentStyle::default().grey()
|
Style::new().grey()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_indent(highlighted: bool) -> ContentStyle {
|
fn style_indent(highlighted: bool) -> Style {
|
||||||
if highlighted {
|
if highlighted {
|
||||||
ContentStyle::default().black().on_white()
|
Style::new().black().on_white()
|
||||||
} else {
|
} else {
|
||||||
ContentStyle::default().dark_grey()
|
Style::new().dark_grey()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_info() -> ContentStyle {
|
fn style_info() -> Style {
|
||||||
ContentStyle::default().italic().dark_grey()
|
Style::new().italic().dark_grey()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_editor_highlight() -> ContentStyle {
|
fn style_editor_highlight() -> Style {
|
||||||
ContentStyle::default().black().on_cyan()
|
Style::new().black().on_cyan()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_pseudo_highlight() -> ContentStyle {
|
fn style_pseudo_highlight() -> Style {
|
||||||
ContentStyle::default().black().on_yellow()
|
Style::new().black().on_yellow()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn msg<M: Msg + ChatMsg>(
|
pub fn msg<M: Msg + ChatMsg>(
|
||||||
|
|
@ -74,7 +73,9 @@ pub fn msg<M: Msg + ChatMsg>(
|
||||||
),
|
),
|
||||||
Segment::new(Indent::new(indent, style_indent(highlighted))),
|
Segment::new(Indent::new(indent, style_indent(highlighted))),
|
||||||
Segment::new(Layer::new(vec![
|
Segment::new(Layer::new(vec![
|
||||||
Indent::new(1, style_indent(false)).into(),
|
Padding::new(Indent::new(1, style_indent(false)))
|
||||||
|
.top(1)
|
||||||
|
.into(),
|
||||||
Padding::new(Text::new(nick)).right(1).into(),
|
Padding::new(Text::new(nick)).right(1).into(),
|
||||||
])),
|
])),
|
||||||
// TODO Minimum content width
|
// TODO Minimum content width
|
||||||
|
|
@ -129,7 +130,9 @@ pub fn editor<M: ChatMsg>(
|
||||||
),
|
),
|
||||||
Segment::new(Indent::new(indent, style_editor_highlight())),
|
Segment::new(Indent::new(indent, style_editor_highlight())),
|
||||||
Segment::new(Layer::new(vec![
|
Segment::new(Layer::new(vec![
|
||||||
Indent::new(1, style_indent(false)).into(),
|
Padding::new(Indent::new(1, style_indent(false)))
|
||||||
|
.top(1)
|
||||||
|
.into(),
|
||||||
Padding::new(Text::new(nick)).right(1).into(),
|
Padding::new(Text::new(nick)).right(1).into(),
|
||||||
])),
|
])),
|
||||||
Segment::new(editor).priority(1).expanding(true),
|
Segment::new(editor).priority(1).expanding(true),
|
||||||
|
|
@ -151,7 +154,9 @@ pub fn pseudo<M: ChatMsg>(indent: usize, nick: &str, editor: &EditorState) -> Bo
|
||||||
),
|
),
|
||||||
Segment::new(Indent::new(indent, style_pseudo_highlight())),
|
Segment::new(Indent::new(indent, style_pseudo_highlight())),
|
||||||
Segment::new(Layer::new(vec![
|
Segment::new(Layer::new(vec![
|
||||||
Indent::new(1, style_indent(false)).into(),
|
Padding::new(Indent::new(1, style_indent(false)))
|
||||||
|
.top(1)
|
||||||
|
.into(),
|
||||||
Padding::new(Text::new(nick)).right(1).into(),
|
Padding::new(Text::new(nick)).right(1).into(),
|
||||||
])),
|
])),
|
||||||
Segment::new(Text::new(content).wrap(true)).priority(1),
|
Segment::new(Text::new(content).wrap(true)).priority(1),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use crossterm::style::ContentStyle;
|
use toss::{Frame, Pos, Size, Style};
|
||||||
use toss::frame::{Frame, Pos, Size};
|
|
||||||
|
|
||||||
use crate::ui::widgets::Widget;
|
use crate::ui::widgets::Widget;
|
||||||
|
|
||||||
|
|
@ -9,11 +8,11 @@ pub const INDENT_WIDTH: usize = 2;
|
||||||
|
|
||||||
pub struct Indent {
|
pub struct Indent {
|
||||||
level: usize,
|
level: usize,
|
||||||
style: ContentStyle,
|
style: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Indent {
|
impl Indent {
|
||||||
pub fn new(level: usize, style: ContentStyle) -> Self {
|
pub fn new(level: usize, style: Style) -> Self {
|
||||||
Self { level, style }
|
Self { level, style }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
|
use toss::Style;
|
||||||
|
|
||||||
use crate::ui::widgets::background::Background;
|
use crate::ui::widgets::background::Background;
|
||||||
use crate::ui::widgets::empty::Empty;
|
use crate::ui::widgets::empty::Empty;
|
||||||
|
|
@ -8,8 +9,8 @@ use crate::ui::widgets::BoxedWidget;
|
||||||
const UNSEEN: &str = "*";
|
const UNSEEN: &str = "*";
|
||||||
const WIDTH: u16 = 1;
|
const WIDTH: u16 = 1;
|
||||||
|
|
||||||
fn seen_style() -> ContentStyle {
|
fn seen_style() -> Style {
|
||||||
ContentStyle::default().black().on_green()
|
Style::new().black().on_green()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn widget(seen: bool) -> BoxedWidget {
|
pub fn widget(seen: bool) -> BoxedWidget {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crossterm::style::ContentStyle;
|
|
||||||
use time::format_description::FormatItem;
|
use time::format_description::FormatItem;
|
||||||
use time::macros::format_description;
|
use time::macros::format_description;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
use toss::Style;
|
||||||
|
|
||||||
use crate::ui::widgets::background::Background;
|
use crate::ui::widgets::background::Background;
|
||||||
use crate::ui::widgets::empty::Empty;
|
use crate::ui::widgets::empty::Empty;
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::ui::widgets::BoxedWidget;
|
||||||
const TIME_FORMAT: &[FormatItem<'_>] = format_description!("[year]-[month]-[day] [hour]:[minute]");
|
const TIME_FORMAT: &[FormatItem<'_>] = format_description!("[year]-[month]-[day] [hour]:[minute]");
|
||||||
const TIME_WIDTH: u16 = 16;
|
const TIME_WIDTH: u16 = 16;
|
||||||
|
|
||||||
pub fn widget(time: Option<OffsetDateTime>, style: ContentStyle) -> BoxedWidget {
|
pub fn widget(time: Option<OffsetDateTime>, style: Style) -> BoxedWidget {
|
||||||
if let Some(time) = time {
|
if let Some(time) = time {
|
||||||
let text = time.format(TIME_FORMAT).expect("could not format time");
|
let text = time.format(TIME_FORMAT).expect("could not format time");
|
||||||
Background::new(Text::new((text, style)))
|
Background::new(Text::new((text, style)))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use euphoxide::api::PersonalAccountView;
|
use euphoxide::api::PersonalAccountView;
|
||||||
use euphoxide::conn;
|
use euphoxide::conn;
|
||||||
use toss::terminal::Terminal;
|
use toss::{Style, Terminal};
|
||||||
|
|
||||||
use crate::euph::{self, Room};
|
use crate::euph::{self, Room};
|
||||||
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
||||||
|
|
@ -36,7 +36,7 @@ impl LoggedOut {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn widget(&self) -> BoxedWidget {
|
fn widget(&self) -> BoxedWidget {
|
||||||
let bold = ContentStyle::default().bold();
|
let bold = Style::new().bold();
|
||||||
VJoin::new(vec![
|
VJoin::new(vec![
|
||||||
Segment::new(Text::new(("Not logged in", bold.yellow()))),
|
Segment::new(Text::new(("Not logged in", bold.yellow()))),
|
||||||
Segment::new(Empty::new().height(1)),
|
Segment::new(Empty::new().height(1)),
|
||||||
|
|
@ -64,7 +64,7 @@ pub struct LoggedIn(PersonalAccountView);
|
||||||
|
|
||||||
impl LoggedIn {
|
impl LoggedIn {
|
||||||
fn widget(&self) -> BoxedWidget {
|
fn widget(&self) -> BoxedWidget {
|
||||||
let bold = ContentStyle::default().bold();
|
let bold = Style::new().bold();
|
||||||
VJoin::new(vec![
|
VJoin::new(vec![
|
||||||
Segment::new(Text::new(("Logged in", bold.green()))),
|
Segment::new(Text::new(("Logged in", bold.green()))),
|
||||||
Segment::new(Empty::new().height(1)),
|
Segment::new(Empty::new().height(1)),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use toss::terminal::Terminal;
|
use toss::Terminal;
|
||||||
|
|
||||||
use crate::euph::Room;
|
use crate::euph::Room;
|
||||||
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use euphoxide::api::{Message, NickEvent, SessionView};
|
use euphoxide::api::{Message, NickEvent, SessionView};
|
||||||
use euphoxide::conn::SessionInfo;
|
use euphoxide::conn::SessionInfo;
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled};
|
||||||
|
|
||||||
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
||||||
use crate::ui::widgets::popup::Popup;
|
use crate::ui::widgets::popup::Popup;
|
||||||
|
|
@ -11,31 +11,33 @@ use crate::ui::widgets::BoxedWidget;
|
||||||
macro_rules! line {
|
macro_rules! line {
|
||||||
( $text:ident, $name:expr, $val:expr ) => {
|
( $text:ident, $name:expr, $val:expr ) => {
|
||||||
$text = $text
|
$text = $text
|
||||||
.then($name, ContentStyle::default().cyan())
|
.then($name, Style::new().cyan())
|
||||||
.then_plain(format!(" {}\n", $val));
|
.then_plain(format!(" {}\n", $val));
|
||||||
};
|
};
|
||||||
( $text:ident, $name:expr, $val:expr, debug ) => {
|
( $text:ident, $name:expr, $val:expr, debug ) => {
|
||||||
$text = $text
|
$text = $text
|
||||||
.then($name, ContentStyle::default().cyan())
|
.then($name, Style::new().cyan())
|
||||||
.then_plain(format!(" {:?}\n", $val));
|
.then_plain(format!(" {:?}\n", $val));
|
||||||
};
|
};
|
||||||
( $text:ident, $name:expr, $val:expr, optional ) => {
|
( $text:ident, $name:expr, $val:expr, optional ) => {
|
||||||
if let Some(val) = $val {
|
if let Some(val) = $val {
|
||||||
$text = $text
|
$text = $text
|
||||||
.then($name, ContentStyle::default().cyan())
|
.then($name, Style::new().cyan())
|
||||||
.then_plain(format!(" {val}\n"));
|
.then_plain(format!(" {val}\n"));
|
||||||
} else {
|
} else {
|
||||||
$text = $text
|
$text = $text
|
||||||
.then($name, ContentStyle::default().cyan())
|
.then($name, Style::new().cyan())
|
||||||
.then_plain(" ")
|
.then_plain(" ")
|
||||||
.then("none", ContentStyle::default().italic().grey())
|
.then("none", Style::new().italic().grey())
|
||||||
.then_plain("\n");
|
.then_plain("\n");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
( $text:ident, $name:expr, $val:expr, yes or no ) => {
|
( $text:ident, $name:expr, $val:expr, yes or no ) => {
|
||||||
$text = $text
|
$text = $text.then($name, Style::new().cyan()).then_plain(if $val {
|
||||||
.then($name, ContentStyle::default().cyan())
|
" yes\n"
|
||||||
.then_plain(if $val { " yes\n" } else { " no\n" });
|
} else {
|
||||||
|
" no\n"
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,7 +89,7 @@ fn message_lines(mut text: Styled, msg: &Message) -> Styled {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn session_widget(session: &SessionInfo) -> BoxedWidget {
|
pub fn session_widget(session: &SessionInfo) -> BoxedWidget {
|
||||||
let heading_style = ContentStyle::default().bold();
|
let heading_style = Style::new().bold();
|
||||||
|
|
||||||
let text = match session {
|
let text = match session {
|
||||||
SessionInfo::Full(session) => {
|
SessionInfo::Full(session) => {
|
||||||
|
|
@ -104,7 +106,7 @@ pub fn session_widget(session: &SessionInfo) -> BoxedWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message_widget(msg: &Message) -> BoxedWidget {
|
pub fn message_widget(msg: &Message) -> BoxedWidget {
|
||||||
let heading_style = ContentStyle::default().bold();
|
let heading_style = Style::new().bold();
|
||||||
|
|
||||||
let mut text = Styled::new("Message", heading_style).then_plain("\n");
|
let mut text = Styled::new("Message", heading_style).then_plain("\n");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use linkify::{LinkFinder, LinkKind};
|
use linkify::{LinkFinder, LinkKind};
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled};
|
||||||
|
|
||||||
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
||||||
use crate::ui::widgets::list::ListState;
|
use crate::ui::widgets::list::ListState;
|
||||||
|
|
@ -40,22 +40,16 @@ impl LinksState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn widget(&self) -> BoxedWidget {
|
pub fn widget(&self) -> BoxedWidget {
|
||||||
let style_selected = ContentStyle::default().black().on_white();
|
let style_selected = Style::new().black().on_white();
|
||||||
|
|
||||||
let mut list = self.list.widget().focus(true);
|
let mut list = self.list.widget().focus(true);
|
||||||
if self.links.is_empty() {
|
if self.links.is_empty() {
|
||||||
list.add_unsel(Text::new((
|
list.add_unsel(Text::new(("No links found", Style::new().grey().italic())))
|
||||||
"No links found",
|
|
||||||
ContentStyle::default().grey().italic(),
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
for (id, link) in self.links.iter().enumerate() {
|
for (id, link) in self.links.iter().enumerate() {
|
||||||
let (line_normal, line_selected) = if let Some(number_key) = NUMBER_KEYS.get(id) {
|
let (line_normal, line_selected) = if let Some(number_key) = NUMBER_KEYS.get(id) {
|
||||||
(
|
(
|
||||||
Styled::new(
|
Styled::new(format!("[{number_key}]"), Style::new().dark_grey().bold())
|
||||||
format!("[{number_key}]"),
|
|
||||||
ContentStyle::default().dark_grey().bold(),
|
|
||||||
)
|
|
||||||
.then_plain(" ")
|
.then_plain(" ")
|
||||||
.then_plain(link),
|
.then_plain(link),
|
||||||
Styled::new(format!("[{number_key}]"), style_selected.bold())
|
Styled::new(format!("[{number_key}]"), style_selected.bold())
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use crossterm::style::ContentStyle;
|
|
||||||
use euphoxide::conn::Joined;
|
use euphoxide::conn::Joined;
|
||||||
use toss::terminal::Terminal;
|
use toss::{Style, Terminal};
|
||||||
|
|
||||||
use crate::euph::{self, Room};
|
use crate::euph::{self, Room};
|
||||||
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
use crate::ui::input::{key, InputEvent, KeyBindingsList};
|
||||||
|
|
@ -17,7 +16,7 @@ pub fn new(joined: Joined) -> EditorState {
|
||||||
pub fn widget(editor: &EditorState) -> BoxedWidget {
|
pub fn widget(editor: &EditorState) -> BoxedWidget {
|
||||||
let editor = editor
|
let editor = editor
|
||||||
.widget()
|
.widget()
|
||||||
.highlight(|s| euph::style_nick_exact(s, ContentStyle::default()));
|
.highlight(|s| euph::style_nick_exact(s, Style::new()));
|
||||||
Popup::new(Padding::new(editor).left(1))
|
Popup::new(Padding::new(editor).left(1))
|
||||||
.title("Choose nick")
|
.title("Choose nick")
|
||||||
.inner_padding(false)
|
.inner_padding(false)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use crossterm::style::{Color, ContentStyle, Stylize};
|
use crossterm::style::{Color, Stylize};
|
||||||
use euphoxide::api::{NickEvent, SessionId, SessionType, SessionView, UserId};
|
use euphoxide::api::{NickEvent, SessionId, SessionType, SessionView, UserId};
|
||||||
use euphoxide::conn::{Joined, SessionInfo};
|
use euphoxide::conn::{Joined, SessionInfo};
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled};
|
||||||
|
|
||||||
use crate::euph;
|
use crate::euph;
|
||||||
use crate::ui::widgets::background::Background;
|
use crate::ui::widgets::background::Background;
|
||||||
|
|
@ -98,7 +98,7 @@ fn render_section(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let heading_style = ContentStyle::new().bold();
|
let heading_style = Style::new().bold();
|
||||||
|
|
||||||
if !list.is_empty() {
|
if !list.is_empty() {
|
||||||
list.add_unsel(Empty::new());
|
list.add_unsel(Empty::new());
|
||||||
|
|
@ -117,16 +117,16 @@ fn render_section(
|
||||||
fn render_row(list: &mut List<SessionId>, session: &HalfSession, own_session: &SessionView) {
|
fn render_row(list: &mut List<SessionId>, session: &HalfSession, own_session: &SessionView) {
|
||||||
let (name, style, style_inv, perms_style_inv) = if session.name.is_empty() {
|
let (name, style, style_inv, perms_style_inv) = if session.name.is_empty() {
|
||||||
let name = "lurk";
|
let name = "lurk";
|
||||||
let style = ContentStyle::default().grey();
|
let style = Style::new().grey();
|
||||||
let style_inv = ContentStyle::default().black().on_grey();
|
let style_inv = Style::new().black().on_grey();
|
||||||
(Cow::Borrowed(name), style, style_inv, style_inv)
|
(Cow::Borrowed(name), style, style_inv, style_inv)
|
||||||
} else {
|
} else {
|
||||||
let name = &session.name as &str;
|
let name = &session.name as &str;
|
||||||
let (r, g, b) = euph::nick_color(name);
|
let (r, g, b) = euph::nick_color(name);
|
||||||
let color = Color::Rgb { r, g, b };
|
let color = Color::Rgb { r, g, b };
|
||||||
let style = ContentStyle::default().bold().with(color);
|
let style = Style::new().bold().with(color);
|
||||||
let style_inv = ContentStyle::default().bold().black().on(color);
|
let style_inv = Style::new().bold().black().on(color);
|
||||||
let perms_style_inv = ContentStyle::default().black().on(color);
|
let perms_style_inv = Style::new().black().on(color);
|
||||||
(euph::EMOJI.replace(name), style, style_inv, perms_style_inv)
|
(euph::EMOJI.replace(name), style, style_inv, perms_style_inv)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled};
|
||||||
|
|
||||||
use crate::ui::widgets::float::Float;
|
use crate::ui::widgets::float::Float;
|
||||||
use crate::ui::widgets::popup::Popup;
|
use crate::ui::widgets::popup::Popup;
|
||||||
|
|
@ -12,10 +12,10 @@ pub enum RoomPopup {
|
||||||
|
|
||||||
impl RoomPopup {
|
impl RoomPopup {
|
||||||
fn server_error_widget(description: &str, reason: &str) -> BoxedWidget {
|
fn server_error_widget(description: &str, reason: &str) -> BoxedWidget {
|
||||||
let border_style = ContentStyle::default().red().bold();
|
let border_style = Style::new().red().bold();
|
||||||
let text = Styled::new_plain(description)
|
let text = Styled::new_plain(description)
|
||||||
.then_plain("\n\n")
|
.then_plain("\n\n")
|
||||||
.then("Reason:", ContentStyle::default().bold())
|
.then("Reason:", Style::new().bold())
|
||||||
.then_plain(" ")
|
.then_plain(" ")
|
||||||
.then_plain(reason);
|
.then_plain(reason);
|
||||||
Popup::new(Text::new(text))
|
Popup::new(Text::new(text))
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use euphoxide::api::{Data, Message, MessageId, PacketType, SessionId};
|
use euphoxide::api::{Data, Message, MessageId, PacketType, SessionId};
|
||||||
use euphoxide::bot::instance::{Event, ServerConfig};
|
use euphoxide::bot::instance::{Event, ServerConfig};
|
||||||
use euphoxide::conn::{self, Joined, Joining, SessionInfo};
|
use euphoxide::conn::{self, Joined, Joining, SessionInfo};
|
||||||
use parking_lot::FairMutex;
|
use parking_lot::FairMutex;
|
||||||
use tokio::sync::oneshot::error::TryRecvError;
|
use tokio::sync::oneshot::error::TryRecvError;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled, Terminal};
|
||||||
use toss::terminal::Terminal;
|
|
||||||
|
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::euph;
|
use crate::euph;
|
||||||
|
|
@ -277,7 +276,7 @@ impl EuphRoom {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn status_widget(&self, state: Option<&euph::State>) -> BoxedWidget {
|
async fn status_widget(&self, state: Option<&euph::State>) -> BoxedWidget {
|
||||||
let room_style = ContentStyle::default().bold().blue();
|
let room_style = Style::new().bold().blue();
|
||||||
let mut info = Styled::new(format!("&{}", self.name()), room_style);
|
let mut info = Styled::new(format!("&{}", self.name()), room_style);
|
||||||
|
|
||||||
info = match state {
|
info = match state {
|
||||||
|
|
@ -296,7 +295,7 @@ impl EuphRoom {
|
||||||
info.then_plain(", present without nick")
|
info.then_plain(", present without nick")
|
||||||
} else {
|
} else {
|
||||||
info.then_plain(", present as ")
|
info.then_plain(", present as ")
|
||||||
.and_then(euph::style_nick(nick, ContentStyle::default()))
|
.and_then(euph::style_nick(nick, Style::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -305,7 +304,7 @@ impl EuphRoom {
|
||||||
if unseen > 0 {
|
if unseen > 0 {
|
||||||
info = info
|
info = info
|
||||||
.then_plain(" (")
|
.then_plain(" (")
|
||||||
.then(format!("{unseen}"), ContentStyle::default().bold().green())
|
.then(format!("{unseen}"), Style::new().bold().green())
|
||||||
.then_plain(")");
|
.then_plain(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
|
|
||||||
use crossterm::event::{Event, KeyCode, KeyModifiers};
|
use crossterm::event::{Event, KeyCode, KeyModifiers};
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled};
|
||||||
|
|
||||||
use super::widgets::background::Background;
|
use super::widgets::background::Background;
|
||||||
use super::widgets::border::Border;
|
use super::widgets::border::Border;
|
||||||
|
|
@ -94,8 +94,8 @@ impl KeyBindingsList {
|
||||||
Self(state.widget())
|
Self(state.widget())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binding_style() -> ContentStyle {
|
fn binding_style() -> Style {
|
||||||
ContentStyle::default().cyan()
|
Style::new().cyan()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn widget(self) -> BoxedWidget {
|
pub fn widget(self) -> BoxedWidget {
|
||||||
|
|
@ -124,8 +124,7 @@ impl KeyBindingsList {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn heading(&mut self, name: &str) {
|
pub fn heading(&mut self, name: &str) {
|
||||||
self.0
|
self.0.add_unsel(Text::new((name, Style::new().bold())));
|
||||||
.add_unsel(Text::new((name, ContentStyle::default().bold())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn binding(&mut self, binding: &str, description: &str) {
|
pub fn binding(&mut self, binding: &str, description: &str) {
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,13 @@ use std::collections::{HashMap, HashSet};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use euphoxide::api::SessionType;
|
use euphoxide::api::SessionType;
|
||||||
use euphoxide::bot::instance::{Event, ServerConfig};
|
use euphoxide::bot::instance::{Event, ServerConfig};
|
||||||
use euphoxide::conn::{self, Joined};
|
use euphoxide::conn::{self, Joined};
|
||||||
use parking_lot::FairMutex;
|
use parking_lot::FairMutex;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use toss::styled::Styled;
|
use toss::{Style, Styled, Terminal};
|
||||||
use toss::terminal::Terminal;
|
|
||||||
|
|
||||||
use crate::config::{Config, RoomsSortOrder};
|
use crate::config::{Config, RoomsSortOrder};
|
||||||
use crate::euph;
|
use crate::euph;
|
||||||
|
|
@ -199,7 +198,7 @@ impl Rooms {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_room_widget(editor: &EditorState) -> BoxedWidget {
|
fn new_room_widget(editor: &EditorState) -> BoxedWidget {
|
||||||
let room_style = ContentStyle::default().bold().blue();
|
let room_style = Style::new().bold().blue();
|
||||||
let editor = editor.widget().highlight(|s| Styled::new(s, room_style));
|
let editor = editor.widget().highlight(|s| Styled::new(s, room_style));
|
||||||
Popup::new(HJoin::new(vec![
|
Popup::new(HJoin::new(vec![
|
||||||
Segment::new(Text::new(("&", room_style))),
|
Segment::new(Text::new(("&", room_style))),
|
||||||
|
|
@ -210,8 +209,8 @@ impl Rooms {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_room_widget(name: &str, editor: &EditorState) -> BoxedWidget {
|
fn delete_room_widget(name: &str, editor: &EditorState) -> BoxedWidget {
|
||||||
let warn_style = ContentStyle::default().bold().red();
|
let warn_style = Style::new().bold().red();
|
||||||
let room_style = ContentStyle::default().bold().blue();
|
let room_style = Style::new().bold().blue();
|
||||||
let editor = editor.widget().highlight(|s| Styled::new(s, room_style));
|
let editor = editor.widget().highlight(|s| Styled::new(s, room_style));
|
||||||
let text = Styled::new_plain("Are you sure you want to delete ")
|
let text = Styled::new_plain("Are you sure you want to delete ")
|
||||||
.then("&", room_style)
|
.then("&", room_style)
|
||||||
|
|
@ -219,7 +218,7 @@ impl Rooms {
|
||||||
.then_plain("?\n\n")
|
.then_plain("?\n\n")
|
||||||
.then_plain("This will delete the entire room history from your vault. ")
|
.then_plain("This will delete the entire room history from your vault. ")
|
||||||
.then_plain("To shrink your vault afterwards, run ")
|
.then_plain("To shrink your vault afterwards, run ")
|
||||||
.then("cove gc", ContentStyle::default().italic().grey())
|
.then("cove gc", Style::new().italic().grey())
|
||||||
.then_plain(".\n\n")
|
.then_plain(".\n\n")
|
||||||
.then_plain("To confirm the deletion, ")
|
.then_plain("To confirm the deletion, ")
|
||||||
.then_plain("enter the full name of the room and press enter:");
|
.then_plain("enter the full name of the room and press enter:");
|
||||||
|
|
@ -304,7 +303,7 @@ impl Rooms {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_room_info(state: Option<&euph::State>, unseen: usize) -> Styled {
|
fn format_room_info(state: Option<&euph::State>, unseen: usize) -> Styled {
|
||||||
let unseen_style = ContentStyle::default().bold().green();
|
let unseen_style = Style::new().bold().green();
|
||||||
|
|
||||||
let state = Self::format_room_state(state);
|
let state = Self::format_room_state(state);
|
||||||
let unseen = Self::format_unseen_msgs(unseen);
|
let unseen = Self::format_unseen_msgs(unseen);
|
||||||
|
|
@ -336,7 +335,7 @@ impl Rooms {
|
||||||
if self.euph_rooms.is_empty() {
|
if self.euph_rooms.is_empty() {
|
||||||
list.add_unsel(Text::new((
|
list.add_unsel(Text::new((
|
||||||
"Press F1 for key bindings",
|
"Press F1 for key bindings",
|
||||||
ContentStyle::default().grey().italic(),
|
Style::new().grey().italic(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -348,8 +347,8 @@ impl Rooms {
|
||||||
}
|
}
|
||||||
self.sort_rooms(&mut rooms);
|
self.sort_rooms(&mut rooms);
|
||||||
for (name, state, unseen) in rooms {
|
for (name, state, unseen) in rooms {
|
||||||
let room_style = ContentStyle::default().bold().blue();
|
let room_style = Style::new().bold().blue();
|
||||||
let room_sel_style = ContentStyle::default().bold().black().on_white();
|
let room_sel_style = Style::new().bold().black().on_white();
|
||||||
|
|
||||||
let mut normal = Styled::new(format!("&{name}"), room_style);
|
let mut normal = Styled::new(format!("&{name}"), room_style);
|
||||||
let mut selected = Styled::new(format!("&{name}"), room_sel_style);
|
let mut selected = Styled::new(format!("&{name}"), room_sel_style);
|
||||||
|
|
@ -363,7 +362,7 @@ impl Rooms {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn rooms_widget(&self) -> BoxedWidget {
|
async fn rooms_widget(&self) -> BoxedWidget {
|
||||||
let heading_style = ContentStyle::default().bold();
|
let heading_style = Style::new().bold();
|
||||||
let amount = self.euph_rooms.len();
|
let amount = self.euph_rooms.len();
|
||||||
let heading =
|
let heading =
|
||||||
Text::new(Styled::new("Rooms", heading_style).then_plain(format!(" ({amount})")));
|
Text::new(Styled::new("Rooms", heading_style).then_plain(format!(" ({amount})")));
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::io;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use parking_lot::FairMutex;
|
use parking_lot::FairMutex;
|
||||||
use toss::terminal::Terminal;
|
use toss::Terminal;
|
||||||
|
|
||||||
use super::input::{key, InputEvent, KeyBindingsList};
|
use super::input::{key, InputEvent, KeyBindingsList};
|
||||||
use super::widgets::editor::EditorState;
|
use super::widgets::editor::EditorState;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ pub mod rules;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Size};
|
use toss::{Frame, Size};
|
||||||
|
|
||||||
// TODO Add Error type and return Result-s (at least in Widget::render)
|
// TODO Add Error type and return Result-s (at least in Widget::render)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,22 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use crossterm::style::ContentStyle;
|
use toss::{Frame, Pos, Size, Style};
|
||||||
use toss::frame::{Frame, Pos, Size};
|
|
||||||
|
|
||||||
use super::{BoxedWidget, Widget};
|
use super::{BoxedWidget, Widget};
|
||||||
|
|
||||||
pub struct Background {
|
pub struct Background {
|
||||||
inner: BoxedWidget,
|
inner: BoxedWidget,
|
||||||
style: ContentStyle,
|
style: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Background {
|
impl Background {
|
||||||
pub fn new<W: Into<BoxedWidget>>(inner: W) -> Self {
|
pub fn new<W: Into<BoxedWidget>>(inner: W) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: inner.into(),
|
inner: inner.into(),
|
||||||
style: ContentStyle::default(),
|
style: Style::new().opaque(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn style(mut self, style: ContentStyle) -> Self {
|
pub fn style(mut self, style: Style) -> Self {
|
||||||
self.style = style;
|
self.style = style;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,22 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use crossterm::style::ContentStyle;
|
use toss::{Frame, Pos, Size, Style};
|
||||||
use toss::frame::{Frame, Pos, Size};
|
|
||||||
|
|
||||||
use super::{BoxedWidget, Widget};
|
use super::{BoxedWidget, Widget};
|
||||||
|
|
||||||
pub struct Border {
|
pub struct Border {
|
||||||
inner: BoxedWidget,
|
inner: BoxedWidget,
|
||||||
style: ContentStyle,
|
style: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Border {
|
impl Border {
|
||||||
pub fn new<W: Into<BoxedWidget>>(inner: W) -> Self {
|
pub fn new<W: Into<BoxedWidget>>(inner: W) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: inner.into(),
|
inner: inner.into(),
|
||||||
style: ContentStyle::default(),
|
style: Style::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn style(mut self, style: ContentStyle) -> Self {
|
pub fn style(mut self, style: Style) -> Self {
|
||||||
self.style = style;
|
self.style = style;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Pos, Size};
|
use toss::{Frame, Pos, Size};
|
||||||
|
|
||||||
use super::{BoxedWidget, Widget};
|
use super::{BoxedWidget, Widget};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,9 @@ use std::sync::Arc;
|
||||||
use std::{io, iter};
|
use std::{io, iter};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::Stylize;
|
||||||
use parking_lot::{FairMutex, Mutex};
|
use parking_lot::{FairMutex, Mutex};
|
||||||
use toss::frame::{Frame, Pos, Size};
|
use toss::{Frame, Pos, Size, Style, Styled, Terminal, WidthDb};
|
||||||
use toss::styled::Styled;
|
|
||||||
use toss::terminal::Terminal;
|
|
||||||
use toss::widthdb::WidthDb;
|
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use crate::ui::util;
|
use crate::ui::util;
|
||||||
|
|
@ -461,7 +458,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hidden(self) -> Self {
|
pub fn hidden(self) -> Self {
|
||||||
self.hidden_with_placeholder(("<hidden>", ContentStyle::default().grey().italic()))
|
self.hidden_with_placeholder(("<hidden>", Style::new().grey().italic()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hidden_with_placeholder<S: Into<Styled>>(mut self, placeholder: S) -> Self {
|
pub fn hidden_with_placeholder<S: Into<Styled>>(mut self, placeholder: S) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Size};
|
use toss::{Frame, Size};
|
||||||
|
|
||||||
use super::Widget;
|
use super::Widget;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Pos, Size};
|
use toss::{Frame, Pos, Size};
|
||||||
|
|
||||||
use super::{BoxedWidget, Widget};
|
use super::{BoxedWidget, Widget};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Pos, Size};
|
use toss::{Frame, Pos, Size};
|
||||||
|
|
||||||
use super::{BoxedWidget, Widget};
|
use super::{BoxedWidget, Widget};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Size};
|
use toss::{Frame, Size};
|
||||||
|
|
||||||
use super::{BoxedWidget, Widget};
|
use super::{BoxedWidget, Widget};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use toss::frame::{Frame, Pos, Size};
|
use toss::{Frame, Pos, Size};
|
||||||
|
|
||||||
use super::{BoxedWidget, Widget};
|
use super::{BoxedWidget, Widget};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Pos, Size};
|
use toss::{Frame, Pos, Size};
|
||||||
|
|
||||||
use super::{BoxedWidget, Widget};
|
use super::{BoxedWidget, Widget};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use crossterm::style::ContentStyle;
|
use toss::{Style, Styled};
|
||||||
use toss::styled::Styled;
|
|
||||||
|
|
||||||
use super::background::Background;
|
use super::background::Background;
|
||||||
use super::border::Border;
|
use super::border::Border;
|
||||||
|
|
@ -13,8 +12,8 @@ pub struct Popup {
|
||||||
inner: BoxedWidget,
|
inner: BoxedWidget,
|
||||||
inner_padding: bool,
|
inner_padding: bool,
|
||||||
title: Option<Styled>,
|
title: Option<Styled>,
|
||||||
border_style: ContentStyle,
|
border_style: Style,
|
||||||
bg_style: ContentStyle,
|
bg_style: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Popup {
|
impl Popup {
|
||||||
|
|
@ -23,8 +22,8 @@ impl Popup {
|
||||||
inner: inner.into(),
|
inner: inner.into(),
|
||||||
inner_padding: true,
|
inner_padding: true,
|
||||||
title: None,
|
title: None,
|
||||||
border_style: ContentStyle::default(),
|
border_style: Style::new(),
|
||||||
bg_style: ContentStyle::default(),
|
bg_style: Style::new().opaque(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,12 +37,12 @@ impl Popup {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn border(mut self, style: ContentStyle) -> Self {
|
pub fn border(mut self, style: Style) -> Self {
|
||||||
self.border_style = style;
|
self.border_style = style;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn background(mut self, style: ContentStyle) -> Self {
|
pub fn background(mut self, style: Style) -> Self {
|
||||||
self.bg_style = style;
|
self.bg_style = style;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Size};
|
use toss::{Frame, Size};
|
||||||
|
|
||||||
use super::{BoxedWidget, Widget};
|
use super::{BoxedWidget, Widget};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Pos, Size};
|
use toss::{Frame, Pos, Size};
|
||||||
|
|
||||||
use super::Widget;
|
use super::Widget;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use toss::frame::{Frame, Pos, Size};
|
use toss::{Frame, Pos, Size, Styled, WidthDb};
|
||||||
use toss::styled::Styled;
|
|
||||||
use toss::widthdb::WidthDb;
|
|
||||||
|
|
||||||
use super::Widget;
|
use super::Widget;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue