diff --git a/Signal/Images.xcassets/settings-avatar-camera.imageset/Contents.json b/Signal/Images.xcassets/settings-avatar-camera.imageset/Contents.json new file mode 100644 index 000000000..c83f5f652 --- /dev/null +++ b/Signal/Images.xcassets/settings-avatar-camera.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "settings-avatar-camera@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "settings-avatar-camera@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "settings-avatar-camera@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/settings-avatar-camera.imageset/settings-avatar-camera@1x.png b/Signal/Images.xcassets/settings-avatar-camera.imageset/settings-avatar-camera@1x.png new file mode 100644 index 000000000..65739dcc2 Binary files /dev/null and b/Signal/Images.xcassets/settings-avatar-camera.imageset/settings-avatar-camera@1x.png differ diff --git a/Signal/Images.xcassets/settings-avatar-camera.imageset/settings-avatar-camera@2x.png b/Signal/Images.xcassets/settings-avatar-camera.imageset/settings-avatar-camera@2x.png new file mode 100644 index 000000000..9b500eb96 Binary files /dev/null and b/Signal/Images.xcassets/settings-avatar-camera.imageset/settings-avatar-camera@2x.png differ diff --git a/Signal/Images.xcassets/settings-avatar-camera.imageset/settings-avatar-camera@3x.png b/Signal/Images.xcassets/settings-avatar-camera.imageset/settings-avatar-camera@3x.png new file mode 100644 index 000000000..414c97c74 Binary files /dev/null and b/Signal/Images.xcassets/settings-avatar-camera.imageset/settings-avatar-camera@3x.png differ diff --git a/Signal/src/Profiles/OWSProfileManager.m b/Signal/src/Profiles/OWSProfileManager.m index 6e7b2508f..78c75a723 100644 --- a/Signal/src/Profiles/OWSProfileManager.m +++ b/Signal/src/Profiles/OWSProfileManager.m @@ -1011,10 +1011,11 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; - (nullable NSData *)encryptProfileNameWithUnpaddedName:(NSString *)name { - if (name.length == 0) { - return nil; - } - + // TODO: Should this be nil or a padded-out empty string? + // if (name.length == 0) { + // return nil; + // } + NSData *nameData = [name dataUsingEncoding:NSUTF8StringEncoding]; if (nameData.length > kOWSProfileManager_NameDataLength) { OWSFail(@"%@ name data is too long with length:%lu", self.tag, (unsigned long)nameData.length); diff --git a/Signal/src/ViewControllers/AppSettingsViewController.m b/Signal/src/ViewControllers/AppSettingsViewController.m index 1e5fd84cf..b1a52d6f5 100644 --- a/Signal/src/ViewControllers/AppSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettingsViewController.m @@ -216,23 +216,36 @@ UITableViewCell *cell = [UITableViewCell new]; cell.preservesSuperviewLayoutMargins = YES; cell.contentView.preservesSuperviewLayoutMargins = YES; + cell.selectionStyle = UITableViewCellSelectionStyleNone; const NSUInteger kAvatarSize = 68; // TODO: Replace this icon. - UIImage *avatarImage - = ([OWSProfileManager.sharedManager localProfileAvatarImage] ?: [UIImage imageNamed:@"profile_avatar_default"]); - // TODO: - // UIImage *avatarImage = - // [OWSAvatarBuilder buildImageForThread:self.thread diameter:kAvatarSize contactsManager:self.contactsManager]; + UIImage *_Nullable localProfileAvatarImage = [OWSProfileManager.sharedManager localProfileAvatarImage]; + UIImage *avatarImage = (localProfileAvatarImage + ?: [[UIImage imageNamed:@"profile_avatar_default"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]); OWSAssert(avatarImage); AvatarImageView *avatarView = [[AvatarImageView alloc] initWithImage:avatarImage]; + if (!localProfileAvatarImage) { + avatarView.tintColor = [UIColor colorWithRGBHex:0x888888]; + } [cell.contentView addSubview:avatarView]; [avatarView autoVCenterInSuperview]; [avatarView autoPinLeadingToSuperView]; [avatarView autoSetDimension:ALDimensionWidth toSize:kAvatarSize]; [avatarView autoSetDimension:ALDimensionHeight toSize:kAvatarSize]; + if (!localProfileAvatarImage) { + UIImage *cameraImage = [UIImage imageNamed:@"settings-avatar-camera"]; + cameraImage = [cameraImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + UIImageView *cameraImageView = [[UIImageView alloc] initWithImage:cameraImage]; + cameraImageView.tintColor = [UIColor ows_materialBlueColor]; + [cell.contentView addSubview:cameraImageView]; + [cameraImageView autoPinTrailingToView:avatarView]; + [cameraImageView autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:avatarView]; + } + UIView *threadNameView = [UIView containerView]; [cell.contentView addSubview:threadNameView]; [threadNameView autoVCenterInSuperview]; @@ -240,11 +253,18 @@ [threadNameView autoPinLeadingToTrailingOfView:avatarView margin:16.f]; UILabel *threadTitleLabel = [UILabel new]; - // TODO: Handle nil case, etc. - NSString *_Nullable profileName = [OWSProfileManager.sharedManager localProfileName]; - threadTitleLabel.text = profileName; - threadTitleLabel.textColor = [UIColor blackColor]; - threadTitleLabel.font = [UIFont ows_dynamicTypeTitle2Font]; + NSString *_Nullable localProfileName = [OWSProfileManager.sharedManager localProfileName]; + if (localProfileName.length > 0) { + threadTitleLabel.text = localProfileName; + threadTitleLabel.textColor = [UIColor blackColor]; + threadTitleLabel.font = [UIFont ows_dynamicTypeTitle2Font]; + } else { + threadTitleLabel.text = NSLocalizedString( + @"APP_SETTINGS_EDIT_PROFILE_NAME_PROMPT", @"Text prompting user to edit their profile name."); + threadTitleLabel.textColor = [UIColor ows_materialBlueColor]; + threadTitleLabel.font = [UIFont ows_dynamicTypeTitle3Font]; + DDLogError(@"threadTitleLabel.font: %f", threadTitleLabel.font.pointSize); + } threadTitleLabel.lineBreakMode = NSLineBreakByTruncatingTail; [threadNameView addSubview:threadTitleLabel]; [threadTitleLabel autoPinEdgeToSuperviewEdge:ALEdgeTop]; diff --git a/Signal/src/ViewControllers/ProfileViewController.m b/Signal/src/ViewControllers/ProfileViewController.m index d0b51a7b9..671b3f48b 100644 --- a/Signal/src/ViewControllers/ProfileViewController.m +++ b/Signal/src/ViewControllers/ProfileViewController.m @@ -21,6 +21,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) AvatarImageView *avatarView; +@property (nonatomic) UIImageView *cameraImageView; + @property (nonatomic) UILabel *avatarLabel; @property (nonatomic, nullable) UIImage *avatar; @@ -64,6 +66,11 @@ NS_ASSUME_NONNULL_BEGIN _avatarView = [AvatarImageView new]; + UIImage *cameraImage = [UIImage imageNamed:@"settings-avatar-camera"]; + cameraImage = [cameraImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + _cameraImageView = [[UIImageView alloc] initWithImage:cameraImage]; + _cameraImageView.tintColor = [UIColor ows_materialBlueColor]; + _avatarLabel = [UILabel new]; _avatarLabel.font = [UIFont ows_regularFontWithSize:14.f]; _avatarLabel.textColor = [UIColor ows_materialBlueColor]; @@ -99,12 +106,16 @@ NS_ASSUME_NONNULL_BEGIN cell.contentView.preservesSuperviewLayoutMargins = YES; AvatarImageView *avatarView = weakSelf.avatarView; - [weakSelf updateAvatarView]; + UIImageView *cameraImageView = weakSelf.cameraImageView; [cell.contentView addSubview:avatarView]; + [cell.contentView addSubview:cameraImageView]; + [weakSelf updateAvatarView]; [avatarView autoHCenterInSuperview]; [avatarView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:kAvatarTopMargin]; [avatarView autoSetDimension:ALDimensionWidth toSize:kAvatarSizePoints]; [avatarView autoSetDimension:ALDimensionHeight toSize:kAvatarSizePoints]; + [cameraImageView autoPinTrailingToView:avatarView]; + [cameraImageView autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:avatarView]; UILabel *avatarLabel = weakSelf.avatarLabel; [cell.contentView addSubview:avatarLabel]; @@ -265,7 +276,11 @@ NS_ASSUME_NONNULL_BEGIN - (void)updateAvatarView { - self.avatarView.image = (self.avatar ?: [UIImage imageNamed:@"profile_avatar_default"]); + self.avatarView.image = (self.avatar + ?: [[UIImage imageNamed:@"profile_avatar_default"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]); + self.avatarView.tintColor = (self.avatar ? nil : [UIColor colorWithRGBHex:0x888888]); + self.cameraImageView.hidden = self.avatar != nil; } #pragma mark - AvatarViewHelperDelegate diff --git a/Signal/src/util/UIFont+OWS.h b/Signal/src/util/UIFont+OWS.h index 9547bda51..9a3f19907 100644 --- a/Signal/src/util/UIFont+OWS.h +++ b/Signal/src/util/UIFont+OWS.h @@ -26,6 +26,7 @@ + (UIFont *)ows_dynamicTypeBodyFont; + (UIFont *)ows_dynamicTypeTitle2Font; ++ (UIFont *)ows_dynamicTypeTitle3Font; + (UIFont *)ows_infoMessageFont; + (UIFont *)ows_footnoteFont; diff --git a/Signal/src/util/UIFont+OWS.m b/Signal/src/util/UIFont+OWS.m index 228d8564f..67dd1b8a6 100644 --- a/Signal/src/util/UIFont+OWS.m +++ b/Signal/src/util/UIFont+OWS.m @@ -87,4 +87,17 @@ } } ++ (UIFont *)ows_dynamicTypeTitle3Font +{ + if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(9, 0)) { + return [UIFont preferredFontForTextStyle:UIFontTextStyleTitle3]; + } else { + // Dynamic title font for ios8 defaults to bold 12.0 pt, whereas ios9+ it's 22.0pt regular weight. + // Here we chose to break dynamic font, in order to have uniform style across versions. + // It's already huge, so it's unlikely to present a usability issue. + // Handy font translations: http://swiftiostutorials.com/comparison-of-system-fonts-on-ios-8-and-ios-9/ + return [self ows_regularFontWithSize:22.0]; + } +} + @end diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 1d4934e52..2789571a4 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -61,6 +61,9 @@ /* No comment provided by engineer. */ "APN_MESSAGE_IN_GROUP_DETAILED" = "%@ in group %@: %@"; +/* Text prompting user to edit their profile name. */ +"APP_SETTINGS_EDIT_PROFILE_NAME_PROMPT" = "Enter your name"; + /* Message format for the 'new app version available' alert. Embeds: {{The latest app version number.}}. */ "APP_UPDATE_NAG_ALERT_MESSAGE_FORMAT" = "Version %@ is now available in the App Store."; @@ -1120,9 +1123,6 @@ /* No comment provided by engineer. */ "REGISTER_RATE_LIMITING_BODY" = "You have tried too often. Please wait a minute before trying again."; -/* No comment provided by engineer. */ -"REGISTERED_NUMBER_TEXT" = "Registered Number"; - /* Title of alert shown when push tokens sync job fails. */ "REGISTRATION_BODY" = "Failed to re-register for push notifications.";