@@ -3,9 +3,11 @@ use gettextrs::gettext;
33use glib:: { clone, closure} ;
44use gtk:: subclass:: prelude:: * ;
55use 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 } ;
79use tdlib:: functions;
8- use tdlib:: types:: { BasicGroupFullInfo , SupergroupFullInfo } ;
10+ use tdlib:: types:: { BasicGroupFullInfo , ChatMember , ChatMembers , SupergroupFullInfo } ;
911
1012use crate :: i18n:: ngettext_f;
1113use crate :: tdlib:: { BasicGroup , BoxedUserStatus , Chat , ChatType , Supergroup , User } ;
@@ -29,6 +31,10 @@ mod imp {
2931 pub ( super ) subtitle_label : TemplateChild < gtk:: Label > ,
3032 #[ template_child]
3133 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 > ,
3238 }
3339
3440 #[ glib:: object_subclass]
@@ -214,6 +220,11 @@ impl ChatInfoWindow {
214220 imp. info_list . append ( & row) ;
215221 }
216222
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+
217228 self . update_info_list_visibility ( ) ;
218229 }
219230
@@ -251,7 +262,7 @@ impl ChatInfoWindow {
251262 let result = functions:: get_supergroup_full_info( supergroup_id, client_id) . await ;
252263 match result {
253264 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) ;
255266 }
256267 Err ( e) => {
257268 log:: warn!( "Failed to get supergroup full info: {e:?}" ) ;
@@ -260,7 +271,12 @@ impl ChatInfoWindow {
260271 } ) ) ;
261272 }
262273
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 ( ) ;
264280 let imp = self . imp ( ) ;
265281
266282 // Description
@@ -273,9 +289,111 @@ impl ChatInfoWindow {
273289 imp. info_list . append ( & row) ;
274290 }
275291
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+
276316 self . update_info_list_visibility ( ) ;
277317 }
278318
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+
279397 fn update_info_list_visibility ( & self ) {
280398 let info_list = & self . imp ( ) . info_list ;
281399 info_list. set_visible ( info_list. first_child ( ) . is_some ( ) ) ;
0 commit comments