Feat: entretien de la codebase

This commit is contained in:
2026-02-09 21:12:49 +01:00
parent 60bc7618d3
commit 80c392c24b
25 changed files with 847 additions and 878 deletions

View File

@@ -12,12 +12,14 @@ use crate::engine::{LinkState, SequencerSnapshot};
use crate::model::SourceSpan;
use crate::page::Page;
use crate::state::{
EditorTarget, EuclideanField, FlashKind, Modal, PanelFocus, PatternField, SidePanel,
EditorTarget, EuclideanField, FlashKind, Modal, PanelFocus, PatternField, RenameTarget,
SidePanel,
};
use crate::theme;
use crate::views::highlight::{self, highlight_line_with_runtime};
use crate::widgets::{
ConfirmModal, ModalFrame, NavMinimap, NavTile, SampleBrowser, TextInputModal,
hint_line, render_props_form, render_search_bar, ConfirmModal, ModalFrame, NavMinimap, NavTile,
SampleBrowser, TextInputModal,
};
use super::{
@@ -497,42 +499,10 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
let user_words: HashSet<String> = app.dict.lock().keys().cloned().collect();
let inner = match &app.ui.modal {
Modal::None => return None,
Modal::ConfirmQuit { selected } => {
ConfirmModal::new("Confirm", "Quit?", *selected).render_centered(frame, term)
}
Modal::ConfirmDeleteStep { step, selected, .. } => {
ConfirmModal::new("Confirm", &format!("Delete step {}?", step + 1), *selected)
Modal::Confirm { action, selected } => {
ConfirmModal::new("Confirm", &action.message(), *selected)
.render_centered(frame, term)
}
Modal::ConfirmDeleteSteps {
steps, selected, ..
} => {
let nums: Vec<String> = steps.iter().map(|s| format!("{:02}", s + 1)).collect();
let label = format!("Delete steps {}?", nums.join(", "));
ConfirmModal::new("Confirm", &label, *selected).render_centered(frame, term)
}
Modal::ConfirmResetPattern {
pattern, selected, ..
} => ConfirmModal::new(
"Confirm",
&format!("Reset pattern {}?", pattern + 1),
*selected,
)
.render_centered(frame, term),
Modal::ConfirmResetBank { bank, selected } => {
ConfirmModal::new("Confirm", &format!("Reset bank {}?", bank + 1), *selected)
.render_centered(frame, term)
}
Modal::ConfirmResetPatterns {
patterns, selected, ..
} => {
let label = format!("Reset {} patterns?", patterns.len());
ConfirmModal::new("Confirm", &label, *selected).render_centered(frame, term)
}
Modal::ConfirmResetBanks { banks, selected } => {
let label = format!("Reset {} banks?", banks.len());
ConfirmModal::new("Confirm", &label, *selected).render_centered(frame, term)
}
Modal::FileBrowser(state) => {
use crate::state::file_browser::FileBrowserMode;
use crate::widgets::FileBrowserModal;
@@ -553,27 +523,14 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
.height(18)
.render_centered(frame, term)
}
Modal::RenameBank { bank, name } => {
TextInputModal::new(&format!("Rename Bank {:02}", bank + 1), name)
Modal::Rename { target, name } => {
let border_color = match target {
RenameTarget::Step { .. } => theme.modal.input,
_ => theme.modal.rename,
};
TextInputModal::new(&target.title(), name)
.width(40)
.border_color(theme.modal.rename)
.render_centered(frame, term)
}
Modal::RenamePattern {
bank,
pattern,
name,
} => TextInputModal::new(
&format!("Rename B{:02}:P{:02}", bank + 1, pattern + 1),
name,
)
.width(40)
.border_color(theme.modal.rename)
.render_centered(frame, term),
Modal::RenameStep { step, name, .. } => {
TextInputModal::new(&format!("Name Step {:02}", step + 1), name)
.width(40)
.border_color(theme.modal.input)
.border_color(border_color)
.render_centered(frame, term)
}
Modal::SetPattern { field, input } => {
@@ -794,18 +751,12 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
let hint_area = Rect::new(inner.x, y, inner.width, 1);
if let Some(sa) = search_area {
let style = if app.editor_ctx.editor.search_active() {
Style::default().fg(theme.search.active)
} else {
Style::default().fg(theme.search.inactive)
};
let cursor = if app.editor_ctx.editor.search_active() {
"_"
} else {
""
};
let text = format!("/{}{}", app.editor_ctx.editor.search_query(), cursor);
frame.render_widget(Paragraph::new(Line::from(Span::styled(text, style))), sa);
render_search_bar(
frame,
sa,
app.editor_ctx.editor.search_query(),
app.editor_ctx.editor.search_active(),
);
}
if let Some(kind) = flash_kind {
@@ -821,17 +772,9 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
.editor
.render(frame, editor_area, &highlighter);
let dim = Style::default().fg(theme.hint.text);
let key = Style::default().fg(theme.hint.key);
if app.editor_ctx.editor.search_active() {
let hint = Line::from(vec![
Span::styled("Enter", key),
Span::styled(" confirm ", dim),
Span::styled("Esc", key),
Span::styled(" cancel", dim),
]);
frame.render_widget(Paragraph::new(hint).alignment(Alignment::Right), hint_area);
let hints = hint_line(&[("Enter", "confirm"), ("Esc", "cancel")]);
frame.render_widget(Paragraph::new(hints).alignment(Alignment::Right), hint_area);
} else if app.editor_ctx.show_stack {
let stack_text = app
.editor_ctx
@@ -840,42 +783,29 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
.as_ref()
.map(|c| c.result.clone())
.unwrap_or_else(|| "Stack: []".to_string());
let hint = Line::from(vec![
Span::styled("Esc", key),
Span::styled(" save ", dim),
Span::styled("C-e", key),
Span::styled(" eval ", dim),
Span::styled("C-s", key),
Span::styled(" hide", dim),
]);
let hints = hint_line(&[("Esc", "save"), ("C-e", "eval"), ("C-s", "hide")]);
let [hint_left, stack_right] = Layout::horizontal([
Constraint::Length(hint.width() as u16),
Constraint::Length(hints.width() as u16),
Constraint::Fill(1),
])
.areas(hint_area);
frame.render_widget(Paragraph::new(hint), hint_left);
frame.render_widget(Paragraph::new(hints), hint_left);
let dim = Style::default().fg(theme.hint.text);
frame.render_widget(
Paragraph::new(Span::styled(stack_text, dim)).alignment(Alignment::Right),
stack_right,
);
} else {
let hint = Line::from(vec![
Span::styled("Esc", key),
Span::styled(" save ", dim),
Span::styled("C-e", key),
Span::styled(" eval ", dim),
Span::styled("C-f", key),
Span::styled(" find ", dim),
Span::styled("C-b", key),
Span::styled(" samples ", dim),
Span::styled("C-s", key),
Span::styled(" stack ", dim),
Span::styled("C-u", key),
Span::styled("/", dim),
Span::styled("C-r", key),
Span::styled(" undo/redo", dim),
let hints = hint_line(&[
("Esc", "save"),
("C-e", "eval"),
("C-f", "find"),
("C-b", "samples"),
("C-s", "stack"),
("C-u", "/"),
("C-r", "undo/redo"),
]);
frame.render_widget(Paragraph::new(hint).alignment(Alignment::Right), hint_area);
frame.render_widget(Paragraph::new(hints).alignment(Alignment::Right), hint_area);
}
inner
@@ -899,70 +829,20 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
.border_color(theme.modal.input)
.render_centered(frame, term);
let fields = [
let speed_label = speed.label();
let fields: Vec<(&str, &str, bool)> = vec![
("Name", name.as_str(), *field == PatternPropsField::Name),
(
"Length",
length.as_str(),
*field == PatternPropsField::Length,
),
("Speed", &speed.label(), *field == PatternPropsField::Speed),
(
"Quantization",
quantization.label(),
*field == PatternPropsField::Quantization,
),
(
"Sync Mode",
sync_mode.label(),
*field == PatternPropsField::SyncMode,
),
("Length", length.as_str(), *field == PatternPropsField::Length),
("Speed", &speed_label, *field == PatternPropsField::Speed),
("Quantization", quantization.label(), *field == PatternPropsField::Quantization),
("Sync Mode", sync_mode.label(), *field == PatternPropsField::SyncMode),
];
for (i, (label, value, selected)) in fields.iter().enumerate() {
let y = inner.y + i as u16;
if y >= inner.y + inner.height {
break;
}
let (label_style, value_style) = if *selected {
(
Style::default()
.fg(theme.hint.key)
.add_modifier(Modifier::BOLD),
Style::default()
.fg(theme.ui.text_primary)
.bg(theme.ui.surface),
)
} else {
(
Style::default().fg(theme.ui.text_muted),
Style::default().fg(theme.ui.text_primary),
)
};
let label_area = Rect::new(inner.x + 1, y, 14, 1);
let value_area = Rect::new(inner.x + 16, y, inner.width.saturating_sub(18), 1);
frame.render_widget(
Paragraph::new(format!("{label}:")).style(label_style),
label_area,
);
frame.render_widget(Paragraph::new(*value).style(value_style), value_area);
}
render_props_form(frame, inner, &fields);
let hint_area = Rect::new(inner.x, inner.y + inner.height - 1, inner.width, 1);
let hint_line = Line::from(vec![
Span::styled("↑↓", Style::default().fg(theme.hint.key)),
Span::styled(" nav ", Style::default().fg(theme.hint.text)),
Span::styled("←→", Style::default().fg(theme.hint.key)),
Span::styled(" change ", Style::default().fg(theme.hint.text)),
Span::styled("Enter", Style::default().fg(theme.hint.key)),
Span::styled(" save ", Style::default().fg(theme.hint.text)),
Span::styled("Esc", Style::default().fg(theme.hint.key)),
Span::styled(" cancel", Style::default().fg(theme.hint.text)),
]);
frame.render_widget(Paragraph::new(hint_line), hint_area);
let hints = hint_line(&[("↑↓", "nav"), ("←→", "change"), ("Enter", "save"), ("Esc", "cancel")]);
frame.render_widget(Paragraph::new(hints), hint_area);
inner
}
@@ -1024,16 +904,9 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
width: inner.width,
height: 1,
};
let keybind_hint = Line::from(vec![
Span::styled("↑↓", Style::default().fg(theme.hint.key)),
Span::styled(" scroll ", Style::default().fg(theme.hint.text)),
Span::styled("PgUp/Dn", Style::default().fg(theme.hint.key)),
Span::styled(" page ", Style::default().fg(theme.hint.text)),
Span::styled("Esc/?", Style::default().fg(theme.hint.key)),
Span::styled(" close", Style::default().fg(theme.hint.text)),
]);
let hints = hint_line(&[("↑↓", "scroll"), ("PgUp/Dn", "page"), ("Esc/?", "close")]);
frame.render_widget(
Paragraph::new(keybind_hint).alignment(Alignment::Right),
Paragraph::new(hints).alignment(Alignment::Right),
hint_area,
);
@@ -1056,51 +929,13 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
.border_color(theme.modal.input)
.render_centered(frame, term);
let fields = [
(
"Pulses",
pulses.as_str(),
*field == EuclideanField::Pulses,
),
let fields: Vec<(&str, &str, bool)> = vec![
("Pulses", pulses.as_str(), *field == EuclideanField::Pulses),
("Steps", steps.as_str(), *field == EuclideanField::Steps),
(
"Rotation",
rotation.as_str(),
*field == EuclideanField::Rotation,
),
("Rotation", rotation.as_str(), *field == EuclideanField::Rotation),
];
for (i, (label, value, selected)) in fields.iter().enumerate() {
let row_y = inner.y + i as u16;
if row_y >= inner.y + inner.height {
break;
}
let (label_style, value_style) = if *selected {
(
Style::default()
.fg(theme.hint.key)
.add_modifier(Modifier::BOLD),
Style::default()
.fg(theme.ui.text_primary)
.bg(theme.ui.surface),
)
} else {
(
Style::default().fg(theme.ui.text_muted),
Style::default().fg(theme.ui.text_primary),
)
};
let label_area = Rect::new(inner.x + 1, row_y, 14, 1);
let value_area = Rect::new(inner.x + 16, row_y, inner.width.saturating_sub(18), 1);
frame.render_widget(
Paragraph::new(format!("{label}:")).style(label_style),
label_area,
);
frame.render_widget(Paragraph::new(*value).style(value_style), value_area);
}
render_props_form(frame, inner, &fields);
let preview_y = inner.y + 4;
if preview_y < inner.y + inner.height {
@@ -1118,17 +953,8 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
}
let hint_area = Rect::new(inner.x, inner.y + inner.height - 1, inner.width, 1);
let hint_line = Line::from(vec![
Span::styled("↑↓", Style::default().fg(theme.hint.key)),
Span::styled(" nav ", Style::default().fg(theme.hint.text)),
Span::styled("←→", Style::default().fg(theme.hint.key)),
Span::styled(" adjust ", Style::default().fg(theme.hint.text)),
Span::styled("Enter", Style::default().fg(theme.hint.key)),
Span::styled(" apply ", Style::default().fg(theme.hint.text)),
Span::styled("Esc", Style::default().fg(theme.hint.key)),
Span::styled(" cancel", Style::default().fg(theme.hint.text)),
]);
frame.render_widget(Paragraph::new(hint_line), hint_area);
let hints = hint_line(&[("↑↓", "nav"), ("←→", "adjust"), ("Enter", "apply"), ("Esc", "cancel")]);
frame.render_widget(Paragraph::new(hints), hint_area);
inner
}