Skip to content

Commit

Permalink
feat: handle small screen size
Browse files Browse the repository at this point in the history
- Prevent crashes when terminal size shrinks too small
- Display notice to resize screen
  • Loading branch information
Goose97 committed Nov 3, 2023
1 parent 3a3522a commit 994885b
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 9 deletions.
40 changes: 33 additions & 7 deletions src/ui/audio_graph.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use ratatui::{
buffer::Buffer,
layout::Rect,
style::Style,
symbols::Marker,
widgets::{Axis, Chart, Dataset, GraphType, StatefulWidget, Widget},
};
use ratatui::buffer::Buffer;
use ratatui::layout::{Alignment, Rect};
use ratatui::style::{Modifier, Style, Stylize};
use ratatui::symbols::Marker;
use ratatui::text::Line;
use ratatui::widgets::Paragraph;
use ratatui::widgets::{Axis, Chart, Dataset, GraphType, StatefulWidget, Widget};

use super::app_color;
use super::utils;
Expand All @@ -31,6 +31,32 @@ impl StatefulWidget for AudioGraph {
return;
}

// The graph is optional, omit it if there's not enough space
if area.height < 4 {
return;
}

if area.height < 8 {
let mut rect = Rect {
x: 0,
y: 0,
width: area.width,
height: 3,
};

utils::center_rect_in_container(&mut rect, &area);

let paragraph = Paragraph::new(vec![
Line::from("Your terminal size is too small"),
Line::from("Resize to see the graph"),
])
.alignment(Alignment::Center)
.style(Style::default().fg(*app_color::TEXT_LIGHT))
.add_modifier(Modifier::BOLD);

return paragraph.render(rect, buf);
}

let dataset = normalize(&state.dataset);

let datasets = vec![Dataset::default()
Expand Down
46 changes: 46 additions & 0 deletions src/ui/insufficient_size_notice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use ratatui::buffer::Buffer;
use ratatui::layout::Alignment;
use ratatui::layout::Rect;
use ratatui::style::{Modifier, Style, Stylize};
use ratatui::text::Line;
use ratatui::widgets::Widget;
use ratatui::widgets::{Block, BorderType, Borders, Paragraph};

use super::{app_color, utils};

#[derive(Clone, Copy)]
pub struct InsufficientSizeNotice;

impl InsufficientSizeNotice {
pub fn new() -> Self {
Self {}
}
}

impl Widget for InsufficientSizeNotice {
fn render(self, area: Rect, buf: &mut Buffer) {
let mut rect = Rect {
x: 0,
y: 0,
width: area.width,
height: 3,
};

utils::center_rect_in_container(&mut rect, &area);

let block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(*app_color::BORDER));

let paragraph = Paragraph::new(vec![
Line::from("Your terminal size is too small"),
Line::from("Please resize to use the app"),
])
.alignment(Alignment::Center)
.add_modifier(Modifier::BOLD);

block.render(area, buf);
paragraph.render(rect, buf);
}
}
17 changes: 15 additions & 2 deletions src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use super::AppEvent;
use app_state::AppState;
use audio_graph::AudioGraph;
use instructions::Instruction;
use insufficient_size_notice::InsufficientSizeNotice;
use tuning_bar::TuningBar;
use tuning_notes::TuningNotes;
use tuning_pegs::TuningPegs;
Expand All @@ -21,6 +22,7 @@ mod app_color;
mod app_state;
mod audio_graph;
mod instructions;
mod insufficient_size_notice;
mod loading_icon;
mod tuning_bar;
mod tuning_notes;
Expand All @@ -32,6 +34,9 @@ pub static mut FRAME_COUNT: usize = 0;
// In cents. 100 cents is 1 semitone
pub const IN_TUNE_RANGE: f64 = 8.0;

pub const MIN_REQUIRED_WIDTH: u16 = 90;
pub const MIN_REQUIRED_HEIGHT: u16 = 35;

pub fn render(event_stream: Receiver<AppEvent>) -> Result<()> {
// startup: Enable raw mode for the terminal, giving us fine control over user input
crossterm::terminal::enable_raw_mode()?;
Expand All @@ -47,13 +52,21 @@ pub fn render(event_stream: Receiver<AppEvent>) -> Result<()> {
FRAME_COUNT += 1;
}

let frame_rect = f.size();

if frame_rect.width < MIN_REQUIRED_WIDTH || frame_rect.height < MIN_REQUIRED_HEIGHT {
let notice = InsufficientSizeNotice::new();
f.render_widget(notice, f.size());
return;
}

let [tuning_strings_rect, instructions_rect, tuning_bar_rect, graph_rect] =
calculate_layout(f.size());
calculate_layout(frame_rect);

// Background
f.render_widget(
Block::default().style(Style::default().bg(*app_color::BACKGROUND_DARK)),
f.size(),
frame_rect,
);

f.render_widget(
Expand Down

0 comments on commit 994885b

Please sign in to comment.