RosterView.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * Copyright 2009-2011, Andrea Anzani. All rights reserved.
  3. * Copyright 2009-2011, Pier Luigi Fiorini. All rights reserved.
  4. * Copyright 2021, Jaidyn Levesque. All rights reserved.
  5. * Distributed under the terms of the MIT License.
  6. *
  7. * Authors:
  8. * Andrea Anzani, andrea.anzani@gmail.com
  9. * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
  10. * Jaidyn Levesque, jadedctrl@teknik.io
  11. */
  12. #include "RosterView.h"
  13. #include <Catalog.h>
  14. #include <LayoutBuilder.h>
  15. #include <Notification.h>
  16. #include <ScrollView.h>
  17. #include <StringItem.h>
  18. #include "AppMessages.h"
  19. #include "AppPreferences.h"
  20. #include "ChatOMatic.h"
  21. #include "ChatProtocolMessages.h"
  22. #include "RosterItem.h"
  23. #include "RosterListView.h"
  24. #undef B_TRANSLATION_CONTEXT
  25. #define B_TRANSLATION_CONTEXT "RosterView"
  26. const uint32 kSearchContact = 'RWSC';
  27. RosterView::RosterView(const char* title, Server* server, bigtime_t account)
  28. :
  29. BGroupView(title, B_VERTICAL, B_USE_DEFAULT_SPACING),
  30. fAccount(-1),
  31. fServer(server),
  32. fManualItem(new BStringItem("")),
  33. fManualStr("Select user %user%" B_UTF8_ELLIPSIS)
  34. {
  35. fSearchBox = new BTextControl("searchBox", "", "",
  36. new BMessage(kSearchContact));
  37. fSearchBox->SetModificationMessage(new BMessage(kSearchContact));
  38. fListView = new RosterListView("buddyView");
  39. BScrollView* scrollView = new BScrollView("scrollview", fListView,
  40. B_WILL_DRAW, false, true);
  41. BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
  42. .AddGroup(B_VERTICAL)
  43. .SetInsets(5, 5, 5, 10)
  44. .Add(fSearchBox)
  45. .Add(scrollView)
  46. .End()
  47. .End();
  48. SetAccount(account);
  49. }
  50. void
  51. RosterView::MessageReceived(BMessage* message)
  52. {
  53. switch (message->what) {
  54. case kSearchContact:
  55. {
  56. RosterMap map = _RosterMap();
  57. for (uint32 i = 0; i < map.CountItems(); i++) {
  58. Contact* linker = map.ValueAt(i);
  59. RosterItem* item = linker->GetRosterItem();
  60. // If the search filter has been deleted show all the items,
  61. // otherwise remove the item in order to show only items
  62. // that matches the search criteria
  63. if (strcmp(fSearchBox->Text(), "") == 0)
  64. fListView->AddItem(item);
  65. else if (linker->GetName().IFindFirst(fSearchBox->Text()) == B_ERROR)
  66. fListView->RemoveItem(item);
  67. else
  68. fListView->AddItem(item);
  69. UpdateListItem(item);
  70. }
  71. // If view has specific account selected, we want the user to be
  72. // able to select non-contacts of that protocol
  73. if (fAccount != - 1 && strcmp(fSearchBox->Text(), "") != 0) {
  74. BString label = fManualStr;
  75. label.ReplaceAll("%user%", fSearchBox->Text());
  76. fManualItem->SetText(label.String());
  77. fListView->AddItem(fManualItem);
  78. }
  79. else if (fListView->HasItem(fManualItem))
  80. fListView->RemoveItem(fManualItem);
  81. break;
  82. }
  83. case IM_MESSAGE:
  84. ImMessage(message);
  85. break;
  86. default:
  87. BGroupView::MessageReceived(message);
  88. }
  89. }
  90. void
  91. RosterView::ImMessage(BMessage* msg)
  92. {
  93. int32 im_what = msg->FindInt32("im_what");
  94. switch (im_what) {
  95. case IM_USER_STATUS_SET:
  96. {
  97. int32 status;
  98. int64 instance;
  99. BString user_id = msg->FindString("user_id");
  100. if (msg->FindInt32("status", &status) != B_OK
  101. || msg->FindInt64("instance", &instance) != B_OK
  102. || user_id.IsEmpty() == true)
  103. return;
  104. Contact* contact = fServer->ContactById(user_id, instance);
  105. if (contact == NULL)
  106. return;
  107. RosterItem* rosterItem = contact->GetRosterItem();
  108. if (rosterItem) {
  109. UpdateListItem(rosterItem);
  110. // Add or remove item
  111. switch (status) {
  112. /*case STATUS_OFFLINE:
  113. // By default offline contacts are hidden
  114. if (!AppPreferences::Item()->HideOffline)
  115. break;
  116. if (HasItem(rosterItem))
  117. RemoveItem(rosterItem);
  118. return;*/
  119. default:
  120. // Add item because it has a non-offline status
  121. fListView->AddItem(rosterItem);
  122. break;
  123. }
  124. UpdateListItem(rosterItem);
  125. // Check if the user want the notification
  126. if (!AppPreferences::Get()->NotifyContactStatus)
  127. break;
  128. switch (status) {
  129. case STATUS_ONLINE:
  130. case STATUS_OFFLINE:
  131. // Notify when contact is online or offline
  132. if (status == STATUS_ONLINE) {
  133. BString message;
  134. message << rosterItem->GetContact()->GetName();
  135. if (status == STATUS_ONLINE)
  136. message.SetTo(B_TRANSLATE("%name% is available!"));
  137. else
  138. message.SetTo(B_TRANSLATE("%name% is offline!"));
  139. message.ReplaceAll("%name%",
  140. rosterItem->GetContact()->GetName());
  141. BNotification notification(B_INFORMATION_NOTIFICATION);
  142. notification.SetGroup(BString(APP_NAME));
  143. notification.SetTitle(BString(B_TRANSLATE("Presence")));
  144. notification.SetIcon(rosterItem->Bitmap());
  145. notification.SetContent(message);
  146. notification.Send();
  147. }
  148. break;
  149. default:
  150. break;
  151. }
  152. }
  153. break;
  154. }
  155. case IM_ROSTER_CONTACT_REMOVED:
  156. {
  157. int32 status = -1;
  158. int64 instance;
  159. BString user_id = msg->FindString("user_id");
  160. if (msg->FindInt32("status", &status) != B_OK
  161. || msg->FindInt64("instance", &instance) != B_OK
  162. || user_id.IsEmpty() == true)
  163. return;
  164. Contact* contact = fServer->ContactById(user_id, instance);
  165. if (contact == NULL)
  166. return;
  167. RosterItem* rosterItem = contact->GetRosterItem();
  168. if (rosterItem)
  169. fListView->RemoveItem(rosterItem);
  170. }
  171. case IM_USER_AVATAR_SET:
  172. case IM_CONTACT_INFO:
  173. case IM_EXTENDED_CONTACT_INFO:
  174. {
  175. int32 status = -1;
  176. int64 instance;
  177. BString user_id = msg->FindString("user_id");
  178. if (msg->FindInt32("status", &status) != B_OK
  179. || msg->FindInt64("instance", &instance) != B_OK
  180. || user_id.IsEmpty() == true)
  181. return;
  182. Contact* contact = fServer->ContactById(user_id, instance);
  183. if (contact == NULL)
  184. return;
  185. RosterItem* rosterItem = contact->GetRosterItem();
  186. if (rosterItem)
  187. UpdateListItem(rosterItem);
  188. break;
  189. }
  190. }
  191. }
  192. void
  193. RosterView::AttachedToWindow()
  194. {
  195. fSearchBox->SetTarget(this);
  196. fSearchBox->MakeFocus(true);
  197. }
  198. void
  199. RosterView::SetInvocationMessage(BMessage* msg)
  200. {
  201. fListView->SetInvocationMessage(msg);
  202. }
  203. void
  204. RosterView::SetAccount(bigtime_t instance_id)
  205. {
  206. fAccount = instance_id;
  207. RosterMap contacts = _RosterMap();
  208. fListView->MakeEmpty();
  209. for (int i = 0; i < contacts.CountItems(); i++)
  210. fListView->AddItem(contacts.ValueAt(i)->GetRosterItem());
  211. }
  212. void
  213. RosterView::UpdateListItem(RosterItem* item)
  214. {
  215. if (fListView->HasItem(item))
  216. fListView->InvalidateItem(fListView->IndexOf(item));
  217. }
  218. RosterListView*
  219. RosterView::ListView()
  220. {
  221. return fListView;
  222. }
  223. RosterMap
  224. RosterView::_RosterMap()
  225. {
  226. RosterMap contacts;
  227. if (fAccount < 0)
  228. contacts = fServer->Contacts();
  229. else {
  230. ProtocolLooper* looper = fServer->GetProtocolLooper(fAccount);
  231. contacts = looper->Contacts();
  232. }
  233. return contacts;
  234. }