refactor: add modal/validation utils and partial App encapsulation

Quick wins refactoring (Variant 1):
- Created src/utils/modal_handler.rs (120+ lines)
  - 4 functions for modal handling (close, confirm, yes/no)
  - ModalAction enum for type-safe processing
  - English and Russian keyboard layout support
  - 4 unit tests
- Created src/utils/validation.rs (180+ lines)
  - 7 validation functions (empty, length, IDs, etc)
  - Covers all common validation patterns
  - 7 unit tests
- Partial App encapsulation:
  - Made config field private (readonly via app.config())
  - Added 30+ getter/setter methods
  - Updated ui/messages.rs to use config()
- Updated documentation:
  - REFACTORING_OPPORTUNITIES.md: #1 Complete, #5 Partial
  - CONTEXT.md: Added quick wins section

Tests: 563 passed, 0 failed

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-02-01 23:55:49 +03:00
parent e690acfb09
commit dff0897da4
7 changed files with 631 additions and 19 deletions

View File

@@ -326,15 +326,15 @@ pub fn render(f: &mut Frame, area: Rect, app: &App) {
}
// Форматируем время (HH:MM) с учётом timezone из config
let time = format_timestamp_with_tz(msg.date(), &app.config.general.timezone);
let time = format_timestamp_with_tz(msg.date(), &app.config().general.timezone);
// Цвет сообщения (из config или жёлтый если выбрано)
let msg_color = if is_selected {
app.config.parse_color(&app.config.colors.selected_message)
app.config().parse_color(&app.config().colors.selected_message)
} else if msg.is_outgoing() {
app.config.parse_color(&app.config.colors.outgoing_message)
app.config().parse_color(&app.config().colors.outgoing_message)
} else {
app.config.parse_color(&app.config.colors.incoming_message)
app.config().parse_color(&app.config().colors.incoming_message)
};
// Маркер выбора
@@ -531,10 +531,10 @@ pub fn render(f: &mut Frame, area: Rect, app: &App) {
let style = if reaction.is_chosen {
Style::default()
.fg(app.config.parse_color(&app.config.colors.reaction_chosen))
.fg(app.config().parse_color(&app.config().colors.reaction_chosen))
} else {
Style::default()
.fg(app.config.parse_color(&app.config.colors.reaction_other))
.fg(app.config().parse_color(&app.config().colors.reaction_other))
};
reaction_spans.push(Span::styled(reaction_text, style));