diff --git a/Classes/Base.lproj/ChatRoomViewController.xib b/Classes/Base.lproj/ChatRoomViewController.xib index 74afbc6db..2a1247799 100644 --- a/Classes/Base.lproj/ChatRoomViewController.xib +++ b/Classes/Base.lproj/ChatRoomViewController.xib @@ -178,6 +178,7 @@ + @@ -191,7 +192,7 @@ - + diff --git a/Classes/Base.lproj/ChatViewController.xib b/Classes/Base.lproj/ChatViewController.xib index a1b500fd2..fb33f11e4 100644 --- a/Classes/Base.lproj/ChatViewController.xib +++ b/Classes/Base.lproj/ChatViewController.xib @@ -14,11 +14,11 @@ - + - - + + - - - - - - - - diff --git a/Classes/LinphoneUI/Base.lproj/UIContactCell.xib b/Classes/LinphoneUI/Base.lproj/UIContactCell.xib index 6c4f16eab..b3f458109 100644 --- a/Classes/LinphoneUI/Base.lproj/UIContactCell.xib +++ b/Classes/LinphoneUI/Base.lproj/UIContactCell.xib @@ -54,7 +54,7 @@ 274 - {{46, 0}, {261, 44}} + {{79, 0}, {281, 44}} @@ -113,7 +113,7 @@ 300 - {{315, 12}, {37, 20}} + {{46, 11}, {25, 22}} @@ -122,7 +122,7 @@ IBCocoaTouchFramework NSImage - incoming_call_icon.png + linphone_user.png @@ -341,7 +341,7 @@ 3 {751, 751} - {111, 62} + {77, 66} diff --git a/Classes/LinphoneUI/Base.lproj/UIContactDetailsHeader.xib b/Classes/LinphoneUI/Base.lproj/UIContactDetailsHeader.xib index 54d88367c..cb76c7954 100644 --- a/Classes/LinphoneUI/Base.lproj/UIContactDetailsHeader.xib +++ b/Classes/LinphoneUI/Base.lproj/UIContactDetailsHeader.xib @@ -1,7 +1,6 @@ - diff --git a/Classes/LinphoneUI/Base.lproj/UIHistoryCell.xib b/Classes/LinphoneUI/Base.lproj/UIHistoryCell.xib index d5ef39440..abe44e0a9 100644 --- a/Classes/LinphoneUI/Base.lproj/UIHistoryCell.xib +++ b/Classes/LinphoneUI/Base.lproj/UIHistoryCell.xib @@ -7,69 +7,60 @@ - - - - + + + - + - - - - - - + + + - + - - - - + + diff --git a/Classes/LinphoneUI/UIChatCell.h b/Classes/LinphoneUI/UIChatCell.h index f8b649cc8..e19261ef3 100644 --- a/Classes/LinphoneUI/UIChatCell.h +++ b/Classes/LinphoneUI/UIChatCell.h @@ -20,6 +20,8 @@ #import #import "UITransparentTVCell.h" +#import "UIRoundedImageView.h" +#import "UIIconButton.h" #include "linphone/linphonecore.h" @@ -27,12 +29,12 @@ LinphoneChatRoom* chatRoom; } -@property (nonatomic, strong) IBOutlet UIImageView *avatarImage; +@property(nonatomic, strong) IBOutlet UIRoundedImageView *avatarImage; @property (nonatomic, strong) IBOutlet UILabel* addressLabel; @property (nonatomic, strong) IBOutlet UILabel* chatContentLabel; @property (nonatomic, strong) IBOutlet UIButton * deleteButton; -@property (nonatomic, strong) IBOutlet UIView * unreadMessageView; -@property (nonatomic, strong) IBOutlet UILabel * unreadMessageLabel; +@property(weak, nonatomic) IBOutlet UILabel *chatLatestTimeLabel; +@property(weak, nonatomic) IBOutlet UIIconButton *unreadCountButton; - (id)initWithIdentifier:(NSString*)identifier; diff --git a/Classes/LinphoneUI/UIChatCell.m b/Classes/LinphoneUI/UIChatCell.m index 916b4fa3d..875531ed9 100644 --- a/Classes/LinphoneUI/UIChatCell.m +++ b/Classes/LinphoneUI/UIChatCell.m @@ -28,8 +28,7 @@ @synthesize addressLabel; @synthesize chatContentLabel; @synthesize deleteButton; -@synthesize unreadMessageLabel; -@synthesize unreadMessageView; +@synthesize unreadCountButton; #pragma mark - Lifecycle Functions @@ -57,58 +56,31 @@ - (NSString *)accessibilityValue { if (chatContentLabel.text) { return [NSString stringWithFormat:@"%@ - %@ (%li)", addressLabel.text, chatContentLabel.text, - (long)[unreadMessageLabel.text integerValue]]; + (long)[unreadCountButton.titleLabel.text integerValue]]; } else { - return [NSString stringWithFormat:@"%@ (%li)", addressLabel.text, (long)[unreadMessageLabel.text integerValue]]; + return [NSString + stringWithFormat:@"%@ (%li)", addressLabel.text, (long)[unreadCountButton.titleLabel.text integerValue]]; } } - (void)update { - NSString *displayName = nil; - UIImage *image = nil; if (chatRoom == nil) { LOGW(@"Cannot update chat cell: null chat"); return; } const LinphoneAddress *linphoneAddress = linphone_chat_room_get_peer_address(chatRoom); - - if (linphoneAddress == NULL) - return; - char *tmp = linphone_address_as_string_uri_only(linphoneAddress); - NSString *normalizedSipAddress = [NSString stringWithUTF8String:tmp]; - ms_free(tmp); - - ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress]; - if (contact != nil) { - displayName = [FastAddressBook getContactDisplayName:contact]; - image = [FastAddressBook getContactImage:contact thumbnail:true]; - } - - // Display name - if (displayName == nil) { - const char *username = linphone_address_get_username(linphoneAddress); - char *address = linphone_address_as_string(linphoneAddress); - displayName = [NSString stringWithUTF8String:username ?: address]; - ms_free(address); - } - [addressLabel setText:displayName]; - - // Avatar - if (image == nil) { - image = [UIImage imageNamed:@"avatar_unknown_small.png"]; - } - [avatarImage setImage:image]; + [FastAddressBook setDisplayNameLabel:addressLabel forAddress:linphoneAddress]; + avatarImage.image = [FastAddressBook avatarForAddress:linphoneAddress]; LinphoneChatMessage *last_message = linphone_chat_room_get_user_data(chatRoom); - if (last_message) { - const char *text = linphone_chat_message_get_text(last_message); const char *url = linphone_chat_message_get_external_body_url(last_message); const LinphoneContent *last_content = linphone_chat_message_get_file_transfer_information(last_message); - // Message + // Last message was a file transfer (image) so display a picture... if (url || last_content) { - [chatContentLabel setText:@"🗻"]; + chatContentLabel.text = @"🗻"; + // otherwise show beginning of the text message } else if (text) { NSString *message = [NSString stringWithUTF8String:text]; // shorten long messages @@ -118,14 +90,17 @@ chatContentLabel.text = message; } - int count = linphone_chat_room_get_unread_messages_count(chatRoom); - unreadMessageLabel.text = [NSString stringWithFormat:@"%i", count]; - [unreadMessageView setHidden:(count <= 0)]; + _chatLatestTimeLabel.text = [LinphoneUtils timeToString:linphone_chat_message_get_time(last_message) + withStyle:NSDateFormatterShortStyle]; + _chatLatestTimeLabel.hidden = NO; } else { chatContentLabel.text = nil; - unreadMessageLabel.text = [NSString stringWithFormat:@"0"]; - [unreadMessageView setHidden:TRUE]; + _chatLatestTimeLabel.hidden = YES; } + + int count = linphone_chat_room_get_unread_messages_count(chatRoom); + [unreadCountButton setTitle:[NSString stringWithFormat:@"%i", count] forState:UIControlStateNormal]; + unreadCountButton.hidden = (count <= 0); } - (void)setEditing:(BOOL)editing { diff --git a/Classes/LinphoneUI/UIChatRoomCell.m b/Classes/LinphoneUI/UIChatRoomCell.m index f32e57d08..59fe44c5f 100644 --- a/Classes/LinphoneUI/UIChatRoomCell.m +++ b/Classes/LinphoneUI/UIChatRoomCell.m @@ -218,14 +218,8 @@ static UIFont *CELL_FONT = nil; } // Date - time_t chattime = linphone_chat_message_get_time(chat); - NSDate *message_date = (chattime == 0) ? [[NSDate alloc] init] : [NSDate dateWithTimeIntervalSince1970:chattime]; - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setTimeStyle:NSDateFormatterMediumStyle]; - [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; - NSLocale *locale = [NSLocale currentLocale]; - [dateFormatter setLocale:locale]; - [dateLabel setText:[dateFormatter stringFromDate:message_date]]; + dateLabel.text = + [LinphoneUtils timeToString:linphone_chat_message_get_time(chat) withStyle:NSDateFormatterMediumStyle]; LinphoneChatMessageState state = linphone_chat_message_get_state(chat); BOOL outgoing = linphone_chat_message_is_outgoing(chat); diff --git a/Classes/LinphoneUI/UIContactCell.m b/Classes/LinphoneUI/UIContactCell.m index ef23b1a34..f98d2e73d 100644 --- a/Classes/LinphoneUI/UIContactCell.m +++ b/Classes/LinphoneUI/UIContactCell.m @@ -45,25 +45,8 @@ - (void)setContact:(ABRecordRef)acontact { contact = acontact; - if (contact != nil) { - NSString *lFirstName = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonFirstNameProperty)); - NSString *lLocalizedFirstName = [FastAddressBook localizedLabel:lFirstName]; - - NSString *lLastName = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonLastNameProperty)); - NSString *lLocalizedLastName = [FastAddressBook localizedLabel:lLastName]; - - NSString *lOrganization = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonOrganizationProperty)); - NSString *lLocalizedOrganization = [FastAddressBook localizedLabel:lOrganization]; - - if (lLocalizedFirstName == nil && lLocalizedLastName == nil) { - [nameLabel setText:(NSString *)(lLocalizedOrganization)]; - } else { - nameLabel.text = [NSString stringWithFormat:@"%@ %@", lLocalizedFirstName, lLocalizedLastName]; - [nameLabel boldSubstring:lLocalizedLastName]; - } - - _linphoneImage.hidden = !([FastAddressBook contactHasValidSipDomain:contact]); - } + [FastAddressBook setDisplayNameLabel:nameLabel forContact:contact]; + _linphoneImage.hidden = !([FastAddressBook contactHasValidSipDomain:contact]); } #pragma mark - diff --git a/Classes/LinphoneUI/UIContactDetailsHeader.m b/Classes/LinphoneUI/UIContactDetailsHeader.m index 8e08541ae..b39a0d350 100644 --- a/Classes/LinphoneUI/UIContactDetailsHeader.m +++ b/Classes/LinphoneUI/UIContactDetailsHeader.m @@ -75,8 +75,6 @@ - (void)viewDidLoad { [super viewDidLoad]; - [tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4 - [tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4 [normalView setAlpha:1.0f]; [editView setAlpha:0.0f]; [tableView setEditing:TRUE animated:false]; diff --git a/Classes/LinphoneUI/UIHistoryCell.h b/Classes/LinphoneUI/UIHistoryCell.h index 8f9801a48..5c47019f7 100644 --- a/Classes/LinphoneUI/UIHistoryCell.h +++ b/Classes/LinphoneUI/UIHistoryCell.h @@ -20,6 +20,8 @@ #import #import "UITransparentTVCell.h" +#import "UIRoundedImageView.h" + #include "linphone/linphonecore.h" @interface UIHistoryCell : UITransparentTVCell { @@ -27,14 +29,10 @@ @property (nonatomic, assign) LinphoneCallLog *callLog; -@property (nonatomic, strong) IBOutlet UIImageView* imageView; -@property (nonatomic, strong) IBOutlet UILabel* addressLabel; -@property (nonatomic, strong) IBOutlet UIButton* detailsButton; -@property (nonatomic, strong) IBOutlet UIButton* deleteButton; +@property(weak, nonatomic) IBOutlet UIRoundedImageView *avatarImage; +@property(nonatomic, strong) IBOutlet UIButton *historyStateButton; +@property(nonatomic, strong) IBOutlet UILabel *displayNameLabel; - (id)initWithIdentifier:(NSString*)identifier; -- (IBAction)onDetails:(id) event; -- (IBAction)onDelete:(id) event; - @end diff --git a/Classes/LinphoneUI/UIHistoryCell.m b/Classes/LinphoneUI/UIHistoryCell.m index 63faa2601..5a7991bac 100644 --- a/Classes/LinphoneUI/UIHistoryCell.m +++ b/Classes/LinphoneUI/UIHistoryCell.m @@ -25,10 +25,8 @@ @implementation UIHistoryCell @synthesize callLog; -@synthesize addressLabel; -@synthesize imageView; -@synthesize deleteButton; -@synthesize detailsButton; +@synthesize displayNameLabel; +@synthesize historyStateButton; #pragma mark - Lifecycle Functions @@ -95,7 +93,7 @@ call_type = missed ? @"Missed" : @"Incoming"; } - return [NSString stringWithFormat:@"%@ from %@", call_type, addressLabel.text]; + return [NSString stringWithFormat:@"%@ from %@", call_type, displayNameLabel.text]; } - (void)update { @@ -105,7 +103,7 @@ } // Set up the cell... - LinphoneAddress *addr; + const LinphoneAddress *addr; UIImage *image; if (linphone_call_log_get_dir(callLog) == LinphoneCallIncoming) { if (linphone_call_log_get_status(callLog) != LinphoneCallMissed) { @@ -113,41 +111,15 @@ } else { image = [UIImage imageNamed:@"call_status_missed.png"]; } - addr = linphone_call_log_get_from(callLog); + addr = linphone_call_log_get_from_address(callLog); } else { image = [UIImage imageNamed:@"call_status_outgoing.png"]; - addr = linphone_call_log_get_to(callLog); + addr = linphone_call_log_get_to_address(callLog); } - NSString *address = nil; - if (addr != NULL) { - BOOL useLinphoneAddress = true; - // contact name - char *lAddress = linphone_address_as_string_uri_only(addr); - if (lAddress) { - NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]]; - ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress]; - if (contact) { - address = [FastAddressBook getContactDisplayName:contact]; - useLinphoneAddress = false; - } - ms_free(lAddress); - } - if (useLinphoneAddress) { - const char *lDisplayName = linphone_address_get_display_name(addr); - const char *lUserName = linphone_address_get_username(addr); - if (lDisplayName) - address = [NSString stringWithUTF8String:lDisplayName]; - else if (lUserName) - address = [NSString stringWithUTF8String:lUserName]; - } - } - if (address == nil) { - address = NSLocalizedString(@"Unknown", nil); - } - - [addressLabel setText:address]; - [imageView setImage:image]; + [FastAddressBook setDisplayNameLabel:displayNameLabel forAddress:addr]; + [_avatarImage setImage:[FastAddressBook avatarForAddress:addr]]; + [historyStateButton setImage:image forState:UIControlStateNormal]; } - (void)setEditing:(BOOL)editing { @@ -159,6 +131,7 @@ [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:0.3]; } +#if 0 if (editing) { [deleteButton setAlpha:1.0f]; [detailsButton setAlpha:0.0f]; @@ -166,6 +139,7 @@ [detailsButton setAlpha:1.0f]; [deleteButton setAlpha:0.0f]; } +#endif if (animated) { [UIView commitAnimations]; } diff --git a/Classes/SettingsViewController.m b/Classes/SettingsViewController.m index 879217b53..ea58f52c4 100644 --- a/Classes/SettingsViewController.m +++ b/Classes/SettingsViewController.m @@ -219,13 +219,6 @@ return r; } -- (void)viewDidLoad { - [super viewDidLoad]; - - [self.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4 - [self.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4 -} - - (id)initWithStyle:(UITableViewStyle)style { self = [super initWithStyle:style]; if (self != nil) { diff --git a/Classes/Utils/FastAddressBook.h b/Classes/Utils/FastAddressBook.h index 909a0dbf1..4d830d9f4 100644 --- a/Classes/Utils/FastAddressBook.h +++ b/Classes/Utils/FastAddressBook.h @@ -20,6 +20,8 @@ #import #import +#include "linphone/linphonecore.h" + @interface FastAddressBook : NSObject { NSMutableDictionary* addressBookMap; @@ -36,10 +38,12 @@ + (NSString*)appendCountryCodeIfPossible:(NSString*)number; + (NSString*)normalizePhoneNumber:(NSString*)number; + (NSString*)normalizeSipURI:(NSString*)address; -+ (BOOL)contactHasValidSipDomain:(ABRecordRef)person; // TOOLS +(NSString*)localizedLabel:(NSString*)label; - ++ (UIImage *)avatarForAddress:(const LinphoneAddress *)addr; ++ (BOOL)contactHasValidSipDomain:(ABRecordRef)person; ++ (void)setDisplayNameLabel:(UILabel *)label forAddress:(const LinphoneAddress *)addr; ++ (void)setDisplayNameLabel:(UILabel *)label forContact:(ABRecordRef)contact; @end diff --git a/Classes/Utils/FastAddressBook.m b/Classes/Utils/FastAddressBook.m index ea2dbace6..0d2088c9a 100644 --- a/Classes/Utils/FastAddressBook.m +++ b/Classes/Utils/FastAddressBook.m @@ -20,6 +20,7 @@ #import "FastAddressBook.h" #import "LinphoneManager.h" #import "ContactsViewController.h" +#import "UILabel+Boldify.h" @implementation FastAddressBook @@ -270,6 +271,9 @@ void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void } + (BOOL)contactHasValidSipDomain:(ABRecordRef)person { + if (person == nil) + return NO; + // Check if one of the contact' sip URI matches the expected SIP filter ABMultiValueRef personSipAddresses = ABRecordCopyValue(person, kABPersonInstantMessageProperty); BOOL match = false; @@ -307,4 +311,67 @@ void sync_address_book(ABAddressBookRef addressBook, CFDictionaryRef info, void return match; } ++ (void)setDisplayNameLabel:(UILabel *)label forContact:(ABRecordRef)contact { + if (contact != nil) { + NSString *lFirstName = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonFirstNameProperty)); + NSString *lLocalizedFirstName = [FastAddressBook localizedLabel:lFirstName]; + + NSString *lLastName = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonLastNameProperty)); + NSString *lLocalizedLastName = [FastAddressBook localizedLabel:lLastName]; + + NSString *lOrganization = CFBridgingRelease(ABRecordCopyValue(contact, kABPersonOrganizationProperty)); + NSString *lLocalizedOrganization = [FastAddressBook localizedLabel:lOrganization]; + + if (lLocalizedFirstName == nil && lLocalizedLastName == nil) { + label.text = (NSString *)lLocalizedOrganization; + } else { + label.text = [NSString stringWithFormat:@"%@ %@", lLocalizedFirstName, lLocalizedLastName]; + [label boldSubstring:lLocalizedLastName]; + } + } +} + ++ (void)setDisplayNameLabel:(UILabel *)label forAddress:(const LinphoneAddress *)addr { + label.text = NSLocalizedString(@"Unknown", nil); + if (addr != NULL) { + char *lAddress = linphone_address_as_string_uri_only(addr); + if (lAddress) { + NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]]; + ms_free(lAddress); + ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress]; + if (contact) { + [FastAddressBook setDisplayNameLabel:label forContact:contact]; + return; + } + } + const char *lDisplayName = linphone_address_get_display_name(addr); + const char *lUserName = linphone_address_get_username(addr); + if (lDisplayName) { + label.text = [NSString stringWithUTF8String:lDisplayName]; + } else if (lUserName) { + label.text = [NSString stringWithUTF8String:lUserName]; + } + } +} + ++ (UIImage *)avatarForAddress:(const LinphoneAddress *)addr { + UIImage *avatar = nil; + if (addr != NULL) { + // contact name + char *lAddress = linphone_address_as_string_uri_only(addr); + if (lAddress) { + NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:[NSString stringWithUTF8String:lAddress]]; + ABRecordRef contact = [[[LinphoneManager instance] fastAddressBook] getContact:normalizedSipAddress]; + if (contact) { + avatar = [FastAddressBook getContactImage:contact thumbnail:TRUE]; + } + ms_free(lAddress); + } + } + if (avatar == nil) { + avatar = [UIImage imageNamed:@"avatar"]; + } + return avatar; +} + @end diff --git a/Classes/Utils/Utils.h b/Classes/Utils/Utils.h index ddc432872..19904c07a 100644 --- a/Classes/Utils/Utils.h +++ b/Classes/Utils/Utils.h @@ -46,6 +46,8 @@ void linphone_iphone_log_handler(int lev, const char *fmt, va_list args); + (void)buttonMultiViewAddAttributes:(NSMutableDictionary*)attributes button:(UIButton*)button; + (void)buttonMultiViewApplyAttributes:(NSDictionary*)attributes button:(UIButton*)button; ++ (NSString *)timeToString:(time_t)time withStyle:(NSDateFormatterStyle)style; + @end @interface NSNumber (HumanReadableSize) diff --git a/Classes/Utils/Utils.m b/Classes/Utils/Utils.m index b8ea23ca1..6a8a62156 100644 --- a/Classes/Utils/Utils.m +++ b/Classes/Utils/Utils.m @@ -81,6 +81,31 @@ void linphone_iphone_log_handler(int lev, const char *fmt, va_list args) { @implementation LinphoneUtils ++ (NSString *)timeToString:(time_t)time withStyle:(NSDateFormatterStyle)style { + NSDate *todayDate = [[NSDate alloc] init]; + NSDate *messageDate = (time == 0) ? todayDate : [NSDate dateWithTimeIntervalSince1970:time]; + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + + [dateFormatter setDateStyle:style]; + + if (style == NSDateFormatterShortStyle) { + // UGLY but single line code! + BOOL sameDay = + [[dateFormatter stringFromDate:todayDate] isEqualToString:[dateFormatter stringFromDate:messageDate]]; + if (sameDay) { + [dateFormatter setDateStyle:NSDateFormatterNoStyle]; + [dateFormatter setTimeStyle:style]; + } else { + [dateFormatter setTimeStyle:NSDateFormatterNoStyle]; + } + } else { + [dateFormatter setTimeStyle:style]; + } + NSLocale *locale = [NSLocale currentLocale]; + [dateFormatter setLocale:locale]; + return [dateFormatter stringFromDate:messageDate]; +} + + (BOOL)findAndResignFirstResponder:(UIView *)view { if (view.isFirstResponder) { [view resignFirstResponder];