Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package kubetui for openSUSE:Factory checked in at 2025-12-09 12:47:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kubetui (Old) and /work/SRC/openSUSE:Factory/.kubetui.new.1939 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kubetui" Tue Dec 9 12:47:17 2025 rev:17 rq:1321515 version:1.11.0 Changes: -------- --- /work/SRC/openSUSE:Factory/kubetui/kubetui.changes 2025-12-05 16:55:06.592555034 +0100 +++ /work/SRC/openSUSE:Factory/.kubetui.new.1939/kubetui.changes 2025-12-09 12:53:40.480317424 +0100 @@ -1,0 +2,30 @@ +Mon Dec 08 08:05:59 UTC 2025 - Johannes Kastl <[email protected]> + +- Update to version 1.11.0: + * Features + - Drag-to-Scroll Text Selection (#880, #885) + Added tmux-like drag-to-scroll functionality for text + selection in log views: + - Automatic scrolling at boundaries: When dragging text + selection to the top or bottom edge (1st line or last + line), the view automatically scrolls in that direction + - Continuous auto-scroll: When the mouse stops moving at + boundaries, scrolling continues automatically every 200ms + - Expanding selection area: The selection range expands + automatically during auto-scroll + - Horizontal scrolling support: Works for horizontal + scrolling when text wrapping is disabled + - Performance optimized: Auto-scroll only processes the + active widget + This enhancement makes it much easier to select and copy + large portions of log data without multiple manual scroll + operations. + * Technical Details + - Uses existing Tick worker (200ms interval) for periodic + updates + - Tracks dragging widget to continue event routing when cursor + moves outside widget bounds + - Stores last mouse position and scroll direction for smooth + auto-scroll behavior + +------------------------------------------------------------------- Old: ---- kubetui-1.10.2.obscpio New: ---- kubetui-1.11.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kubetui.spec ++++++ --- /var/tmp/diff_new_pack.xGnlS8/_old 2025-12-09 12:54:01.713207397 +0100 +++ /var/tmp/diff_new_pack.xGnlS8/_new 2025-12-09 12:54:01.717207564 +0100 @@ -17,7 +17,7 @@ Name: kubetui -Version: 1.10.2 +Version: 1.11.0 Release: 0 Summary: A terminal UI for Kubernetes License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.xGnlS8/_old 2025-12-09 12:54:01.769209745 +0100 +++ /var/tmp/diff_new_pack.xGnlS8/_new 2025-12-09 12:54:01.773209912 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/sarub0b0/kubetui.git</param> <param name="versionformat">@PARENT_TAG@</param> <param name="scm">git</param> - <param name="revision">v1.10.2</param> + <param name="revision">v1.11.0</param> <param name="match-tag">*</param> <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param> <param name="versionrewrite-replacement">\1</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.xGnlS8/_old 2025-12-09 12:54:01.801211086 +0100 +++ /var/tmp/diff_new_pack.xGnlS8/_new 2025-12-09 12:54:01.809211421 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/sarub0b0/kubetui.git</param> - <param name="changesrevision">3044f88eceaac8a3ba2f355c417f11e923a96a02</param></service></servicedata> + <param name="changesrevision">3c5d682ec1047cadeccc541a122197fd9a87cf61</param></service></servicedata> (No newline at EOF) ++++++ kubetui-1.10.2.obscpio -> kubetui-1.11.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubetui-1.10.2/.github/workflows/release.yml new/kubetui-1.11.0/.github/workflows/release.yml --- old/kubetui-1.10.2/.github/workflows/release.yml 2025-11-30 05:50:35.000000000 +0100 +++ new/kubetui-1.11.0/.github/workflows/release.yml 2025-12-06 08:59:53.000000000 +0100 @@ -34,7 +34,7 @@ steps: - name: Checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: Install musl-tools if: matrix.target == 'x86_64-unknown-linux-musl' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubetui-1.10.2/.github/workflows/test.yml new/kubetui-1.11.0/.github/workflows/test.yml --- old/kubetui-1.10.2/.github/workflows/test.yml 2025-11-30 05:50:35.000000000 +0100 +++ new/kubetui-1.11.0/.github/workflows/test.yml 2025-12-06 08:59:53.000000000 +0100 @@ -14,7 +14,7 @@ runs-on: ubuntu-latest steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - uses: dtolnay/rust-toolchain@stable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubetui-1.10.2/.github/workflows/upload-artifact.yml new/kubetui-1.11.0/.github/workflows/upload-artifact.yml --- old/kubetui-1.10.2/.github/workflows/upload-artifact.yml 2025-11-30 05:50:35.000000000 +0100 +++ new/kubetui-1.11.0/.github/workflows/upload-artifact.yml 2025-12-06 08:59:53.000000000 +0100 @@ -34,7 +34,7 @@ steps: - name: Checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: Install musl-tools if: matrix.target == 'x86_64-unknown-linux-musl' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubetui-1.10.2/Cargo.lock new/kubetui-1.11.0/Cargo.lock --- old/kubetui-1.10.2/Cargo.lock 2025-11-30 05:50:35.000000000 +0100 +++ new/kubetui-1.11.0/Cargo.lock 2025-12-06 08:59:53.000000000 +0100 @@ -691,9 +691,9 @@ [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "a2152dbcb980c05735e2a651d96011320a949eb31a0c8b38b72645ce97dec676" dependencies = [ "crc32fast", "miniz_oxide", @@ -1278,7 +1278,7 @@ [[package]] name = "kubetui" -version = "1.10.2" +version = "1.11.0" dependencies = [ "anyhow", "arboard", @@ -1372,11 +1372,11 @@ [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" dependencies = [ - "serde", + "serde_core", ] [[package]] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubetui-1.10.2/Cargo.toml new/kubetui-1.11.0/Cargo.toml --- old/kubetui-1.10.2/Cargo.toml 2025-11-30 05:50:35.000000000 +0100 +++ new/kubetui-1.11.0/Cargo.toml 2025-12-06 08:59:53.000000000 +0100 @@ -1,6 +1,6 @@ [package] name = "kubetui" -version = "1.10.2" +version = "1.11.0" authors = ["kosay <[email protected]>"] edition = "2021" license = "MIT" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubetui-1.10.2/src/ui/tab.rs new/kubetui-1.11.0/src/ui/tab.rs --- old/kubetui-1.10.2/src/ui/tab.rs 2025-11-30 05:50:35.000000000 +0100 +++ new/kubetui-1.11.0/src/ui/tab.rs 2025-12-06 08:59:53.000000000 +0100 @@ -23,6 +23,7 @@ active_widget_index: usize, activatable_widget_indices: Vec<usize>, mouse_over_widget_index: Option<usize>, + dragging_widget_index: Option<usize>, } #[allow(dead_code)] @@ -51,6 +52,7 @@ activatable_widget_indices, active_widget_index: 0, mouse_over_widget_index: None, + dragging_widget_index: None, } } @@ -144,6 +146,8 @@ match ev.kind { MouseEventKind::Down(MouseButton::Left) => { + self.dragging_widget_index = Some(index); + if id != active_widget_id { self.activate_widget_by_id(&id); } @@ -151,6 +155,22 @@ MouseEventKind::Moved => { self.mouse_over_widget_index = Some(index); } + + MouseEventKind::Drag(MouseButton::Left) => { + if let Some(dragging_index) = self.dragging_widget_index { + return self.widgets[dragging_index].on_mouse_event(ev); + } + } + MouseEventKind::Up(MouseButton::Left) => { + let result = if let Some(dragging_index) = self.dragging_widget_index { + self.widgets[dragging_index].on_mouse_event(ev) + } else { + EventResult::Ignore + }; + + self.dragging_widget_index = None; + return result; + } _ => {} } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubetui-1.10.2/src/ui/widget/text.rs new/kubetui-1.11.0/src/ui/widget/text.rs --- old/kubetui-1.10.2/src/ui/widget/text.rs 2025-11-30 05:50:35.000000000 +0100 +++ new/kubetui-1.11.0/src/ui/widget/text.rs 2025-12-06 08:59:53.000000000 +0100 @@ -116,12 +116,28 @@ SearchConfirm, } +#[derive(Debug, Default, Clone, Copy)] +enum AutoScrollDirection { + #[default] + None, + Up, + Down, + Left, + Right, +} + #[derive(Debug)] enum InteractionState { /// アイドル状態 Idle, /// マウスで範囲選択中 - Selecting { area: HighlightArea }, + Selecting { + area: HighlightArea, + /// 自動スクロールの方向(縦、横) + auto_scroll: (AutoScrollDirection, AutoScrollDirection), + /// 最後のマウス位置(相対座標) + last_mouse_pos: Point, + }, } impl Default for InteractionState { @@ -439,6 +455,55 @@ .saturating_sub(self.inner_chunk().height as usize) } + /// Tick イベント時に呼ばれ、ドラッグ中の自動スクロールを実行する + pub fn on_tick(&mut self) { + // auto_scrollとlast_mouse_posの値をコピーして借用チェッカーのエラーを回避 + let (auto_scroll, last_mouse_pos) = + if let InteractionState::Selecting { + auto_scroll, + last_mouse_pos, + .. + } = &self.interaction_state + { + (*auto_scroll, *last_mouse_pos) + } else { + return; + }; + + // 縦方向の自動スクロール + match auto_scroll.0 { + AutoScrollDirection::Up => { + self.select_prev(1); + } + AutoScrollDirection::Down => { + self.select_next(1); + } + _ => {} + } + + // 横方向の自動スクロール + if !self.wrap { + match auto_scroll.1 { + AutoScrollDirection::Left => { + self.scroll_left(1); + } + AutoScrollDirection::Right => { + self.scroll_right(1); + } + _ => {} + } + } + + // スクロール後の座標で選択範囲を更新 + if let InteractionState::Selecting { area, .. } = &mut self.interaction_state { + let (x, y) = ( + last_mouse_pos.x + self.scroll.x, + last_mouse_pos.y + self.scroll.y, + ); + *area = area.end(x, y); + } + } + pub fn chunk(&self) -> Rect { let Rect { x, @@ -590,19 +655,65 @@ let area = HighlightArea::new().start(x, y).end(x, y); - self.interaction_state = InteractionState::Selecting { area }; + self.interaction_state = InteractionState::Selecting { + area, + auto_scroll: Default::default(), + last_mouse_pos: pos, + }; } MouseEventKind::Drag(MouseButton::Left) => { - if let InteractionState::Selecting { area } = &mut self.interaction_state { - let (x, y) = (pos.x + self.scroll.x, pos.y + self.scroll.y); - *area = area.end(x, y); + if let InteractionState::Selecting { .. } = self.interaction_state { + let inner_chunk = self.inner_chunk(); + + // スクロール方向を判定 + let vertical_scroll = if ev.row <= inner_chunk.top() { + // 1行目以下(1行目も枠外も含む) + self.select_prev(1); + AutoScrollDirection::Up + } else if ev.row >= inner_chunk.bottom().saturating_sub(1) { + // 最終行以上(最終行も枠外も含む) + self.select_next(1); + AutoScrollDirection::Down + } else { + AutoScrollDirection::None + }; + + // 横方向の境界チェックとスクロール(wrap無効時のみ) + let horizontal_scroll = if !self.wrap { + if ev.column <= inner_chunk.left() { + // 1列目以下(1列目も枠外も含む) + self.scroll_left(1); + AutoScrollDirection::Left + } else if ev.column >= inner_chunk.right().saturating_sub(1) { + // 最終列以上(最終列も枠外も含む) + self.scroll_right(1); + AutoScrollDirection::Right + } else { + AutoScrollDirection::None + } + } else { + AutoScrollDirection::None + }; + + // スクロール後の座標で選択範囲を更新し、スクロール方向とマウス位置を記録 + if let InteractionState::Selecting { + area, + auto_scroll, + last_mouse_pos, + } = &mut self.interaction_state + { + let (x, y) = (pos.x + self.scroll.x, pos.y + self.scroll.y); + *area = area.end(x, y); + *auto_scroll = (vertical_scroll, horizontal_scroll); + *last_mouse_pos = pos; + } } } // ハイライトの削除とクリップボードに保存 MouseEventKind::Up(MouseButton::Left) => { - if let InteractionState::Selecting { area } = &self.interaction_state { + if let InteractionState::Selecting { area, .. } = &self.interaction_state { let area = area.area(); let lines = &self.item.wrapped_lines(); @@ -840,7 +951,7 @@ .highlight_style(self.theme.selecton) .scroll(self.scroll); - if let InteractionState::Selecting { area } = &self.interaction_state { + if let InteractionState::Selecting { area, .. } = &self.interaction_state { builder = builder.highlight_area(Some(*area)); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubetui-1.10.2/src/ui/window.rs new/kubetui-1.11.0/src/ui/window.rs --- old/kubetui-1.10.2/src/ui/window.rs 2025-11-30 05:50:35.000000000 +0100 +++ new/kubetui-1.11.0/src/ui/window.rs 2025-12-06 08:59:53.000000000 +0100 @@ -466,6 +466,14 @@ } } } + + pub fn on_tick(&mut self) { + // アクティブなタブのアクティブなウィジェットにだけon_tickを呼び出す + let active_widget = self.active_tab_mut().active_widget_mut(); + if let Widget::Text(text_widget) = active_widget { + text_widget.on_tick(); + } + } } // Render diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubetui-1.10.2/src/workers/render/action.rs new/kubetui-1.11.0/src/workers/render/action.rs --- old/kubetui-1.10.2/src/workers/render/action.rs 2025-11-30 05:50:35.000000000 +0100 +++ new/kubetui-1.11.0/src/workers/render/action.rs 2025-12-06 08:59:53.000000000 +0100 @@ -86,7 +86,9 @@ } }, - Message::Tick => {} + Message::Tick => { + window.on_tick(); + } Message::Kube(k) => return WindowAction::UpdateContents(k), Message::Error(err) => { logger!(error, "Error: {:?}", err); ++++++ kubetui.obsinfo ++++++ --- /var/tmp/diff_new_pack.xGnlS8/_old 2025-12-09 12:54:02.861255517 +0100 +++ /var/tmp/diff_new_pack.xGnlS8/_new 2025-12-09 12:54:02.881256355 +0100 @@ -1,5 +1,5 @@ name: kubetui -version: 1.10.2 -mtime: 1764478235 -commit: 3044f88eceaac8a3ba2f355c417f11e923a96a02 +version: 1.11.0 +mtime: 1765007993 +commit: 3c5d682ec1047cadeccc541a122197fd9a87cf61 ++++++ vendor.tar.zst ++++++ /work/SRC/openSUSE:Factory/kubetui/vendor.tar.zst /work/SRC/openSUSE:Factory/.kubetui.new.1939/vendor.tar.zst differ: char 7, line 1
