use std::ops::Deref;
use gtk::{glib, prelude::*, subclass::prelude::*};
use matrix_sdk_ui::timeline::VirtualTimelineItem;
use ruma::MilliSecondsSinceUnixEpoch;
use super::{TimelineItem, TimelineItemImpl};
#[derive(Debug, Default, Eq, PartialEq, Clone)]
pub enum VirtualItemKind {
#[default]
Spinner,
Typing,
TimelineStart,
DayDivider(glib::DateTime),
NewMessages,
}
impl VirtualItemKind {
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)]
pub 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 {
fn id(&self) -> String {
match &**self.kind.borrow() {
VirtualItemKind::Spinner => "VirtualItem::Spinner".to_owned(),
VirtualItemKind::Typing => "VirtualItem::Typing".to_owned(),
VirtualItemKind::TimelineStart => "VirtualItem::TimelineStart".to_owned(),
VirtualItemKind::DayDivider(date) => {
format!("VirtualItem::DayDivider({})", date.format("%F").unwrap())
}
VirtualItemKind::NewMessages => "VirtualItem::NewMessages".to_owned(),
}
}
}
}
glib::wrapper! {
pub struct VirtualItem(ObjectSubclass<imp::VirtualItem>) @extends TimelineItem;
}
impl VirtualItem {
pub fn new(item: &VirtualTimelineItem) -> Self {
match item {
VirtualTimelineItem::DayDivider(ts) => Self::day_divider_with_timestamp(*ts),
VirtualTimelineItem::ReadMarker => Self::new_messages(),
}
}
pub fn spinner() -> Self {
glib::Object::builder()
.property("kind", VirtualItemKind::Spinner.boxed())
.build()
}
pub fn typing() -> Self {
glib::Object::builder()
.property("kind", VirtualItemKind::Typing.boxed())
.build()
}
pub fn timeline_start() -> Self {
glib::Object::builder()
.property("kind", VirtualItemKind::TimelineStart.boxed())
.build()
}
pub fn new_messages() -> Self {
glib::Object::builder()
.property("kind", VirtualItemKind::NewMessages.boxed())
.build()
}
pub fn day_divider_with_timestamp(timestamp: MilliSecondsSinceUnixEpoch) -> Self {
let date = glib::DateTime::from_unix_utc(timestamp.as_secs().into())
.or_else(|_| glib::DateTime::now_local())
.expect("We should be able to get the current time");
glib::Object::builder()
.property("kind", VirtualItemKind::DayDivider(date).boxed())
.build()
}
}