conversations: safe interaction access
Fix possible crash by checking if interactions exists before
update view for interaction.
Change-Id: I2d434037c4be632cd9fdedab2b4a0b938693586c
diff --git a/src/MessagesVC.mm b/src/MessagesVC.mm
index 20f445c..a88b8cf 100644
--- a/src/MessagesVC.mm
+++ b/src/MessagesVC.mm
@@ -83,6 +83,7 @@
CGFloat const MAX_TRANSFERED_IMAGE_SIZE = 250;
CGFloat const BUBBLE_HEIGHT_FOR_TRANSFERED_FILE = 87;
CGFloat const HEIGHT_FOR_COMPOSING_INDICATOR = 37;
+CGFloat const HEIGHT_DEFAULT = 1;
NSInteger const MEESAGE_MARGIN = 21;
NSInteger const SEND_PANEL_DEFAULT_HEIGHT = 60;
NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
@@ -533,6 +534,9 @@
IMTableCellView* result;
auto it = conv->interactions.begin();
auto size = conv->interactions.size();
+ if (row > size) {
+ return [[NSView alloc] init];
+ }
if (row == size) {
if (size < 1) {
@@ -541,15 +545,17 @@
//last row peer composing view
result = [tableView makeViewWithIdentifier:@"PeerComposingMsgView" owner:conversationView];
std::advance(it, row-1);
- //if previous message not from peer display avatar
- auto interaction = it->second;
- bool isOutgoing = lrc::api::interaction::isOutgoing(interaction);
- [result.photoView setHidden: YES];
- if(isOutgoing) {
- auto& imageManip = reinterpret_cast<Interfaces::ImageManipulationDelegate&>(GlobalInstances::pixmapManipulator());
- auto* conv = [self getCurrentConversation];
- [result.photoView setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(imageManip.conversationPhoto(*conv, convModel_->owner)))];
- [result.photoView setHidden: NO];
+ if (it != conv->interactions.end()) {
+ //if previous message not from peer display avatar
+ auto interaction = it->second;
+ bool isOutgoing = lrc::api::interaction::isOutgoing(interaction);
+ [result.photoView setHidden: YES];
+ if(isOutgoing) {
+ auto& imageManip = reinterpret_cast<Interfaces::ImageManipulationDelegate&>(GlobalInstances::pixmapManipulator());
+ auto* conv = [self getCurrentConversation];
+ [result.photoView setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(imageManip.conversationPhoto(*conv, convModel_->owner)))];
+ [result.photoView setHidden: NO];
+ }
}
CGFloat alpha = peerComposingMessage ? 1 : 0;
result.alphaValue = 0;
@@ -567,6 +573,10 @@
std::advance(it, row);
+ if (it == conv->interactions.end()) {
+ return [[NSView alloc] init];
+ }
+
auto interaction = it->second;
bool isOutgoing = lrc::api::interaction::isOutgoing(interaction);
@@ -675,7 +685,11 @@
auto* conv = [self getCurrentConversation];
if (conv == nil)
- return 0;
+ return HEIGHT_DEFAULT;
+
+ if (row > conv->interactions.size()) {
+ return HEIGHT_DEFAULT;
+ }
auto size = conv->interactions.size();
if (row == size) {
@@ -690,6 +704,10 @@
std::advance(it, row);
+ if (it == conv->interactions.end()) {
+ return HEIGHT_DEFAULT;
+ }
+
auto interaction = it->second;
MessageSequencing sequence = [self computeSequencingFor:row];
@@ -724,11 +742,6 @@
if(interaction.type == lrc::api::interaction::Type::CONTACT || interaction.type == lrc::api::interaction::Type::CALL)
return GENERIC_CELL_HEIGHT;
- // TODO Implement interactions other than messages
- if(interaction.type != lrc::api::interaction::Type::TEXT) {
- return 0;
- }
-
NSString *text = interaction.body.toNSString();
text = [text removeEmptyLinesAtBorders];
@@ -785,6 +798,9 @@
return SINGLE_WITHOUT_TIME;
auto it = conv->interactions.begin();
std::advance(it, row);
+ if (it == conv->interactions.end()) {
+ return SINGLE_WITHOUT_TIME;
+ }
auto interaction = it->second;
if (interaction.type != lrc::api::interaction::Type::TEXT) {
return SINGLE_WITH_TIME;
@@ -1018,6 +1034,8 @@
text = [text stringByReplacingOccurrencesOfString: separatorString withString: @"\n"];
if (text && text.length > 0) {
auto* conv = [self getCurrentConversation];
+ if (conv == nil)
+ return;
convModel_->sendMessage(convUid_, QString::fromNSString(text));
self.message = @"";
if(sendPanelHeight.constant != SEND_PANEL_DEFAULT_HEIGHT) {