From 73c71a931947189b5e88bb2cc51895bb194478c1 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Wed, 15 May 2024 23:00:05 +0200 Subject: [PATCH 1/6] ci(rust): improve workflow --- .github/workflows/coverage.yml | 11 +++---- .github/workflows/rust.yml | 58 ++++++++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index b35d9a5d..b917173b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -9,6 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup Rust + id: rust uses: dtolnay/rust-toolchain@master with: toolchain: stable @@ -20,15 +21,11 @@ jobs: tool: cargo-llvm-cov - uses: actions/checkout@v4 - + - run: cargo fetch - uses: actions/cache@v4 with: - key: coverage-${{ hashFiles('**/Cargo.lock') }} - path: | - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ + key: coverage-${{ steps.rust.outputs.cachekey }}-${{ hashFiles('**/Cargo.*') }} + path: target/ - name: Run cargo-llvm-cov run: cargo llvm-cov --all-features --html diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0cb116cf..adc9ca2f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -5,6 +5,10 @@ on: pull_request: workflow_dispatch: +env: + CARGO_INCREMENTAL: 0 + CARGO_TERM_COLOR: always + jobs: rustfmt: runs-on: ubuntu-latest @@ -32,15 +36,45 @@ jobs: RUSTFLAGS: --deny warnings steps: - name: Setup Rust + id: rust uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.toolchain }} components: clippy - uses: actions/checkout@v4 - - run: cargo fetch --locked + - run: cargo fetch + - uses: actions/cache@v4 + with: + key: clippy-${{ steps.rust.outputs.cachekey }}-${{ hashFiles('**/Cargo.*') }} + path: target/ - run: cargo clippy --offline --all-targets - run: cargo doc --offline --no-deps + msrv: # minimum supported Rust version + name: MSRV ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - macos-latest + - windows-latest + env: + RUSTFLAGS: --allow unknown-lints --deny warnings + steps: + - name: Install cargo-hack + uses: taiki-e/install-action@v2 + with: + tool: cargo-hack + - uses: actions/checkout@v4 + - run: cargo fetch --locked + - uses: actions/cache@v4 + with: + key: msrv-${{ matrix.os }}-${{ hashFiles('**/Cargo.*') }} + path: target/ + - run: cargo hack --keep-going --feature-powerset --no-dev-deps --rust-version check --offline + test: name: Test ${{ matrix.toolchain }} ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -52,27 +86,28 @@ jobs: - stable - beta - nightly - - 1.74 # MSRV: minimum supported Rust version os: - ubuntu-latest - macos-latest - windows-latest - env: - RUSTFLAGS: --allow unknown-lints --deny warnings steps: - name: Setup Rust + id: rust uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.toolchain }} - uses: actions/checkout@v4 - - run: cargo fetch --locked + - run: cargo fetch + - uses: actions/cache@v4 + with: + key: test-${{ matrix.os }}-${{ steps.rust.outputs.cachekey }}-${{ hashFiles('**/Cargo.*') }} + path: target/ - run: cargo build --offline --all-targets - - run: cargo test --offline + - run: cargo test --offline --no-fail-fast - github-release: + release: name: Release ${{ matrix.triple }} runs-on: ${{ matrix.os }} - needs: test permissions: contents: write strategy: @@ -103,9 +138,10 @@ jobs: - triple: aarch64-pc-windows-msvc os: windows-latest env: - RUSTFLAGS: --allow unknown-lints --deny warnings + RUSTFLAGS: --deny warnings steps: - name: Setup Rust + id: rust uses: dtolnay/rust-toolchain@master with: toolchain: stable @@ -133,6 +169,10 @@ jobs: echo "ARTIFACT_NAME=$name" >> $GITHUB_ENV - run: cargo fetch --locked + - uses: actions/cache@v4 + with: + key: release-${{ matrix.triple }}-${{ steps.rust.outputs.cachekey }}-${{ hashFiles('**/Cargo.*') }} + path: target/ - name: Build run: ${{ runner.os == 'Linux' && 'cross' || 'cargo' }} build --release --offline --target ${{ matrix.triple }} From 2f58393288601b8053f968679e4431f852d68940 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Wed, 15 May 2024 23:13:10 +0200 Subject: [PATCH 2/6] refactor: update to tree widget v0.20 --- Cargo.lock | 3 +- Cargo.toml | 2 +- src/interactive/details/mod.rs | 6 +- src/interactive/mod.rs | 111 ++++-------------------------- src/interactive/topic_overview.rs | 2 +- 5 files changed, 19 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77264412..ae18e7b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1424,8 +1424,7 @@ dependencies = [ [[package]] name = "tui-tree-widget" version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0c6f924587e719c50b8f83485afbe4d4c16edca6b641d5d9a3204edeba5cf0" +source = "git+https://github.com/EdJoPaTo/tui-rs-tree-widget#fc2495396fa2f0f97dca1b1357411e58b0a75e35" dependencies = [ "ratatui", "unicode-width", diff --git a/Cargo.toml b/Cargo.toml index ef82cdf6..d27e1d7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ rustls-pemfile = "2" rustls-pki-types = "1" serde = { version = "1", features = ["derive"] } serde_json = "1" -tui-tree-widget = "0.19" +tui-tree-widget = { git = "https://github.com/EdJoPaTo/tui-rs-tree-widget" } url = "2" # https://crates.io/crates/cargo-deb diff --git a/src/interactive/details/mod.rs b/src/interactive/details/mod.rs index cb219ec5..a73fdb7b 100644 --- a/src/interactive/details/mod.rs +++ b/src/interactive/details/mod.rs @@ -61,10 +61,10 @@ impl Details { entry, ); let binary_address = self.payload.binary_state.selected_address(); - let json_selector = self.payload.json_state.selected(); + let json_selector = self.payload.json_state.get_selected(); let table_area = - graph::Graph::parse(topic_history, binary_address.unwrap_or(0), &json_selector).map_or( + graph::Graph::parse(topic_history, binary_address.unwrap_or(0), json_selector).map_or( history_area, |graph| { let (table_area, graph_area) = @@ -79,7 +79,7 @@ impl Details { table_area, topic_history, binary_address, - &json_selector, + json_selector, &mut self.table_state, matches!(focus, ElementInFocus::HistoryTable), ); diff --git a/src/interactive/mod.rs b/src/interactive/mod.rs index 36fc18f0..9da965b5 100644 --- a/src/interactive/mod.rs +++ b/src/interactive/mod.rs @@ -7,11 +7,10 @@ use ratatui::text::Span; use ratatui::widgets::Paragraph; use ratatui::{Frame, Terminal}; use rumqttc::{Client, Connection}; -use tui_tree_widget::TreeItem; use self::ui::ElementInFocus; use crate::cli::Broker; -use crate::payload::{tree_items_from_json, tree_items_from_messagepack, Payload}; +use crate::payload::Payload; mod clean_retained; mod details; @@ -161,11 +160,6 @@ impl App { } } - fn get_topic_tree_items(&self) -> Vec> { - let (_topics, _messages, items) = self.mqtt_thread.get_history().to_tree_items(); - items - } - fn can_switch_to_history_table(&self) -> bool { let Some(topic) = self.topic_overview.get_selected() else { return false; @@ -228,24 +222,12 @@ impl App { } KeyCode::Esc => self.topic_overview.state.select(vec![]), KeyCode::Enter | KeyCode::Char(' ') => self.topic_overview.state.toggle_selected(), - KeyCode::Down | KeyCode::Char('j') => { - let items = self.get_topic_tree_items(); - self.topic_overview.state.key_down(&items) - } - KeyCode::Up | KeyCode::Char('k') => { - let items = self.get_topic_tree_items(); - self.topic_overview.state.key_up(&items) - } + KeyCode::Down | KeyCode::Char('j') => self.topic_overview.state.key_down(), + KeyCode::Up | KeyCode::Char('k') => self.topic_overview.state.key_up(), KeyCode::Left | KeyCode::Char('h') => self.topic_overview.state.key_left(), KeyCode::Right | KeyCode::Char('l') => self.topic_overview.state.key_right(), - KeyCode::Home => { - let items = self.get_topic_tree_items(); - self.topic_overview.state.select_first(&items) - } - KeyCode::End => { - let items = self.get_topic_tree_items(); - self.topic_overview.state.select_last(&items) - } + KeyCode::Home => self.topic_overview.state.select_first(), + KeyCode::End => self.topic_overview.state.select_last(), KeyCode::PageUp => { let page_jump = (self.topic_overview.last_area.height / 3) as usize; self.topic_overview.state.scroll_up(page_jump) @@ -357,18 +339,16 @@ impl App { } _ => false, }, - Some(Payload::Json(json)) => match key.code { + Some(Payload::Json(_) | Payload::MessagePack(_)) => match key.code { KeyCode::Esc => self.details.payload.json_state.select(vec![]), KeyCode::Enter | KeyCode::Char(' ') => { self.details.payload.json_state.toggle_selected() } KeyCode::Down | KeyCode::Char('j') => { - let items = tree_items_from_json(&json); - self.details.payload.json_state.key_down(&items) + self.details.payload.json_state.key_down() } KeyCode::Up | KeyCode::Char('k') => { - let items = tree_items_from_json(&json); - self.details.payload.json_state.key_up(&items) + self.details.payload.json_state.key_up() } KeyCode::Left | KeyCode::Char('h') => { self.details.payload.json_state.key_left() @@ -376,51 +356,8 @@ impl App { KeyCode::Right | KeyCode::Char('l') => { self.details.payload.json_state.key_right() } - KeyCode::Home => { - let items = tree_items_from_json(&json); - self.details.payload.json_state.select_first(&items) - } - KeyCode::End => { - let items = tree_items_from_json(&json); - self.details.payload.json_state.select_last(&items) - } - KeyCode::PageUp => self.details.payload.json_state.scroll_up(3), - KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => { - self.details.payload.json_state.scroll_up(3) - } - KeyCode::PageDown => self.details.payload.json_state.scroll_down(3), - KeyCode::Char('d') if key.modifiers.contains(KeyModifiers::CONTROL) => { - self.details.payload.json_state.scroll_down(3) - } - _ => false, - }, - Some(Payload::MessagePack(messagepack)) => match key.code { - KeyCode::Esc => self.details.payload.json_state.select(vec![]), - KeyCode::Enter | KeyCode::Char(' ') => { - self.details.payload.json_state.toggle_selected() - } - KeyCode::Down | KeyCode::Char('j') => { - let items = tree_items_from_messagepack(&messagepack); - self.details.payload.json_state.key_down(&items) - } - KeyCode::Up | KeyCode::Char('k') => { - let items = tree_items_from_messagepack(&messagepack); - self.details.payload.json_state.key_up(&items) - } - KeyCode::Left | KeyCode::Char('h') => { - self.details.payload.json_state.key_left() - } - KeyCode::Right | KeyCode::Char('l') => { - self.details.payload.json_state.key_right() - } - KeyCode::Home => { - let items = tree_items_from_messagepack(&messagepack); - self.details.payload.json_state.select_first(&items) - } - KeyCode::End => { - let items = tree_items_from_messagepack(&messagepack); - self.details.payload.json_state.select_last(&items) - } + KeyCode::Home => self.details.payload.json_state.select_first(), + KeyCode::End => self.details.payload.json_state.select_last(), KeyCode::PageUp => self.details.payload.json_state.scroll_up(3), KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => { self.details.payload.json_state.scroll_up(3) @@ -560,11 +497,7 @@ impl App { fn on_click(&mut self, column: u16, row: u16) -> Refresh { if let Some(index) = self.topic_overview.index_of_click(column, row) { - let items = self.get_topic_tree_items(); - let changed = self - .topic_overview - .state - .select_visible_index(&items, index); + let changed = self.topic_overview.state.select_visible_index(index); if !changed { self.topic_overview.state.toggle_selected(); } @@ -590,26 +523,8 @@ impl App { return Refresh::Update; } } - Some(Payload::Json(json)) => { - let items = tree_items_from_json(&json); - let changed = self - .details - .payload - .json_state - .select_visible_index(&items, index); - if !changed { - self.details.payload.json_state.toggle_selected(); - } - self.focus = ElementInFocus::Payload; - return Refresh::Update; - } - Some(Payload::MessagePack(messagepack)) => { - let items = tree_items_from_messagepack(&messagepack); - let changed = self - .details - .payload - .json_state - .select_visible_index(&items, index); + Some(Payload::Json(_) | Payload::MessagePack(_)) => { + let changed = self.details.payload.json_state.select_visible_index(index); if !changed { self.details.payload.json_state.toggle_selected(); } diff --git a/src/interactive/topic_overview.rs b/src/interactive/topic_overview.rs index 0d021f38..d4e5dc50 100644 --- a/src/interactive/topic_overview.rs +++ b/src/interactive/topic_overview.rs @@ -15,7 +15,7 @@ pub struct TopicOverview { impl TopicOverview { pub fn get_selected(&self) -> Option { - let selected = self.state.selected(); + let selected = self.state.get_selected(); if selected.is_empty() { return None; } From 25ea7abe0c910aca9f56e5e53476ee00b69da22f Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Thu, 16 May 2024 10:24:34 +0200 Subject: [PATCH 3/6] refactor: items by reference --- Cargo.lock | 2 +- src/interactive/details/payload_view.rs | 4 ++-- src/interactive/mod.rs | 5 +---- src/interactive/topic_overview.rs | 18 ++++++------------ 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae18e7b1..4914e188 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1424,7 +1424,7 @@ dependencies = [ [[package]] name = "tui-tree-widget" version = "0.19.0" -source = "git+https://github.com/EdJoPaTo/tui-rs-tree-widget#fc2495396fa2f0f97dca1b1357411e58b0a75e35" +source = "git+https://github.com/EdJoPaTo/tui-rs-tree-widget#b07b537067e22dcf684342ccef1a52ff9d637da0" dependencies = [ "ratatui", "unicode-width", diff --git a/src/interactive/details/payload_view.rs b/src/interactive/details/payload_view.rs index bc1ee4da..789d95b1 100644 --- a/src/interactive/details/payload_view.rs +++ b/src/interactive/details/payload_view.rs @@ -111,7 +111,7 @@ impl PayloadView { let (payload_area, remaining_area) = self.areas(area, has_focus, content_height); let focus_color = focus_color(has_focus); - let widget = Tree::new(items) + let widget = Tree::new(&items) .unwrap() .experimental_scrollbar(Some( Scrollbar::new(ScrollbarOrientation::VerticalRight) @@ -151,7 +151,7 @@ impl PayloadView { let (payload_area, remaining_area) = self.areas(area, has_focus, content_height); let focus_color = focus_color(has_focus); - let widget = Tree::new(items) + let widget = Tree::new(&items) .unwrap() .experimental_scrollbar(Some( Scrollbar::new(ScrollbarOrientation::VerticalRight) diff --git a/src/interactive/mod.rs b/src/interactive/mod.rs index 9da965b5..47f13e10 100644 --- a/src/interactive/mod.rs +++ b/src/interactive/mod.rs @@ -685,13 +685,10 @@ impl App { } }); - let (topic_amount, message_amount, tree_items) = history.to_tree_items(); self.topic_overview.draw( frame, overview_area, - topic_amount, - message_amount, - tree_items, + &history, matches!(self.focus, ElementInFocus::TopicOverview), ); drop(history); diff --git a/src/interactive/topic_overview.rs b/src/interactive/topic_overview.rs index d4e5dc50..817f6926 100644 --- a/src/interactive/topic_overview.rs +++ b/src/interactive/topic_overview.rs @@ -2,9 +2,10 @@ use ratatui::layout::{Alignment, Rect}; use ratatui::style::{Color, Style}; use ratatui::widgets::{Block, BorderType, Scrollbar, ScrollbarOrientation}; use ratatui::Frame; -use tui_tree_widget::{Tree, TreeItem, TreeState}; +use tui_tree_widget::{Tree, TreeState}; -use crate::interactive::ui::{focus_color, get_row_inside, BORDERS_TOP_RIGHT}; +use super::mqtt_history::MqttHistory; +use super::ui::{focus_color, get_row_inside, BORDERS_TOP_RIGHT}; #[derive(Default)] pub struct TopicOverview { @@ -22,18 +23,11 @@ impl TopicOverview { Some(selected.join("/")) } - pub fn draw( - &mut self, - frame: &mut Frame, - area: Rect, - topic_amount: usize, - message_amount: usize, - tree_items: Vec>, - has_focus: bool, - ) { + pub fn draw(&mut self, frame: &mut Frame, area: Rect, history: &MqttHistory, has_focus: bool) { + let (topic_amount, message_amount, tree_items) = history.to_tree_items(); let title = format!("Topics ({topic_amount}, {message_amount} messages)"); let focus_color = focus_color(has_focus); - let widget = Tree::new(tree_items) + let widget = Tree::new(&tree_items) .unwrap() .experimental_scrollbar(Some( Scrollbar::new(ScrollbarOrientation::VerticalRight) From 9ba4c6b403b7c71296a0dc4afe89bdccc527a864 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Tue, 21 May 2024 11:59:50 +0200 Subject: [PATCH 4/6] refactor: use updated ratatui-binary-data-widget --- Cargo.lock | 2 +- src/interactive/mod.rs | 16 +++------------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77264412..4f12bbc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -914,7 +914,7 @@ dependencies = [ [[package]] name = "ratatui-binary-data-widget" version = "0.1.0" -source = "git+https://github.com/EdJoPaTo/ratatui-binary-data-widget?branch=main#dcc0ef5e9492b6e638d0bf0ca0e9eb94f47e3795" +source = "git+https://github.com/EdJoPaTo/ratatui-binary-data-widget?branch=main#4405e4547d25917f217a810920813bf1a00de1fc" dependencies = [ "ratatui", ] diff --git a/src/interactive/mod.rs b/src/interactive/mod.rs index 36fc18f0..5f030700 100644 --- a/src/interactive/mod.rs +++ b/src/interactive/mod.rs @@ -576,19 +576,9 @@ impl App { match self.get_selected_payload() { None => return Refresh::Update, // No payload but click into payload area -> redraw Some(Payload::Binary(_)) => { - if let Some(address) = self - .details - .payload - .binary_state - .clicked_address(column, row) - { - self.details - .payload - .binary_state - .select_address(Some(address)); - self.focus = ElementInFocus::Payload; - return Refresh::Update; - } + self.details.payload.binary_state.select_at(column, row); + self.focus = ElementInFocus::Payload; + return Refresh::Update; } Some(Payload::Json(json)) => { let items = tree_items_from_json(&json); From 75693367f8d936d014d9bacd804213a2446afe9c Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Wed, 22 May 2024 08:36:43 +0200 Subject: [PATCH 5/6] refactor(tree): use click/rendered_at --- Cargo.lock | 2 +- src/interactive/details/mod.rs | 12 ++++---- src/interactive/details/payload_view.rs | 11 +------- src/interactive/mod.rs | 37 ++++++++++++++++--------- src/interactive/topic_overview.rs | 12 +------- src/interactive/ui.rs | 34 +---------------------- 6 files changed, 34 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4914e188..9c8a7cc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1424,7 +1424,7 @@ dependencies = [ [[package]] name = "tui-tree-widget" version = "0.19.0" -source = "git+https://github.com/EdJoPaTo/tui-rs-tree-widget#b07b537067e22dcf684342ccef1a52ff9d637da0" +source = "git+https://github.com/EdJoPaTo/tui-rs-tree-widget#d23f55b2ad2ce830da64d8ec44f044633ed5b65e" dependencies = [ "ratatui", "unicode-width", diff --git a/src/interactive/details/mod.rs b/src/interactive/details/mod.rs index a73fdb7b..df9b63fe 100644 --- a/src/interactive/details/mod.rs +++ b/src/interactive/details/mod.rs @@ -24,20 +24,20 @@ impl Details { .min(topic_history_length.saturating_sub(1)) } - const fn table_index_of_click(&self, column: u16, row: u16) -> Option { + const fn table_index_of_click(&self, position: Position) -> Option { let area = self.last_table_area; - if !area.contains(Position { x: column, y: row }) { + if !area.contains(position) { return None; } - let visible = row.saturating_sub(area.top()).saturating_sub(2); // subtract block & header + let visible_index = position.y.saturating_sub(area.top()).saturating_sub(2); // subtract block & header let offset = self.table_state.offset(); - let index = (visible as usize) + offset; + let index = (visible_index as usize) + offset; Some(index) } /// Handles a click. Checks if its on the table. When it is the index get selected and true is returned. - pub fn table_click(&mut self, column: u16, row: u16) -> bool { - let Some(index) = self.table_index_of_click(column, row) else { + pub fn table_click(&mut self, position: Position) -> bool { + let Some(index) = self.table_index_of_click(position) else { return false; }; self.table_state.select(Some(index)); diff --git a/src/interactive/details/payload_view.rs b/src/interactive/details/payload_view.rs index 789d95b1..ee47c545 100644 --- a/src/interactive/details/payload_view.rs +++ b/src/interactive/details/payload_view.rs @@ -8,9 +8,7 @@ use ratatui::Frame; use ratatui_binary_data_widget::{BinaryDataWidget, BinaryDataWidgetState}; use tui_tree_widget::{Tree, TreeState}; -use crate::interactive::ui::{ - focus_color, get_row_inside, split_area_vertically, BORDERS_TOP_RIGHT, -}; +use crate::interactive::ui::{focus_color, split_area_vertically, BORDERS_TOP_RIGHT}; use crate::mqtt::HistoryEntry; use crate::payload::{tree_items_from_json, tree_items_from_messagepack, JsonSelector, Payload}; @@ -40,13 +38,6 @@ impl PayloadView { } } - pub fn json_index_of_click(&self, column: u16, row: u16) -> Option { - get_row_inside(self.last_area, column, row).map(|index| { - let offset = self.json_state.get_offset(); - (index as usize) + offset - }) - } - fn areas(&mut self, area: Rect, has_focus: bool, content_height: usize) -> (Rect, Rect) { let max_payload_height = if has_focus { area.height.saturating_mul(2) / 3 diff --git a/src/interactive/mod.rs b/src/interactive/mod.rs index 47f13e10..25544f82 100644 --- a/src/interactive/mod.rs +++ b/src/interactive/mod.rs @@ -2,7 +2,7 @@ use std::time::{Duration, Instant}; use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEventKind}; use ratatui::backend::{Backend, CrosstermBackend}; -use ratatui::layout::{Alignment, Rect}; +use ratatui::layout::{Alignment, Position, Rect}; use ratatui::text::Span; use ratatui::widgets::Paragraph; use ratatui::{Frame, Terminal}; @@ -496,16 +496,30 @@ impl App { } fn on_click(&mut self, column: u16, row: u16) -> Refresh { - if let Some(index) = self.topic_overview.index_of_click(column, row) { - let changed = self.topic_overview.state.select_visible_index(index); - if !changed { - self.topic_overview.state.toggle_selected(); + let position = Position::new(column, row); + + if let Some(identifier) = self.topic_overview.state.rendered_at(position) { + let is_already_selected = identifier == self.topic_overview.state.get_selected(); + if is_already_selected { + // change focus or toggle, don't do both + if matches!(self.focus, ElementInFocus::TopicOverview) { + self.topic_overview.state.toggle_selected(); + } else { + self.focus = ElementInFocus::TopicOverview; + } + } else { + self.focus = ElementInFocus::TopicOverview; + self.topic_overview.state.select(identifier.to_vec()); } + + return Refresh::Update; + } + if self.topic_overview.state.click_at(position) { self.focus = ElementInFocus::TopicOverview; return Refresh::Update; } - if let Some(index) = self.details.payload.json_index_of_click(column, row) { + if self.details.payload.last_area.contains(position) { match self.get_selected_payload() { None => return Refresh::Update, // No payload but click into payload area -> redraw Some(Payload::Binary(_)) => { @@ -519,15 +533,12 @@ impl App { .payload .binary_state .select_address(Some(address)); - self.focus = ElementInFocus::Payload; - return Refresh::Update; } + self.focus = ElementInFocus::Payload; + return Refresh::Update; } Some(Payload::Json(_) | Payload::MessagePack(_)) => { - let changed = self.details.payload.json_state.select_visible_index(index); - if !changed { - self.details.payload.json_state.toggle_selected(); - } + self.details.payload.json_state.click_at(position); self.focus = ElementInFocus::Payload; return Refresh::Update; } @@ -535,7 +546,7 @@ impl App { } } - if self.details.table_click(column, row) { + if self.details.table_click(position) { self.focus = ElementInFocus::HistoryTable; return Refresh::Update; } diff --git a/src/interactive/topic_overview.rs b/src/interactive/topic_overview.rs index 817f6926..e878c9b0 100644 --- a/src/interactive/topic_overview.rs +++ b/src/interactive/topic_overview.rs @@ -5,7 +5,7 @@ use ratatui::Frame; use tui_tree_widget::{Tree, TreeState}; use super::mqtt_history::MqttHistory; -use super::ui::{focus_color, get_row_inside, BORDERS_TOP_RIGHT}; +use super::ui::{focus_color, BORDERS_TOP_RIGHT}; #[derive(Default)] pub struct TopicOverview { @@ -47,14 +47,4 @@ impl TopicOverview { frame.render_stateful_widget(widget, area, &mut self.state); self.last_area = area; } - - pub const fn index_of_click(&self, column: u16, row: u16) -> Option { - if let Some(index) = get_row_inside(self.last_area, column, row) { - let offset = self.state.get_offset(); - let new_index = (index as usize) + offset; - Some(new_index) - } else { - None - } - } } diff --git a/src/interactive/ui.rs b/src/interactive/ui.rs index b4402286..1a37cce6 100644 --- a/src/interactive/ui.rs +++ b/src/interactive/ui.rs @@ -1,4 +1,4 @@ -use ratatui::layout::{Position, Rect}; +use ratatui::layout::Rect; use ratatui::style::{Color, Modifier, Style}; use ratatui::widgets::Borders; @@ -21,38 +21,6 @@ pub const fn focus_color(has_focus: bool) -> Color { } } -/// When the column/row is inside the area, return the row relative to the area. -/// Otherwise `None` is returned. -pub const fn get_row_inside(area: Rect, column: u16, row: u16) -> Option { - #[allow(clippy::if_then_some_else_none)] - if area.contains(Position { x: column, y: row }) { - Some(row.saturating_sub(area.top()).saturating_sub(1)) - } else { - None - } -} - -#[test] -fn row_outside() { - let area = Rect::new(5, 5, 5, 10); - let result = get_row_inside(area, 7, 1); - assert_eq!(result, None); -} - -#[test] -fn column_outside() { - let area = Rect::new(5, 5, 5, 10); - let result = get_row_inside(area, 1, 7); - assert_eq!(result, None); -} - -#[test] -fn is_inside() { - let area = Rect::new(5, 5, 5, 10); - let result = get_row_inside(area, 7, 10); - assert_eq!(result, Some(4)); -} - pub const fn split_area_vertically(area: Rect, height_first: u16) -> (Rect, Rect) { let first = Rect { height: height_first, From af51f2ea2a020a9f66ba46af95384ef9e329e0b7 Mon Sep 17 00:00:00 2001 From: EdJoPaTo Date: Wed, 22 May 2024 15:13:42 +0200 Subject: [PATCH 6/6] rerfactor: adapt to method renaming --- Cargo.lock | 2 +- src/interactive/details/mod.rs | 2 +- src/interactive/mod.rs | 2 +- src/interactive/topic_overview.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index faf5140e..0eca6339 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1424,7 +1424,7 @@ dependencies = [ [[package]] name = "tui-tree-widget" version = "0.19.0" -source = "git+https://github.com/EdJoPaTo/tui-rs-tree-widget#d23f55b2ad2ce830da64d8ec44f044633ed5b65e" +source = "git+https://github.com/EdJoPaTo/tui-rs-tree-widget#051f49fd7260613b7058a325a24913a51881b0f4" dependencies = [ "ratatui", "unicode-width", diff --git a/src/interactive/details/mod.rs b/src/interactive/details/mod.rs index df9b63fe..803006f6 100644 --- a/src/interactive/details/mod.rs +++ b/src/interactive/details/mod.rs @@ -61,7 +61,7 @@ impl Details { entry, ); let binary_address = self.payload.binary_state.selected_address(); - let json_selector = self.payload.json_state.get_selected(); + let json_selector = self.payload.json_state.selected(); let table_area = graph::Graph::parse(topic_history, binary_address.unwrap_or(0), json_selector).map_or( diff --git a/src/interactive/mod.rs b/src/interactive/mod.rs index 0bf70c56..79c40fff 100644 --- a/src/interactive/mod.rs +++ b/src/interactive/mod.rs @@ -499,7 +499,7 @@ impl App { let position = Position::new(column, row); if let Some(identifier) = self.topic_overview.state.rendered_at(position) { - let is_already_selected = identifier == self.topic_overview.state.get_selected(); + let is_already_selected = identifier == self.topic_overview.state.selected(); if is_already_selected { // change focus or toggle, don't do both if matches!(self.focus, ElementInFocus::TopicOverview) { diff --git a/src/interactive/topic_overview.rs b/src/interactive/topic_overview.rs index e878c9b0..d301e74e 100644 --- a/src/interactive/topic_overview.rs +++ b/src/interactive/topic_overview.rs @@ -16,7 +16,7 @@ pub struct TopicOverview { impl TopicOverview { pub fn get_selected(&self) -> Option { - let selected = self.state.get_selected(); + let selected = self.state.selected(); if selected.is_empty() { return None; }