@@ -3,9 +3,11 @@ use gettextrs::gettext;
3
3
use glib:: { clone, closure} ;
4
4
use gtk:: subclass:: prelude:: * ;
5
5
use gtk:: { glib, CompositeTemplate } ;
6
- use tdlib:: enums:: UserType ;
6
+ use tdlib:: enums:: ChatMembers :: ChatMembers as TdChatMembers ;
7
+ use tdlib:: enums:: User :: User as TdUser ;
8
+ use tdlib:: enums:: { ChatMemberStatus , MessageSender , UserType } ;
7
9
use tdlib:: functions;
8
- use tdlib:: types:: { BasicGroupFullInfo , SupergroupFullInfo } ;
10
+ use tdlib:: types:: { BasicGroupFullInfo , ChatMember , ChatMembers , SupergroupFullInfo } ;
9
11
10
12
use crate :: i18n:: ngettext_f;
11
13
use crate :: tdlib:: { BasicGroup , BoxedUserStatus , Chat , ChatType , Supergroup , User } ;
@@ -29,6 +31,10 @@ mod imp {
29
31
pub ( super ) subtitle_label : TemplateChild < gtk:: Inscription > ,
30
32
#[ template_child]
31
33
pub ( super ) info_list : TemplateChild < gtk:: ListBox > ,
34
+ #[ template_child]
35
+ pub ( super ) members_page : TemplateChild < adw:: ViewStackPage > ,
36
+ #[ template_child]
37
+ pub ( super ) members_list : TemplateChild < gtk:: ListBox > ,
32
38
}
33
39
34
40
#[ glib:: object_subclass]
@@ -208,6 +214,11 @@ impl ChatInfoWindow {
208
214
imp. info_list . append ( & row) ;
209
215
}
210
216
217
+ imp. members_page . set_visible ( true ) ;
218
+ spawn ( clone ! ( @weak self as obj => async move {
219
+ obj. append_members( basic_group_full_info. members) . await ;
220
+ } ) ) ;
221
+
211
222
self . update_info_list_visibility ( ) ;
212
223
}
213
224
@@ -245,7 +256,7 @@ impl ChatInfoWindow {
245
256
let result = functions:: get_supergroup_full_info( supergroup_id, client_id) . await ;
246
257
match result {
247
258
Ok ( tdlib:: enums:: SupergroupFullInfo :: SupergroupFullInfo ( full_info) ) => {
248
- obj. setup_supergroup_full_info( full_info) ;
259
+ obj. setup_supergroup_full_info( supergroup_id , full_info) ;
249
260
}
250
261
Err ( e) => {
251
262
log:: warn!( "Failed to get supergroup full info: {e:?}" ) ;
@@ -254,7 +265,12 @@ impl ChatInfoWindow {
254
265
} ) ) ;
255
266
}
256
267
257
- fn setup_supergroup_full_info ( & self , supergroup_full_info : SupergroupFullInfo ) {
268
+ fn setup_supergroup_full_info (
269
+ & self ,
270
+ supergroup_id : i64 ,
271
+ supergroup_full_info : SupergroupFullInfo ,
272
+ ) {
273
+ let client_id = self . chat ( ) . unwrap ( ) . session ( ) . client_id ( ) ;
258
274
let imp = self . imp ( ) ;
259
275
260
276
// Description
@@ -267,9 +283,111 @@ impl ChatInfoWindow {
267
283
imp. info_list . append ( & row) ;
268
284
}
269
285
286
+ if supergroup_full_info. can_get_members {
287
+ imp. members_page . set_visible ( true ) ;
288
+ spawn ( clone ! ( @weak self as obj => async move {
289
+ let limit = 200 ;
290
+ let mut offset = 0 ;
291
+ while let Ok ( TdChatMembers ( ChatMembers { members, total_count} ) ) = functions:: get_supergroup_members(
292
+ supergroup_id,
293
+ None ,
294
+ offset,
295
+ limit,
296
+ client_id,
297
+ ) . await
298
+ {
299
+ if offset > total_count {
300
+ break ;
301
+ }
302
+
303
+ obj. append_members( members) . await ;
304
+
305
+ offset += limit;
306
+ }
307
+ } ) ) ;
308
+ }
309
+
270
310
self . update_info_list_visibility ( ) ;
271
311
}
272
312
313
+ async fn append_members ( & self , members : Vec < ChatMember > ) {
314
+ let session = self . chat ( ) . unwrap ( ) . session ( ) ;
315
+ let client_id = session. client_id ( ) ;
316
+
317
+ let members_list = & self . imp ( ) . members_list ;
318
+
319
+ for member in members {
320
+ if let MessageSender :: User ( user) = member. member_id {
321
+ if let Ok ( TdUser ( user) ) = functions:: get_user ( user. user_id , client_id) . await {
322
+ let user_row = adw:: ActionRow :: new ( ) ;
323
+ user_row. set_title_lines ( 1 ) ;
324
+ user_row. set_subtitle_lines ( 1 ) ;
325
+
326
+ let user = User :: from_td_object ( user, & session) ;
327
+
328
+ let user_expression = gtk:: ObjectExpression :: new ( & user) ;
329
+ let name_expression = expressions:: user_display_name ( & user_expression) ;
330
+ name_expression. bind ( & user_row, "title" , Some ( & user) ) ;
331
+
332
+ User :: this_expression ( "status" )
333
+ . chain_closure :: < String > ( closure ! (
334
+ |_: Option <glib:: Object >, status: BoxedUserStatus | {
335
+ strings:: user_status( & status. 0 )
336
+ }
337
+ ) )
338
+ . bind ( & user_row, "subtitle" , Some ( & user) ) ;
339
+
340
+ if let UserType :: Bot ( _) = user. type_ ( ) . 0 {
341
+ user_row. set_subtitle ( & gettext ( "bot" ) ) ;
342
+ } else {
343
+ User :: this_expression ( "status" )
344
+ . chain_closure :: < String > ( closure ! (
345
+ |_: Option <glib:: Object >, status: BoxedUserStatus | {
346
+ strings:: user_status( & status. 0 )
347
+ }
348
+ ) )
349
+ . bind ( & user_row, "subtitle" , Some ( & user) ) ;
350
+ } ;
351
+
352
+ let avatar = crate :: session:: components:: Avatar :: new ( ) ;
353
+
354
+ avatar. set_item ( Some ( user. upcast ( ) ) ) ;
355
+ avatar. set_size ( 32 ) ;
356
+ user_row. add_prefix ( & avatar) ;
357
+
358
+ let status = match member. status {
359
+ ChatMemberStatus :: Creator ( owner) => {
360
+ let title = if owner. custom_title . is_empty ( ) {
361
+ gettext ( "Owner" )
362
+ } else {
363
+ owner. custom_title
364
+ } ;
365
+ Some ( title)
366
+ }
367
+ ChatMemberStatus :: Administrator ( admin) => {
368
+ let title = if admin. custom_title . is_empty ( ) {
369
+ gettext ( "Admin" )
370
+ } else {
371
+ admin. custom_title
372
+ } ;
373
+ Some ( title)
374
+ }
375
+ _ => None ,
376
+ } ;
377
+
378
+ if let Some ( text) = status {
379
+ let owner_label = gtk:: Label :: new ( Some ( & text) ) ;
380
+ owner_label. set_yalign ( 0.2 ) ;
381
+ owner_label. set_css_classes ( & [ "caption" , "accent" ] ) ;
382
+ user_row. add_suffix ( & owner_label) ;
383
+ }
384
+
385
+ members_list. append ( & user_row) ;
386
+ }
387
+ }
388
+ }
389
+ }
390
+
273
391
fn update_info_list_visibility ( & self ) {
274
392
let info_list = & self . imp ( ) . info_list ;
275
393
info_list. set_visible ( info_list. first_child ( ) . is_some ( ) ) ;
0 commit comments