@@ -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:: Label > ,
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]
@@ -214,6 +220,11 @@ impl ChatInfoWindow {
214
220
imp. info_list . append ( & row) ;
215
221
}
216
222
223
+ imp. members_page . set_visible ( true ) ;
224
+ spawn ( clone ! ( @weak self as obj => async move {
225
+ obj. append_members( basic_group_full_info. members) . await ;
226
+ } ) ) ;
227
+
217
228
self . update_info_list_visibility ( ) ;
218
229
}
219
230
@@ -251,7 +262,7 @@ impl ChatInfoWindow {
251
262
let result = functions:: get_supergroup_full_info( supergroup_id, client_id) . await ;
252
263
match result {
253
264
Ok ( tdlib:: enums:: SupergroupFullInfo :: SupergroupFullInfo ( full_info) ) => {
254
- obj. setup_supergroup_full_info( full_info) ;
265
+ obj. setup_supergroup_full_info( supergroup_id , full_info) ;
255
266
}
256
267
Err ( e) => {
257
268
log:: warn!( "Failed to get supergroup full info: {e:?}" ) ;
@@ -260,7 +271,12 @@ impl ChatInfoWindow {
260
271
} ) ) ;
261
272
}
262
273
263
- fn setup_supergroup_full_info ( & self , supergroup_full_info : SupergroupFullInfo ) {
274
+ fn setup_supergroup_full_info (
275
+ & self ,
276
+ supergroup_id : i64 ,
277
+ supergroup_full_info : SupergroupFullInfo ,
278
+ ) {
279
+ let client_id = self . chat ( ) . unwrap ( ) . session ( ) . client_id ( ) ;
264
280
let imp = self . imp ( ) ;
265
281
266
282
// Description
@@ -273,9 +289,111 @@ impl ChatInfoWindow {
273
289
imp. info_list . append ( & row) ;
274
290
}
275
291
292
+ if supergroup_full_info. can_get_members {
293
+ imp. members_page . set_visible ( true ) ;
294
+ spawn ( clone ! ( @weak self as obj => async move {
295
+ let limit = 200 ;
296
+ let mut offset = 0 ;
297
+ while let Ok ( TdChatMembers ( ChatMembers { members, total_count} ) ) = functions:: get_supergroup_members(
298
+ supergroup_id,
299
+ None ,
300
+ offset,
301
+ limit,
302
+ client_id,
303
+ ) . await
304
+ {
305
+ if offset > total_count {
306
+ break ;
307
+ }
308
+
309
+ obj. append_members( members) . await ;
310
+
311
+ offset += limit;
312
+ }
313
+ } ) ) ;
314
+ }
315
+
276
316
self . update_info_list_visibility ( ) ;
277
317
}
278
318
319
+ async fn append_members ( & self , members : Vec < ChatMember > ) {
320
+ let session = self . chat ( ) . unwrap ( ) . session ( ) ;
321
+ let client_id = session. client_id ( ) ;
322
+
323
+ let members_list = & self . imp ( ) . members_list ;
324
+
325
+ for member in members {
326
+ if let MessageSender :: User ( user) = member. member_id {
327
+ if let Ok ( TdUser ( user) ) = functions:: get_user ( user. user_id , client_id) . await {
328
+ let user_row = adw:: ActionRow :: new ( ) ;
329
+ user_row. set_title_lines ( 1 ) ;
330
+ user_row. set_subtitle_lines ( 1 ) ;
331
+
332
+ let user = User :: from_td_object ( user, & session) ;
333
+
334
+ let user_expression = gtk:: ObjectExpression :: new ( & user) ;
335
+ let name_expression = expressions:: user_display_name ( & user_expression) ;
336
+ name_expression. bind ( & user_row, "title" , Some ( & user) ) ;
337
+
338
+ User :: this_expression ( "status" )
339
+ . chain_closure :: < String > ( closure ! (
340
+ |_: Option <glib:: Object >, status: BoxedUserStatus | {
341
+ strings:: user_status( & status. 0 )
342
+ }
343
+ ) )
344
+ . bind ( & user_row, "subtitle" , Some ( & user) ) ;
345
+
346
+ if let UserType :: Bot ( _) = user. type_ ( ) . 0 {
347
+ user_row. set_subtitle ( & gettext ( "bot" ) ) ;
348
+ } else {
349
+ User :: this_expression ( "status" )
350
+ . chain_closure :: < String > ( closure ! (
351
+ |_: Option <glib:: Object >, status: BoxedUserStatus | {
352
+ strings:: user_status( & status. 0 )
353
+ }
354
+ ) )
355
+ . bind ( & user_row, "subtitle" , Some ( & user) ) ;
356
+ } ;
357
+
358
+ let avatar = crate :: session:: components:: Avatar :: new ( ) ;
359
+
360
+ avatar. set_item ( Some ( user. upcast ( ) ) ) ;
361
+ avatar. set_size ( 32 ) ;
362
+ user_row. add_prefix ( & avatar) ;
363
+
364
+ let status = match member. status {
365
+ ChatMemberStatus :: Creator ( owner) => {
366
+ let title = if owner. custom_title . is_empty ( ) {
367
+ gettext ( "Owner" )
368
+ } else {
369
+ owner. custom_title
370
+ } ;
371
+ Some ( title)
372
+ }
373
+ ChatMemberStatus :: Administrator ( admin) => {
374
+ let title = if admin. custom_title . is_empty ( ) {
375
+ gettext ( "Admin" )
376
+ } else {
377
+ admin. custom_title
378
+ } ;
379
+ Some ( title)
380
+ }
381
+ _ => None ,
382
+ } ;
383
+
384
+ if let Some ( text) = status {
385
+ let owner_label = gtk:: Label :: new ( Some ( & text) ) ;
386
+ owner_label. set_yalign ( 0.2 ) ;
387
+ owner_label. set_css_classes ( & [ "caption" , "accent" ] ) ;
388
+ user_row. add_suffix ( & owner_label) ;
389
+ }
390
+
391
+ members_list. append ( & user_row) ;
392
+ }
393
+ }
394
+ }
395
+ }
396
+
279
397
fn update_info_list_visibility ( & self ) {
280
398
let info_list = & self . imp ( ) . info_list ;
281
399
info_list. set_visible ( info_list. first_child ( ) . is_some ( ) ) ;
0 commit comments