mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
parent
3cb52bd198
commit
f74b5fac9a
15 changed files with 99 additions and 50 deletions
|
@ -49,7 +49,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
UIImage* avatarImage = [AvatarGenerator generateRoomAvatar:self.state.roomId andDisplayName:self.vectorDisplayname];
|
||||
UIImage* avatarImage = [AvatarGenerator generateAvatarForMatrixItem:self.state.roomId withDisplayName:self.vectorDisplayname];
|
||||
|
||||
if (roomAvatarUrl)
|
||||
{
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
// replace the identicon icon by the Vector style one
|
||||
if (_mxMember && ([_mxMember.avatarUrl rangeOfString:@"identicon"].location != NSNotFound))
|
||||
{
|
||||
thumbnail = [AvatarGenerator generateRoomMemberAvatar:_mxMember.userId displayName:_mxMember.displayname];
|
||||
thumbnail = [AvatarGenerator generateAvatarForMatrixItem:_mxMember.userId withDisplayName:_mxMember.displayname];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
|
|||
if (self)
|
||||
{
|
||||
// Use the vector style placeholder
|
||||
self.senderAvatarPlaceholder = [AvatarGenerator generateRoomMemberAvatar:self.senderId displayName:self.senderDisplayName];
|
||||
self.senderAvatarPlaceholder = [AvatarGenerator generateAvatarForMatrixItem:self.senderId withDisplayName:self.senderDisplayName];
|
||||
|
||||
// Increase maximum number of components
|
||||
self.maxComponentCount = 20;
|
||||
|
|
|
@ -157,7 +157,7 @@
|
|||
if (roomMember)
|
||||
{
|
||||
[roomMembers addObject:roomMember];
|
||||
[placeholders addObject:[AvatarGenerator generateRoomMemberAvatar:roomMember.userId displayName:roomMember.displayname]];
|
||||
[placeholders addObject:[AvatarGenerator generateAvatarForMatrixItem:roomMember.userId withDisplayName:roomMember.displayname]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
@interface AvatarGenerator : NSObject
|
||||
|
||||
/**
|
||||
Create an UIImage with the text and the background color.
|
||||
Create a squared UIImage with the text and the background color.
|
||||
@param text the text.
|
||||
@param color the background color.
|
||||
@return the avatar image.
|
||||
|
@ -30,20 +30,22 @@
|
|||
+ (UIImage *)imageFromText:(NSString*)text withBackgroundColor:(UIColor*)color;
|
||||
|
||||
/**
|
||||
Generate an avatar for a room.
|
||||
@param roomId the id of the room.
|
||||
@param displayName the display name of the room.
|
||||
Generate a squared avatar for a matrix item (room, room member...).
|
||||
@param itemId the matrix identifier of the item
|
||||
@param displayname the item displayname (if nil, the itemId is used by default).
|
||||
@return the avatar image
|
||||
*/
|
||||
+ (UIImage*)generateRoomAvatar:(NSString*)roomId andDisplayName:(NSString*)displayName;
|
||||
+ (UIImage*)generateAvatarForMatrixItem:(NSString*)itemId withDisplayName:(NSString*)displayname;
|
||||
|
||||
/**
|
||||
Generate an avatar for a room member.
|
||||
@param userId the member userId
|
||||
@param displayname the member displayname
|
||||
Generate a squared avatar for a matrix item (room, room member...) with a preferred size
|
||||
@param itemId the matrix identifier of the item
|
||||
@param displayname the item displayname (if nil, the itemId is used by default).
|
||||
@param size the expected size of the returned image
|
||||
@param fontSize the expected font size
|
||||
@return the avatar image
|
||||
*/
|
||||
+ (UIImage*)generateRoomMemberAvatar:(NSString*)userId displayName:(NSString*)displayname;
|
||||
+ (UIImage*)generateAvatarForMatrixItem:(NSString*)itemId withDisplayName:(NSString*)displayname size:(CGFloat)size andFontSize:(CGFloat)fontSize;
|
||||
|
||||
/**
|
||||
Generate an avatar for a text.
|
||||
|
|
|
@ -64,8 +64,26 @@ static UILabel* backgroundLabel = nil;
|
|||
}
|
||||
|
||||
/**
|
||||
Create an UIImage with the text and the background color.
|
||||
Return the first valid character for avatar creation.
|
||||
*/
|
||||
+ (NSString *)firstChar:(NSString *)text
|
||||
{
|
||||
if ([text hasPrefix:@"@"] || [text hasPrefix:@"#"] || [text hasPrefix:@"!"])
|
||||
{
|
||||
text = [text substringFromIndex:1];
|
||||
}
|
||||
|
||||
// default firstchar
|
||||
NSString* firstChar = @" ";
|
||||
|
||||
if (text.length > 0)
|
||||
{
|
||||
firstChar = [[text substringToIndex:1] uppercaseString];
|
||||
}
|
||||
|
||||
return firstChar;
|
||||
}
|
||||
|
||||
+ (UIImage *)imageFromText:(NSString*)text withBackgroundColor:(UIColor*)color
|
||||
{
|
||||
if (!backgroundLabel)
|
||||
|
@ -93,24 +111,37 @@ static UILabel* backgroundLabel = nil;
|
|||
return image;
|
||||
}
|
||||
|
||||
+ (UIImage *)imageFromText:(NSString*)text withBackgroundColor:(UIColor*)color size:(CGFloat)size andFontSize:(CGFloat)fontSize
|
||||
{
|
||||
UILabel *bgLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, size, size)];
|
||||
bgLabel.textColor = [UIColor whiteColor];
|
||||
bgLabel.textAlignment = NSTextAlignmentCenter;
|
||||
bgLabel.font = [UIFont boldSystemFontOfSize:fontSize];
|
||||
|
||||
bgLabel.text = text;
|
||||
bgLabel.backgroundColor = color;
|
||||
|
||||
// Create a "canvas" (image context) to draw in.
|
||||
UIGraphicsBeginImageContextWithOptions(bgLabel.frame.size, NO, 0);
|
||||
|
||||
// set to the top quality
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
|
||||
[[bgLabel layer] renderInContext: UIGraphicsGetCurrentContext()];
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
// Return the image.
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the UIImage for the text and a selected color.
|
||||
It checks first if it is not yet cached before generating one.
|
||||
*/
|
||||
+ (UIImage*)avatarForText:(NSString*)aText andColorIndex:(NSUInteger)colorIndex
|
||||
+ (UIImage*)avatarForText:(NSString*)text andColorIndex:(NSUInteger)colorIndex
|
||||
{
|
||||
if ([aText hasPrefix:@"@"] || [aText hasPrefix:@"#"] || [aText hasPrefix:@"!"])
|
||||
{
|
||||
aText = [aText substringFromIndex:1];
|
||||
}
|
||||
|
||||
// default firstchar
|
||||
NSString* firstChar = @" ";
|
||||
|
||||
if (aText.length > 0)
|
||||
{
|
||||
firstChar = [[aText substringToIndex:1] uppercaseString];
|
||||
}
|
||||
NSString* firstChar = [AvatarGenerator firstChar:text];
|
||||
|
||||
// the images are cached to avoid create them several times
|
||||
// the key is <first upper character><index in the colors array>
|
||||
|
@ -138,18 +169,17 @@ static UILabel* backgroundLabel = nil;
|
|||
return [AvatarGenerator avatarForText:text andColorIndex:[AvatarGenerator colorIndexForText:text]];
|
||||
}
|
||||
|
||||
+ (UIImage*)generateRoomMemberAvatar:(NSString*)userId displayName:(NSString*)displayname
|
||||
+ (UIImage*)generateAvatarForMatrixItem:(NSString*)itemId withDisplayName:(NSString*)displayname
|
||||
{
|
||||
// the selected color is based on the userId
|
||||
NSUInteger index = [AvatarGenerator colorIndexForText:userId];
|
||||
NSString* text = displayname ? displayname : userId;
|
||||
|
||||
return [AvatarGenerator avatarForText:text andColorIndex:index];
|
||||
return [AvatarGenerator avatarForText:(displayname ? displayname : itemId) andColorIndex:[AvatarGenerator colorIndexForText:itemId]];
|
||||
}
|
||||
|
||||
+ (UIImage*)generateRoomAvatar:(NSString*)roomId andDisplayName:(NSString*)displayName
|
||||
+ (UIImage*)generateAvatarForMatrixItem:(NSString*)itemId withDisplayName:(NSString*)displayname size:(CGFloat)size andFontSize:(CGFloat)fontSize
|
||||
{
|
||||
return [AvatarGenerator avatarForText:displayName andColorIndex:[AvatarGenerator colorIndexForText:roomId]];
|
||||
NSString* firstChar = [AvatarGenerator firstChar:(displayname ? displayname : itemId)];
|
||||
NSUInteger colorIndex = [AvatarGenerator colorIndexForText:itemId];
|
||||
|
||||
return [AvatarGenerator imageFromText:firstChar withBackgroundColor:[colorsList objectAtIndex:colorIndex] size:size andFontSize:fontSize];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -24,4 +24,6 @@
|
|||
@property (weak, nonatomic) IBOutlet UIView *gradientMaskContainerView;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *chatButton;
|
||||
|
||||
@property (unsafe_unretained, nonatomic) IBOutlet NSLayoutConstraint *callerImageViewWidthConstraint;
|
||||
|
||||
@end
|
||||
|
|
|
@ -111,6 +111,11 @@
|
|||
gradientMaskLayer.bounds = CGRectMake(0, 0, self.callContainerView.frame.size.width, self.callContainerView.frame.size.height + 20);
|
||||
gradientMaskLayer.anchorPoint = CGPointZero;
|
||||
|
||||
// Define caller image view size
|
||||
CGSize size = [[UIScreen mainScreen] bounds].size;
|
||||
CGFloat minSize = MIN(size.width, size.height);
|
||||
self.callerImageViewWidthConstraint.constant = minSize / 2;
|
||||
|
||||
// CAConstraint is not supported on IOS.
|
||||
// it seems only being supported on Mac OS.
|
||||
// so viewDidLayoutSubviews will refresh the layout bounds.
|
||||
|
@ -136,6 +141,10 @@
|
|||
gradientMaskLayer.bounds = newBounds;
|
||||
}
|
||||
}
|
||||
|
||||
// The caller image view is circular
|
||||
self.callerImageView.layer.cornerRadius = self.callerImageViewWidthConstraint.constant / 2;
|
||||
self.callerImageView.clipsToBounds = YES;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
|
@ -156,14 +165,16 @@
|
|||
|
||||
- (UIImage*)picturePlaceholder
|
||||
{
|
||||
CGFloat fontSize = floor(self.callerImageViewWidthConstraint.constant * 0.7);
|
||||
|
||||
if (self.peer)
|
||||
{
|
||||
// Use the vector style placeholder
|
||||
return [AvatarGenerator generateRoomMemberAvatar:self.peer.userId displayName:self.peer.displayname];
|
||||
return [AvatarGenerator generateAvatarForMatrixItem:self.peer.userId withDisplayName:self.peer.displayname size:self.callerImageViewWidthConstraint.constant andFontSize:fontSize];
|
||||
}
|
||||
else if (self.mxCall.room)
|
||||
{
|
||||
return [AvatarGenerator generateRoomAvatar:self.mxCall.room.roomId andDisplayName:self.mxCall.room.state.displayname];
|
||||
return [AvatarGenerator generateAvatarForMatrixItem:self.mxCall.room.roomId withDisplayName:self.mxCall.room.vectorDisplayname size:self.callerImageViewWidthConstraint.constant andFontSize:fontSize];
|
||||
}
|
||||
|
||||
return [UIImage imageNamed:@"placeholder"];
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -15,6 +16,7 @@
|
|||
<outlet property="callControlContainerView" destination="nk9-Un-LVP" id="ZV3-qr-BtW"/>
|
||||
<outlet property="callStatusLabel" destination="29y-MK-OWH" id="Kcn-MX-MUH"/>
|
||||
<outlet property="callerImageView" destination="v1I-LH-wvv" id="dpZ-KD-4Hg"/>
|
||||
<outlet property="callerImageViewWidthConstraint" destination="PAF-29-Cis" id="Crz-nE-p4c"/>
|
||||
<outlet property="callerNameLabel" destination="IW8-8P-mS3" id="eaa-oo-l01"/>
|
||||
<outlet property="cameraSwitchButton" destination="Iiz-W1-oNW" id="bsM-mH-ti8"/>
|
||||
<outlet property="chatButton" destination="xCi-hD-FBs" id="h3w-6I-Agn"/>
|
||||
|
@ -46,8 +48,12 @@
|
|||
<rect key="frame" x="277" y="285" width="46" height="30"/>
|
||||
</button>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="v1I-LH-wvv" customClass="MXKImageView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<rect key="frame" x="150" y="90" width="300" height="300"/>
|
||||
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="300" id="PAF-29-Cis"/>
|
||||
<constraint firstAttribute="width" secondItem="v1I-LH-wvv" secondAttribute="height" multiplier="1:1" id="pzY-9x-dH7"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="Tjb-57-yB1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
|
@ -270,23 +276,21 @@
|
|||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="v1I-LH-wvv" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" multiplier="0.8" id="7bF-kf-k3o"/>
|
||||
<constraint firstAttribute="bottom" secondItem="STO-VX-5VW" secondAttribute="bottom" id="DhB-zy-SJA"/>
|
||||
<constraint firstAttribute="trailing" secondItem="JAR-tn-sGN" secondAttribute="trailing" id="IGf-YS-JEj"/>
|
||||
<constraint firstAttribute="bottom" secondItem="JAR-tn-sGN" secondAttribute="bottom" id="KDu-Kr-vji"/>
|
||||
<constraint firstItem="STO-VX-5VW" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Tyh-Du-Ztt"/>
|
||||
<constraint firstItem="v1I-LH-wvv" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="VF9-js-1ub"/>
|
||||
<constraint firstItem="6gQ-zo-2Zw" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" priority="750" constant="420" id="VUy-XN-XzH"/>
|
||||
<constraint firstAttribute="trailing" secondItem="STO-VX-5VW" secondAttribute="trailing" id="X0Q-UU-v3g"/>
|
||||
<constraint firstItem="JAR-tn-sGN" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Z6W-gz-KKT"/>
|
||||
<constraint firstItem="v1I-LH-wvv" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="ZfI-qE-l2V"/>
|
||||
<constraint firstItem="Tjb-57-yB1" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="aKy-Ol-bhc"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Tjb-57-yB1" secondAttribute="bottom" id="akt-pO-kWM"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="6gQ-zo-2Zw" secondAttribute="bottom" constant="74" id="bmf-4N-mLk"/>
|
||||
<constraint firstItem="v1I-LH-wvv" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="cq1-0k-TFN"/>
|
||||
<constraint firstItem="6gQ-zo-2Zw" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" id="dq3-4E-bhT"/>
|
||||
<constraint firstItem="STO-VX-5VW" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="e4c-aG-jOB"/>
|
||||
<constraint firstAttribute="trailing" secondItem="v1I-LH-wvv" secondAttribute="trailing" id="eL2-a4-lJd"/>
|
||||
<constraint firstItem="Tjb-57-yB1" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="mW3-RA-hx2"/>
|
||||
<constraint firstAttribute="bottom" secondItem="v1I-LH-wvv" secondAttribute="bottom" id="o10-x3-vgo"/>
|
||||
<constraint firstItem="JAR-tn-sGN" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="pei-Ab-VHX"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Tjb-57-yB1" secondAttribute="trailing" id="rXn-dm-69F"/>
|
||||
</constraints>
|
||||
|
|
|
@ -376,7 +376,7 @@
|
|||
|
||||
if (matrixId)
|
||||
{
|
||||
image = [AvatarGenerator generateRoomMemberAvatar:matrixId displayName:_contact.displayName];
|
||||
image = [AvatarGenerator generateAvatarForMatrixItem:matrixId withDisplayName:_contact.displayName];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -215,7 +215,7 @@
|
|||
if (self.mxRoomMember)
|
||||
{
|
||||
// Use the vector style placeholder
|
||||
return [AvatarGenerator generateRoomMemberAvatar:self.mxRoomMember.userId displayName:self.mxRoomMember.displayname];
|
||||
return [AvatarGenerator generateAvatarForMatrixItem:self.mxRoomMember.userId withDisplayName:self.mxRoomMember.displayname];
|
||||
}
|
||||
|
||||
return [UIImage imageNamed:@"placeholder"];
|
||||
|
|
|
@ -925,7 +925,7 @@
|
|||
MXKImageView *userPictureView = roomInputToolbarView.pictureView;
|
||||
if (userPictureView)
|
||||
{
|
||||
UIImage *preview = [AvatarGenerator generateRoomMemberAvatar:self.mainSession.myUser.userId displayName:self.mainSession.myUser.displayname];
|
||||
UIImage *preview = [AvatarGenerator generateAvatarForMatrixItem:self.mainSession.myUser.userId withDisplayName:self.mainSession.myUser.displayname];
|
||||
NSString *avatarThumbURL = nil;
|
||||
if (self.mainSession.myUser.avatarUrl)
|
||||
{
|
||||
|
@ -1204,7 +1204,7 @@
|
|||
}
|
||||
else if (roomPreviewData.roomId && roomPreviewData.roomName)
|
||||
{
|
||||
roomAvatarTitleView.roomAvatarPlaceholder = [AvatarGenerator generateRoomAvatar:roomPreviewData.roomId andDisplayName:roomPreviewData.roomName];
|
||||
roomAvatarTitleView.roomAvatarPlaceholder = [AvatarGenerator generateAvatarForMatrixItem:roomPreviewData.roomId withDisplayName:roomPreviewData.roomName];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -691,7 +691,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
|
|||
}
|
||||
else
|
||||
{
|
||||
UIImage* avatarImage = [AvatarGenerator generateRoomMemberAvatar:myUser.userId displayName:myUser.displayname];
|
||||
UIImage* avatarImage = [AvatarGenerator generateAvatarForMatrixItem:myUser.userId withDisplayName:myUser.displayname];
|
||||
|
||||
if (myUser.avatarUrl)
|
||||
{
|
||||
|
|
|
@ -180,7 +180,7 @@
|
|||
|
||||
if (matrixId)
|
||||
{
|
||||
image = [AvatarGenerator generateRoomMemberAvatar:matrixId displayName:contact.displayName];
|
||||
image = [AvatarGenerator generateAvatarForMatrixItem:matrixId withDisplayName:contact.displayName];
|
||||
}
|
||||
else if (contact.isThirdPartyInvite)
|
||||
{
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
}
|
||||
|
||||
// Set the avatar
|
||||
UIImage* avatarImage = [AvatarGenerator generateRoomAvatar:publicRoom.roomId andDisplayName:self.roomDisplayName.text];
|
||||
UIImage* avatarImage = [AvatarGenerator generateAvatarForMatrixItem:publicRoom.roomId withDisplayName:self.roomDisplayName.text];
|
||||
|
||||
if (publicRoom.avatarUrl)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue