Skip to content

Commit a53cb9b

Browse files
committed
temp: Introduce ChatSubtitleString
1 parent ee5ffee commit a53cb9b

File tree

7 files changed

+419
-1
lines changed

7 files changed

+419
-1
lines changed

src/expressions.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,93 @@ fn restriction_label_expression<T: glib::StaticType, V: glib::ToValue>(
130130
)
131131
.upcast()
132132
}
133+
134+
/*pub(crate) fn subtitle_expression(chat: &Chat) -> gtk::Expression {
135+
let actions_expression = gtk::ConstantExpression::new(chat)
136+
.chain_property::<Chat>("actions")
137+
.upcast();
138+
let online_count_expression =
139+
gtk::ConstantExpression::new(chat).chain_property::<Chat>("online-member-count");
140+
141+
let status_expression = if !chat.is_own_chat() {
142+
match chat.type_() {
143+
ChatType::Private(user) => {
144+
if let UserType::Bot(_) = user.type_().0 {
145+
gtk::ConstantExpression::new(gettext("bot")).upcast()
146+
} else {
147+
gtk::ConstantExpression::new(user)
148+
.chain_property::<User>("status")
149+
.chain_closure::<String>(closure!(
150+
|_: glib::Object, status: BoxedUserStatus| {
151+
strings::user_status(&status.0)
152+
}
153+
))
154+
.upcast()
155+
}
156+
}
157+
ChatType::Secret(data) => gtk::ConstantExpression::new(data.user())
158+
.chain_property::<User>("status")
159+
.chain_closure::<String>(closure!(|_: glib::Object, status: BoxedUserStatus| {
160+
strings::user_status(&status.0)
161+
}))
162+
.upcast(),
163+
ChatType::Supergroup(data) => {
164+
if data.is_channel() {
165+
gtk::ConstantExpression::new(data)
166+
.chain_property::<Supergroup>("member-count")
167+
.chain_closure::<String>(closure!(|_: glib::Object, sub_count: i32| {
168+
match sub_count {
169+
0 => gettext("channel"),
170+
1 => gettext("1 subscriber"),
171+
_ => gettext_f(
172+
"{count} subscribers",
173+
&[("count", &sub_count.to_string())],
174+
),
175+
}
176+
}))
177+
.upcast()
178+
} else {
179+
let member_count_expression = gtk::ConstantExpression::new(data)
180+
.chain_property::<Supergroup>("member-count");
181+
gtk::ClosureExpression::with_callback(
182+
&[member_count_expression, online_count_expression],
183+
|args| {
184+
strings::group_subtitle(
185+
args[1].get::<i32>().unwrap(),
186+
args[2].get::<i32>().unwrap(),
187+
)
188+
},
189+
)
190+
.upcast()
191+
}
192+
}
193+
ChatType::BasicGroup(data) => {
194+
let member_count_expression =
195+
gtk::ConstantExpression::new(data).chain_property::<BasicGroup>("member-count");
196+
gtk::ClosureExpression::with_callback(
197+
&[member_count_expression, online_count_expression],
198+
|args| {
199+
strings::group_subtitle(
200+
args[1].get::<i32>().unwrap(),
201+
args[2].get::<i32>().unwrap(),
202+
)
203+
},
204+
)
205+
.upcast()
206+
}
207+
}
208+
} else {
209+
gtk::ConstantExpression::new(String::new()).upcast()
210+
};
211+
212+
gtk::ClosureExpression::with_callback(&[actions_expression, status_expression], |args| {
213+
let actions = args[1].get::<ChatActionList>().unwrap();
214+
let status = args[2].get::<String>().unwrap();
215+
if let Some(action) = actions.last() {
216+
strings::chat_action(&action)
217+
} else {
218+
status
219+
}
220+
})
221+
.upcast()
222+
}*/

src/session/content/chat_history.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::session::content::ChatHistoryError;
2121
use crate::session::content::ChatHistoryModel;
2222
use crate::session::content::ChatHistoryRow;
2323
use crate::session::content::ChatInfoWindow;
24+
use crate::strings::ChatSubtitleString;
2425
use crate::tdlib::Chat;
2526
use crate::tdlib::ChatType;
2627
use crate::tdlib::SponsoredMessage;
@@ -52,6 +53,7 @@ mod imp {
5253
pub(super) list_view: TemplateChild<gtk::ListView>,
5354
#[template_child]
5455
pub(super) chat_action_bar: TemplateChild<ChatActionBar>,
56+
pub binding: RefCell<Option<gtk::ExpressionWatch>>,
5557
}
5658

5759
#[glib::object_subclass]
@@ -373,6 +375,16 @@ impl ChatHistory {
373375
imp.list_view.set_model(Some(&selection));
374376

375377
imp.model.replace(Some(model));
378+
if let Some(binding) = imp.binding.take() {
379+
binding.unwatch()
380+
}
381+
382+
// Bind subtitle
383+
imp.binding.replace(Some(
384+
gtk::ConstantExpression::new(ChatSubtitleString::new(chat.clone()))
385+
.chain_property::<ChatSubtitleString>("subtitle")
386+
.bind(&*imp.window_title, "subtitle", Some(self)),
387+
));
376388
}
377389

378390
imp.chat.replace(chat);

src/session/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ impl Session {
253253
Update::ChatUnreadMentionCount(ref data) => {
254254
self.chat(data.chat_id).handle_update(update)
255255
}
256+
Update::ChatOnlineMemberCount(ref data) => {
257+
self.chat(data.chat_id).handle_update(update)
258+
}
256259
Update::ChatIsBlocked(ref data) => self.chat(data.chat_id).handle_update(update),
257260
Update::ChatIsMarkedAsUnread(ref data) => self.chat(data.chat_id).handle_update(update),
258261
Update::DeleteMessages(ref data) => self.chat(data.chat_id).handle_update(update),

src/strings/chat_subtitle_string.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
use gettextrs::gettext;
2+
use glib::clone;
3+
use gtk::glib;
4+
use gtk::prelude::*;
5+
use gtk::subclass::prelude::*;
6+
7+
use super::UserStatusString;
8+
use crate::i18n::*;
9+
use crate::strings;
10+
use crate::tdlib::Chat;
11+
use crate::tdlib::ChatType;
12+
13+
mod imp {
14+
use once_cell::sync::Lazy;
15+
use once_cell::unsync::OnceCell;
16+
17+
use super::*;
18+
19+
#[derive(Debug, Default)]
20+
pub(crate) struct ChatSubtitleString {
21+
pub(super) chat: OnceCell<Chat>,
22+
pub(super) user_status_string: OnceCell<UserStatusString>,
23+
}
24+
25+
#[glib::object_subclass]
26+
impl ObjectSubclass for ChatSubtitleString {
27+
const NAME: &'static str = "ChatSubtitleString";
28+
type Type = super::ChatSubtitleString;
29+
}
30+
31+
impl ObjectImpl for ChatSubtitleString {
32+
fn properties() -> &'static [glib::ParamSpec] {
33+
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
34+
vec![glib::ParamSpecString::builder("subtitle")
35+
.read_only()
36+
.build()]
37+
});
38+
PROPERTIES.as_ref()
39+
}
40+
41+
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
42+
let obj = self.obj();
43+
44+
match pspec.name() {
45+
"subtitle" => obj.subtitle().to_value(),
46+
_ => unimplemented!(),
47+
}
48+
}
49+
}
50+
}
51+
52+
glib::wrapper! {
53+
pub(crate) struct ChatSubtitleString(ObjectSubclass<imp::ChatSubtitleString>);
54+
}
55+
56+
impl ChatSubtitleString {
57+
pub(crate) fn new(chat: Chat) -> ChatSubtitleString {
58+
let obj: ChatSubtitleString = glib::Object::builder().build();
59+
60+
chat.connect_chat_action_changed(clone!(@weak obj => move |_| {
61+
obj.notify("subtitle");
62+
}));
63+
64+
chat.connect_notify_local(
65+
Some("online-member-count"),
66+
clone!(@weak obj => move |_, _| {
67+
obj.notify("subtitle");
68+
}),
69+
);
70+
match chat.type_() {
71+
ChatType::BasicGroup(basic) => {
72+
basic.connect_notify_local(
73+
Some("member-count"),
74+
clone!(@weak obj => move |_, _| {
75+
obj.notify("subtitle");
76+
}),
77+
);
78+
}
79+
ChatType::Supergroup(group) => {
80+
group.connect_notify_local(
81+
Some("member-count"),
82+
clone!(@weak obj => move |_, _| {
83+
obj.notify("subtitle");
84+
}),
85+
);
86+
}
87+
ChatType::Private(user) => {
88+
let user_status_string = UserStatusString::new(user.clone());
89+
user_status_string.connect_notify_local(
90+
Some("string"),
91+
clone!(@weak obj => move |_, _| {
92+
obj.notify("subtitle");
93+
}),
94+
);
95+
obj.imp()
96+
.user_status_string
97+
.set(user_status_string)
98+
.unwrap();
99+
}
100+
ChatType::Secret(secret) => {
101+
let user = secret.user();
102+
let user_status_string = UserStatusString::new(user.clone());
103+
user_status_string.connect_notify_local(
104+
Some("string"),
105+
clone!(@weak obj => move |_, _| {
106+
obj.notify("subtitle");
107+
}),
108+
);
109+
obj.imp()
110+
.user_status_string
111+
.set(user_status_string)
112+
.unwrap();
113+
}
114+
}
115+
116+
obj.imp().chat.set(chat).unwrap();
117+
obj
118+
}
119+
120+
pub(crate) fn subtitle(&self) -> String {
121+
let chat = self.imp().chat.get().unwrap();
122+
let action = chat.actions().last();
123+
if let Some(action) = action {
124+
strings::chat_action(&action)
125+
} else {
126+
format!(
127+
"{}{}",
128+
match chat.type_() {
129+
ChatType::Private(_) | ChatType::Secret(_) =>
130+
self.imp().user_status_string.get().unwrap().string(),
131+
ChatType::BasicGroup(basic) => {
132+
let m_count = basic.member_count();
133+
match m_count {
134+
0 => gettext("group"),
135+
_ => ngettext_f(
136+
"{num} member",
137+
"{num} members",
138+
m_count as u32,
139+
&[("num", &m_count.to_string())],
140+
),
141+
}
142+
}
143+
ChatType::Supergroup(data) if data.is_channel() => {
144+
let m_count = data.member_count();
145+
match m_count {
146+
0 => gettext("channel"),
147+
_ => ngettext_f(
148+
"{num} subscriber",
149+
"{num} subscribers",
150+
m_count as u32,
151+
&[("num", &m_count.to_string())],
152+
),
153+
}
154+
}
155+
ChatType::Supergroup(data) => {
156+
let m_count = data.member_count();
157+
match m_count {
158+
0 => gettext("group"),
159+
_ => ngettext_f(
160+
"{num} member",
161+
"{num} members",
162+
m_count as u32,
163+
&[("num", &m_count.to_string())],
164+
),
165+
}
166+
}
167+
},
168+
if chat.online_member_count() > 1 {
169+
format!(
170+
", {}",
171+
ngettext_f(
172+
"{num} online",
173+
"{num} online",
174+
chat.online_member_count() as u32,
175+
&[("num", &chat.online_member_count().to_string())]
176+
)
177+
)
178+
} else {
179+
String::new()
180+
}
181+
)
182+
}
183+
}
184+
}

src/strings.rs renamed to src/strings/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
mod chat_subtitle_string;
2+
mod user_status_string;
3+
4+
pub(crate) use chat_subtitle_string::ChatSubtitleString;
15
use ellipse::Ellipse;
26
use gettextrs::gettext;
37
use gtk::glib;
@@ -6,6 +10,7 @@ use tdlib::enums::UserStatus;
610
use tdlib::enums::UserType;
711
use tdlib::types::MessageGame;
812
use tdlib::types::MessageGameScore;
13+
pub(crate) use user_status_string::UserStatusString;
914

1015
use crate::i18n::gettext_f;
1116
use crate::i18n::ngettext_f;
@@ -842,3 +847,18 @@ fn message_contact_registered(sender: &MessageSender) -> String {
842847
let sender = message_sender(sender, true);
843848
gettext_f("{sender} joined Telegram", &[("sender", &sender)])
844849
}
850+
851+
/*pub(crate) fn group_subtitle(member_count: i32, online_count: i32) -> String {
852+
format!(
853+
"{}{}",
854+
match member_count {
855+
1 => gettext("1 member"),
856+
_ => gettext!("{} members", member_count),
857+
},
858+
if online_count > 1 {
859+
gettext!(", {} online", online_count)
860+
} else {
861+
String::new()
862+
}
863+
)
864+
}*/

0 commit comments

Comments
 (0)