mirror of
https://github.com/Xithrius/twitch-tui.git
synced 2024-09-11 05:35:26 +03:00
Added support for inversion of scrolling (#270)
This commit is contained in:
parent
21488160f7
commit
3d6d8b9701
@ -53,3 +53,5 @@ theme = "dark"
|
||||
username_highlight = true
|
||||
# The shape of the cursor, block (default), underscore, or line.
|
||||
cursor_shape = "block"
|
||||
# If the scrolling should be inverted.
|
||||
inverted_scrolling = false
|
||||
|
@ -61,7 +61,44 @@ impl ToString for State {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Scrolling {
|
||||
/// Offset of scroll
|
||||
offset: usize,
|
||||
/// If the scrolling is currently inverted
|
||||
inverted: bool,
|
||||
}
|
||||
|
||||
impl Scrolling {
|
||||
pub const fn new(inverted: bool) -> Self {
|
||||
Self {
|
||||
offset: 0,
|
||||
inverted,
|
||||
}
|
||||
}
|
||||
|
||||
/// Scrolling upwards, towards the start of the chat
|
||||
pub fn up(&mut self) {
|
||||
self.offset += 1;
|
||||
}
|
||||
|
||||
/// Scrolling downwards, towards the most recent message(s)
|
||||
pub fn down(&mut self) {
|
||||
self.offset = self.offset.saturating_sub(1);
|
||||
}
|
||||
|
||||
pub const fn inverted(&self) -> bool {
|
||||
self.inverted
|
||||
}
|
||||
|
||||
pub fn jump_to(&mut self, index: usize) {
|
||||
self.offset = index;
|
||||
}
|
||||
|
||||
pub const fn get_offset(&self) -> usize {
|
||||
self.offset
|
||||
}
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
/// History of recorded messages (time, username, message, etc.)
|
||||
pub messages: VecDeque<Data>,
|
||||
@ -75,8 +112,8 @@ pub struct App {
|
||||
pub input_buffer: LineBuffer,
|
||||
/// The current suggestion, if any
|
||||
pub buffer_suggestion: Option<String>,
|
||||
/// Scrolling offset for the main window
|
||||
pub scroll_offset: usize,
|
||||
/// Interactions with scrolling of the application
|
||||
pub scrolling: Scrolling,
|
||||
/// The theme selected by the user
|
||||
pub theme_style: Style,
|
||||
}
|
||||
@ -90,11 +127,11 @@ impl App {
|
||||
state: config.terminal.start_state.clone(),
|
||||
input_buffer: LineBuffer::with_capacity(INPUT_BUFFER_LIMIT),
|
||||
buffer_suggestion: None,
|
||||
scroll_offset: 0,
|
||||
theme_style: match config.frontend.theme {
|
||||
Theme::Light => BORDER_NAME_LIGHT,
|
||||
_ => BORDER_NAME_DARK,
|
||||
},
|
||||
scrolling: Scrolling::new(config.frontend.inverted_scrolling),
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,6 +142,25 @@ impl App {
|
||||
pub fn clear_messages(&mut self) {
|
||||
self.messages.clear();
|
||||
|
||||
self.scroll_offset = 0;
|
||||
self.scrolling.jump_to(0);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn rotate_theme(&mut self) {
|
||||
todo!("Rotate through different themes")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_no_scroll_overflow_not_inverted() {
|
||||
let mut scroll = Scrolling::new(false);
|
||||
assert_eq!(scroll.get_offset(), 0);
|
||||
|
||||
scroll.down();
|
||||
assert_eq!(scroll.get_offset(), 0);
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +107,8 @@ pub struct FrontendConfig {
|
||||
pub state_tabs: bool,
|
||||
/// The shape of the cursor in insert boxes.
|
||||
pub cursor_shape: CursorType,
|
||||
/// If the scrolling should be inverted
|
||||
pub inverted_scrolling: bool,
|
||||
}
|
||||
|
||||
impl Default for TwitchConfig {
|
||||
@ -147,6 +149,7 @@ impl Default for FrontendConfig {
|
||||
username_highlight: true,
|
||||
state_tabs: false,
|
||||
cursor_shape: CursorType::default(),
|
||||
inverted_scrolling: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,19 +188,29 @@ async fn handle_insert_type_movements(action: &mut UserActionAttributes<'_, '_>)
|
||||
|
||||
fn handle_user_scroll(app: &mut App, key: Key) {
|
||||
match app.state {
|
||||
State::Insert | State::MessageSearch | State::Normal => match key {
|
||||
Key::ScrollUp => {
|
||||
if app.scroll_offset < app.messages.len() {
|
||||
app.scroll_offset += 1;
|
||||
State::Insert | State::MessageSearch | State::Normal => {
|
||||
let limit = app.scrolling.get_offset() < app.messages.len();
|
||||
|
||||
match key {
|
||||
Key::ScrollUp => {
|
||||
if limit {
|
||||
app.scrolling.up();
|
||||
} else if app.scrolling.inverted() {
|
||||
app.scrolling.down();
|
||||
}
|
||||
}
|
||||
}
|
||||
Key::ScrollDown => {
|
||||
if app.scroll_offset > 0 {
|
||||
app.scroll_offset -= 1;
|
||||
Key::ScrollDown => {
|
||||
if app.scrolling.inverted() {
|
||||
if limit {
|
||||
app.scrolling.up();
|
||||
}
|
||||
} else {
|
||||
app.scrolling.down();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -251,7 +261,8 @@ pub async fn handle_stateful_user_input(
|
||||
return Some(TerminalAction::Quitting);
|
||||
}
|
||||
Key::Esc => {
|
||||
app.scroll_offset = 0;
|
||||
app.scrolling.jump_to(0);
|
||||
|
||||
app.state = State::Normal;
|
||||
}
|
||||
_ => {}
|
||||
|
@ -119,8 +119,8 @@ pub async fn ui_driver(
|
||||
app.messages.push_front(info);
|
||||
|
||||
// If scrolling is enabled, pad for more messages.
|
||||
if app.scroll_offset > 0 {
|
||||
app.scroll_offset += 1;
|
||||
if app.scrolling.get_offset() > 0 {
|
||||
app.scrolling.up();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ pub fn draw_ui<T: Backend>(frame: &mut Frame<T>, app: &mut App, config: &Complet
|
||||
let mut total_row_height: usize = 0;
|
||||
let mut display_rows = VecDeque::new();
|
||||
|
||||
let mut scroll_offset = app.scroll_offset;
|
||||
let mut scroll_offset = app.scrolling.get_offset();
|
||||
|
||||
let mut total_num_search_results = 0;
|
||||
'outer: for data in &app.messages {
|
||||
|
Loading…
Reference in New Issue
Block a user