Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -1,5 +1,10 @@ +2025-04-16 Sergei Golovan + + * chats.tcl, plugins/chat/nick_colors.tcl: Cache the groupchat roster + and not rebuild it every time it needs to be redrawn. + 2025-04-13 Sergei Golovan * plugins/unix/tktray.tcl: Add a workaround for a race condition in Tcl 9 when the configure events for size of the tray icon come in incorrect order. Index: chats.tcl ================================================================== --- chats.tcl +++ chats.tcl @@ -442,10 +442,20 @@ hook::run open_chat_pre_hook $chatid $type set chats(type,$chatid) $type set chats(subject,$chatid) "" set chats(exit_status,$chatid) "" + + if {$type eq "groupchat"} { + # Variable to hold groupchat roster items + + set chats(roster,$chatid) [dict create moderator {} \ + participant {} \ + visitor {} \ + user {}] + } + add_to_opened $chatid set chat_id($cw) $chatid lassign [chat::window_titles $chatid] chats(tabtitlename,$chatid) \ @@ -1108,84 +1118,114 @@ hook::add client_presence_hook chat::change_presence 70 ############################################################################### proc chat::process_roster_event {chatid jid nick status args} { - debugmsg chat "ROSTER: $chatid $jid $nick $status" + variable chats - if {[string equal $nick ""]} return + debugmsg chat "ROSTER: $chatid $jid $nick $status $args" + + if {$nick eq ""} return + + foreach role {moderator participant visitor user} { + dict unset chats(roster,$chatid) $role $nick + } + + if {$status ne "unavailable"} { + set role user + array set tmp $args + switch -- $tmp(-role) { + moderator - + participant - + visitor { + set role $tmp(-role) + } + default { + set role user + } + } + + if {$::plugins::nickcolors::options(use_colored_roster_nicks)} { + set foreground [plugins::nickcolors::get_color $nick] + } else { + set foreground [ifacetk::roster::get_foreground $status] + } + + dict set chats(roster,$chatid) $role $nick [list $jid $status $foreground] + } + + chat::redraw_roster_after_idle $chatid +} + +proc chat::update_roster_foregrounds {chatid} { + variable chats + + foreach role {moderator participant visitor user} { + dict for {nick val} [dict get $chats(roster,$chatid) $role] { + lassign $val jid status foreground + + if {$::plugins::nickcolors::options(use_colored_roster_nicks)} { + set foreground [plugins::nickcolors::get_color $nick] + } else { + set foreground [ifacetk::roster::get_foreground $status] + } + + dict set chats(roster,$chatid) $role $nick [list $jid $status $foreground] + } + } chat::redraw_roster_after_idle $chatid } namespace eval chat { variable g2l - array set g2l [list 1 [::msgcat::mc "Moderators"] \ - 2 [::msgcat::mc "Participants"] \ - 3 [::msgcat::mc "Visitors"] \ - 4 [::msgcat::mc "Users"]] + array set g2l [list moderator [::msgcat::mc "Moderators"] \ + participant [::msgcat::mc "Participants"] \ + visitor [::msgcat::mc "Visitors"] \ + user [::msgcat::mc "Users"]] } proc chat::redraw_roster {chatid} { variable g2l + variable chats set userswin [users_win $chatid] if {![winfo exists $userswin]} return ifacetk::roster::clear $userswin 0 set xlib [get_xlib $chatid] - set group [get_jid $chatid] - - set levels {} - foreach nick [::muc::roster $chatid] { - set jid $group/$nick - set role [::muc::get_role $xlib $jid] - - switch -- $role { - moderator {set level 1} - participant {set level 2} - visitor {set level 3} - default {set level 4} - } - lappend levels $level - lappend levelusers($level) [list $jid $nick] - } - set levels [lsort -unique $levels] - - foreach level $levels { - ifacetk::roster::addline $userswin group \ - "$g2l($level) ([llength $levelusers($level)])" $level $level {} 0 - - foreach item [lsort -index 1 -dictionary $levelusers($level)] { - lassign $item jid nick - set status [get_user_status $xlib $jid] - - if {$::plugins::nickcolors::options(use_colored_roster_nicks)} { - set foreground [plugins::nickcolors::get_color $nick] - } else { - set foreground [ifacetk::roster::get_foreground $status] - } - ifacetk::roster::addline $userswin jid $nick \ - [list $xlib $jid] $level {} 0 \ - {} roster/user/$status $foreground + + foreach role {moderator participant visitor user} { + set users [lsort -dictionary [dict keys [dict get $chats(roster,$chatid) $role]]] + set nusers [llength $users] + if {$nusers == 0} { + continue + } + ifacetk::roster::addline $userswin group "$g2l($role) ($nusers)" $role $role {} 0 + + foreach nick $users { + lassign [dict get $chats(roster,$chatid) $role $nick] jid status foreground + + ifacetk::roster::addline $userswin jid $nick [list $xlib $jid] $role {} 0 \ + {} roster/user/$status $foreground } } ifacetk::roster::update_scrollregion $userswin } -proc chat::redraw_roster_after_idle {group} { +proc chat::redraw_roster_after_idle {chatid} { variable afterid - if {[info exists afterid($group)]} \ + if {[info exists afterid($chatid)]} \ return - set afterid($group) [after idle " - chat::redraw_roster [list $group] - unset [list ::chat::afterid($group)] + set afterid($chatid) [after idle " + chat::redraw_roster [list $chatid] + unset [list ::chat::afterid($chatid)] "] } proc chat::restore_subject {chatid} { variable chats Index: plugins/chat/nick_colors.tcl ================================================================== --- plugins/chat/nick_colors.tcl +++ plugins/chat/nick_colors.tcl @@ -261,11 +261,11 @@ foreach chatid [chat::opened] { set wn [chat::chat_win $chatid] if {[winfo exists $wn]} { if {[chat::is_groupchat $chatid]} { - chat::redraw_roster_after_idle $chatid + chat::update_roster_foregrounds $chatid } foreach nick $NicksInChat($chatid) { set clr [get_color $nick] $wn tag configure NICK-$nick \ -foreground [expr {$options(use_colored_nicks) ? $clr : ""}]