arch: push wire types out of ClientApp, extract event_service, cleanup dead code

- ClientApp stores domain types, RepaintCommand carries DisplayHint + Vec<(String,Value)>
- adapters no longer convert Wire→Domain (eliminated duplication in esp32 + desktop)
- event_service in application layer handles LayoutChanged/WebhookDataReceived/ThemeChanged
- bootstrap event_handler reduced to 10-line dispatcher
- polling_service reuses event_service::apply_and_broadcast (deduplicated broadcast pattern)
- AppState.config_service() replaces 11 inline ConfigService::new() calls
- delete unused poll_interval_secs parameter chain
- delete unused StoragePort/ClientConfig (zero implementations)
This commit is contained in:
2026-06-19 18:30:14 +02:00
parent 7001b5e911
commit fa097771d4
21 changed files with 264 additions and 217 deletions

View File

@@ -1,10 +1,12 @@
use std::sync::mpsc;
use std::time::{Duration, Instant};
use client_application::RepaintCommand;
use client_domain::{
BoundingBox, Color, DisplayPort, FontMetrics, RenderEngine, RepaintRequest, ThemeConfig,
WidgetRenderer,
};
use client_application::{ClientApp, RepaintCommand, conversions};
use client_application::ClientApp;
use protocol::ServerMessage;
use super::RenderEvent;
use crate::config::RENDER_POLL_INTERVAL;
@@ -17,17 +19,14 @@ const INDICATOR_MARGIN: u16 = 4;
const COLOR_CONNECTED: Color = Color(0, 200, 0);
const COLOR_DISCONNECTED: Color = Color(200, 0, 0);
fn to_repaint_requests(repaints: &[RepaintCommand]) -> Vec<RepaintRequest> {
repaints
.iter()
.map(|cmd| RepaintRequest {
widget_id: cmd.widget_id,
bounds: cmd.bounds,
display_hint: conversions::wire_to_display_hint(cmd.display_hint.clone()),
data: cmd.state.data.iter().map(|kv| (kv.key.clone(), conversions::wire_to_value(kv.value.clone()))).collect(),
error: cmd.state.error.as_ref().map(|e| conversions::wire_to_widget_error(e.clone())),
})
.collect()
fn to_request(cmd: &RepaintCommand) -> RepaintRequest {
RepaintRequest {
widget_id: cmd.widget_id,
bounds: cmd.bounds,
display_hint: cmd.display_hint.clone(),
data: cmd.data.clone(),
error: cmd.error.clone(),
}
}
pub fn run(
@@ -52,7 +51,11 @@ pub fn run(
loop {
let has_scrollers = renderer.has_active_scrollers();
let timeout = if has_scrollers { SCROLL_TICK } else { RENDER_POLL_INTERVAL };
let timeout = if has_scrollers {
SCROLL_TICK
} else {
RENDER_POLL_INTERVAL
};
match rx.recv_timeout(timeout) {
Ok(RenderEvent::ConnectionStatus(status)) => {
if status != connected {
@@ -76,12 +79,14 @@ pub fn run(
first_update = false;
}
let requests = to_repaint_requests(&repaints);
let requests: Vec<_> = repaints.iter().map(to_request).collect();
let updates = renderer.apply_repaints(&engine, requests);
for update in &updates {
display.fill_rect(update.bounds, bg).unwrap();
for dc in &update.commands {
display.draw_text_span(&dc.text, dc.x, dc.y, dc.color, dc.font).unwrap();
display
.draw_text_span(&dc.text, dc.x, dc.y, dc.color, dc.font)
.unwrap();
}
}
@@ -107,7 +112,9 @@ pub fn run(
for update in &scroll_updates {
display.fill_rect(update.bounds, bg).unwrap();
for dc in &update.commands {
display.draw_text_span(&dc.text, dc.x, dc.y, dc.color, dc.font).unwrap();
display
.draw_text_span(&dc.text, dc.x, dc.y, dc.color, dc.font)
.unwrap();
}
}
draw_indicator(&mut display, screen, connected);
@@ -117,8 +124,14 @@ pub fn run(
}
fn draw_indicator(display: &mut Esp32DisplayAdapter, screen: BoundingBox, connected: bool) {
let color = if connected { COLOR_CONNECTED } else { COLOR_DISCONNECTED };
let color = if connected {
COLOR_CONNECTED
} else {
COLOR_DISCONNECTED
};
let x = screen.x + screen.width - INDICATOR_DIAMETER - INDICATOR_MARGIN;
let y = screen.y + screen.height - INDICATOR_DIAMETER - INDICATOR_MARGIN;
display.fill_circle(x, y, INDICATOR_DIAMETER, color).unwrap();
display
.fill_circle(x, y, INDICATOR_DIAMETER, color)
.unwrap();
}