@@ -3,9 +3,10 @@ use gettextrs::gettext;
33use glib:: { clone, closure} ;
44use gtk:: subclass:: prelude:: * ;
55use gtk:: { glib, CompositeTemplate } ;
6- use tdlib:: enums:: UserType ;
6+ use tdlib:: enums:: { ChatMemberStatus , MessageSender , UserType } ;
7+ use tdlib:: enums:: { ChatMembers :: ChatMembers as TdChatMembers , User :: User as TdUser } ;
78use tdlib:: functions;
8- use tdlib:: types:: { BasicGroupFullInfo , SupergroupFullInfo } ;
9+ use tdlib:: types:: { BasicGroupFullInfo , ChatMember , ChatMembers , SupergroupFullInfo } ;
910
1011use crate :: i18n:: ngettext_f;
1112use crate :: tdlib:: { BasicGroup , BoxedUserStatus , Chat , ChatType , Supergroup , User } ;
@@ -29,6 +30,10 @@ mod imp {
2930 pub ( super ) subtitle_label : TemplateChild < gtk:: Label > ,
3031 #[ template_child]
3132 pub ( super ) info_list : TemplateChild < gtk:: ListBox > ,
33+ #[ template_child]
34+ pub ( super ) members_page : TemplateChild < adw:: ViewStackPage > ,
35+ #[ template_child]
36+ pub ( super ) members_list : TemplateChild < gtk:: ListBox > ,
3237 }
3338
3439 #[ glib:: object_subclass]
@@ -214,6 +219,11 @@ impl ChatInfoWindow {
214219 imp. info_list . append ( & row) ;
215220 }
216221
222+ imp. members_page . set_visible ( true ) ;
223+ spawn ( clone ! ( @weak self as obj => async move {
224+ obj. append_members( basic_group_full_info. members) . await ;
225+ } ) ) ;
226+
217227 self . update_info_list_visibility ( ) ;
218228 }
219229
@@ -251,7 +261,7 @@ impl ChatInfoWindow {
251261 let result = functions:: get_supergroup_full_info( supergroup_id, client_id) . await ;
252262 match result {
253263 Ok ( tdlib:: enums:: SupergroupFullInfo :: SupergroupFullInfo ( full_info) ) => {
254- obj. setup_supergroup_full_info( full_info) ;
264+ obj. setup_supergroup_full_info( supergroup_id , full_info) ;
255265 }
256266 Err ( e) => {
257267 log:: warn!( "Failed to get supergroup full info: {e:?}" ) ;
@@ -260,7 +270,12 @@ impl ChatInfoWindow {
260270 } ) ) ;
261271 }
262272
263- fn setup_supergroup_full_info ( & self , supergroup_full_info : SupergroupFullInfo ) {
273+ fn setup_supergroup_full_info (
274+ & self ,
275+ supergroup_id : i64 ,
276+ supergroup_full_info : SupergroupFullInfo ,
277+ ) {
278+ let client_id = self . chat ( ) . unwrap ( ) . session ( ) . client_id ( ) ;
264279 let imp = self . imp ( ) ;
265280
266281 // Description
@@ -273,9 +288,111 @@ impl ChatInfoWindow {
273288 imp. info_list . append ( & row) ;
274289 }
275290
291+ if supergroup_full_info. can_get_members {
292+ imp. members_page . set_visible ( true ) ;
293+ spawn ( clone ! ( @weak self as obj => async move {
294+ let limit = 200 ;
295+ let mut offset = 0 ;
296+ while let Ok ( TdChatMembers ( ChatMembers { members, total_count} ) ) = functions:: get_supergroup_members(
297+ supergroup_id,
298+ None ,
299+ offset,
300+ limit,
301+ client_id,
302+ ) . await
303+ {
304+ if offset > total_count {
305+ break ;
306+ }
307+
308+ obj. append_members( members) . await ;
309+
310+ offset += limit;
311+ }
312+ } ) ) ;
313+ }
314+
276315 self . update_info_list_visibility ( ) ;
277316 }
278317
318+ async fn append_members ( & self , members : Vec < ChatMember > ) {
319+ let session = self . chat ( ) . unwrap ( ) . session ( ) ;
320+ let client_id = session. client_id ( ) ;
321+
322+ let members_list = & self . imp ( ) . members_list ;
323+
324+ for member in members {
325+ if let MessageSender :: User ( user) = member. member_id {
326+ if let Ok ( TdUser ( user) ) = functions:: get_user ( user. user_id , client_id) . await {
327+ let user_row = adw:: ActionRow :: new ( ) ;
328+ user_row. set_title_lines ( 1 ) ;
329+ user_row. set_subtitle_lines ( 1 ) ;
330+
331+ let user = User :: from_td_object ( user, & session) ;
332+
333+ let user_expression = gtk:: ObjectExpression :: new ( & user) ;
334+ let name_expression = expressions:: user_display_name ( & user_expression) ;
335+ name_expression. bind ( & user_row, "title" , Some ( & user) ) ;
336+
337+ User :: this_expression ( "status" )
338+ . chain_closure :: < String > ( closure ! (
339+ |_: Option <glib:: Object >, status: BoxedUserStatus | {
340+ strings:: user_status( & status. 0 )
341+ }
342+ ) )
343+ . bind ( & user_row, "subtitle" , Some ( & user) ) ;
344+
345+ if let UserType :: Bot ( _) = user. type_ ( ) . 0 {
346+ user_row. set_subtitle ( & gettext ( "bot" ) ) ;
347+ } else {
348+ User :: this_expression ( "status" )
349+ . chain_closure :: < String > ( closure ! (
350+ |_: Option <glib:: Object >, status: BoxedUserStatus | {
351+ strings:: user_status( & status. 0 )
352+ }
353+ ) )
354+ . bind ( & user_row, "subtitle" , Some ( & user) ) ;
355+ } ;
356+
357+ let avatar = crate :: session:: components:: Avatar :: new ( ) ;
358+
359+ avatar. set_item ( Some ( user. upcast ( ) ) ) ;
360+ avatar. set_size ( 32 ) ;
361+ user_row. add_prefix ( & avatar) ;
362+
363+ let status = match member. status {
364+ ChatMemberStatus :: Creator ( owner) => {
365+ let title = if owner. custom_title . is_empty ( ) {
366+ gettext ( "Owner" )
367+ } else {
368+ owner. custom_title
369+ } ;
370+ Some ( title)
371+ }
372+ ChatMemberStatus :: Administrator ( admin) => {
373+ let title = if admin. custom_title . is_empty ( ) {
374+ gettext ( "Admin" )
375+ } else {
376+ admin. custom_title
377+ } ;
378+ Some ( title)
379+ }
380+ _ => None ,
381+ } ;
382+
383+ if let Some ( text) = status {
384+ let owner_label = gtk:: Label :: new ( Some ( & text) ) ;
385+ owner_label. set_yalign ( 0.2 ) ;
386+ owner_label. set_css_classes ( & [ "caption" , "accent" ] ) ;
387+ user_row. add_suffix ( & owner_label) ;
388+ }
389+
390+ members_list. append ( & user_row) ;
391+ }
392+ }
393+ }
394+ }
395+
279396 fn update_info_list_visibility ( & self ) {
280397 let info_list = & self . imp ( ) . info_list ;
281398 info_list. set_visible ( info_list. first_child ( ) . is_some ( ) ) ;
0 commit comments