fractal/session/model/room/timeline/
virtual_item.rsuse std::ops::Deref;
use gtk::{glib, prelude::*, subclass::prelude::*};
use matrix_sdk_ui::timeline::VirtualTimelineItem;
use ruma::MilliSecondsSinceUnixEpoch;
use super::{TimelineItem, TimelineItemImpl};
use crate::utils::matrix::timestamp_to_date;
#[derive(Debug, Default, Eq, PartialEq, Clone)]
pub enum VirtualItemKind {
#[default]
Spinner,
Typing,
TimelineStart,
DayDivider(glib::DateTime),
NewMessages,
}
impl VirtualItemKind {
fn with_timestamp(ts: MilliSecondsSinceUnixEpoch) -> Self {
Self::DayDivider(timestamp_to_date(ts))
}
fn boxed(self) -> BoxedVirtualItemKind {
BoxedVirtualItemKind(self)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, glib::Boxed)]
#[boxed_type(name = "BoxedVirtualItemKind")]
pub struct BoxedVirtualItemKind(VirtualItemKind);
impl Deref for BoxedVirtualItemKind {
type Target = VirtualItemKind;
fn deref(&self) -> &Self::Target {
&self.0
}
}
mod imp {
use std::cell::RefCell;
use super::*;
#[derive(Debug, Default, glib::Properties)]
#[properties(wrapper_type = super::VirtualItem)]
pub struct VirtualItem {
#[property(get, set, construct)]
kind: RefCell<BoxedVirtualItemKind>,
}
#[glib::object_subclass]
impl ObjectSubclass for VirtualItem {
const NAME: &'static str = "TimelineVirtualItem";
type Type = super::VirtualItem;
type ParentType = TimelineItem;
}
#[glib::derived_properties]
impl ObjectImpl for VirtualItem {}
impl TimelineItemImpl for VirtualItem {}
}
glib::wrapper! {
pub struct VirtualItem(ObjectSubclass<imp::VirtualItem>) @extends TimelineItem;
}
impl VirtualItem {
pub(crate) fn with_item(item: &VirtualTimelineItem, timeline_id: &str) -> Self {
match item {
VirtualTimelineItem::DateDivider(ts) => {
Self::day_divider_with_timestamp(*ts, timeline_id)
}
VirtualTimelineItem::ReadMarker => Self::new_messages(timeline_id),
}
}
pub(crate) fn update_with_item(&self, item: &VirtualTimelineItem) {
let kind = match item {
VirtualTimelineItem::DateDivider(ts) => VirtualItemKind::with_timestamp(*ts),
VirtualTimelineItem::ReadMarker => VirtualItemKind::NewMessages,
};
self.set_kind(kind.boxed());
}
pub(crate) fn spinner() -> Self {
glib::Object::builder()
.property("kind", VirtualItemKind::Spinner.boxed())
.property("timeline-id", "VirtualItemKind::Spinner")
.build()
}
pub(crate) fn typing() -> Self {
glib::Object::builder()
.property("kind", VirtualItemKind::Typing.boxed())
.property("timeline-id", "VirtualItemKind::Typing")
.build()
}
pub(crate) fn timeline_start() -> Self {
glib::Object::builder()
.property("kind", VirtualItemKind::TimelineStart.boxed())
.property("timeline-id", "VirtualItemKind::TimelineStart")
.build()
}
fn new_messages(timeline_id: &str) -> Self {
glib::Object::builder()
.property("kind", VirtualItemKind::NewMessages.boxed())
.property("timeline-id", timeline_id)
.build()
}
fn day_divider_with_timestamp(
timestamp: MilliSecondsSinceUnixEpoch,
timeline_id: &str,
) -> Self {
glib::Object::builder()
.property("kind", VirtualItemKind::with_timestamp(timestamp).boxed())
.property("timeline-id", timeline_id)
.build()
}
}