Exemplo n.º 1
0
void
HippoChatRoomWrapper::notifyMessage(HippoChatMessage *message)
{
    HippoPerson *user;

    user = hippo_chat_message_get_person(message);

    for (unsigned long i = 0; i < listeners_.length(); i++)
        listeners_[i]->onMessage(this, message);

    HippoPtr<IConnectionPoint> point;
    if (FAILED(connectionPointContainer_.FindConnectionPoint(__uuidof(IHippoChatRoomEvents), &point)))
        return;

    HippoPtr<IEnumConnections> e;
    if (FAILED(point->EnumConnections(&e)))
        return;

    HippoBSTR name = HippoBSTR::fromUTF8(hippo_entity_get_name(HIPPO_ENTITY(user)), -1);
    HippoBSTR guid = HippoBSTR::fromUTF8(hippo_entity_get_guid(HIPPO_ENTITY(user)), -1);
    HippoBSTR photoUrl = HippoBSTR::fromUTF8(hippo_entity_get_small_photo_url(HIPPO_ENTITY(user)), -1);
    HippoBSTR text = HippoBSTR::fromUTF8(hippo_chat_message_get_text(message), -1);

    CONNECTDATA data;
    ULONG fetched;
    while (e->Next(1, &data, &fetched) == S_OK) {
        HippoQIPtr<IDispatch> dispatch(data.pUnk);
        if (dispatch) {
            DISPPARAMS dispParams; 
            VARIANTARG args[6];

            args[0].vt = VT_INT;
            args[0].intVal = hippo_chat_message_get_serial(message);
            args[1].vt = VT_R8;
            args[1].dblVal = (DOUBLE)hippo_chat_message_get_timestamp(message);
            args[2].vt = VT_BSTR;
            args[2].bstrVal = text.m_str;
            args[3].vt = VT_BSTR;
            args[3].bstrVal = name.m_str;
            args[4].vt = VT_BSTR;
            args[4].bstrVal = photoUrl.m_str;
            args[5].vt = VT_BSTR;
            args[5].bstrVal = guid.m_str;

            dispParams.rgvarg = args;
            dispParams.cArgs = 6;
            dispParams.cNamedArgs = 0;
            dispParams.rgdispidNamedArgs = NULL;

            HRESULT hr = dispatch->Invoke(HIPPO_DISPID_ONMESSAGE, IID_NULL, 0 /* LCID */,
                                          DISPATCH_METHOD, &dispParams, 
                                          NULL /* result */, NULL /* exception */, NULL /* argError */);
            if (!SUCCEEDED(hr))
                hippoDebugDialog(L"OnMessage invoke failed %x", hr);
        }
    }
}
Exemplo n.º 2
0
void
hippo_actions_invite_to_group(HippoActions    *actions,
                              HippoGroup      *group,
                              HippoPerson     *person)
{
    hippo_connection_do_invite_to_group(get_connection(actions),
                                        hippo_entity_get_guid(HIPPO_ENTITY(group)),
                                        hippo_entity_get_guid(HIPPO_ENTITY(person)));
}
Exemplo n.º 3
0
void
hippo_actions_invite_to_group(HippoActions    *actions,
                              HippoGroup      *group,
                              HippoPerson     *person)
{
    ddm_data_model_update(actions->model,
                          "http://mugshot.org/p/groups#inviteUser", NULL,
                          "groupId", hippo_entity_get_guid(HIPPO_ENTITY(group)),
                          "userId", hippo_entity_get_guid(HIPPO_ENTITY(person)),
                          NULL);
}
Exemplo n.º 4
0
void
HippoChatRoomWrapper::notifyUserJoin(HippoPerson *user)
{
    for (unsigned long i = 0; i < listeners_.length(); i++)
        listeners_[i]->onUserJoin(this, user);

    HippoPtr<IConnectionPoint> point;
    if (FAILED(connectionPointContainer_.FindConnectionPoint(__uuidof(IHippoChatRoomEvents), &point)))
        return;

    HippoPtr<IEnumConnections> e;
    if (FAILED(point->EnumConnections(&e)))
        return;

    HippoChatState state = hippo_chat_room_get_user_state(delegate_, user);
    g_return_if_fail(state != HIPPO_CHAT_STATE_NONMEMBER);

    HippoBSTR name = HippoBSTR::fromUTF8(hippo_entity_get_name(HIPPO_ENTITY(user)), -1);
    HippoBSTR guid = HippoBSTR::fromUTF8(hippo_entity_get_guid(HIPPO_ENTITY(user)), -1);
    HippoBSTR photoUrl = HippoBSTR::fromUTF8(hippo_entity_get_small_photo_url(HIPPO_ENTITY(user)), -1);

    CONNECTDATA data;
    ULONG fetched;
    while (e->Next(1, &data, &fetched) == S_OK) {
        HippoQIPtr<IDispatch> dispatch(data.pUnk);
        if (dispatch) {
            DISPPARAMS dispParams;
            VARIANTARG args[4];

            args[0].vt = VT_BOOL;
            args[0].boolVal = state == HIPPO_CHAT_STATE_PARTICIPANT ? TRUE : FALSE;
            args[1].vt = VT_BSTR;
            args[1].bstrVal = name.m_str;
            args[2].vt = VT_BSTR;
            args[2].bstrVal = photoUrl.m_str;            
            args[3].vt = VT_BSTR;
            args[3].bstrVal = guid.m_str;

            dispParams.rgvarg = args;
            dispParams.cArgs = 4;
            dispParams.cNamedArgs = 0;
            dispParams.rgdispidNamedArgs = NULL;

            HRESULT hr = dispatch->Invoke(HIPPO_DISPID_ONUSERJOIN, IID_NULL, 0 /* LCID */,
                                          DISPATCH_METHOD, &dispParams, 
                                          NULL /* result */, NULL /* exception */, NULL /* argError */);
            if (!SUCCEEDED(hr))
                hippoDebugDialog(L"OnUserJoin invoke failed %x", hr);
        }
    }
}
static void
on_group_changed(HippoBlock *block,
                 GParamSpec *arg, /* null when first calling this */
                 HippoCanvasBlock *canvas_block)
{
    HippoGroup *group;
    HippoCanvasBlockGroupChat *canvas_group_chat;

    canvas_group_chat = HIPPO_CANVAS_BLOCK_GROUP_CHAT(canvas_block);
    g_assert(block == canvas_block->block);
    group = NULL;
    g_object_get(G_OBJECT(block), "group", &group, NULL);

    if (group == NULL) {
        /* can't think of much sensible to do here, presumably it will
         * get set back to non-null later
         */
    } else {
        update_chat_messages(canvas_group_chat);
                                     
        hippo_canvas_block_set_sender(HIPPO_CANVAS_BLOCK(canvas_group_chat),
                                      hippo_entity_get_guid(HIPPO_ENTITY(group)));

        g_object_unref(group);
    }
}
Exemplo n.º 6
0
void
HippoChatRoomWrapper::notifyUserChange(HippoPerson *person)
{
    // FIXME if user is only viewing, skip this

    // FIXME this is historically only about music changing ... should be modified 
    // to include also the name and photo so those will update

    for (unsigned long i = 0; i < listeners_.length(); i++)
        listeners_[i]->onUserChange(this, person);

    HippoPtr<IConnectionPoint> point;
    if (FAILED(connectionPointContainer_.FindConnectionPoint(__uuidof(IHippoChatRoomEvents), &point)))
        return;

    HippoPtr<IEnumConnections> e;
    if (FAILED(point->EnumConnections(&e)))
        return;

    HippoBSTR artist = HippoBSTR::fromUTF8(hippo_person_get_current_artist(person), -1);
    HippoBSTR song = HippoBSTR::fromUTF8(hippo_person_get_current_song(person), -1);
    HippoBSTR guid = HippoBSTR::fromUTF8(hippo_entity_get_guid(HIPPO_ENTITY(person)), -1);

    CONNECTDATA data;
    ULONG fetched;
    while (e->Next(1, &data, &fetched) == S_OK) {
        HippoQIPtr<IDispatch> dispatch(data.pUnk);
        if (dispatch) {
            DISPPARAMS dispParams;
            VARIANTARG args[4];

            // order of these arguments gets reversed, so we need to supply
            // the musicPlaying flag as the first argument, and the userId as the last one
            args[0].vt = VT_BOOL;
            args[0].boolVal = hippo_person_get_music_playing(person);
            args[1].vt = VT_BSTR;
            args[1].bstrVal = artist.m_str;
            args[2].vt = VT_BSTR;
            args[2].bstrVal = song.m_str;
            args[3].vt = VT_BSTR;
            args[3].bstrVal = guid.m_str;

            dispParams.rgvarg = args;
            dispParams.cArgs = 4;
            dispParams.cNamedArgs = 0;
            dispParams.rgdispidNamedArgs = NULL;

            HRESULT hr = dispatch->Invoke(HIPPO_DISPID_ONUSERMUSICCHANGE, IID_NULL, 0 /* LCID */,
                                          DISPATCH_METHOD, &dispParams, 
                                          NULL /* result */, NULL /* exception */, NULL /* argError */);
            if (!SUCCEEDED(hr))
                hippoDebugDialog(L"OnUserChange invoke failed %x", hr);
        }
    }
}
Exemplo n.º 7
0
void
hippo_group_set_chat_room(HippoGroup    *group,
                           HippoChatRoom  *room)
{
    g_return_if_fail(HIPPO_IS_GROUP(group));
    
    if (room == group->room)
        return;
    
    if (room)
        g_object_ref(room);
    if (group->room)
        g_object_unref(group->room);
    group->room = room;

    if (group->room)
        hippo_chat_room_set_title(group->room, hippo_entity_get_name(HIPPO_ENTITY(group)));
    
    hippo_entity_notify(HIPPO_ENTITY(group));
}
Exemplo n.º 8
0
void             
hippo_group_set_date_last_ignored(HippoGroup   *group,
                                   GTime          date) 
{
    g_return_if_fail(HIPPO_IS_GROUP(group));
    
    if (group->date_last_ignored != date) {
        group->date_last_ignored = date;
        hippo_entity_notify(HIPPO_ENTITY(group));
    }
}
static void
update_caches(HippoPersonRenderer *renderer,
              GtkWidget           *widget)
{
    const char *name;
    const char *song;
    const char *artist;
    GtkIconTheme *icon_theme;
    GdkPixbuf *note_on;
    GdkPixbuf *note_off;            
    
    if (renderer->person == NULL) {
        name = NULL;
        song = NULL;
        artist = NULL;
    } else {
        /* some of these can return NULL */
        name = hippo_entity_get_name(HIPPO_ENTITY(renderer->person));
        song = hippo_person_get_current_song(renderer->person);
        artist = hippo_person_get_current_artist(renderer->person);
    }
    
    make_layout(widget, &renderer->name_layout, name);
    /* FIXME better to omit the note and the space for music 
     * entirely, but this keeps it from looking broken for now
     */
    if (song == NULL || *song == '\0')
        song = _("No song");
    make_layout(widget, &renderer->song_layout, song);
    make_layout(widget, &renderer->artist_layout, artist);
    
    /* this strongly relies on the icon theme caching the pixbufs
     * so it typically ends up as a no-op
     */
    icon_theme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(widget));
    note_on = gtk_icon_theme_load_icon(icon_theme, "mugshot_note_on", NOTE_SIZE, 0, NULL);
    note_off = gtk_icon_theme_load_icon(icon_theme, "mugshot_note_on", NOTE_SIZE, 0, NULL);
    
    if (note_on) {
        if (renderer->note_on)
            g_object_unref(renderer->note_on);
        renderer->note_on = note_on;
    }
    if (note_off) {
        if (renderer->note_off)
            g_object_unref(renderer->note_off);
        renderer->note_off = note_off;
    }
}
Exemplo n.º 10
0
static void
on_user_changed(HippoBlock *block,
                GParamSpec *arg, /* null when first calling this */
                HippoCanvasBlockMusic *block_music)
{
    HippoPerson *person;
    person = NULL;
    g_object_get(G_OBJECT(block), "user", &person, NULL);
    
    hippo_canvas_block_set_sender(HIPPO_CANVAS_BLOCK(block_music),
                                  person ? hippo_entity_get_guid(HIPPO_ENTITY(person)) : NULL);
    
    if (person)
        g_object_unref(person);
}
Exemplo n.º 11
0
STDMETHODIMP
HippoPostWrapper::get_LastChatSender(IHippoEntity **sender)
{
    *sender = NULL;

    HippoChatRoom *room = hippo_post_get_chat_room(delegate_);
    if (room) {
        HippoChatMessage *m = hippo_chat_room_get_last_message(room);
        if (m != NULL) {
            HippoPerson *person = hippo_chat_message_get_person(m);
            if (person != NULL)
                entityToCom(HIPPO_ENTITY(person), sender);
        }
    }

    return S_OK;
}
Exemplo n.º 12
0
void 
HippoListenerProxyImpl::onMessage(HippoChatRoom *room, HippoChatMessage *message, HippoEndpointProxy *endpointProxy)
{
    HippoPerson *sender = hippo_chat_message_get_person(message);

    HippoBSTR chatId = HippoBSTR::fromUTF8(hippo_chat_room_get_id(room), -1);
    HippoBSTR entityId = HippoBSTR::fromUTF8(hippo_entity_get_guid(HIPPO_ENTITY(sender)), -1);
    HippoBSTR text = HippoBSTR::fromUTF8(hippo_chat_message_get_text(message), -1);

    if (listener_)
        listener_->OnMessage(hippo_endpoint_proxy_get_id(endpointProxy),
                             chatId,
                             entityId,
                             text,
                             hippo_chat_message_get_timestamp(message),
                             hippo_chat_message_get_serial(message));
}
static void
set_person(HippoCanvasBlockFacebookEvent *block_facebook_event,
           HippoPerson                 *person)
{
    if (person == block_facebook_event->person)
        return;

    if (block_facebook_event->person) {
        g_object_unref(block_facebook_event->person);
        block_facebook_event->person = NULL;
    }

    if (person) {
        block_facebook_event->person = person;
        g_object_ref(G_OBJECT(person));
    }

    hippo_canvas_block_set_sender(HIPPO_CANVAS_BLOCK(block_facebook_event),
                                  person ? hippo_entity_get_guid(HIPPO_ENTITY(person)) : NULL);
}
Exemplo n.º 14
0
HippoChatState
hippo_chat_room_get_user_state(HippoChatRoom *room,
                               HippoPerson   *person)
{
    HippoChatState state;
    const char *guid;
    
    g_return_val_if_fail(HIPPO_IS_CHAT_ROOM(room), HIPPO_CHAT_STATE_NONMEMBER);
    
    guid = hippo_entity_get_guid(HIPPO_ENTITY(person));
    
    if (g_hash_table_lookup(room->viewers, guid) != NULL)
        state = HIPPO_CHAT_STATE_VISITOR;
    else if (g_hash_table_lookup(room->chatters, guid) != NULL)
        state = HIPPO_CHAT_STATE_PARTICIPANT;
    else
        state = HIPPO_CHAT_STATE_NONMEMBER;
        
    return state;
}
static void
set_person(HippoCanvasBlockNetflixMovie *block_netflix,
           HippoPerson                  *person)
{
    if (person == block_netflix->person)
        return;

    if (block_netflix->person) {
        g_object_unref(block_netflix->person);
        block_netflix->person = NULL;
    }

    if (person) {
        block_netflix->person = person;
        g_object_ref(G_OBJECT(person));
    }

    hippo_canvas_block_set_sender(HIPPO_CANVAS_BLOCK(block_netflix),
                                  person ? hippo_entity_get_guid(HIPPO_ENTITY(person)) : NULL);
}
Exemplo n.º 16
0
static void
notification_is_needed_callback(HippoCanvasItem *item,
                                void            *data)
{
    NotificationNeededInfo *info = data;
    gboolean notify_for_block = TRUE;

    HippoBlock *block;

    g_object_get(G_OBJECT(item), "block", &block, NULL);

    g_debug("Checking if notification is needed for block %s\n", hippo_block_get_guid(block));
    
    if (HIPPO_IS_BLOCK_POST(block)) {
        HippoPost *post;
        
        g_object_get(G_OBJECT(block), "post", &post, NULL);
        if (post) {
            if (chat_is_visible(info->manager, hippo_post_get_guid(post)))
                notify_for_block = FALSE;
            g_object_unref(post);
        }
    } else if (HIPPO_IS_BLOCK_GROUP_CHAT(block)) {
        HippoGroup *group;
        
        g_object_get(G_OBJECT(block), "group", &group, NULL);
        if (group) {
            if (chat_is_visible(info->manager, hippo_entity_get_guid(HIPPO_ENTITY(group))))
                notify_for_block = FALSE;
            g_object_unref(group);
        }
    } else if (block->type == HIPPO_BLOCK_TYPE_MUSIC_CHAT) {
        if (chat_is_visible(info->manager, hippo_block_get_chat_id(block)))
            notify_for_block = FALSE;
    }

    g_object_unref(block);

    if (notify_for_block)
        info->is_needed = TRUE;
}
Exemplo n.º 17
0
void
HippoChatRoomWrapper::notifyUserLeave(HippoPerson *user)
{
    for (unsigned long j = 0; j < listeners_.length(); j++)
        listeners_[j]->onUserLeave(this, user);

    HippoPtr<IConnectionPoint> point;
    if (FAILED(connectionPointContainer_.FindConnectionPoint(__uuidof(IHippoChatRoomEvents), &point)))
        return;

    HippoPtr<IEnumConnections> e;
    if (FAILED(point->EnumConnections(&e)))
        return;

    HippoBSTR guid = HippoBSTR::fromUTF8(hippo_entity_get_guid(HIPPO_ENTITY(user)), -1);

    CONNECTDATA data;
    ULONG fetched;
    while (e->Next(1, &data, &fetched) == S_OK) {
        HippoQIPtr<IDispatch> dispatch(data.pUnk);
        if (dispatch) {
            DISPPARAMS dispParams;
            VARIANTARG args[1];

            args[0].vt = VT_BSTR;
            args[0].bstrVal = guid.m_str;

            dispParams.rgvarg = args;
            dispParams.cArgs = 1;
            dispParams.cNamedArgs = 0;
            dispParams.rgdispidNamedArgs = NULL;

            HRESULT hr = dispatch->Invoke(HIPPO_DISPID_ONUSERLEAVE, IID_NULL, 0 /* LCID */,
                                          DISPATCH_METHOD, &dispParams, 
                                          NULL /* result */, NULL /* exception */, NULL /* argError */);
            if (!SUCCEEDED(hr))
                hippoDebugDialog(L"Invoke failed %x", hr);
        }
    }
}
Exemplo n.º 18
0
STDMETHODIMP 
HippoPostWrapper::get_Viewers(IHippoEntityCollection **viewers)
{
    if (!viewers_) {
        // create viewers object
        viewers_ = new HippoEntityCollection();
        viewers_->Release(); // the smart pointer has got it

        // this list isn't copied, no need to free it
        GSList *cRecipients = hippo_post_get_viewers(delegate_);
        
        for (GSList *link = cRecipients; link != NULL; link = link->next) {
            HippoEntity *r = HIPPO_ENTITY(link->data);
            viewers_->addMember(r);
        }    
    }

    viewers_->AddRef();
    *viewers = viewers_;

    return S_OK;
}
static void
hippo_canvas_block_group_chat_title_activated(HippoCanvasBlock *canvas_block)
{
    HippoActions *actions;
    HippoGroup *group;

    if (canvas_block->block == NULL)
        return;

    actions = hippo_canvas_block_get_actions(canvas_block);

    group = NULL;
    g_object_get(G_OBJECT(canvas_block->block),
                 "group", &group,
                 NULL);

    if (group == NULL)
        return;

    hippo_actions_join_chat_id(actions, hippo_entity_get_guid(HIPPO_ENTITY(group)));

    g_object_unref(group);
}
Exemplo n.º 20
0
STDMETHODIMP
HippoPostWrapper::get_CurrentViewers(IHippoEntityCollection **viewers)
{
    // We keep a pointer to the CurrentViewers object so something like
    // for (i = 0; i < post.CurrentViewers.length; i++) { ... } 
    // doesn't continually create new objects, but we don't try to 
    // incrementally update it, we just clear it and demand create
    // a new one.

    if (!currentViewers_) {
        currentViewers_ = new HippoEntityCollection();
        currentViewers_->Release(); // the smart pointer has got it

        HippoChatRoom *room = hippo_post_get_chat_room(delegate_);
        if (room) {
            GSList *members = hippo_chat_room_get_users(room);
            for (GSList *link = members; link != NULL; link = link->next) {
                HippoEntity *entity = HIPPO_ENTITY(link->data);
                currentViewers_->addMember(entity);
                g_object_unref(entity);
            }
            g_slist_free(members);

            // connect up to clear cache if chat room changes
            userStateChanged_.connect(G_OBJECT(room), "user-state-changed", 
                slot(this, &HippoPostWrapper::onUserStateChanged));
            cleared_.connect(G_OBJECT(room), "cleared",
                slot(this, &HippoPostWrapper::onCleared));
        }
    }

    currentViewers_->AddRef();
    *viewers = currentViewers_;

    return S_OK;
}
Exemplo n.º 21
0
void
hippo_chat_room_set_user_state(HippoChatRoom *room,
                               HippoPerson   *person,
                               HippoChatState state)
{
    HippoChatState old_state;
    const char *guid;
    
    g_return_if_fail(HIPPO_IS_CHAT_ROOM(room));
    
    old_state = hippo_chat_room_get_user_state(room, person);
    
    g_debug("Updating chat state room '%s' person '%s/%s' old state %d state %d",
            room->id, hippo_entity_get_guid(HIPPO_ENTITY(person)),
            hippo_entity_get_name(HIPPO_ENTITY(person)) ? 
            hippo_entity_get_name(HIPPO_ENTITY(person)) : "NULL",
            old_state, state);
    
    if (old_state == state)
        return;
    
    guid = hippo_entity_get_guid(HIPPO_ENTITY(person));

    /* so we can remove from our hash tables and then 
     * still safely emit the signal 
     */
    g_object_ref(person);
    
    switch (old_state) {
    case HIPPO_CHAT_STATE_VISITOR:
        g_hash_table_remove(room->viewers, guid);
        break; 
    case HIPPO_CHAT_STATE_PARTICIPANT:
        g_hash_table_remove(room->chatters, guid);
        break;
    case HIPPO_CHAT_STATE_NONMEMBER:
        /* no old entry to remove */        
        break;
    }
    
    switch(state) {
    case HIPPO_CHAT_STATE_VISITOR:
        g_object_ref(person); /* extra ref for the hash */
        g_hash_table_replace(room->viewers, g_strdup(guid), person);
        break; 
    case HIPPO_CHAT_STATE_PARTICIPANT:
        g_object_ref(person); /* extra ref for the hash */    
        g_hash_table_replace(room->chatters, g_strdup(guid), person);    
        break;
    case HIPPO_CHAT_STATE_NONMEMBER:
        /* no new entry to insert */
        break;
    }

    g_signal_emit(room, signals[USER_STATE_CHANGED], 0, person);

    if (!room->loading && old_state == HIPPO_CHAT_STATE_NONMEMBER) {
        g_signal_emit(room, signals[USER_JOINED], 0, person);
    }

    g_object_unref(person);
}
static void
update_chat_messages(HippoCanvasBlockGroupChat *canvas_group_chat)
{
    HippoGroup *group;
    HippoBlock *block;
    HippoCanvasBlock *canvas_block;
    HippoChatMessage *last_message = NULL;
    HippoChatRoom *room;
    
    canvas_block = HIPPO_CANVAS_BLOCK(canvas_group_chat);
    block = canvas_block->block;
    g_assert(block != NULL);
    group = NULL;
    g_object_get(G_OBJECT(block), "group", &group, NULL);    

    if (group == NULL) {  /* should only happen transiently if at all */
        /* unset all the chat preview */
        g_object_set(G_OBJECT(canvas_group_chat->chat_preview),
                     "chat-id", NULL,
                     "chat-room", NULL,
                     NULL);
        return;
    }
    
    /* FIXME the title should probably be something like "N people chatting" or
     * "N messages" but we don't have that info yet
     */
    hippo_canvas_block_set_title(HIPPO_CANVAS_BLOCK(canvas_group_chat),
                                 "New chat activity",
                                 "Click to join group chat");
    
    /* For the chat preview, prefer to use the chat room if
     * we have one, otherwise use the static recent messages
     * summary.
     */

    room = hippo_group_get_chat_room(group);
    g_object_set(G_OBJECT(canvas_group_chat->chat_preview),
                 "chat-id", hippo_entity_get_guid(HIPPO_ENTITY(group)),
                 "chat-room", room,
                 NULL);
    
    if (room) {
        last_message = hippo_chat_room_get_last_message(room);
    } else {
        /* We need to use recent messages summary from the block instead */
        GSList *messages;

        g_object_get(G_OBJECT(block), "recent-messages", &messages, NULL);
        
        if (messages)
            last_message = messages->data;

        while (messages) {
            g_object_set(G_OBJECT(canvas_group_chat->chat_preview),
                         "recent-message", messages->data,
                         NULL);
            messages = messages->next;
        }
    }
    
    g_object_set(G_OBJECT(canvas_group_chat->single_message_preview),
                 "message", last_message,
                 NULL);

    canvas_group_chat->have_messages = last_message != NULL;

    hippo_canvas_block_group_update_visibility(canvas_group_chat);

    g_object_unref(group);
}