From 6f73db12b7de876a1fdabe2f89c9f4934a81edc9 Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Sat, 17 Jul 2021 00:23:56 -0500 Subject: [PATCH] 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. --- application/Conversation.cpp | 42 +++++++++++++++++++------- application/Conversation.h | 3 +- application/NotifyMessage.h | 5 ++- application/views/ConversationItem.cpp | 42 +++++++++++++++++++++++++- application/views/ConversationItem.h | 16 +++++----- application/views/ConversationView.cpp | 4 +++ application/views/ConversationView.h | 2 +- 7 files changed, 92 insertions(+), 22 deletions(-) diff --git a/application/Conversation.cpp b/application/Conversation.cpp index c25df99..14a9cd6 100644 --- a/application/Conversation.cpp +++ b/application/Conversation.cpp @@ -39,7 +39,8 @@ Conversation::Conversation(BString id, BMessenger msgn) fDateFormatter(), fRoomFlags(0), fDisallowedFlags(0), - fNotifyCount(0) + fNotifyMessageCount(0), + fNotifyMentionCount(0) { fConversationItem = new ConversationItem(fName.String(), this); RegisterObserver(fConversationItem); @@ -81,29 +82,34 @@ Conversation::ImMessage(BMessage* msg) BString text = msg->FindString("body"); Contact* contact = GetOwnContact(); + BWindow* win = fChatView->Window(); + + bool winFocused = (win != NULL && + (win->IsFront() && !(win->IsMinimized()))); bool mentioned = ((text.IFindFirst(contact->GetName()) != B_ERROR) || (text.IFindFirst(contact->GetName()) != B_ERROR)); - // Send a notification, if it's appropriate - BWindow* win = fChatView->Window(); - if ((win == NULL || !win->IsFront() || win->IsMinimized()) - && AppPreferences::Item()->NotifyNewMessage - && (fUsers.CountItems() <= 2 || mentioned)) + // Send a notification, if appropriate + if (winFocused == false && AppPreferences::Item()->NotifyNewMessage + && (fUsers.CountItems() <= 2 || mentioned == true)) { - fNotifyCount++; - BString notifyTitle = "New mention"; BString notifyText = "You've been summoned from %source%."; if (mentioned == false) { + fNotifyMessageCount++; + notifyTitle.SetTo("New message"); notifyText.SetTo(""); BStringFormat pmFormat("{0, plural," "=1{You've got a new message from %source%.}" "other{You've got # new messages from %source%.}}"); - pmFormat.Format(notifyText, fNotifyCount); + pmFormat.Format(notifyText, fNotifyMessageCount); } + else + fNotifyMentionCount++; + notifyText.ReplaceAll("%source%", GetName()); BBitmap* icon = IconBitmap(); @@ -119,6 +125,13 @@ Conversation::ImMessage(BMessage* msg) notification.SetMessageID(fID); 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; } case IM_MESSAGE_SENT: @@ -215,7 +228,12 @@ Conversation::ObserveString(int32 what, BString str) void 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; fChatView = new ConversationView(this); + fChatView->RegisterObserver(fConversationItem); + fChatView->RegisterObserver(this); + RegisterObserver(fChatView); if (!(fRoomFlags & ROOM_POPULATE_LOGS)) return fChatView; @@ -324,7 +345,6 @@ Conversation::GetView() if (_GetChatLogs(&logMsg) == B_OK) fChatView->MessageReceived(&logMsg); - RegisterObserver(fChatView); return fChatView; } diff --git a/application/Conversation.h b/application/Conversation.h index 5ce59b7..aff8b93 100644 --- a/application/Conversation.h +++ b/application/Conversation.h @@ -90,7 +90,8 @@ private: ProtocolLooper* fLooper; ConversationView* fChatView; ConversationItem* fConversationItem; - int32 fNotifyCount; + int32 fNotifyMessageCount; + int32 fNotifyMentionCount; BString fID; BString fName; diff --git a/application/NotifyMessage.h b/application/NotifyMessage.h index 385ade8..3f77d92 100644 --- a/application/NotifyMessage.h +++ b/application/NotifyMessage.h @@ -15,7 +15,10 @@ enum { INT_ACCOUNT_STATUS, INT_CONTACT_STATUS, - INT_USER_PERMS + INT_USER_PERMS, + INT_NEW_MESSAGE, + INT_NEW_MENTION, + INT_WINDOW_FOCUSED }; #endif // _NOTIFY_MESSAGE_H diff --git a/application/views/ConversationItem.cpp b/application/views/ConversationItem.cpp index 7e850dc..a047683 100644 --- a/application/views/ConversationItem.cpp +++ b/application/views/ConversationItem.cpp @@ -5,18 +5,42 @@ #include "ConversationItem.h" +#include +#include + #include "Conversation.h" #include "NotifyMessage.h" +#include "Utils.h" + + +const int8 kMentioned = 1; +const int8 kMessage = 2; ConversationItem::ConversationItem(const char* name, Conversation* chat) : 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* 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; + } +} diff --git a/application/views/ConversationItem.h b/application/views/ConversationItem.h index d6cbe0a..36ef6a0 100644 --- a/application/views/ConversationItem.h +++ b/application/views/ConversationItem.h @@ -2,8 +2,8 @@ * Copyright 2021, Jaidyn Levesque * All rights reserved. Distributed under the terms of the MIT license. */ -#ifndef CONVERSATIONITEM_H -#define CONVERSATIONITEM_H +#ifndef _CONVERSATION_ITEM_H +#define _CONVERSATION_ITEM_H #include @@ -16,14 +16,16 @@ class ConversationItem : public BStringItem, public Observer { public: ConversationItem(const char* name, Conversation* chat); - Conversation* GetConversation(); + virtual void DrawItem(BView* owner, BRect frame, bool complete=false); -protected: - void ObserveString(int32 what, BString str); + Conversation* GetConversation(); + + void ObserveString(int32 what, BString str); + void ObserveInteger(int32 what, int32 num); private: Conversation* fChat; + int8 fStatus; }; - -#endif // CONVERSATIONITEM_H +#endif // _CONVERSATION_ITEM_H diff --git a/application/views/ConversationView.cpp b/application/views/ConversationView.cpp index fac611a..d9b2d3a 100644 --- a/application/views/ConversationView.cpp +++ b/application/views/ConversationView.cpp @@ -79,6 +79,7 @@ ConversationView::AttachedToWindow() if (fSubjectTextView->Text() != fConversation->GetSubject()) fSubjectTextView->SetText(fConversation->GetSubject()); } + NotifyInteger(INT_WINDOW_FOCUSED, 0); } @@ -129,11 +130,14 @@ ConversationView::ImMessage(BMessage* msg) case IM_MESSAGE_RECEIVED: { _AppendOrEnqueueMessage(msg); + fReceiveView->ScrollToBottom(); break; } case IM_MESSAGE_SENT: case IM_LOGS_RECEIVED: { + if (im_what == IM_MESSAGE_SENT) + fReceiveView->ScrollToBottom(); _AppendOrEnqueueMessage(msg); break; } diff --git a/application/views/ConversationView.h b/application/views/ConversationView.h index cc9fa21..d45335b 100644 --- a/application/views/ConversationView.h +++ b/application/views/ConversationView.h @@ -22,7 +22,7 @@ class User; class UserListView; -class ConversationView : public BGroupView, public Observer { +class ConversationView : public BGroupView, public Observer, public Notifier { public: ConversationView(); ConversationView(Conversation* chat);