about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/command/cmd_ac.c1
-rw-r--r--src/command/cmd_funcs.c12
-rw-r--r--src/config/preferences.c3
-rw-r--r--src/config/preferences.h1
-rw-r--r--src/config/theme.c1
-rw-r--r--src/ui/console.c5
-rw-r--r--src/ui/mucwin.c3
-rw-r--r--src/ui/occupantswin.c74
-rw-r--r--src/ui/win_types.h1
-rw-r--r--src/ui/window.c5
10 files changed, 96 insertions, 10 deletions
diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c
index 65d73b33..40c8d7ed 100644
--- a/src/command/cmd_ac.c
+++ b/src/command/cmd_ac.c
@@ -790,6 +790,7 @@ cmd_ac_init(void)
 
     occupants_show_ac = autocomplete_new();
     autocomplete_add(occupants_show_ac, "jid");
+    autocomplete_add(occupants_show_ac, "offline");
 
     occupants_char_ac = autocomplete_new();
     autocomplete_add(occupants_char_ac, "none");
diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c
index d2cf2307..55965690 100644
--- a/src/command/cmd_funcs.c
+++ b/src/command/cmd_funcs.c
@@ -4370,6 +4370,9 @@ cmd_occupants(ProfWin* window, const char* const command, gchar** args)
             if (g_strcmp0(args[2], "jid") == 0) {
                 cons_show("Occupant jids enabled.");
                 prefs_set_boolean(PREF_OCCUPANTS_JID, TRUE);
+            } else if (g_strcmp0(args[2], "offline") == 0) {
+                cons_show("Occupants offline enabled.");
+                prefs_set_boolean(PREF_OCCUPANTS_OFFLINE, TRUE);
             } else {
                 cons_show("Occupant list enabled.");
                 prefs_set_boolean(PREF_OCCUPANTS, TRUE);
@@ -4379,6 +4382,9 @@ cmd_occupants(ProfWin* window, const char* const command, gchar** args)
             if (g_strcmp0(args[2], "jid") == 0) {
                 cons_show("Occupant jids disabled.");
                 prefs_set_boolean(PREF_OCCUPANTS_JID, FALSE);
+            } else if (g_strcmp0(args[2], "offline") == 0) {
+                cons_show("Occupants offline disabled.");
+                prefs_set_boolean(PREF_OCCUPANTS_OFFLINE, FALSE);
             } else {
                 cons_show("Occupant list disabled.");
                 prefs_set_boolean(PREF_OCCUPANTS, FALSE);
@@ -4430,6 +4436,9 @@ cmd_occupants(ProfWin* window, const char* const command, gchar** args)
         if (g_strcmp0(args[1], "jid") == 0) {
             mucwin->showjid = TRUE;
             mucwin_update_occupants(mucwin);
+        } else if (g_strcmp0(args[1], "offline") == 0) {
+            mucwin->showoffline = TRUE;
+            mucwin_update_occupants(mucwin);
         } else {
             mucwin_show_occupants(mucwin);
         }
@@ -4437,6 +4446,9 @@ cmd_occupants(ProfWin* window, const char* const command, gchar** args)
         if (g_strcmp0(args[1], "jid") == 0) {
             mucwin->showjid = FALSE;
             mucwin_update_occupants(mucwin);
+        } else if (g_strcmp0(args[1], "offline") == 0) {
+            mucwin->showoffline = FALSE;
+            mucwin_update_occupants(mucwin);
         } else {
             mucwin_hide_occupants(mucwin);
         }
diff --git a/src/config/preferences.c b/src/config/preferences.c
index c2411507..f09cb746 100644
--- a/src/config/preferences.c
+++ b/src/config/preferences.c
@@ -1806,6 +1806,7 @@ _get_group(preference_t pref)
     case PREF_HISTORY:
     case PREF_OCCUPANTS:
     case PREF_OCCUPANTS_JID:
+    case PREF_OCCUPANTS_OFFLINE:
     case PREF_OCCUPANTS_WRAP:
     case PREF_STATUSES:
     case PREF_STATUSES_CONSOLE:
@@ -1978,6 +1979,8 @@ _get_key(preference_t pref)
         return "occupants";
     case PREF_OCCUPANTS_JID:
         return "occupants.jid";
+    case PREF_OCCUPANTS_OFFLINE:
+        return "occupants.offline";
     case PREF_OCCUPANTS_WRAP:
         return "occupants.wrap";
     case PREF_MUC_PRIVILEGES:
diff --git a/src/config/preferences.h b/src/config/preferences.h
index 51d9ca12..49c2c438 100644
--- a/src/config/preferences.h
+++ b/src/config/preferences.h
@@ -67,6 +67,7 @@ typedef enum {
     PREF_OCCUPANTS,
     PREF_OCCUPANTS_SIZE,
     PREF_OCCUPANTS_JID,
+    PREF_OCCUPANTS_OFFLINE,
     PREF_ROSTER,
     PREF_ROSTER_SIZE,
     PREF_ROSTER_OFFLINE,
diff --git a/src/config/theme.c b/src/config/theme.c
index 2c653988..dd19dc57 100644
--- a/src/config/theme.c
+++ b/src/config/theme.c
@@ -305,6 +305,7 @@ _load_preferences(void)
     _set_boolean_preference("resource.message", PREF_RESOURCE_MESSAGE);
     _set_boolean_preference("occupants", PREF_OCCUPANTS);
     _set_boolean_preference("occupants.jid", PREF_OCCUPANTS_JID);
+    _set_boolean_preference("occupants.offline", PREF_OCCUPANTS_OFFLINE);
     _set_boolean_preference("occupants.wrap", PREF_OCCUPANTS_WRAP);
     _set_boolean_preference("roster", PREF_ROSTER);
     _set_boolean_preference("roster.offline", PREF_ROSTER_OFFLINE);
diff --git a/src/ui/console.c b/src/ui/console.c
index 190adeea..a2f5db60 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -1255,6 +1255,11 @@ cons_occupants_setting(void)
     else
         cons_show("Occupant jids (/occupants)          : hide");
 
+    if (prefs_get_boolean(PREF_OCCUPANTS_OFFLINE))
+        cons_show("Occupants offline (/occupants)      : show");
+    else
+        cons_show("Occupants offline (/occupants)      : hide");
+
     if (prefs_get_boolean(PREF_OCCUPANTS_WRAP))
         cons_show("Occupants wrap (/occupants)         : ON");
     else
diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c
index 808567f4..a3300ab4 100644
--- a/src/ui/mucwin.c
+++ b/src/ui/mucwin.c
@@ -34,6 +34,7 @@
  *
  */
 
+#include "ui.h"
 #define _GNU_SOURCE 1
 
 #include <string.h>
@@ -67,6 +68,8 @@ mucwin_new(const char* const barejid)
     }
 #endif
 
+    // Force redraw here to show correct offline users; before this point muc_members returns a wrong list
+    ui_redraw_all_room_rosters();
     return mucwin;
 }
 
diff --git a/src/ui/occupantswin.c b/src/ui/occupantswin.c
index 3bb95485..f72d1567 100644
--- a/src/ui/occupantswin.c
+++ b/src/ui/occupantswin.c
@@ -42,12 +42,15 @@
 #include "ui/window_list.h"
 
 static void
-_occuptantswin_occupant(ProfLayoutSplit* layout, Occupant* occupant, gboolean showjid)
+_occuptantswin_occupant(ProfLayoutSplit* layout, GList* item, gboolean showjid, gboolean isoffline)
 {
     int colour = 0;                                     //init to workaround compiler warning
     theme_item_t presence_colour = THEME_ROSTER_ONLINE; //init to workaround compiler warning
+    Occupant* occupant = item->data;
 
-    if (prefs_get_boolean(PREF_OCCUPANTS_COLOR_NICK)) {
+    if (isoffline) {
+        wattron(layout->subwin, theme_attrs(THEME_ROSTER_OFFLINE));
+    } else if (prefs_get_boolean(PREF_OCCUPANTS_COLOR_NICK)) {
         colour = theme_hash_attrs(occupant->nick);
 
         wattron(layout->subwin, colour);
@@ -79,12 +82,18 @@ _occuptantswin_occupant(ProfLayoutSplit* layout, Occupant* occupant, gboolean sh
 
     gboolean wrap = prefs_get_boolean(PREF_OCCUPANTS_WRAP);
 
-    g_string_append(msg, occupant->nick);
+    if (isoffline) {
+        Jid* jid = jid_create(item->data);
+        g_string_append(msg, jid->barejid);
+        jid_destroy(jid);
+    } else {
+        g_string_append(msg, occupant->nick);
+    }
     win_sub_newline_lazy(layout->subwin);
     win_sub_print(layout->subwin, msg->str, FALSE, wrap, current_indent);
     g_string_free(msg, TRUE);
 
-    if (showjid && occupant->jid) {
+    if (showjid && !isoffline && occupant->jid) {
         GString* msg = g_string_new(spaces->str);
         g_string_append(msg, " ");
 
@@ -96,7 +105,9 @@ _occuptantswin_occupant(ProfLayoutSplit* layout, Occupant* occupant, gboolean sh
 
     g_string_free(spaces, TRUE);
 
-    if (prefs_get_boolean(PREF_OCCUPANTS_COLOR_NICK)) {
+    if (isoffline) {
+        wattroff(layout->subwin, theme_attrs(THEME_ROSTER_OFFLINE));
+    } else if (prefs_get_boolean(PREF_OCCUPANTS_COLOR_NICK)) {
         wattroff(layout->subwin, colour);
     } else {
         wattroff(layout->subwin, theme_attrs(presence_colour));
@@ -124,6 +135,8 @@ occupantswin_occupants(const char* const roomjid)
 
             if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
 
+                GList* online_occupants = { NULL };
+
                 GString* role = g_string_new(prefix->str);
                 g_string_append(role, "Moderators");
 
@@ -136,9 +149,10 @@ occupantswin_occupants(const char* const roomjid)
                 while (roster_curr) {
                     Occupant* occupant = roster_curr->data;
                     if (occupant->role == MUC_ROLE_MODERATOR) {
-                        _occuptantswin_occupant(layout, occupant, mucwin->showjid);
+                        _occuptantswin_occupant(layout, roster_curr, mucwin->showjid, false);
                     }
                     roster_curr = g_list_next(roster_curr);
+                    online_occupants = g_list_append(online_occupants, occupant->jid);
                 }
 
                 role = g_string_new(prefix->str);
@@ -153,9 +167,10 @@ occupantswin_occupants(const char* const roomjid)
                 while (roster_curr) {
                     Occupant* occupant = roster_curr->data;
                     if (occupant->role == MUC_ROLE_PARTICIPANT) {
-                        _occuptantswin_occupant(layout, occupant, mucwin->showjid);
+                        _occuptantswin_occupant(layout, roster_curr, mucwin->showjid, false);
                     }
                     roster_curr = g_list_next(roster_curr);
+                    online_occupants = g_list_append(online_occupants, occupant->jid);
                 }
 
                 role = g_string_new(prefix->str);
@@ -170,10 +185,50 @@ occupantswin_occupants(const char* const roomjid)
                 while (roster_curr) {
                     Occupant* occupant = roster_curr->data;
                     if (occupant->role == MUC_ROLE_VISITOR) {
-                        _occuptantswin_occupant(layout, occupant, mucwin->showjid);
+                        _occuptantswin_occupant(layout, roster_curr, mucwin->showjid, false);
                     }
                     roster_curr = g_list_next(roster_curr);
+                    online_occupants = g_list_append(online_occupants, occupant->jid);
+                }
+
+                if (mucwin->showoffline) {
+                    GList* members = muc_members(roomjid);
+                    // offline_occupants is used to display the same account on multiple devices once
+                    GList* offline_occupants = { NULL };
+
+                    role = g_string_new(prefix->str);
+                    g_string_append(role, "Offline");
+
+                    wattron(layout->subwin, theme_attrs(THEME_OCCUPANTS_HEADER));
+                    win_sub_newline_lazy(layout->subwin);
+                    win_sub_print(layout->subwin, role->str, TRUE, FALSE, 0);
+                    wattroff(layout->subwin, theme_attrs(THEME_OCCUPANTS_HEADER));
+                    g_string_free(role, TRUE);
+                    roster_curr = members;
+                    while (roster_curr) {
+                        Jid* jid = jid_create(roster_curr->data);
+                        gboolean found = false;
+                        GList* iter = online_occupants;
+                        for (; iter != NULL; iter = iter->next) {
+                            if (strstr(iter->data, jid->barejid)) {
+                                found = true;
+                                break;
+                            }
+                        }
+
+                        if (!found && g_list_index(offline_occupants, jid->barejid) == -1) {
+                            _occuptantswin_occupant(layout, roster_curr, mucwin->showjid, true);
+                            offline_occupants = g_list_append(offline_occupants, jid->barejid);
+                        }
+
+                        jid_destroy(jid);
+                        roster_curr = g_list_next(roster_curr);
+                    }
+                    g_list_free(members);
+                    g_list_free(offline_occupants);
                 }
+                g_list_free(online_occupants);
+
             } else {
                 GString* role = g_string_new(prefix->str);
                 g_string_append(role, "Occupants\n");
@@ -186,8 +241,7 @@ occupantswin_occupants(const char* const roomjid)
 
                 GList* roster_curr = occupants;
                 while (roster_curr) {
-                    Occupant* occupant = roster_curr->data;
-                    _occuptantswin_occupant(layout, occupant, mucwin->showjid);
+                    _occuptantswin_occupant(layout, roster_curr, mucwin->showjid, false);
                     roster_curr = g_list_next(roster_curr);
                 }
             }
diff --git a/src/ui/win_types.h b/src/ui/win_types.h
index 7beaca5f..e740b543 100644
--- a/src/ui/win_types.h
+++ b/src/ui/win_types.h
@@ -187,6 +187,7 @@ typedef struct prof_muc_win_t
     gboolean unread_mentions;
     gboolean unread_triggers;
     gboolean showjid;
+    gboolean showoffline;
     gboolean is_omemo;
     unsigned long memcheck;
     char* enctext;
diff --git a/src/ui/window.c b/src/ui/window.c
index 8afb23f4..b6676774 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -203,6 +203,11 @@ win_create_muc(const char* const roomjid)
     } else {
         new_win->showjid = FALSE;
     }
+    if (prefs_get_boolean(PREF_OCCUPANTS_OFFLINE)) {
+        new_win->showoffline = TRUE;
+    } else {
+        new_win->showoffline = FALSE;
+    }
     new_win->enctext = NULL;
     new_win->message_char = NULL;
     new_win->is_omemo = FALSE;