Highlight room list-items, auto-scroll in chat

When a new message is posted (or the user is messaged), the room's item
in the roomlist is now highlighted, like Vision.

Chat also auto-scrolls when new messages are posted.
This commit is contained in:
Jaidyn Ann 2021-07-17 00:23:56 -05:00
parent fe4d0661a7
commit 6f73db12b7
7 changed files with 92 additions and 22 deletions

View File

@ -39,7 +39,8 @@ Conversation::Conversation(BString id, BMessenger msgn)
fDateFormatter(), fDateFormatter(),
fRoomFlags(0), fRoomFlags(0),
fDisallowedFlags(0), fDisallowedFlags(0),
fNotifyCount(0) fNotifyMessageCount(0),
fNotifyMentionCount(0)
{ {
fConversationItem = new ConversationItem(fName.String(), this); fConversationItem = new ConversationItem(fName.String(), this);
RegisterObserver(fConversationItem); RegisterObserver(fConversationItem);
@ -81,29 +82,34 @@ Conversation::ImMessage(BMessage* msg)
BString text = msg->FindString("body"); BString text = msg->FindString("body");
Contact* contact = GetOwnContact(); Contact* contact = GetOwnContact();
BWindow* win = fChatView->Window();
bool winFocused = (win != NULL &&
(win->IsFront() && !(win->IsMinimized())));
bool mentioned = ((text.IFindFirst(contact->GetName()) != B_ERROR) bool mentioned = ((text.IFindFirst(contact->GetName()) != B_ERROR)
|| (text.IFindFirst(contact->GetName()) != B_ERROR)); || (text.IFindFirst(contact->GetName()) != B_ERROR));
// Send a notification, if it's appropriate // Send a notification, if appropriate
BWindow* win = fChatView->Window(); if (winFocused == false && AppPreferences::Item()->NotifyNewMessage
if ((win == NULL || !win->IsFront() || win->IsMinimized()) && (fUsers.CountItems() <= 2 || mentioned == true))
&& AppPreferences::Item()->NotifyNewMessage
&& (fUsers.CountItems() <= 2 || mentioned))
{ {
fNotifyCount++;
BString notifyTitle = "New mention"; BString notifyTitle = "New mention";
BString notifyText = "You've been summoned from %source%."; BString notifyText = "You've been summoned from %source%.";
if (mentioned == false) { if (mentioned == false) {
fNotifyMessageCount++;
notifyTitle.SetTo("New message"); notifyTitle.SetTo("New message");
notifyText.SetTo(""); notifyText.SetTo("");
BStringFormat pmFormat("{0, plural," BStringFormat pmFormat("{0, plural,"
"=1{You've got a new message from %source%.}" "=1{You've got a new message from %source%.}"
"other{You've got # new messages from %source%.}}"); "other{You've got # new messages from %source%.}}");
pmFormat.Format(notifyText, fNotifyCount); pmFormat.Format(notifyText, fNotifyMessageCount);
} }
else
fNotifyMentionCount++;
notifyText.ReplaceAll("%source%", GetName()); notifyText.ReplaceAll("%source%", GetName());
BBitmap* icon = IconBitmap(); BBitmap* icon = IconBitmap();
@ -119,6 +125,13 @@ Conversation::ImMessage(BMessage* msg)
notification.SetMessageID(fID); notification.SetMessageID(fID);
notification.Send(); notification.Send();
} }
// If unattached, highlight the ConversationItem
if (win == NULL && mentioned == true)
NotifyInteger(INT_NEW_MENTION, fNotifyMentionCount);
else if (win == NULL)
NotifyInteger(INT_NEW_MESSAGE, fNotifyMessageCount);
break; break;
} }
case IM_MESSAGE_SENT: case IM_MESSAGE_SENT:
@ -215,7 +228,12 @@ Conversation::ObserveString(int32 what, BString str)
void void
Conversation::ObserveInteger(int32 what, int32 value) Conversation::ObserveInteger(int32 what, int32 value)
{ {
GetView()->InvalidateUserList(); if (what == INT_WINDOW_FOCUSED) {
fNotifyMessageCount = 0;
fNotifyMentionCount = 0;
}
else
GetView()->InvalidateUserList();
} }
@ -316,6 +334,9 @@ Conversation::GetView()
return fChatView; return fChatView;
fChatView = new ConversationView(this); fChatView = new ConversationView(this);
fChatView->RegisterObserver(fConversationItem);
fChatView->RegisterObserver(this);
RegisterObserver(fChatView);
if (!(fRoomFlags & ROOM_POPULATE_LOGS)) if (!(fRoomFlags & ROOM_POPULATE_LOGS))
return fChatView; return fChatView;
@ -324,7 +345,6 @@ Conversation::GetView()
if (_GetChatLogs(&logMsg) == B_OK) if (_GetChatLogs(&logMsg) == B_OK)
fChatView->MessageReceived(&logMsg); fChatView->MessageReceived(&logMsg);
RegisterObserver(fChatView);
return fChatView; return fChatView;
} }

View File

@ -90,7 +90,8 @@ private:
ProtocolLooper* fLooper; ProtocolLooper* fLooper;
ConversationView* fChatView; ConversationView* fChatView;
ConversationItem* fConversationItem; ConversationItem* fConversationItem;
int32 fNotifyCount; int32 fNotifyMessageCount;
int32 fNotifyMentionCount;
BString fID; BString fID;
BString fName; BString fName;

View File

@ -15,7 +15,10 @@ enum {
INT_ACCOUNT_STATUS, INT_ACCOUNT_STATUS,
INT_CONTACT_STATUS, INT_CONTACT_STATUS,
INT_USER_PERMS INT_USER_PERMS,
INT_NEW_MESSAGE,
INT_NEW_MENTION,
INT_WINDOW_FOCUSED
}; };
#endif // _NOTIFY_MESSAGE_H #endif // _NOTIFY_MESSAGE_H

View File

@ -5,18 +5,42 @@
#include "ConversationItem.h" #include "ConversationItem.h"
#include <InterfaceDefs.h>
#include <View.h>
#include "Conversation.h" #include "Conversation.h"
#include "NotifyMessage.h" #include "NotifyMessage.h"
#include "Utils.h"
const int8 kMentioned = 1;
const int8 kMessage = 2;
ConversationItem::ConversationItem(const char* name, Conversation* chat) ConversationItem::ConversationItem(const char* name, Conversation* chat)
: :
BStringItem(name), BStringItem(name),
fChat(chat) fChat(chat),
fStatus(0)
{ {
} }
void
ConversationItem::DrawItem(BView* owner, BRect frame, bool complete)
{
rgb_color old = owner->HighColor();
if (fStatus & kMentioned)
owner->SetHighUIColor(B_SUCCESS_COLOR);
else if (fStatus & kMessage)
owner->SetHighColor(TintColor(ui_color(B_LIST_ITEM_TEXT_COLOR), 2));
BStringItem::DrawItem(owner, frame, complete);
owner->SetHighColor(old);
}
Conversation* Conversation*
ConversationItem::GetConversation() ConversationItem::GetConversation()
{ {
@ -36,3 +60,19 @@ ConversationItem::ObserveString(int32 what, BString str)
} }
void
ConversationItem::ObserveInteger(int32 what, int32 num)
{
switch (what)
{
case INT_NEW_MESSAGE:
fStatus |= kMessage;
break;
case INT_NEW_MENTION:
fStatus |= kMentioned;
break;
case INT_WINDOW_FOCUSED:
fStatus = 0;
break;
}
}

View File

@ -2,8 +2,8 @@
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io> * Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license. * All rights reserved. Distributed under the terms of the MIT license.
*/ */
#ifndef CONVERSATIONITEM_H #ifndef _CONVERSATION_ITEM_H
#define CONVERSATIONITEM_H #define _CONVERSATION_ITEM_H
#include <StringItem.h> #include <StringItem.h>
@ -16,14 +16,16 @@ class ConversationItem : public BStringItem, public Observer {
public: public:
ConversationItem(const char* name, Conversation* chat); ConversationItem(const char* name, Conversation* chat);
Conversation* GetConversation(); virtual void DrawItem(BView* owner, BRect frame, bool complete=false);
protected: Conversation* GetConversation();
void ObserveString(int32 what, BString str);
void ObserveString(int32 what, BString str);
void ObserveInteger(int32 what, int32 num);
private: private:
Conversation* fChat; Conversation* fChat;
int8 fStatus;
}; };
#endif // _CONVERSATION_ITEM_H
#endif // CONVERSATIONITEM_H

View File

@ -79,6 +79,7 @@ ConversationView::AttachedToWindow()
if (fSubjectTextView->Text() != fConversation->GetSubject()) if (fSubjectTextView->Text() != fConversation->GetSubject())
fSubjectTextView->SetText(fConversation->GetSubject()); fSubjectTextView->SetText(fConversation->GetSubject());
} }
NotifyInteger(INT_WINDOW_FOCUSED, 0);
} }
@ -129,11 +130,14 @@ ConversationView::ImMessage(BMessage* msg)
case IM_MESSAGE_RECEIVED: case IM_MESSAGE_RECEIVED:
{ {
_AppendOrEnqueueMessage(msg); _AppendOrEnqueueMessage(msg);
fReceiveView->ScrollToBottom();
break; break;
} }
case IM_MESSAGE_SENT: case IM_MESSAGE_SENT:
case IM_LOGS_RECEIVED: case IM_LOGS_RECEIVED:
{ {
if (im_what == IM_MESSAGE_SENT)
fReceiveView->ScrollToBottom();
_AppendOrEnqueueMessage(msg); _AppendOrEnqueueMessage(msg);
break; break;
} }

View File

@ -22,7 +22,7 @@ class User;
class UserListView; class UserListView;
class ConversationView : public BGroupView, public Observer { class ConversationView : public BGroupView, public Observer, public Notifier {
public: public:
ConversationView(); ConversationView();
ConversationView(Conversation* chat); ConversationView(Conversation* chat);