diff --git a/DemoProject/SOSimpleChatDemo.xcodeproj/project.pbxproj b/DemoProject/SOSimpleChatDemo.xcodeproj/project.pbxproj index 96303ac..e2816a5 100644 --- a/DemoProject/SOSimpleChatDemo.xcodeproj/project.pbxproj +++ b/DemoProject/SOSimpleChatDemo.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ 3EBD811A191A61F90007B68A /* bubble_rect_receiving@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EBD8116191A61F90007B68A /* bubble_rect_receiving@2x.png */; }; 3EBD811B191A61F90007B68A /* bubble_rect_sending.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EBD8117191A61F90007B68A /* bubble_rect_sending.png */; }; 3EBD811C191A61F90007B68A /* bubble_rect_sending@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EBD8118191A61F90007B68A /* bubble_rect_sending@2x.png */; }; + 3ED720E9197CF32200393C27 /* Type4VC.m in Sources */ = {isa = PBXBuildFile; fileRef = 3ED720E8197CF32200393C27 /* Type4VC.m */; }; 75493C1219070071006C6BCD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75493C1119070071006C6BCD /* Foundation.framework */; }; 75493C1419070071006C6BCD /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75493C1319070071006C6BCD /* CoreGraphics.framework */; }; 75493C1619070071006C6BCD /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75493C1519070071006C6BCD /* UIKit.framework */; }; @@ -88,6 +89,8 @@ 3EBD8116191A61F90007B68A /* bubble_rect_receiving@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bubble_rect_receiving@2x.png"; sourceTree = ""; }; 3EBD8117191A61F90007B68A /* bubble_rect_sending.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bubble_rect_sending.png; sourceTree = ""; }; 3EBD8118191A61F90007B68A /* bubble_rect_sending@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bubble_rect_sending@2x.png"; sourceTree = ""; }; + 3ED720E7197CF32200393C27 /* Type4VC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Type4VC.h; sourceTree = ""; }; + 3ED720E8197CF32200393C27 /* Type4VC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Type4VC.m; sourceTree = ""; }; 75493C0E19070071006C6BCD /* SOSimpleChatDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SOSimpleChatDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 75493C1119070071006C6BCD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 75493C1319070071006C6BCD /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; @@ -310,6 +313,8 @@ 3EBD8108191A4D0A0007B68A /* Type2VC.m */, 3EBD810A191A4D2B0007B68A /* Type3VC.h */, 3EBD810B191A4D2B0007B68A /* Type3VC.m */, + 3ED720E7197CF32200393C27 /* Type4VC.h */, + 3ED720E8197CF32200393C27 /* Type4VC.m */, ); path = Controllers; sourceTree = ""; @@ -500,6 +505,7 @@ 3EBD810C191A4D2B0007B68A /* Type3VC.m in Sources */, 75B35A3C1922B80800513423 /* SOMessagingViewController.m in Sources */, 75B35A3A1922B80800513423 /* SOMessageCell.m in Sources */, + 3ED720E9197CF32200393C27 /* Type4VC.m in Sources */, 3E207894193DFC6300EC9FA4 /* Message.m in Sources */, 3EBD8109191A4D0A0007B68A /* Type2VC.m in Sources */, 75493C1E19070071006C6BCD /* main.m in Sources */, diff --git a/DemoProject/SOSimpleChatDemo.xcodeproj/xcuserdata/mattmoss.xcuserdatad/xcschemes/SOSimpleChatDemo.xcscheme b/DemoProject/SOSimpleChatDemo.xcodeproj/xcuserdata/mattmoss.xcuserdatad/xcschemes/SOSimpleChatDemo.xcscheme new file mode 100644 index 0000000..ca17d6b --- /dev/null +++ b/DemoProject/SOSimpleChatDemo.xcodeproj/xcuserdata/mattmoss.xcuserdatad/xcschemes/SOSimpleChatDemo.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DemoProject/SOSimpleChatDemo.xcodeproj/xcuserdata/mattmoss.xcuserdatad/xcschemes/xcschememanagement.plist b/DemoProject/SOSimpleChatDemo.xcodeproj/xcuserdata/mattmoss.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..d79f873 --- /dev/null +++ b/DemoProject/SOSimpleChatDemo.xcodeproj/xcuserdata/mattmoss.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,27 @@ + + + + + SchemeUserState + + SOSimpleChatDemo.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 75493C0D19070071006C6BCD + + primary + + + 75493C2E19070071006C6BCD + + primary + + + + + diff --git a/DemoProject/SOSimpleChatDemo/Base.lproj/Main.storyboard b/DemoProject/SOSimpleChatDemo/Base.lproj/Main.storyboard index 0a5364c..f24f4bd 100644 --- a/DemoProject/SOSimpleChatDemo/Base.lproj/Main.storyboard +++ b/DemoProject/SOSimpleChatDemo/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -17,7 +17,7 @@ - + @@ -72,6 +72,16 @@ + @@ -94,7 +104,7 @@ - + @@ -109,7 +119,22 @@ - + + + + + + + + + + + + + + + + diff --git a/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type3VC.m b/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type3VC.m index 8fb100a..4fccbd1 100644 --- a/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type3VC.m +++ b/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type3VC.m @@ -90,24 +90,25 @@ - (void)configureMessageCell:(SOMessageCell *)cell forMessageAtIndex:(NSInteger) //-----------------------------------------------// // Adding datetime label under balloon //-----------------------------------------------// - UILabel *label = [self generateLabelForCell:cell]; - - UILabel *existingLabel = [[cell.contentView.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"tag == %d",label.tag]] lastObject];; - [existingLabel removeFromSuperview]; - - [cell.contentView addSubview:label]; + [self generateLabelForCell:cell]; //-----------------------------------------------// } -- (UILabel *)generateLabelForCell:(SOMessageCell *)cell +- (void)generateLabelForCell:(SOMessageCell *)cell { + static NSInteger labelTag = 90; + Message *message = (Message *)cell.message; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"dd.MM.yyyy HH:mm"]; - UILabel *label = [[UILabel alloc] init]; - label.font = [UIFont systemFontOfSize:8]; - label.textColor = [UIColor grayColor]; - label.tag = 90; + UILabel *label = (UILabel *)[cell.contentView viewWithTag:labelTag]; + if (!label) { + label = [[UILabel alloc] init]; + label.font = [UIFont systemFontOfSize:8]; + label.textColor = [UIColor grayColor]; + label.tag = labelTag; + [cell.contentView addSubview:label]; + } label.text = [formatter stringFromDate:message.date]; [label sizeToFit]; CGRect frame = label.frame; @@ -119,13 +120,14 @@ - (UILabel *)generateLabelForCell:(SOMessageCell *)cell if (message.fromMe) { frame.origin.x = cell.contentView.frame.size.width - cell.userImageView.frame.size.width - frame.size.width - rightMargin; frame.origin.y = cell.containerView.frame.origin.y + cell.containerView.frame.size.height + topMargin; + label.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; } else { frame.origin.x = cell.containerView.frame.origin.x + cell.userImageView.frame.origin.x + cell.userImageView.frame.size.width + leftMargin; frame.origin.y = cell.containerView.frame.origin.y + cell.containerView.frame.size.height + topMargin; + label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; } - label.frame = frame; - return label; + label.frame = frame; } - (UIImage *)balloonImageForSending diff --git a/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type4VC.h b/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type4VC.h new file mode 100644 index 0000000..2f65422 --- /dev/null +++ b/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type4VC.h @@ -0,0 +1,13 @@ +// +// Type4VC.h +// SOSimpleChatDemo +// +// Created by Artur Mkrtchyan on 7/21/14. +// Copyright (c) 2014 SocialOjbects Software. All rights reserved. +// + +#import "SOMessagingViewController.h" + +@interface Type4VC : SOMessagingViewController + +@end diff --git a/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type4VC.m b/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type4VC.m new file mode 100644 index 0000000..3e7a4b9 --- /dev/null +++ b/DemoProject/SOSimpleChatDemo/Sources/Controllers/Type4VC.m @@ -0,0 +1,149 @@ +// +// Type4VC.m +// SOSimpleChatDemo +// +// Created by Artur Mkrtchyan on 7/21/14. +// Copyright (c) 2014 SocialOjbects Software. All rights reserved. +// + +#import "Type4VC.h" +#import "ContentManager.h" +#import "Message.h" + +@interface Type4VC () + +@property (strong, nonatomic) NSMutableArray *dataSource; + +@property (strong, nonatomic) UIImage *myImage; +@property (strong, nonatomic) UIImage *partnerImage; + + +@end + +@implementation Type4VC + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view. + + self.myImage = [UIImage imageNamed:@"arturdev.jpg"]; + self.partnerImage = [UIImage imageNamed:@"jobs.jpg"]; + + + [self loadMessages]; +} + +- (void)loadMessages +{ + self.dataSource = [[[ContentManager sharedManager] generateConversation] mutableCopy]; +} + +#pragma mark - SOMessaging data source +- (NSMutableArray *)messages +{ + return self.dataSource; +} + +- (NSTimeInterval)intervalForMessagesGrouping +{ + // Return 0 for disableing grouping + return 2 * 24 * 3600; +} + +- (void)configureMessageCell:(SOMessageCell *)cell forMessageAtIndex:(NSInteger)index +{ + Message *message = self.dataSource[index]; + + // Adjusting content for 3pt. (In this demo the width of bubble's tail is 3pt) + if (!message.fromMe) { + cell.contentInsets = UIEdgeInsetsMake(0, 3.0f, 0, 0); //Move content for 3 pt. to right + cell.textView.textColor = [UIColor blackColor]; + } else { + cell.contentInsets = UIEdgeInsetsMake(0, 0, 0, 3.0f); //Move content for 3 pt. to left + cell.textView.textColor = [UIColor whiteColor]; + } + + cell.userImageView.layer.cornerRadius = self.userImageSize.width/2; + + // Fix user image position on top or bottom. + cell.userImageView.autoresizingMask = message.fromMe ? UIViewAutoresizingFlexibleTopMargin : UIViewAutoresizingFlexibleBottomMargin; + + // Setting user images + cell.userImage = message.fromMe ? self.myImage : self.partnerImage; + + [self generateUsernameLabelForCell:cell]; +} + +- (void)generateUsernameLabelForCell:(SOMessageCell *)cell +{ + static NSInteger labelTag = 666; + + Message *message = (Message *)cell.message; + UILabel *label = (UILabel *)[cell.containerView viewWithTag:labelTag]; + if (!label) { + label = [[UILabel alloc] init]; + label.font = [UIFont systemFontOfSize:8]; + label.textColor = [UIColor grayColor]; + label.tag = labelTag; + [cell.containerView addSubview:label]; + } + label.text = message.fromMe ? @"Me" : @"Steve Jobs"; + [label sizeToFit]; + + CGRect frame = label.frame; + + CGFloat topMargin = 2.0f; + if (message.fromMe) { + frame.origin.x = cell.userImageView.frame.origin.x + cell.userImageView.frame.size.width/2 - frame.size.width/2; + frame.origin.y = cell.containerView.frame.size.height + topMargin; + + } else { + frame.origin.x = cell.userImageView.frame.origin.x + cell.userImageView.frame.size.width/2 - frame.size.width/2; + frame.origin.y = cell.userImageView.frame.origin.y + cell.userImageView.frame.size.height + topMargin; + } + label.frame = frame; +} + +- (CGFloat)messageMaxWidth +{ + return 140; +} + +- (CGSize)userImageSize +{ + return CGSizeMake(40, 40); +} + +- (CGFloat)messageMinHeight +{ + return 0; +} + +#pragma mark - SOMessaging delegate + +- (void)didSelectMedia:(NSData *)media inMessageCell:(SOMessageCell *)cell +{ + // Show selected media in fullscreen + [super didSelectMedia:media inMessageCell:cell]; +} + +- (void)messageInputView:(SOMessageInputView *)inputView didSendMessage:(NSString *)message +{ + if (![[message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]) { + return; + } + + Message *msg = [[Message alloc] init]; + msg.text = message; + msg.fromMe = YES; + + [self sendMessage:msg]; +} + +- (void)messageInputViewDidSelectMediaButton:(SOMessageInputView *)inputView +{ + // Take a photo/video or choose from gallery +} + +@end diff --git a/SOMessaging/NSString+Calculation.m b/SOMessaging/NSString+Calculation.m index fedd6d7..01ed18b 100644 --- a/SOMessaging/NSString+Calculation.m +++ b/SOMessaging/NSString+Calculation.m @@ -40,7 +40,7 @@ - (CGSize)usedSizeForMaxWidth:(CGFloat)width withFont:(UIFont *)font [layoutManager glyphRangeForTextContainer:textContainer]; CGRect frame = [layoutManager usedRectForTextContainer:textContainer]; - return frame.size; + return CGSizeMake(ceilf(frame.size.width),ceilf(frame.size.height)); } - (CGSize)usedSizeForMaxWidth:(CGFloat)width withAttributes:(NSDictionary *)attributes @@ -56,7 +56,7 @@ - (CGSize)usedSizeForMaxWidth:(CGFloat)width withAttributes:(NSDictionary *)attr CGRect usedFrame = [tempTextView.layoutManager usedRectForTextContainer:tempTextView.textContainer]; - return usedFrame.size; + return CGSizeMake(ceilf(usedFrame.size.width),ceilf(usedFrame.size.height)); } @end diff --git a/SOMessaging/SOMessagingViewController.m b/SOMessaging/SOMessagingViewController.m index 3c02bb3..54313db 100644 --- a/SOMessaging/SOMessagingViewController.m +++ b/SOMessaging/SOMessagingViewController.m @@ -365,12 +365,13 @@ - (void)refreshMessages self.conversation = [self grouppedMessages]; [self.tableView reloadData]; - NSInteger section = [self numberOfSectionsInTableView:self.tableView] - 1; - NSInteger row = [self tableView:self.tableView numberOfRowsInSection:section] - 1; - - if (row >= 0) { + NSInteger section = [self.tableView numberOfSections] - 1; + if (section >= 0) { + NSInteger row = [self.tableView numberOfRowsInSection:section] - 1; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section]; - [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; + if (row >= 0) { + [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; + } } }