Repository: LiveSplit/livesplit-core (rust)

Issue:
Splits component is 1 split behind when the visual split count is 1
This line needs to be moved earlier so that we're not applying the 0 bound too early: https://github.com/LiveSplit/livesplit-core/blob/master/src/component/splits/mod.rs#L308

Pull request:
Fix splits component logic with 1 visual split
Fix #347 

Patch:
diff --git a/src/component/splits/mod.rs b/src/component/splits/mod.rs
index 261295e..2e7692f 100644
--- a/src/component/splits/mod.rs
+++ b/src/component/splits/mod.rs
@@ -294,19 +294,21 @@ impl Component {
         let current_split = timer.current_split_index();
         let method = timer.current_timing_method();
 
-        let always_show_last_split = if self.settings.always_show_last_split {
-            0
-        } else {
+        let locked_last_split = if self.settings.always_show_last_split {
             1
+        } else {
+            0
         };
         let skip_count = min(
             current_split.map_or(0, |current_split| {
-                current_split.saturating_sub(
-                    visual_split_count
-                        .saturating_sub(2)
-                        .saturating_sub(self.settings.split_preview_count)
-                        .saturating_add(always_show_last_split),
-                ) as isize
+                max(
+                    0,
+                    current_split as isize
+                        + self.settings.split_preview_count as isize
+                        + locked_last_split
+                        + 1
+                        - visual_split_count as isize
+                )
             }),
             run.len() as isize - visual_split_count as isize,
         );
@@ -315,7 +317,7 @@ impl Component {
             run.len() as isize - skip_count - visual_split_count as isize,
         );
         let skip_count = max(0, skip_count + self.scroll_offset) as usize;
-        let take_count = visual_split_count + always_show_last_split as usize - 1;
+        let take_count = visual_split_count - locked_last_split as usize;
         let always_show_last_split = self.settings.always_show_last_split;
 
         let show_final_separator = self.settings.separator_last_split


Test patch:
diff --git a/src/component/splits/tests/mod.rs b/src/component/splits/tests/mod.rs
index c8cbb80..7790791 100644
--- a/src/component/splits/tests/mod.rs
+++ b/src/component/splits/tests/mod.rs
@@ -35,6 +35,48 @@ fn zero_visual_split_count_always_shows_all_splits() {
     assert_eq!(state.splits.len(), 32);
 }
 
+#[test]
+fn one_visual_split() {
+    let mut run = Run::new();
+    
+    run.push_segment(Segment::new("A"));
+    run.push_segment(Segment::new("B"));
+    run.push_segment(Segment::new("C"));
+
+    let mut timer = Timer::new(run).unwrap();
+    let layout_settings = Default::default();
+    let mut component = Component::with_settings(Settings {
+        always_show_last_split: false,
+        split_preview_count: 0,
+        visual_split_count: 1,
+        ..Default::default()
+    });
+
+    let mut state = component.state(&timer.snapshot(), &layout_settings);
+    assert_eq!(state.splits[0].name, "A");
+    assert_eq!(state.splits.len(), 1);
+
+    timer.start();
+    state = component.state(&timer.snapshot(), &layout_settings);
+    assert_eq!(state.splits[0].name, "A");
+    assert_eq!(state.splits.len(), 1);
+
+    timer.split();
+    state = component.state(&timer.snapshot(), &layout_settings);
+    assert_eq!(state.splits[0].name, "B");
+    assert_eq!(state.splits.len(), 1);
+
+    timer.split();
+    state = component.state(&timer.snapshot(), &layout_settings);
+    assert_eq!(state.splits[0].name, "C");
+    assert_eq!(state.splits.len(), 1);
+
+    timer.split();
+    state = component.state(&timer.snapshot(), &layout_settings);
+    assert_eq!(state.splits[0].name, "C");
+    assert_eq!(state.splits.len(), 1);
+}
+
 #[test]
 fn negative_segment_times() {
     let mut run = Run::new();