Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
xvfb

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.94.1
with:
components: rustfmt, clippy

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ jobs:
xvfb

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.94.1
with:
components: rustfmt, clippy

Expand All @@ -126,7 +126,7 @@ jobs:
ref: ${{ github.event.inputs.tag || github.ref }}

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.94.1

- name: Cache cargo registry and target
uses: Swatinem/rust-cache@v2
Expand Down Expand Up @@ -226,7 +226,7 @@ jobs:
fuse libfuse2

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.94.1

- name: Cache cargo registry and target
uses: Swatinem/rust-cache@v2
Expand Down Expand Up @@ -294,7 +294,7 @@ jobs:
ref: ${{ github.event.inputs.tag || github.ref }}

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.94.1

- name: Cache cargo registry and target
uses: Swatinem/rust-cache@v2
Expand Down
156 changes: 144 additions & 12 deletions crates/rgitui_workspace/src/detail_panel.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
use std::collections::HashSet;
use std::sync::Arc;

#[derive(Default, Clone, Copy)]
#[allow(dead_code)]
enum FileViewMode {
#[default]
Flat,
Tree,
}
use std::time::{Duration, Instant};

use gpui::prelude::*;
Expand All @@ -22,12 +14,42 @@ use rgitui_git::{
use rgitui_settings::SettingsState;
use rgitui_theme::{ActiveTheme, Color, StyledExt};
use rgitui_ui::{
AvatarCache, Badge, ButtonSize, ButtonStyle, DiffStat, Icon, IconButton, IconName, IconSize,
Label, LabelSize,
AvatarCache, Badge, Button, ButtonSize, ButtonStyle, DiffStat, Icon, IconButton, IconName,
IconSize, Label, LabelSize,
};

use crate::markdown_view::render_markdown;

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
enum FileViewMode {
#[default]
Flat,
Tree,
}

impl FileViewMode {
fn toggled(self) -> Self {
match self {
Self::Flat => Self::Tree,
Self::Tree => Self::Flat,
}
}

fn label(self) -> &'static str {
match self {
Self::Flat => "Flat",
Self::Tree => "Tree",
}
}

fn toggle_tooltip(self) -> &'static str {
match self {
Self::Flat => "Switch to tree view (v)",
Self::Tree => "Switch to flat view (v)",
}
}
}

fn format_absolute_date(timestamp: i64) -> String {
let dt = chrono::DateTime::from_timestamp(timestamp, 0);
match dt {
Expand Down Expand Up @@ -326,10 +348,19 @@ impl DetailPanel {
cx.notify();
}
}
// Toggle flat/tree file view mode
"v" => {
self.toggle_file_view_mode(cx);
}
_ => {}
}
}

fn toggle_file_view_mode(&mut self, cx: &mut Context<Self>) {
self.file_view_mode = self.file_view_mode.toggled();
cx.notify();
}

fn emit_file_selected(&self, cx: &mut Context<Self>) {
if let (Some(idx), Some(diff)) = (self.selected_file_index, &self.commit_diff) {
if let Some(file) = diff.files.get(idx) {
Expand Down Expand Up @@ -1382,6 +1413,25 @@ impl Render for DetailPanel {
}

// Diff stat
if !is_searching && total_file_count > 0 {
let view_mode = self.file_view_mode;
children.push(
Button::new("detail-panel-file-view-toggle", view_mode.label())
.icon(match view_mode {
FileViewMode::Flat => IconName::File,
FileViewMode::Tree => IconName::Folder,
})
.size(ButtonSize::Compact)
.style(ButtonStyle::Transparent)
.selected(matches!(view_mode, FileViewMode::Tree))
.tooltip(view_mode.toggle_tooltip())
.on_click(cx.listener(|this, _: &ClickEvent, _, cx| {
this.toggle_file_view_mode(cx);
}))
.into_any_element(),
);
}

let diff_stat: gpui::AnyElement =
DiffStat::new(total_additions, total_deletions).into_any_element();
children.push(diff_stat);
Expand All @@ -1406,7 +1456,7 @@ impl Render for DetailPanel {
}
content = content.child(header);

// Show search hint when not searching and there are files
// Show view mode toggle hint when not searching and there are files
if !is_searching && total_file_count > 0 {
content = content.child(
div()
Expand All @@ -1417,7 +1467,7 @@ impl Render for DetailPanel {
.items_center()
.gap_1()
.child(
Label::new("/ to search files")
Label::new("/ to search · v to toggle view")
.size(LabelSize::XSmall)
.color(Color::Placeholder),
)
Expand Down Expand Up @@ -1791,4 +1841,86 @@ mod tests {
"very/deeply/nested/directory/structure/"
);
}

// --- FileViewMode tests ---

#[test]
fn test_file_view_mode_default_is_flat() {
assert_eq!(FileViewMode::default(), FileViewMode::Flat);
}

#[test]
fn test_file_view_mode_toggles_between_flat_and_tree() {
assert_eq!(FileViewMode::Flat.toggled(), FileViewMode::Tree);
assert_eq!(FileViewMode::Tree.toggled(), FileViewMode::Flat);
}

#[test]
fn test_file_view_mode_labels_and_tooltips_match_next_action() {
assert_eq!(FileViewMode::Flat.label(), "Flat");
assert_eq!(FileViewMode::Tree.label(), "Tree");
assert_eq!(
FileViewMode::Flat.toggle_tooltip(),
"Switch to tree view (v)"
);
assert_eq!(
FileViewMode::Tree.toggle_tooltip(),
"Switch to flat view (v)"
);
}

// --- filtered_file_indices tests ---

#[test]
fn test_filtered_file_indices_no_query_returns_all() {
let files = [
make_file_diff("src/main.rs", FileChangeKind::Modified),
make_file_diff("lib.rs", FileChangeKind::Added),
];
// Can't test filtered_file_indices directly without a full DetailPanel
// instance since it needs cx.global::<SettingsState>(). Instead, test
// the fuzzy_score behavior directly.
use crate::command_palette::CommandPalette;
// Query "src" matches "src/main.rs" but not "lib.rs"
let results: Vec<_> = files
.iter()
.enumerate()
.filter_map(|(i, f)| {
CommandPalette::fuzzy_score("src", &f.path.to_string_lossy()).map(|_| i)
})
.collect();
assert_eq!(results, vec![0]); // only src/main.rs matches
}

#[test]
fn test_filtered_file_indices_empty_query_returns_all() {
let files = [
make_file_diff("a.rs", FileChangeKind::Modified),
make_file_diff("b.rs", FileChangeKind::Added),
];
// Empty query returns all indices (0..file_count)
let results: Vec<_> = (0..files.len()).collect();
assert_eq!(results, vec![0, 1]);
}

#[test]
fn test_filtered_file_indices_partial_path_match() {
use crate::command_palette::CommandPalette;
let files = [
make_file_diff(
"crates/rgitui_workspace/src/panel.rs",
FileChangeKind::Modified,
),
make_file_diff("crates/rgitui_git/src/lib.rs", FileChangeKind::Added),
];
// "workspace" matches the workspace path but not git path
let results: Vec<_> = files
.iter()
.enumerate()
.filter_map(|(i, f)| {
CommandPalette::fuzzy_score("workspace", &f.path.to_string_lossy()).map(|_| i)
})
.collect();
assert_eq!(results, vec![0]);
}
}
4 changes: 2 additions & 2 deletions crates/rgitui_workspace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ pub use rename_dialog::*;
pub use repo_opener::*;
pub use search_panel::*;
pub use settings_window::{
settings_window_options, SettingsView, SettingsViewEvent, SettingsWindow,
SettingsWindowAction, SettingsWindowActionGlobal,
settings_window_options, SettingsView, SettingsViewEvent, SettingsWindow, SettingsWindowAction,
SettingsWindowActionGlobal,
};
pub use shortcuts_help::*;
pub use sidebar::*;
Expand Down
5 changes: 1 addition & 4 deletions crates/rgitui_workspace/src/settings_window/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ impl SettingsWindowActionGlobal {

/// Build an unbounded channel suitable for installing as the global sender and
/// driving the workspace consumer loop.
pub fn channel() -> (
Sender<SettingsWindowAction>,
Receiver<SettingsWindowAction>,
) {
pub fn channel() -> (Sender<SettingsWindowAction>, Receiver<SettingsWindowAction>) {
unbounded()
}
1 change: 0 additions & 1 deletion crates/rgitui_workspace/src/settings_window/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3967,4 +3967,3 @@ impl SettingsView {
.into_any_element()
}
}

1 change: 1 addition & 0 deletions crates/rgitui_workspace/src/shortcuts_help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl ShortcutsHelp {
("Ctrl+F", "Toggle commit graph search"),
("/", "Start in-graph search"),
("d", "Toggle diff mode (unified / split)"),
("v", "Toggle changed-files view (flat / tree)"),
("b", "Toggle blame view for selected file"),
("h", "Toggle file history view for selected file"),
("y", "Copy SHA of selected commit"),
Expand Down
8 changes: 4 additions & 4 deletions crates/rgitui_workspace/src/workspace/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ use crate::{
ConfirmAction, ConfirmDialog, ConfirmDialogEvent, CreatePrDialog, CreatePrDialogEvent,
DetailPanel, DetailPanelEvent, FileHistoryView, FileHistoryViewEvent, GlobalSearchView,
GlobalSearchViewEvent, InteractiveRebase, InteractiveRebaseEvent, ReflogView, ReflogViewEvent,
RenameDialog, RenameDialogEvent, RepoOpener, RepoOpenerEvent, ShortcutsHelp, ShortcutsHelpEvent,
Sidebar, SidebarEvent, StashBranchDialog, StashBranchDialogEvent, SubmoduleView,
SubmoduleViewEvent, TagDialog, TagDialogEvent, ToastKind, Toolbar, ToolbarEvent, WorktreeDialog,
WorktreeDialogEvent,
RenameDialog, RenameDialogEvent, RepoOpener, RepoOpenerEvent, ShortcutsHelp,
ShortcutsHelpEvent, Sidebar, SidebarEvent, StashBranchDialog, StashBranchDialogEvent,
SubmoduleView, SubmoduleViewEvent, TagDialog, TagDialogEvent, ToastKind, Toolbar, ToolbarEvent,
WorktreeDialog, WorktreeDialogEvent,
};

use super::{ActiveOperation, BottomPanelMode, OperationOutput, UndoAction, UndoEntry, Workspace};
Expand Down
7 changes: 4 additions & 3 deletions crates/rgitui_workspace/src/workspace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ use std::path::PathBuf;
use std::time::Instant;

use gpui::prelude::*;
use gpui::{div, Bounds, Context, Entity, EventEmitter, Render, SharedString, Window, WindowHandle};
use gpui::{
div, Bounds, Context, Entity, EventEmitter, Render, SharedString, Window, WindowHandle,
};
use rgitui_ai::AiGenerator;
use rgitui_git::GitProject;

Expand Down Expand Up @@ -474,8 +476,7 @@ impl Workspace {
.and_then(|r| r.url.clone());

if let Some(url) = remote_url {
if let Some((owner, repo_name)) =
crate::issues_panel::parse_github_owner_repo(&url)
if let Some((owner, repo_name)) = crate::issues_panel::parse_github_owner_repo(&url)
{
tab.issues_panel.update(cx, |ip, cx| {
ip.configure(token.clone(), owner.clone(), repo_name.clone(), cx);
Expand Down
Loading