|
1 | 1 | use colored::Colorize; |
| 2 | +use std::io::{self, Write}; |
2 | 3 |
|
| 4 | +use crate::image_display; |
3 | 5 | use crate::steam::SteamStats; |
| 6 | +use crate::ImageProtocol; |
4 | 7 |
|
5 | | -pub fn render(stats: &SteamStats) { |
| 8 | +const IMAGE_COLS: u32 = 34; |
| 9 | +const IMAGE_ROWS: u32 = 18; |
| 10 | + |
| 11 | +pub struct ImageConfig { |
| 12 | + pub enabled: bool, |
| 13 | + pub protocol: ImageProtocol, |
| 14 | +} |
| 15 | + |
| 16 | +pub async fn render(stats: &SteamStats, image_config: &ImageConfig) { |
6 | 17 | let info_lines = build_info_lines(stats); |
| 18 | + |
| 19 | + if image_config.enabled { |
| 20 | + render_with_image(stats, &info_lines, image_config).await; |
| 21 | + } else { |
| 22 | + render_with_ascii(&info_lines); |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +async fn render_with_image(stats: &SteamStats, info_lines: &[String], config: &ImageConfig) { |
| 27 | + let avatar = match &stats.avatar_url { |
| 28 | + Some(url) => { |
| 29 | + let cache_key = format!("avatar_{}.png", stats.username); |
| 30 | + image_display::load_cached_or_download(url, &cache_key).await |
| 31 | + } |
| 32 | + None => None, |
| 33 | + }; |
| 34 | + |
| 35 | + let Some(img) = avatar else { |
| 36 | + return render_with_ascii(info_lines); |
| 37 | + }; |
| 38 | + |
| 39 | + println!(); |
| 40 | + |
| 41 | + // Print image and rewind cursor to top-left of image area |
| 42 | + let image_rows = |
| 43 | + image_display::print_image_and_rewind(&img, &config.protocol, IMAGE_COLS, IMAGE_ROWS); |
| 44 | + |
| 45 | + let Some(image_rows) = image_rows else { |
| 46 | + return render_with_ascii(info_lines); |
| 47 | + }; |
| 48 | + |
| 49 | + let col_offset = IMAGE_COLS + 3; // image width + gap |
| 50 | + let mut stdout = io::stdout().lock(); |
| 51 | + |
| 52 | + // Print info lines to the right of the image |
| 53 | + for (i, line) in info_lines.iter().enumerate() { |
| 54 | + if i > 0 { |
| 55 | + writeln!(stdout).unwrap(); |
| 56 | + } |
| 57 | + image_display::cursor_right(col_offset); |
| 58 | + write!(stdout, "{}", line).unwrap(); |
| 59 | + } |
| 60 | + |
| 61 | + // Ensure we end up below the image area |
| 62 | + let extra = (image_rows as usize).saturating_sub(info_lines.len()); |
| 63 | + for _ in 0..=extra { |
| 64 | + writeln!(stdout).unwrap(); |
| 65 | + } |
| 66 | + stdout.flush().unwrap(); |
| 67 | +} |
| 68 | + |
| 69 | +fn render_with_ascii(info_lines: &[String]) { |
7 | 70 | let logo_lines = build_logo(); |
8 | 71 |
|
9 | 72 | println!(); |
10 | 73 | for (i, logo_line) in logo_lines.iter().enumerate() { |
11 | | - // Offset info by 1 line to align vertically |
12 | 74 | let info = if i == 0 { |
13 | 75 | "" |
14 | 76 | } else { |
|
0 commit comments