mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 21:59:52 -07:00
Add support for previewing images in room scrollback (#108)
This commit is contained in:
parent
974775b29b
commit
221faa828d
15 changed files with 588 additions and 29 deletions
|
@ -51,7 +51,9 @@ use modalkit::tui::{
|
|||
};
|
||||
|
||||
use modalkit::editing::{base::ViewportContext, cursor::Cursor};
|
||||
use ratatui_image::protocol::Protocol;
|
||||
|
||||
use crate::config::ImagePreviewSize;
|
||||
use crate::{
|
||||
base::{IambResult, RoomInfo},
|
||||
config::ApplicationSettings,
|
||||
|
@ -585,12 +587,20 @@ impl<'a> MessageFormatter<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum ImageStatus {
|
||||
None,
|
||||
Downloading(ImagePreviewSize),
|
||||
Loaded(Box<dyn Protocol>),
|
||||
Error(String),
|
||||
}
|
||||
|
||||
pub struct Message {
|
||||
pub event: MessageEvent,
|
||||
pub sender: OwnedUserId,
|
||||
pub timestamp: MessageTimeStamp,
|
||||
pub downloaded: bool,
|
||||
pub html: Option<StyleTree>,
|
||||
pub image_preview: ImageStatus,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
|
@ -598,7 +608,14 @@ impl Message {
|
|||
let html = event.html();
|
||||
let downloaded = false;
|
||||
|
||||
Message { event, sender, timestamp, downloaded, html }
|
||||
Message {
|
||||
event,
|
||||
sender,
|
||||
timestamp,
|
||||
downloaded,
|
||||
html,
|
||||
image_preview: ImageStatus::None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reply_to(&self) -> Option<OwnedEventId> {
|
||||
|
@ -681,6 +698,36 @@ impl Message {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the image preview Protocol and x,y offset, based on get_render_format.
|
||||
pub fn line_preview<'a>(
|
||||
&'a self,
|
||||
prev: Option<&Message>,
|
||||
vwctx: &ViewportContext<MessageCursor>,
|
||||
info: &'a RoomInfo,
|
||||
) -> Option<(&dyn Protocol, u16, u16)> {
|
||||
let width = vwctx.get_width();
|
||||
// The x position where get_render_format would render the text.
|
||||
let x = (if USER_GUTTER + MIN_MSG_LEN <= width {
|
||||
USER_GUTTER
|
||||
} else {
|
||||
0
|
||||
} + 1) as u16;
|
||||
// See get_render_format; account for possible "date" line.
|
||||
let date_y = match &prev {
|
||||
Some(prev) if !prev.timestamp.same_day(&self.timestamp) => 1,
|
||||
_ => 0,
|
||||
};
|
||||
if let ImageStatus::Loaded(backend) = &self.image_preview {
|
||||
return Some((backend.as_ref(), x, date_y));
|
||||
} else if let Some(reply) = self.reply_to().and_then(|e| info.get_event(&e)) {
|
||||
if let ImageStatus::Loaded(backend) = &reply.image_preview {
|
||||
// The reply should be offset a bit:
|
||||
return Some((backend.as_ref(), x + 2, date_y + 1));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn show<'a>(
|
||||
&'a self,
|
||||
prev: Option<&Message>,
|
||||
|
@ -791,6 +838,19 @@ impl Message {
|
|||
msg.to_mut().push_str(" \u{2705}");
|
||||
}
|
||||
|
||||
if let Some(placeholder) = match &self.image_preview {
|
||||
ImageStatus::None => None,
|
||||
ImageStatus::Downloading(image_preview_size) => {
|
||||
Some(Message::placeholder_frame(Some("Downloading..."), image_preview_size))
|
||||
},
|
||||
ImageStatus::Loaded(backend) => {
|
||||
Some(Message::placeholder_frame(None, &backend.rect().into()))
|
||||
},
|
||||
ImageStatus::Error(err) => Some(format!("[Image error: {err}]\n")),
|
||||
} {
|
||||
msg.to_mut().insert_str(0, &placeholder);
|
||||
}
|
||||
|
||||
wrapped_text(msg, width, style)
|
||||
}
|
||||
}
|
||||
|
@ -803,6 +863,24 @@ impl Message {
|
|||
settings.get_user_span(self.sender.as_ref(), info)
|
||||
}
|
||||
|
||||
/// Before the image is loaded, already display a placeholder frame of the image size.
|
||||
fn placeholder_frame(text: Option<&str>, image_preview_size: &ImagePreviewSize) -> String {
|
||||
let ImagePreviewSize { width, height } = image_preview_size;
|
||||
let mut placeholder = "\u{230c}".to_string();
|
||||
placeholder.push_str(&" ".repeat(width - 2));
|
||||
placeholder.push_str("\u{230d}\n");
|
||||
placeholder.push(' ');
|
||||
if let Some(text) = text {
|
||||
placeholder.push_str(text);
|
||||
}
|
||||
|
||||
placeholder.push_str(&"\n".repeat(height - 2));
|
||||
placeholder.push('\u{230e}');
|
||||
placeholder.push_str(&" ".repeat(width - 2));
|
||||
placeholder.push_str("\u{230f}\n");
|
||||
placeholder
|
||||
}
|
||||
|
||||
fn show_sender<'a>(
|
||||
&'a self,
|
||||
prev: Option<&Message>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue