fractal/session/view/content/room_history/message_row/
message_state_stack.rsuse adw::subclass::prelude::*;
use gtk::{glib, glib::clone, prelude::*, CompositeTemplate};
use crate::session::model::MessageState;
const SENT_VISIBLE_SECONDS: u32 = 3;
mod imp {
use std::cell::Cell;
use glib::subclass::InitializingObject;
use super::*;
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
#[template(
resource = "/org/gnome/Fractal/ui/session/view/content/room_history/message_row/message_state_stack.ui"
)]
#[properties(wrapper_type = super::MessageStateStack)]
pub struct MessageStateStack {
#[property(get, set = Self::set_state, explicit_notify, builder(MessageState::default()))]
state: Cell<MessageState>,
#[template_child]
stack: TemplateChild<gtk::Stack>,
}
#[glib::object_subclass]
impl ObjectSubclass for MessageStateStack {
const NAME: &'static str = "MessageStateStack";
type Type = super::MessageStateStack;
type ParentType = adw::Bin;
fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for MessageStateStack {}
impl WidgetImpl for MessageStateStack {}
impl BinImpl for MessageStateStack {}
impl MessageStateStack {
fn set_state(&self, state: MessageState) {
let prev_state = self.state.get();
if prev_state == state {
return;
}
let stack = &self.stack;
let name = match state {
MessageState::None => {
if matches!(
prev_state,
MessageState::Sending
| MessageState::RecoverableError
| MessageState::PermanentError
) {
glib::timeout_add_seconds_local_once(
SENT_VISIBLE_SECONDS,
clone!(
#[weak]
stack,
move || {
stack.set_visible_child_name("none");
}
),
);
"sent"
} else {
"none"
}
}
MessageState::Sending => "sending",
MessageState::RecoverableError => "warning",
MessageState::PermanentError => "error",
MessageState::Edited => {
if matches!(
prev_state,
MessageState::Sending
| MessageState::RecoverableError
| MessageState::PermanentError
) {
glib::timeout_add_seconds_local_once(
SENT_VISIBLE_SECONDS,
clone!(
#[weak]
stack,
move || {
stack.set_visible_child_name("edited");
}
),
);
"sent"
} else {
"edited"
}
}
};
stack.set_visible_child_name(name);
self.state.set(state);
self.obj().notify_state();
}
}
}
glib::wrapper! {
pub struct MessageStateStack(ObjectSubclass<imp::MessageStateStack>)
@extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
}
impl MessageStateStack {
pub fn new() -> Self {
glib::Object::new()
}
}