mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-19 21:29:52 -07:00
Fix image preview in replies and threads (#366)
This commit is contained in:
parent
3e45ca3d2c
commit
a9c1e69a89
2 changed files with 34 additions and 14 deletions
|
@ -70,6 +70,8 @@ mod printer;
|
||||||
|
|
||||||
pub use self::compose::text_to_message;
|
pub use self::compose::text_to_message;
|
||||||
|
|
||||||
|
type ProtocolPreview<'a> = (&'a dyn Protocol, u16, u16);
|
||||||
|
|
||||||
pub type MessageKey = (MessageTimeStamp, OwnedEventId);
|
pub type MessageKey = (MessageTimeStamp, OwnedEventId);
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -715,11 +717,12 @@ impl<'a> MessageFormatter<'a> {
|
||||||
style: Style,
|
style: Style,
|
||||||
text: &mut Text<'a>,
|
text: &mut Text<'a>,
|
||||||
info: &'a RoomInfo,
|
info: &'a RoomInfo,
|
||||||
) {
|
settings: &'a ApplicationSettings,
|
||||||
|
) -> Option<ProtocolPreview<'a>> {
|
||||||
let width = self.width();
|
let width = self.width();
|
||||||
let w = width.saturating_sub(2);
|
let w = width.saturating_sub(2);
|
||||||
let shortcodes = self.settings.tunables.message_shortcode_display;
|
let shortcodes = self.settings.tunables.message_shortcode_display;
|
||||||
let (mut replied, _) = msg.show_msg(w, style, true, shortcodes);
|
let (mut replied, proto) = msg.show_msg(w, style, true, shortcodes);
|
||||||
let mut sender = msg.sender_span(info, self.settings);
|
let mut sender = msg.sender_span(info, self.settings);
|
||||||
let sender_width = UnicodeWidthStr::width(sender.content.as_ref());
|
let sender_width = UnicodeWidthStr::width(sender.content.as_ref());
|
||||||
let trailing = w.saturating_sub(sender_width + 1);
|
let trailing = w.saturating_sub(sender_width + 1);
|
||||||
|
@ -738,12 +741,22 @@ impl<'a> MessageFormatter<'a> {
|
||||||
text,
|
text,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Determine the image offset of the reply header, taking into account the formatting
|
||||||
|
let proto = proto.map(|p| {
|
||||||
|
let y_off = text.lines.len() as u16;
|
||||||
|
// Adjust x_off by 2 to account for the vertical line and indent
|
||||||
|
let x_off = self.cols.user_gutter_width(settings) + 2;
|
||||||
|
(p, x_off, y_off)
|
||||||
|
});
|
||||||
|
|
||||||
for line in replied.lines.iter_mut() {
|
for line in replied.lines.iter_mut() {
|
||||||
line.spans.insert(0, Span::styled(THICK_VERTICAL, style));
|
line.spans.insert(0, Span::styled(THICK_VERTICAL, style));
|
||||||
line.spans.insert(0, Span::styled(" ", style));
|
line.spans.insert(0, Span::styled(" ", style));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.push_text(replied, style, text);
|
self.push_text(replied, style, text);
|
||||||
|
|
||||||
|
proto
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_reactions(&mut self, counts: Vec<(&'a str, usize)>, style: Style, text: &mut Text<'a>) {
|
fn push_reactions(&mut self, counts: Vec<(&'a str, usize)>, style: Style, text: &mut Text<'a>) {
|
||||||
|
@ -961,7 +974,7 @@ impl Message {
|
||||||
vwctx: &ViewportContext<MessageCursor>,
|
vwctx: &ViewportContext<MessageCursor>,
|
||||||
info: &'a RoomInfo,
|
info: &'a RoomInfo,
|
||||||
settings: &'a ApplicationSettings,
|
settings: &'a ApplicationSettings,
|
||||||
) -> (Text<'a>, Option<(&'a dyn Protocol, u16, u16)>) {
|
) -> (Text<'a>, [Option<ProtocolPreview<'a>>; 2]) {
|
||||||
let width = vwctx.get_width();
|
let width = vwctx.get_width();
|
||||||
|
|
||||||
let style = self.get_render_style(selected, settings);
|
let style = self.get_render_style(selected, settings);
|
||||||
|
@ -974,10 +987,10 @@ impl Message {
|
||||||
.reply_to()
|
.reply_to()
|
||||||
.or_else(|| self.thread_root())
|
.or_else(|| self.thread_root())
|
||||||
.and_then(|e| info.get_event(&e));
|
.and_then(|e| info.get_event(&e));
|
||||||
|
let proto_reply = reply.as_ref().and_then(|r| {
|
||||||
if let Some(r) = &reply {
|
// Format the reply header, push it into the `Text` buffer, and get any image.
|
||||||
fmt.push_in_reply(r, style, &mut text, info);
|
fmt.push_in_reply(r, style, &mut text, info, settings)
|
||||||
}
|
});
|
||||||
|
|
||||||
// Now show the message contents, and the inlined reply if we couldn't find it above.
|
// Now show the message contents, and the inlined reply if we couldn't find it above.
|
||||||
let (msg, proto) = self.show_msg(
|
let (msg, proto) = self.show_msg(
|
||||||
|
@ -988,10 +1001,11 @@ impl Message {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Given our text so far, determine the image offset.
|
// Given our text so far, determine the image offset.
|
||||||
let proto = proto.map(|p| {
|
let proto_main = proto.map(|p| {
|
||||||
let y_off = text.lines.len() as u16;
|
let y_off = text.lines.len() as u16;
|
||||||
let x_off = fmt.cols.user_gutter_width(settings);
|
let x_off = fmt.cols.user_gutter_width(settings);
|
||||||
// Adjust y_off by 1 if a date was printed before the message to account for the extra line.
|
// Adjust y_off by 1 if a date was printed before the message to account for
|
||||||
|
// the extra line we're going to print.
|
||||||
let y_off = if fmt.date.is_some() { y_off + 1 } else { y_off };
|
let y_off = if fmt.date.is_some() { y_off + 1 } else { y_off };
|
||||||
(p, x_off, y_off)
|
(p, x_off, y_off)
|
||||||
});
|
});
|
||||||
|
@ -1012,7 +1026,7 @@ impl Message {
|
||||||
fmt.push_thread_reply_count(thread.len(), &mut text);
|
fmt.push_thread_reply_count(thread.len(), &mut text);
|
||||||
}
|
}
|
||||||
|
|
||||||
(text, proto)
|
(text, [proto_main, proto_reply])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show<'a>(
|
pub fn show<'a>(
|
||||||
|
@ -1053,7 +1067,7 @@ impl Message {
|
||||||
},
|
},
|
||||||
ImageStatus::Loaded(backend) => {
|
ImageStatus::Loaded(backend) => {
|
||||||
proto = Some(backend.as_ref());
|
proto = Some(backend.as_ref());
|
||||||
placeholder_frame(None, width, &backend.rect().into())
|
placeholder_frame(Some("Loading..."), width, &backend.rect().into())
|
||||||
},
|
},
|
||||||
ImageStatus::Error(err) => Some(format!("[Image error: {err}]\n")),
|
ImageStatus::Error(err) => Some(format!("[Image error: {err}]\n")),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1340,7 +1340,7 @@ impl<'a> StatefulWidget for Scrollback<'a> {
|
||||||
|
|
||||||
for (key, item) in thread.range(&corner_key..) {
|
for (key, item) in thread.range(&corner_key..) {
|
||||||
let sel = key == cursor_key;
|
let sel = key == cursor_key;
|
||||||
let (txt, mut msg_preview) =
|
let (txt, [mut msg_preview, mut reply_preview]) =
|
||||||
item.show_with_preview(prev, foc && sel, &state.viewctx, info, settings);
|
item.show_with_preview(prev, foc && sel, &state.viewctx, info, settings);
|
||||||
|
|
||||||
let incomplete_ok = !full || !sel;
|
let incomplete_ok = !full || !sel;
|
||||||
|
@ -1357,11 +1357,17 @@ impl<'a> StatefulWidget for Scrollback<'a> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only take the preview into the matching row number.
|
||||||
|
// `reply` and `msg` previews are on rows,
|
||||||
|
// so an `or` works to pick the one that matches (if any)
|
||||||
let line_preview = match msg_preview {
|
let line_preview = match msg_preview {
|
||||||
// Only take the preview into the matching row number.
|
|
||||||
Some((_, _, y)) if y as usize == row => msg_preview.take(),
|
Some((_, _, y)) if y as usize == row => msg_preview.take(),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
}
|
||||||
|
.or(match reply_preview {
|
||||||
|
Some((_, _, y)) if y as usize == row => reply_preview.take(),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
lines.push((key, row, line, line_preview));
|
lines.push((key, row, line, line_preview));
|
||||||
sawit |= sel;
|
sawit |= sel;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue