render media list
This commit is contained in:
@@ -9,9 +9,9 @@ use gpui::prelude::FluentBuilder;
|
|||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
||||||
Focusable, InteractiveElement, IntoElement, ListAlignment, ListOffset, ListState, MouseButton,
|
Focusable, InteractiveElement, IntoElement, ListAlignment, ListOffset, ListState, MouseButton,
|
||||||
ObjectFit, ParentElement, PathPromptOptions, Render, SharedString, StatefulInteractiveElement,
|
ObjectFit, ParentElement, PathPromptOptions, Render, SharedString, SharedUri,
|
||||||
Styled, StyledImage, Subscription, Task, WeakEntity, Window, deferred, div, img, list, px, red,
|
StatefulInteractiveElement, Styled, StyledImage, Subscription, Task, WeakEntity, Window,
|
||||||
relative, svg, white,
|
deferred, div, img, list, px, red, relative, svg, white,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
@@ -914,7 +914,8 @@ impl ChatPanel {
|
|||||||
.when(has_replies, |this| {
|
.when(has_replies, |this| {
|
||||||
this.children(self.render_message_replies(replies, cx))
|
this.children(self.render_message_replies(replies, cx))
|
||||||
})
|
})
|
||||||
.child(rendered_text),
|
.child(rendered_text)
|
||||||
|
.child(self.render_media(&message.media, cx)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
@@ -941,6 +942,55 @@ impl ChatPanel {
|
|||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_media(&self, media: &[SharedUri], cx: &Context<Self>) -> impl IntoElement {
|
||||||
|
// No media: return empty div
|
||||||
|
if media.is_empty() {
|
||||||
|
return div();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Single media item: render full-width image
|
||||||
|
if media.len() == 1 {
|
||||||
|
return div().child(
|
||||||
|
img(media[0].clone())
|
||||||
|
.border_1()
|
||||||
|
.border_color(cx.theme().border_variant)
|
||||||
|
.h(px(250.))
|
||||||
|
.object_fit(ObjectFit::Cover)
|
||||||
|
.rounded(cx.theme().radius),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiple media items: render in a row
|
||||||
|
div()
|
||||||
|
.w_full()
|
||||||
|
.flex_1()
|
||||||
|
.flex()
|
||||||
|
.flex_row()
|
||||||
|
.flex_wrap()
|
||||||
|
.gap_2()
|
||||||
|
.children({
|
||||||
|
let mut items = vec![];
|
||||||
|
|
||||||
|
for (ix, item) in media.iter().enumerate() {
|
||||||
|
items.push(
|
||||||
|
div()
|
||||||
|
.id(format!("media-{ix}"))
|
||||||
|
.flex_grow_0()
|
||||||
|
.flex_shrink_0()
|
||||||
|
.child(
|
||||||
|
img(item.clone())
|
||||||
|
.h_32()
|
||||||
|
.border_1()
|
||||||
|
.border_color(cx.theme().border_variant)
|
||||||
|
.rounded(cx.theme().radius),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
items
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn render_message_replies(
|
fn render_message_replies(
|
||||||
&self,
|
&self,
|
||||||
replies: &[EventId],
|
replies: &[EventId],
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ impl MediaExtractor {
|
|||||||
|
|
||||||
// Remove multiple consecutive spaces
|
// Remove multiple consecutive spaces
|
||||||
let re = Regex::new(r"\s+").unwrap();
|
let re = Regex::new(r"\s+").unwrap();
|
||||||
re.replace_all(text, " ").to_string()
|
re.replace_all(text, " ").trim().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates if a URL is a valid media URL
|
/// Validates if a URL is a valid media URL
|
||||||
|
|||||||
Reference in New Issue
Block a user