diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml
index 607d1544..bfb305e4 100644
--- a/data/resources/resources.gresource.xml
+++ b/data/resources/resources.gresource.xml
@@ -22,6 +22,7 @@
ui/event-menu.ui
ui/event-source-dialog.ui
ui/login.ui
+ ui/media-viewer.ui
ui/session.ui
ui/sidebar.ui
ui/sidebar-account-switcher.ui
diff --git a/data/resources/ui/content-item.ui b/data/resources/ui/content-item.ui
index 3a2c3bce..19ef73bd 100644
--- a/data/resources/ui/content-item.ui
+++ b/data/resources/ui/content-item.ui
@@ -1,12 +1,16 @@
- False
+
+
+ row
+
+
False
-
diff --git a/data/resources/ui/content-room-history.ui b/data/resources/ui/content-room-history.ui
index f02d5f67..b4d9cd09 100644
--- a/data/resources/ui/content-room-history.ui
+++ b/data/resources/ui/content-room-history.ui
@@ -142,6 +142,7 @@
/org/gnome/FractalNext/content-item.ui
+ True
Room History
@@ -227,4 +228,3 @@
-
diff --git a/data/resources/ui/media-viewer.ui b/data/resources/ui/media-viewer.ui
new file mode 100644
index 00000000..c470ae48
--- /dev/null
+++ b/data/resources/ui/media-viewer.ui
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+ vertical
+
+
+
+
+
+ center
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/resources/ui/session.ui b/data/resources/ui/session.ui
index f8dee1d9..ca7d10a5 100644
--- a/data/resources/ui/session.ui
+++ b/data/resources/ui/session.ui
@@ -61,8 +61,10 @@
+
+
+
-
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c47338ca..bd618fcd 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -28,6 +28,7 @@ data/resources/ui/event-menu.ui
data/resources/ui/event-source-dialog.ui
data/resources/ui/login.ui
data/resources/ui/in-app-notification.ui
+data/resources/ui/media-viewer.ui
data/resources/ui/room-creation.ui
data/resources/ui/session.ui
data/resources/ui/session-verification.ui
@@ -86,6 +87,7 @@ src/session/content/room_history/message_row/mod.rs
src/session/content/room_history/message_row/text.rs
src/session/content/room_history/mod.rs
src/session/content/room_history/state_row.rs
+src/session/media_viewer.rs
src/session/mod.rs
src/session/room_creation/mod.rs
src/session/room_list.rs
diff --git a/src/meson.build b/src/meson.build
index ccc4245e..229e3a88 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -71,7 +71,7 @@ sources = files(
'session/content/mod.rs',
'session/content/room_details/member_page.rs',
'session/content/room_details/mod.rs',
- 'session/room/event_actions.rs',
+ 'session/media_viewer.rs',
'session/room/event.rs',
'session/room/highlight_flags.rs',
'session/room/item.rs',
diff --git a/src/session/content/room_history/mod.rs b/src/session/content/room_history/mod.rs
index 715b9d08..176346a1 100644
--- a/src/session/content/room_history/mod.rs
+++ b/src/session/content/room_history/mod.rs
@@ -16,7 +16,7 @@ use sourceview::prelude::*;
use crate::components::{CustomEntry, RoomTitle};
use crate::session::content::{MarkdownPopover, RoomDetails};
-use crate::session::room::{Room, RoomType};
+use crate::session::room::{Item, Room, RoomType};
mod imp {
use super::*;
@@ -193,6 +193,21 @@ mod imp {
self.listview
.set_vscroll_policy(gtk::ScrollablePolicy::Natural);
+ self.listview
+ .connect_activate(clone!(@weak obj => move |listview, pos| {
+ if let Some(item) = listview
+ .model()
+ .and_then(|model| model.item(pos))
+ .and_then(|o| o.downcast::- ().ok())
+ {
+ if let Some(event) = item.event() {
+ if let Some(room) = obj.room() {
+ room.session().show_media(event);
+ }
+ }
+ }
+ }));
+
obj.set_sticky(true);
let adj = self.listview.vadjustment().unwrap();
diff --git a/src/session/media_viewer.rs b/src/session/media_viewer.rs
new file mode 100644
index 00000000..aaa84659
--- /dev/null
+++ b/src/session/media_viewer.rs
@@ -0,0 +1,272 @@
+use adw::{prelude::*, subclass::prelude::*};
+use gettextrs::gettext;
+use gtk::{
+ gdk, gdk_pixbuf::Pixbuf, gio, glib, glib::clone, subclass::prelude::*, CompositeTemplate,
+};
+use log::warn;
+use matrix_sdk::ruma::events::{room::message::MessageType, AnyMessageEventContent};
+
+use crate::{
+ components::{ContextMenuBin, ContextMenuBinImpl},
+ session::room::Event,
+ spawn, Window,
+};
+
+use super::room::EventActions;
+
+mod imp {
+ use crate::components::ContextMenuBinExt;
+
+ use super::*;
+ use glib::object::WeakRef;
+ use glib::subclass::InitializingObject;
+ use once_cell::sync::Lazy;
+ use std::cell::{Cell, RefCell};
+
+ #[derive(Debug, Default, CompositeTemplate)]
+ #[template(resource = "/org/gnome/FractalNext/media-viewer.ui")]
+ pub struct MediaViewer {
+ pub fullscreened: Cell,
+ pub event: RefCell