Silence warnings, run cargo fmt
This commit is contained in:
parent
fe1c1d3655
commit
af1c767f5f
77 changed files with 1904 additions and 903 deletions
|
|
@ -9,7 +9,7 @@ use uuid::Uuid;
|
|||
|
||||
use chattyness_db::models::ChannelMemberWithAvatar;
|
||||
|
||||
use super::chat_types::{emotion_bubble_colors, ActiveBubble};
|
||||
use super::chat_types::{ActiveBubble, emotion_bubble_colors};
|
||||
|
||||
/// Base text size multiplier. Text at 100% slider = base_sizes * 1.4
|
||||
const BASE_TEXT_SCALE: f64 = 1.4;
|
||||
|
|
@ -65,18 +65,47 @@ impl ContentBounds {
|
|||
let mid_col = [1, 4, 7].iter().any(|&p| has_content_at(p));
|
||||
let right_col = [2, 5, 8].iter().any(|&p| has_content_at(p));
|
||||
|
||||
let min_col = if left_col { 0 } else if mid_col { 1 } else { 2 };
|
||||
let max_col = if right_col { 2 } else if mid_col { 1 } else { 0 };
|
||||
let min_col = if left_col {
|
||||
0
|
||||
} else if mid_col {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
};
|
||||
let max_col = if right_col {
|
||||
2
|
||||
} else if mid_col {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
// Rows: 0 (top), 1 (middle), 2 (bottom)
|
||||
let top_row = [0, 1, 2].iter().any(|&p| has_content_at(p));
|
||||
let mid_row = [3, 4, 5].iter().any(|&p| has_content_at(p));
|
||||
let bot_row = [6, 7, 8].iter().any(|&p| has_content_at(p));
|
||||
|
||||
let min_row = if top_row { 0 } else if mid_row { 1 } else { 2 };
|
||||
let max_row = if bot_row { 2 } else if mid_row { 1 } else { 0 };
|
||||
let min_row = if top_row {
|
||||
0
|
||||
} else if mid_row {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
};
|
||||
let max_row = if bot_row {
|
||||
2
|
||||
} else if mid_row {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
Self { min_col, max_col, min_row, max_row }
|
||||
Self {
|
||||
min_col,
|
||||
max_col,
|
||||
min_row,
|
||||
max_row,
|
||||
}
|
||||
}
|
||||
|
||||
/// Content center column (0.0 to 2.0, grid center is 1.0).
|
||||
|
|
@ -158,8 +187,12 @@ impl ScreenBoundaries {
|
|||
half_width: f64,
|
||||
half_height: f64,
|
||||
) -> (f64, f64) {
|
||||
let clamped_x = center_x.max(self.min_x + half_width).min(self.max_x - half_width);
|
||||
let clamped_y = center_y.max(self.min_y + half_height).min(self.max_y - half_height);
|
||||
let clamped_x = center_x
|
||||
.max(self.min_x + half_width)
|
||||
.min(self.max_x - half_width);
|
||||
let clamped_y = center_y
|
||||
.max(self.min_y + half_height)
|
||||
.min(self.max_y - half_height);
|
||||
(clamped_x, clamped_y)
|
||||
}
|
||||
}
|
||||
|
|
@ -310,7 +343,8 @@ pub fn AvatarCanvas(
|
|||
let avatar_half_height = avatar_size / 2.0 + y_content_offset;
|
||||
|
||||
// Calculate bubble height using actual content (includes tail + gap)
|
||||
let estimated_bubble_height = bubble.as_ref()
|
||||
let estimated_bubble_height = bubble
|
||||
.as_ref()
|
||||
.map(|b| estimate_bubble_height(&b.message.content, text_scale))
|
||||
.unwrap_or(0.0);
|
||||
|
||||
|
|
@ -363,8 +397,8 @@ pub fn AvatarCanvas(
|
|||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use wasm_bindgen::closure::Closure;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen::closure::Closure;
|
||||
|
||||
// Image cache for this avatar (persists across re-renders)
|
||||
let image_cache: Rc<RefCell<HashMap<String, web_sys::HtmlImageElement>>> =
|
||||
|
|
@ -426,7 +460,8 @@ pub fn AvatarCanvas(
|
|||
let avatar_half_height = avatar_size / 2.0 + y_content_offset;
|
||||
|
||||
// Calculate bubble height using actual content (includes tail + gap)
|
||||
let estimated_bubble_height = bubble.as_ref()
|
||||
let estimated_bubble_height = bubble
|
||||
.as_ref()
|
||||
.map(|b| estimate_bubble_height(&b.message.content, text_scale))
|
||||
.unwrap_or(0.0);
|
||||
|
||||
|
|
@ -470,7 +505,12 @@ pub fn AvatarCanvas(
|
|||
|
||||
// Helper to load and draw an image
|
||||
// Images are cached; when loaded, triggers a redraw via signal
|
||||
let draw_image = |path: &str, cache: &Rc<RefCell<HashMap<String, web_sys::HtmlImageElement>>>, ctx: &web_sys::CanvasRenderingContext2d, x: f64, y: f64, size: f64| {
|
||||
let draw_image = |path: &str,
|
||||
cache: &Rc<RefCell<HashMap<String, web_sys::HtmlImageElement>>>,
|
||||
ctx: &web_sys::CanvasRenderingContext2d,
|
||||
x: f64,
|
||||
y: f64,
|
||||
size: f64| {
|
||||
let normalized_path = normalize_asset_path(path);
|
||||
let mut cache_borrow = cache.borrow_mut();
|
||||
|
||||
|
|
@ -526,7 +566,14 @@ pub fn AvatarCanvas(
|
|||
let row = pos / 3;
|
||||
let cell_cx = grid_origin_x + (col as f64 + 0.5) * cell_size;
|
||||
let cell_cy = grid_origin_y + (row as f64 + 0.5) * cell_size;
|
||||
draw_image(clothes_path, &image_cache, &ctx, cell_cx, cell_cy, cell_size);
|
||||
draw_image(
|
||||
clothes_path,
|
||||
&image_cache,
|
||||
&ctx,
|
||||
cell_cx,
|
||||
cell_cy,
|
||||
cell_size,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -537,7 +584,14 @@ pub fn AvatarCanvas(
|
|||
let row = pos / 3;
|
||||
let cell_cx = grid_origin_x + (col as f64 + 0.5) * cell_size;
|
||||
let cell_cy = grid_origin_y + (row as f64 + 0.5) * cell_size;
|
||||
draw_image(accessories_path, &image_cache, &ctx, cell_cx, cell_cy, cell_size);
|
||||
draw_image(
|
||||
accessories_path,
|
||||
&image_cache,
|
||||
&ctx,
|
||||
cell_cx,
|
||||
cell_cy,
|
||||
cell_size,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -548,7 +602,14 @@ pub fn AvatarCanvas(
|
|||
let row = pos / 3;
|
||||
let cell_cx = grid_origin_x + (col as f64 + 0.5) * cell_size;
|
||||
let cell_cy = grid_origin_y + (row as f64 + 0.5) * cell_size;
|
||||
draw_image(emotion_path, &image_cache, &ctx, cell_cx, cell_cy, cell_size);
|
||||
draw_image(
|
||||
emotion_path,
|
||||
&image_cache,
|
||||
&ctx,
|
||||
cell_cx,
|
||||
cell_cy,
|
||||
cell_size,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -560,7 +621,13 @@ pub fn AvatarCanvas(
|
|||
let badge_y = avatar_cy - avatar_size / 2.0 - badge_size / 2.0;
|
||||
|
||||
ctx.begin_path();
|
||||
let _ = ctx.arc(badge_x, badge_y, badge_size / 2.0, 0.0, std::f64::consts::PI * 2.0);
|
||||
let _ = ctx.arc(
|
||||
badge_x,
|
||||
badge_y,
|
||||
badge_size / 2.0,
|
||||
0.0,
|
||||
std::f64::consts::PI * 2.0,
|
||||
);
|
||||
ctx.set_fill_style_str("#f59e0b");
|
||||
ctx.fill();
|
||||
|
||||
|
|
@ -580,7 +647,8 @@ pub fn AvatarCanvas(
|
|||
ctx.set_font(&format!("{}px sans-serif", 12.0 * text_scale));
|
||||
ctx.set_text_align("center");
|
||||
ctx.set_text_baseline("alphabetic");
|
||||
let name_y = avatar_cy + avatar_size / 2.0 - (empty_bottom_rows as f64 * cell_size) + 15.0 * text_scale;
|
||||
let name_y = avatar_cy + avatar_size / 2.0 - (empty_bottom_rows as f64 * cell_size)
|
||||
+ 15.0 * text_scale;
|
||||
// Black outline
|
||||
ctx.set_stroke_style_str("#000");
|
||||
ctx.set_line_width(3.0);
|
||||
|
|
@ -630,7 +698,9 @@ pub fn AvatarCanvas(
|
|||
// Compute data-member-id reactively
|
||||
let data_member_id = move || {
|
||||
let m = member.get();
|
||||
m.member.user_id.map(|u| u.to_string())
|
||||
m.member
|
||||
.user_id
|
||||
.map(|u| u.to_string())
|
||||
.or_else(|| m.member.guest_session_id.map(|g| g.to_string()))
|
||||
.unwrap_or_default()
|
||||
};
|
||||
|
|
@ -693,11 +763,19 @@ fn draw_bubble(
|
|||
let (bg_color, border_color, text_color) = emotion_bubble_colors(&bubble.message.emotion);
|
||||
|
||||
// Use italic font for whispers
|
||||
let font_style = if bubble.message.is_whisper { "italic " } else { "" };
|
||||
let font_style = if bubble.message.is_whisper {
|
||||
"italic "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
// Measure and wrap text
|
||||
ctx.set_font(&format!("{}{}px sans-serif", font_style, font_size));
|
||||
let lines = wrap_text(ctx, &bubble.message.content, max_bubble_width - padding * 2.0);
|
||||
let lines = wrap_text(
|
||||
ctx,
|
||||
&bubble.message.content,
|
||||
max_bubble_width - padding * 2.0,
|
||||
);
|
||||
|
||||
// Calculate bubble dimensions
|
||||
let bubble_width = lines
|
||||
|
|
@ -747,7 +825,14 @@ fn draw_bubble(
|
|||
};
|
||||
|
||||
// Draw bubble background
|
||||
draw_rounded_rect(ctx, bubble_x, bubble_y, bubble_width, bubble_height, border_radius);
|
||||
draw_rounded_rect(
|
||||
ctx,
|
||||
bubble_x,
|
||||
bubble_y,
|
||||
bubble_width,
|
||||
bubble_height,
|
||||
border_radius,
|
||||
);
|
||||
ctx.set_fill_style_str(bg_color);
|
||||
ctx.fill();
|
||||
ctx.set_stroke_style_str(border_color);
|
||||
|
|
@ -782,7 +867,11 @@ fn draw_bubble(
|
|||
ctx.set_text_align("left");
|
||||
ctx.set_text_baseline("top");
|
||||
for (i, line) in lines.iter().enumerate() {
|
||||
let _ = ctx.fill_text(line, bubble_x + padding, bubble_y + padding + (i as f64) * line_height);
|
||||
let _ = ctx.fill_text(
|
||||
line,
|
||||
bubble_x + padding,
|
||||
bubble_y + padding + (i as f64) * line_height,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -800,7 +889,10 @@ fn wrap_text(ctx: &web_sys::CanvasRenderingContext2d, text: &str, max_width: f64
|
|||
format!("{} {}", current_line, word)
|
||||
};
|
||||
|
||||
let width = ctx.measure_text(&test_line).map(|m| m.width()).unwrap_or(0.0);
|
||||
let width = ctx
|
||||
.measure_text(&test_line)
|
||||
.map(|m| m.width())
|
||||
.unwrap_or(0.0);
|
||||
|
||||
if width > max_width && !current_line.is_empty() {
|
||||
lines.push(current_line);
|
||||
|
|
@ -834,11 +926,7 @@ fn wrap_text(ctx: &web_sys::CanvasRenderingContext2d, text: &str, max_width: f64
|
|||
/// Returns true if the alpha channel at the clicked pixel is > 0.
|
||||
/// This enables pixel-perfect hit detection on avatar canvases.
|
||||
#[cfg(feature = "hydrate")]
|
||||
pub fn hit_test_canvas(
|
||||
canvas: &web_sys::HtmlCanvasElement,
|
||||
client_x: f64,
|
||||
client_y: f64,
|
||||
) -> bool {
|
||||
pub fn hit_test_canvas(canvas: &web_sys::HtmlCanvasElement, client_x: f64, client_y: f64) -> bool {
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
// Get the canvas bounding rect to transform client coords to canvas coords
|
||||
|
|
@ -849,7 +937,11 @@ pub fn hit_test_canvas(
|
|||
let relative_y = client_y - rect.top();
|
||||
|
||||
// Check if click is within canvas bounds
|
||||
if relative_x < 0.0 || relative_y < 0.0 || relative_x >= rect.width() || relative_y >= rect.height() {
|
||||
if relative_x < 0.0
|
||||
|| relative_y < 0.0
|
||||
|| relative_x >= rect.width()
|
||||
|| relative_y >= rect.height()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue