fix: use char boundaries instead of byte indices for UTF-8 strings in notifications

PANIC FIX: Notification preview truncation was using byte indices (`[..147]`)
instead of char boundaries, causing panic when truncating UTF-8 strings
containing multi-byte characters (Cyrillic, emoji, etc.).

Error message:
"byte index 147 is not a char boundary; it is inside 'п' (bytes 146..148)"

Fix:
- Replace `beautified.len() > 150` with `beautified.chars().count() > MAX_PREVIEW_CHARS`
- Replace `&beautified[..147]` with `beautified.chars().take(MAX_PREVIEW_CHARS).collect()`
- Add constant MAX_PREVIEW_CHARS = 147 for clarity

This ensures we truncate at character boundaries, not byte boundaries,
preventing panics on multi-byte UTF-8 sequences.

Impact: Notifications for messages with Russian/emoji text crashed the app.

Root cause: Classic Rust UTF-8 indexing mistake - slicing by bytes instead
of characters.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-02-05 13:06:40 +03:00
parent 5f1d715e8f
commit 7dbb2209c8

View File

@@ -164,9 +164,12 @@ impl NotificationManager {
// Beautify media labels with emojis
let beautified = Self::beautify_media_labels(text);
// Limit preview length
if beautified.len() > 150 {
format!("{}...", &beautified[..147])
// Limit preview length (use char count, not byte count for UTF-8 safety)
const MAX_PREVIEW_CHARS: usize = 147;
let char_count = beautified.chars().count();
if char_count > MAX_PREVIEW_CHARS {
let truncated: String = beautified.chars().take(MAX_PREVIEW_CHARS).collect();
format!("{}...", truncated)
} else {
beautified
}