@@ -5,12 +5,15 @@ use gtk::subclass::prelude::*;
55use gtk:: { glib, CompositeTemplate } ;
66use tdlib:: enums:: ChatMembers :: ChatMembers as TdChatMembers ;
77use tdlib:: enums:: User :: User as TdUser ;
8- use tdlib:: enums:: { ChatMemberStatus , MessageSender , UserType } ;
8+ use tdlib:: enums:: { MessageSender , UserType } ;
99use tdlib:: functions;
10- use tdlib:: types:: { BasicGroupFullInfo , ChatMember , ChatMembers , SupergroupFullInfo } ;
10+ use tdlib:: types:: {
11+ BasicGroupFullInfo , ChatMember as TdChatMember , ChatMembers , SupergroupFullInfo ,
12+ } ;
1113
1214use crate :: i18n:: ngettext_f;
13- use crate :: tdlib:: { BasicGroup , BoxedUserStatus , Chat , ChatType , Supergroup , User } ;
15+ use crate :: session:: components:: ChatMemberRow ;
16+ use crate :: tdlib:: { BasicGroup , BoxedUserStatus , Chat , ChatMember , ChatType , Supergroup , User } ;
1417use crate :: utils:: spawn;
1518use crate :: { expressions, strings} ;
1619
@@ -34,7 +37,7 @@ mod imp {
3437 #[ template_child]
3538 pub ( super ) members_page : TemplateChild < adw:: ViewStackPage > ,
3639 #[ template_child]
37- pub ( super ) members_list : TemplateChild < gtk:: ListBox > ,
40+ pub ( super ) members_list : TemplateChild < gtk:: ListView > ,
3841 }
3942
4043 #[ glib:: object_subclass]
@@ -310,81 +313,63 @@ impl ChatInfoWindow {
310313 self . update_info_list_visibility ( ) ;
311314 }
312315
313- async fn append_members ( & self , members : Vec < ChatMember > ) {
314- let session = self . chat ( ) . unwrap ( ) . session ( ) ;
315- let client_id = session . client_id ( ) ;
316+ async fn append_members ( & self , members : Vec < TdChatMember > ) {
317+ let members : Vec < _ > = {
318+ let mut users : Vec < User > = vec ! [ ] ;
316319
317- let members_list = & self . imp ( ) . members_list ;
320+ let session = self . chat ( ) . unwrap ( ) . session ( ) ;
321+ let client_id = session. client_id ( ) ;
318322
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) ;
323+ for member in & members {
324+ let user = match member. member_id {
325+ MessageSender :: User ( ref user) => {
326+ let TdUser ( user) =
327+ functions:: get_user ( user. user_id , client_id) . await . unwrap ( ) ;
328+ User :: from_td_object ( user, & session)
383329 }
384-
385- members_list . append ( & user_row ) ;
386- }
330+ MessageSender :: Chat ( _ ) => unreachable ! ( ) ,
331+ } ;
332+ users . push ( user ) ;
387333 }
334+
335+ members
336+ . into_iter ( )
337+ . zip ( users. into_iter ( ) )
338+ . map ( |( member, user) | ChatMember :: new ( member, user) )
339+ . collect ( )
340+ } ;
341+
342+ let members_list = & self . imp ( ) . members_list ;
343+
344+ let selection_model: gtk:: NoSelection = members_list. model ( ) . unwrap ( ) . downcast ( ) . unwrap ( ) ;
345+
346+ let model: gtk:: gio:: ListStore = if let Some ( model) = selection_model. model ( ) {
347+ model. downcast ( ) . unwrap ( )
348+ } else {
349+ let model = gtk:: gio:: ListStore :: new ( ChatMember :: static_type ( ) ) ;
350+ selection_model. set_model ( Some ( & model) ) ;
351+ model
352+ } ;
353+
354+ model. extend_from_slice ( & members) ;
355+
356+ if members_list. factory ( ) . is_none ( ) {
357+ let factory = gtk:: SignalListItemFactory :: new ( ) ;
358+
359+ factory. connect_setup ( move |_, list_item| {
360+ list_item. set_property ( "child" , ChatMemberRow :: new ( ) ) ;
361+ } ) ;
362+
363+ factory. connect_bind ( move |_, list_item| {
364+ let list_item: & gtk:: ListItem = list_item. downcast_ref ( ) . unwrap ( ) ;
365+
366+ let user_row: ChatMemberRow = list_item. child ( ) . unwrap ( ) . downcast ( ) . unwrap ( ) ;
367+ let member: ChatMember = list_item. item ( ) . unwrap ( ) . downcast ( ) . unwrap ( ) ;
368+
369+ user_row. bind_member ( member) ;
370+ } ) ;
371+
372+ members_list. set_factory ( Some ( & factory) ) ;
388373 }
389374 }
390375
0 commit comments