Merge remote-tracking branch 'origin/develop' into mxfilestore

This commit is contained in:
manuroe 2014-12-18 15:51:42 +01:00
commit fdfce7b5db
14 changed files with 410 additions and 106 deletions

View file

@ -21,6 +21,7 @@
@property (nonatomic) BOOL displayAllEvents;
@property (nonatomic) BOOL hideUnsupportedMessages;
@property (nonatomic) BOOL sortMembersUsingLastSeenTime;
@property (nonatomic) BOOL displayLeftUsers;
+ (AppSettings *)sharedSettings;

View file

@ -47,6 +47,7 @@ static AppSettings *sharedSettings = nil;
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"displayAllEvents"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"hideUnsupportedMessages"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"sortMembersUsingLastSeenTime"];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"displayLeftUsers"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
@ -87,4 +88,12 @@ static AppSettings *sharedSettings = nil;
[[NSUserDefaults standardUserDefaults] setBool:sortMembersUsingLastSeen forKey:@"sortMembersUsingLastSeenTime"];
}
- (BOOL)displayLeftUsers {
return [[NSUserDefaults standardUserDefaults] boolForKey:@"displayLeftUsers"];
}
- (void)setDisplayLeftUsers:(BOOL)displayLeftUsers {
[[NSUserDefaults standardUserDefaults] setBool:displayLeftUsers forKey:@"displayLeftUsers"];
}
@end

View file

@ -4,6 +4,7 @@
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<scenes>
<!--Recents-->
@ -307,45 +308,43 @@
<constraint firstAttribute="width" constant="40" id="pLY-G3-fxB"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="userLabel" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="uVK-4R-arl" userLabel="userLabel">
<rect key="frame" x="56" y="5" width="464" height="34"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="userLabel" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uVK-4R-arl" userLabel="userLabel">
<rect key="frame" x="56" y="5" width="520" height="34"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="lastActiveLabel" textAlignment="center" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="R86-SF-Vqh">
<rect key="frame" x="528" y="5" width="64" height="39"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="UDn-QR-f6Q">
<rect key="frame" x="56" y="42" width="464" height="2"/>
</progressView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wDo-tA-Ar7" userLabel="PowerContainer">
<rect key="frame" x="578" y="18" width="14" height="14"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="14" id="12z-f1-s6Z"/>
<constraint firstAttribute="width" constant="14" id="pnc-pv-ZIj"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="UDn-QR-f6Q" firstAttribute="leading" secondItem="prD-ap-cDD" secondAttribute="leading" constant="56" id="2HY-kb-aUu"/>
<constraint firstAttribute="bottom" secondItem="R86-SF-Vqh" secondAttribute="bottom" constant="5" id="3dt-Qu-01M"/>
<constraint firstAttribute="bottom" secondItem="UDn-QR-f6Q" secondAttribute="bottom" constant="5" id="49f-EW-vEr"/>
<constraint firstItem="RW8-nh-DTj" firstAttribute="top" secondItem="prD-ap-cDD" secondAttribute="top" constant="5" id="6La-Gc-4B8"/>
<constraint firstItem="UDn-QR-f6Q" firstAttribute="top" secondItem="uVK-4R-arl" secondAttribute="bottom" constant="3" id="81T-EM-1pe"/>
<constraint firstAttribute="trailing" secondItem="R86-SF-Vqh" secondAttribute="trailing" constant="8" id="BvW-r7-R0r"/>
<constraint firstAttribute="trailing" secondItem="UDn-QR-f6Q" secondAttribute="trailing" constant="80" id="Nrk-rv-6eb"/>
<constraint firstAttribute="trailingMargin" secondItem="wDo-tA-Ar7" secondAttribute="trailing" id="GKG-lb-3k0"/>
<constraint firstItem="uVK-4R-arl" firstAttribute="leading" secondItem="RW8-nh-DTj" secondAttribute="trailing" constant="8" id="O2H-DM-jOU"/>
<constraint firstAttribute="trailing" secondItem="uVK-4R-arl" secondAttribute="trailing" constant="80" id="RSx-Sk-WrV"/>
<constraint firstAttribute="trailing" secondItem="uVK-4R-arl" secondAttribute="trailing" constant="24" id="RSx-Sk-WrV"/>
<constraint firstAttribute="centerY" secondItem="wDo-tA-Ar7" secondAttribute="centerY" id="a3l-Wn-dkq"/>
<constraint firstAttribute="trailing" secondItem="wDo-tA-Ar7" secondAttribute="trailing" constant="21" id="cAm-Af-t17"/>
<constraint firstItem="uVK-4R-arl" firstAttribute="top" secondItem="prD-ap-cDD" secondAttribute="top" constant="5" id="cFa-Qa-p2W"/>
<constraint firstItem="RW8-nh-DTj" firstAttribute="leading" secondItem="prD-ap-cDD" secondAttribute="leading" constant="8" id="hXV-sM-uhV"/>
<constraint firstAttribute="bottom" secondItem="uVK-4R-arl" secondAttribute="bottom" constant="10" id="l5F-M4-LOB"/>
<constraint firstItem="R86-SF-Vqh" firstAttribute="top" secondItem="prD-ap-cDD" secondAttribute="top" constant="5" id="mNu-kF-Hb7"/>
<constraint firstItem="R86-SF-Vqh" firstAttribute="leading" secondItem="uVK-4R-arl" secondAttribute="trailing" constant="8" id="tz0-aZ-yaX"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="cAm-Af-t17"/>
</mask>
</variation>
</tableViewCellContentView>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<outlet property="lastActiveAgoLabel" destination="R86-SF-Vqh" id="AIr-OL-gqM"/>
<outlet property="pictureView" destination="RW8-nh-DTj" id="1Lk-bd-tKv"/>
<outlet property="powerContainer" destination="wDo-tA-Ar7" id="sub-O0-L9d"/>
<outlet property="userLabel" destination="uVK-4R-arl" id="OhP-VD-vj0"/>
<outlet property="userPowerLevel" destination="UDn-QR-f6Q" id="Ts8-l1-Lyv"/>
</connections>
</tableViewCell>
</prototypes>
@ -450,7 +449,7 @@
<scene sceneID="3rt-8o-eGh">
<objects>
<tableViewController title="Home" id="ldZ-75-BUU" customClass="HomeViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="40" sectionFooterHeight="22" id="LbI-fz-LaI">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="interactive" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="40" sectionFooterHeight="22" id="LbI-fz-LaI">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>

View file

@ -59,4 +59,6 @@ extern NSString *const kMatrixHandlerUnsupportedMessagePrefix;
- (NSString*)senderAvatarUrlForEvent:(MXEvent*)event withRoomState:(MXRoomState*)roomState;
- (NSString*)displayTextForEvent:(MXEvent*)event withRoomState:(MXRoomState*)roomState inSubtitleMode:(BOOL)isSubtitle;
// search if a 1:1 conversation has been started with this member
- (NSString*) getRoomStartedWithMember:(MXRoomMember*)roomMember;
@end

View file

@ -543,7 +543,13 @@ static MatrixHandler *sharedHandler = nil;
prevDisplayname = nil;
}
if ((displayname || prevDisplayname) && ([displayname isEqualToString:prevDisplayname] == NO)) {
displayText = [NSString stringWithFormat:@"%@ changed their display name from %@ to %@", event.userId, prevDisplayname, displayname];
if (!prevDisplayname) {
displayText = [NSString stringWithFormat:@"%@ set their display name to %@", event.userId, displayname];
} else if (!displayname) {
displayText = [NSString stringWithFormat:@"%@ removed their display name (previouly named %@)", event.userId, prevDisplayname];
} else {
displayText = [NSString stringWithFormat:@"%@ changed their display name from %@ to %@", event.userId, prevDisplayname, displayname];
}
}
// Check whether the avatar has been changed
@ -731,4 +737,37 @@ static MatrixHandler *sharedHandler = nil;
return displayText;
}
// search if a conversation has been started with this user
- (NSString*) getRoomStartedWithMember:(MXRoomMember*)roomMember {
//
if (self.mxSession) {
// list the last messages of each room to get the rooms list
NSArray *recentEvents = [NSMutableArray arrayWithArray:[self.mxSession recentsWithTypeIn:self.eventsFilterForMessages]];
// loops
for (MXEvent *mxEvent in recentEvents) {
// get the dedicated mxRooms
MXRoom *mxRoom = [self.mxSession roomWithRoomId:mxEvent.roomId];
// accept only room with 2 users
if (mxRoom.state.members.count == 2) {
NSArray* roomMembers = mxRoom.state.members;
MXRoomMember* member1 = [roomMembers objectAtIndex:0];
MXRoomMember* member2 = [roomMembers objectAtIndex:1];
// check if they are the dedicated users
if (
([member1.userId isEqualToString:self.mxSession.myUser.userId] || [member1.userId isEqualToString:roomMember.userId]) &&
([member2.userId isEqualToString:self.mxSession.myUser.userId] || [member2.userId isEqualToString:roomMember.userId])) {
return mxRoom.state.roomId;
}
}
}
}
return nil;
}
@end

View file

@ -22,10 +22,13 @@
// Room Member Table View Cell
@interface RoomMemberTableCell : UITableViewCell
{
//
CAShapeLayer* powerContainerLayer;
}
@property (strong, nonatomic) IBOutlet CustomImageView *pictureView;
@property (weak, nonatomic) IBOutlet UILabel *userLabel;
@property (weak, nonatomic) IBOutlet UIProgressView *userPowerLevel;
@property (weak, nonatomic) IBOutlet UILabel *lastActiveAgoLabel;
@property (weak, nonatomic) IBOutlet UIView *powerContainer;
- (void)setRoomMember:(MXRoomMember *)roomMember withRoom:(MXRoom *)room;
@end

View file

@ -19,11 +19,125 @@
@implementation RoomMemberTableCell
// returns the presence color
// nil if there is no valid one
- (UIColor*) getUserPresenceColor:(MXUser*) user
{
if (user) {
switch (user.presence) {
case MXPresenceOnline:
return [UIColor colorWithRed:0.2 green:0.9 blue:0.2 alpha:1.0];
case MXPresenceUnavailable:
return [UIColor colorWithRed:0.9 green:0.9 blue:0.0 alpha:1.0];
case MXPresenceOffline:
return [UIColor colorWithRed:0.9 green:0.2 blue:0.2 alpha:1.0];
case MXPresenceUnknown:
case MXPresenceFreeForChat:
case MXPresenceHidden:
default:
return nil;
}
}
return nil;
}
- (NSString*)getLastPresenceText:(MXUser*)user {
NSString* presenceText = nil;
// Prepare last active ago string
NSUInteger lastActiveAgoInSec = user.lastActiveAgo / 1000;
if (lastActiveAgoInSec < 60) {
presenceText = [NSString stringWithFormat:@"%lus", (unsigned long)lastActiveAgoInSec];
} else if (lastActiveAgoInSec < 3600) {
presenceText = [NSString stringWithFormat:@"%lum", (unsigned long)(lastActiveAgoInSec / 60)];
} else if (lastActiveAgoInSec < 86400) {
presenceText = [NSString stringWithFormat:@"%luh", (unsigned long)(lastActiveAgoInSec / 3600)];
} else {
presenceText = [NSString stringWithFormat:@"%lud", (unsigned long)(lastActiveAgoInSec / 86400)];
}
// Check presence
switch (user.presence) {
case MXPresenceOffline: {
presenceText = @"offline";
break;
}
case MXPresenceHidden:
case MXPresenceUnknown:
case MXPresenceFreeForChat: {
presenceText = nil;
break;
}
case MXPresenceOnline:
case MXPresenceUnavailable:
default:
break;
}
return presenceText;
}
- (void) setPowerContainerValue:(CGFloat)progress
{
// no power level -> hide the pie
if (0 == progress) {
self.powerContainer.hidden = YES;
return;
}
// display it
self.powerContainer.hidden = NO;
// defines the view settings
CGFloat radius = self.powerContainer.frame.size.width / 2;
// draw a rounded view
[self.powerContainer.layer setCornerRadius:radius];
// the default body color is gray
self.powerContainer.backgroundColor = [UIColor lightGrayColor];
// draw the pie
CALayer* layer = [self.powerContainer layer];
// remove any previous drawn layer
if (powerContainerLayer) {
[powerContainerLayer removeFromSuperlayer];
}
// create the red layer
powerContainerLayer = [CAShapeLayer layer];
[powerContainerLayer setZPosition:0];
[powerContainerLayer setStrokeColor:NULL];
// power level is drawn in red
powerContainerLayer.fillColor = [UIColor redColor].CGColor;
// build the path
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, radius, radius);
CGPathAddArc(path, NULL, radius, radius, radius, -M_PI / 2, (progress * 2 * M_PI) - (M_PI / 2), 0);
CGPathCloseSubpath(path);
[powerContainerLayer setPath:path];
CFRelease(path);
// add the sub layer
[layer addSublayer:powerContainerLayer];
}
- (void)setRoomMember:(MXRoomMember *)roomMember withRoom:(MXRoom *)room {
if (room && roomMember) {
// set the user info
self.userLabel.text = [room.state memberName:roomMember.userId];
// user
self.pictureView.placeholder = @"default-profile";
self.pictureView.imageURL = roomMember.avatarUrl;
// Round image view
[self.pictureView.layer setCornerRadius:self.pictureView.frame.size.width / 2];
self.pictureView.clipsToBounds = YES;
@ -38,20 +152,21 @@
view.alpha = 1;
}
}
// user info
CGFloat powerLevel = 0;
NSString* presenceText = nil;
UIColor* thumbnailBorderColor = nil;
// Customize banned and left (kicked) members
if (roomMember.membership == MXMembershipLeave || roomMember.membership == MXMembershipBan) {
self.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0];
self.userPowerLevel.hidden = YES;
self.lastActiveAgoLabel.backgroundColor = [UIColor lightGrayColor];
self.lastActiveAgoLabel.text = (roomMember.membership == MXMembershipLeave) ? @"left" : @"banned";
presenceText = (roomMember.membership == MXMembershipLeave) ? @"left" : @"banned";
} else {
self.backgroundColor = [UIColor whiteColor];
// Handle power level display
self.userPowerLevel.hidden = NO;
//self.userPowerLevel.hidden = NO;
MXRoomPowerLevels *roomPowerLevels = room.state.powerLevels;
int maxLevel = 0;
@ -66,68 +181,63 @@
if (userPowerLevel) {
userPowerLevelFloat = userPowerLevel;
}
self.userPowerLevel.progress = maxLevel ? userPowerLevelFloat / maxLevel : 1;
powerLevel = maxLevel ? userPowerLevelFloat / maxLevel : 1;
// get the user presence and his thumbnail border color
if (roomMember.membership == MXMembershipInvite) {
self.lastActiveAgoLabel.backgroundColor = [UIColor lightGrayColor];
self.lastActiveAgoLabel.text = @"invited";
thumbnailBorderColor = [UIColor lightGrayColor];
presenceText = @"invited";
} else {
// Get the user that corresponds to this member
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
MXUser *user = [mxHandler.mxSession userWithUserId:roomMember.userId];
// Prepare last active ago string
NSUInteger lastActiveAgoInSec = user.lastActiveAgo / 1000;
NSString *lastActive;
if (lastActiveAgoInSec < 60) {
lastActive = [NSString stringWithFormat:@"%lus ago", (unsigned long)lastActiveAgoInSec];
} else if (lastActiveAgoInSec < 3600) {
lastActive = [NSString stringWithFormat:@"%lum ago", (unsigned long)(lastActiveAgoInSec / 60)];
} else if (lastActiveAgoInSec < 86400) {
lastActive = [NSString stringWithFormat:@"%luh ago", (unsigned long)(lastActiveAgoInSec / 3600)];
} else {
lastActive = [NSString stringWithFormat:@"%lud ago", (unsigned long)(lastActiveAgoInSec / 86400)];
}
// Check presence
switch (user.presence) {
case MXPresenceUnknown: {
self.lastActiveAgoLabel.backgroundColor = [UIColor clearColor];
self.lastActiveAgoLabel.text = nil;//@"unknown";
break;
}
case MXPresenceOnline: {
self.lastActiveAgoLabel.backgroundColor = [UIColor colorWithRed:0.2 green:0.9 blue:0.2 alpha:1.0];
self.lastActiveAgoLabel.text = lastActive;
self.lastActiveAgoLabel.numberOfLines = 0;
break;
}
case MXPresenceUnavailable: {
self.lastActiveAgoLabel.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.0 alpha:1.0];
self.lastActiveAgoLabel.text = lastActive;
self.lastActiveAgoLabel.numberOfLines = 0;
break;
}
case MXPresenceOffline: {
self.lastActiveAgoLabel.backgroundColor = [UIColor colorWithRed:0.9 green:0.2 blue:0.2 alpha:1.0];
self.lastActiveAgoLabel.text = @"offline";
break;
}
case MXPresenceFreeForChat: {
self.lastActiveAgoLabel.backgroundColor = [UIColor clearColor];
self.lastActiveAgoLabel.text = nil;//@"free for chat";
break;
}
case MXPresenceHidden: {
self.lastActiveAgoLabel.backgroundColor = [UIColor clearColor];
self.lastActiveAgoLabel.text = nil;//@"hidden";
break;
}
default:
break;
// existing user ?
if (user) {
thumbnailBorderColor = [self getUserPresenceColor:user];
presenceText = [self getLastPresenceText:user];
}
}
}
// display the power level pie
[self setPowerContainerValue:powerLevel];
// if the thumbnail is defined
if (thumbnailBorderColor) {
self.pictureView.layer.borderWidth = 2;
self.pictureView.layer.borderColor = thumbnailBorderColor.CGColor;
} else {
// remove the border
// else it draws black border
self.pictureView.layer.borderWidth = 0;
}
// and the presence text (if any)
if (presenceText) {
NSString* extraText = [NSString stringWithFormat:@"(%@)", presenceText];
self.userLabel.text = [NSString stringWithFormat:@"%@ %@", self.userLabel.text, extraText];
NSRange range = [self.userLabel.text rangeOfString:extraText];
UIFont* font = self.userLabel.font;
// Create the attributes
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
font, NSFontAttributeName,
self.userLabel.textColor, NSForegroundColorAttributeName, nil];
NSDictionary *subAttrs = [NSDictionary dictionaryWithObjectsAndKeys:
font, NSFontAttributeName,
[UIColor lightGrayColor], NSForegroundColorAttributeName, nil];
// Create the attributed string (text + attributes)
NSMutableAttributedString *attributedText =[[NSMutableAttributedString alloc] initWithString:self.userLabel.text attributes:attrs];
[attributedText setAttributes:subAttrs range:range];
// Set it in our UILabel and we are done!
[self.userLabel setAttributedText:attributedText];
}
}
}
@end

View file

@ -16,6 +16,7 @@
#import <UIKit/UIKit.h>
#import "CustomImageView.h"
#import "RoomMessage.h"
// Room Message Table View Cell
@interface RoomMessageTableCell : UITableViewCell
@ -28,6 +29,9 @@
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewWidthConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachViewTopConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *dateTimeLabelContainerTopConstraint;
// reference to the linked message
@property (strong, nonatomic) RoomMessage *message;
@end
@interface IncomingMessageTableCell : RoomMessageTableCell

View file

@ -26,4 +26,12 @@
@implementation OutgoingMessageTableCell
- (void)layoutSubviews {
[super layoutSubviews];
// ensure that the text is still aligned to the left side of the screen
// even during animation while enlarging/reducing the viewcontroller (with UISplitViewController)
CGFloat leftInset = self.message.maxTextViewWidth - self.message.contentSize.width;
self.messageTextView.contentInset = UIEdgeInsetsMake(0, leftInset, 0, -leftInset);
}
@end

View file

@ -318,6 +318,29 @@
}
}
#pragma mark - scrollView delegate
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
// hide the keyboard if the user scrolls the public rooms list
if (!filteredPublicRooms) {
if ([self.roomNameTextField isFirstResponder]) {
[self.roomNameTextField resignFirstResponder];
[self.tableView becomeFirstResponder];
}
if ([self.roomAliasTextField isFirstResponder]) {
[self.roomNameTextField resignFirstResponder];
[self.tableView becomeFirstResponder];
}
if ([self.participantsTextField isFirstResponder]) {
[self.participantsTextField resignFirstResponder];
[self.tableView becomeFirstResponder];
}
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

View file

@ -21,6 +21,10 @@
#import "CustomAlert.h"
@interface LoginViewController ()
{
// reference to any opened alert view
CustomAlert *alert;
}
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewBottomConstraint;
@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
@ -90,6 +94,12 @@
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// close any opened alert
if (alert) {
[alert dismiss:NO];
alert = nil;
}
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
@ -211,8 +221,41 @@
_loginBtn.enabled = YES;
NSLog(@"Login failed: %@", error);
// translate the error code to a human message
NSString* message = error.localizedDescription;
NSDictionary* dict = error.userInfo;
// detect if it is a Matrix SDK issue
if (dict) {
NSString* localizedError = [dict valueForKey:@"error"];
NSString* errCode = [dict valueForKey:@"errcode"];
if (errCode) {
if ([errCode isEqualToString:@"M_FORBIDDEN"]) {
message = @"Invalid username/password";
} else if (localizedError .length > 0) {
message = localizedError;
} else if ([errCode isEqualToString:@"M_UNKNOWN_TOKEN"]) {
message = @"The access token specified was not recognised";
} else if ([errCode isEqualToString:@"M_BAD_JSON"]) {
message = @"Malformed JSON";
} else if ([errCode isEqualToString:@"M_NOT_JSON"]) {
message = @"Did not contain valid JSON";
} else if ([errCode isEqualToString:@"M_LIMIT_EXCEEDED"]) {
message = @"Too many requests have been sent";
} else if ([errCode isEqualToString:@"M_USER_IN_USE"]) {
message = @"This user name is already used";
} else if ([errCode isEqualToString:@"M_LOGIN_EMAIL_URL_NOT_YET"]) {
message = @"The email link which has not been clicked yet";
} else {
message = errCode;
}
}
}
//Alert user
CustomAlert *alert = [[CustomAlert alloc] initWithTitle:@"Login Failed" message:@"Invalid username/password" style:CustomAlertStyleAlert];
alert = [[CustomAlert alloc] initWithTitle:@"Login Failed" message:message style:CustomAlertStyleAlert];
[alert addActionWithTitle:@"Dismiss" style:CustomAlertActionStyleCancel handler:^(CustomAlert *alert) {}];
[alert showInViewController:self];
}];

View file

@ -647,7 +647,21 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
# pragma mark - Room members
- (void)updateRoomMembers {
members = [[self.mxRoom.state members] sortedArrayUsingComparator:^NSComparisonResult(MXRoomMember *member1, MXRoomMember *member2) {
NSArray* membersList = [self.mxRoom.state members];
if (![[AppSettings sharedSettings] displayLeftUsers]) {
NSMutableArray* filteredMembers = [[NSMutableArray alloc] init];
for (MXRoomMember* member in membersList) {
if (member.membership != MXMembershipLeave) {
[filteredMembers addObject:member];
}
}
membersList = filteredMembers;
}
members = [membersList sortedArrayUsingComparator:^NSComparisonResult(MXRoomMember *member1, MXRoomMember *member2) {
// Move banned and left members at the end of the list
if (member1.membership == MXMembershipLeave || member1.membership == MXMembershipBan) {
if (member2.membership != MXMembershipLeave && member2.membership != MXMembershipBan) {
@ -665,7 +679,7 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
} else if (member2.membership == MXMembershipInvite) {
return NSOrderedAscending;
}
if ([[AppSettings sharedSettings] sortMembersUsingLastSeenTime]) {
// Get the users that correspond to these members
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
@ -1188,6 +1202,7 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
}
// Restore initial settings
cell.message = message;
cell.attachmentView.imageURL = nil; // Cancel potential attachment loading
cell.attachmentView.hidden = YES;
cell.playIconView.hidden = YES;
@ -1417,13 +1432,15 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
MXRoomPowerLevels *powerLevels = [self.mxRoom.state powerLevels];
NSUInteger userPowerLevel = [powerLevels powerLevelOfUserWithUserID:mxHandler.userId];
NSUInteger memberPowerLevel = [powerLevels powerLevelOfUserWithUserID:roomMember.userId];
self.actionMenu = [[CustomAlert alloc] initWithTitle:@"Select an action:" message:nil style:CustomAlertStyleActionSheet];
// Consider membership of the selected member
switch (roomMember.membership) {
case MXMembershipInvite:
case MXMembershipJoin: {
// Check conditions to be able to kick someone
if (userPowerLevel >= [powerLevels kick] && userPowerLevel >= memberPowerLevel) {
self.actionMenu = [[CustomAlert alloc] initWithTitle:@"Select an action:" message:nil style:CustomAlertStyleActionSheet];
[self.actionMenu addActionWithTitle:@"Kick" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
if (weakSelf) {
weakSelf.actionMenu = nil;
@ -1441,9 +1458,6 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
}
// Check conditions to be able to ban someone
if (userPowerLevel >= [powerLevels ban] && userPowerLevel >= memberPowerLevel) {
if (!self.actionMenu) {
self.actionMenu = [[CustomAlert alloc] initWithTitle:@"Select an action:" message:nil style:CustomAlertStyleActionSheet];
}
[self.actionMenu addActionWithTitle:@"Ban" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
if (weakSelf) {
weakSelf.actionMenu = nil;
@ -1464,7 +1478,6 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
case MXMembershipLeave: {
// Check conditions to be able to invite someone
if (userPowerLevel >= [powerLevels invite]) {
self.actionMenu = [[CustomAlert alloc] initWithTitle:@"Select an action:" message:nil style:CustomAlertStyleActionSheet];
[self.actionMenu addActionWithTitle:@"Invite" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
if (weakSelf) {
weakSelf.actionMenu = nil;
@ -1481,9 +1494,6 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
}
// Check conditions to be able to ban someone
if (userPowerLevel >= [powerLevels ban] && userPowerLevel >= memberPowerLevel) {
if (!self.actionMenu) {
self.actionMenu = [[CustomAlert alloc] initWithTitle:@"Select an action:" message:nil style:CustomAlertStyleActionSheet];
}
[self.actionMenu addActionWithTitle:@"Ban" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
if (weakSelf) {
weakSelf.actionMenu = nil;
@ -1504,7 +1514,6 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
case MXMembershipBan: {
// Check conditions to be able to unban someone
if (userPowerLevel >= [powerLevels ban] && userPowerLevel >= memberPowerLevel) {
self.actionMenu = [[CustomAlert alloc] initWithTitle:@"Select an action:" message:nil style:CustomAlertStyleActionSheet];
[self.actionMenu addActionWithTitle:@"Unban" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
if (weakSelf) {
weakSelf.actionMenu = nil;
@ -1525,6 +1534,45 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
break;
}
}
// the current web interface always creates a new room
// uncoment this line opens any existing room with the same uers
__block NSString* startedRoomID = nil; // [mxHandler getRoomStartedWithMember:roomMember];
//, offer to chat with this user only
if (startedRoomID) {
[self.actionMenu addActionWithTitle:@"Open chat" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
// Open created room
[[AppDelegate theDelegate].masterTabBarController showRoom:startedRoomID];
}];
} else {
[self.actionMenu addActionWithTitle:@"Start chat" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
// Create new room
[mxHandler.mxRestClient createRoom:(roomMember.displayname) ? roomMember.displayname : roomMember.userId
visibility:kMXRoomVisibilityPrivate
roomAlias:nil
topic:nil
success:^(MXCreateRoomResponse *response) {
// add the user
[mxHandler.mxRestClient inviteUser:roomMember.userId toRoom:response.roomId success:^{
//NSLog(@"%@ has been invited (roomId: %@)", roomMember.userId, response.roomId);
} failure:^(NSError *error) {
NSLog(@"%@ invitation failed (roomId: %@): %@", roomMember.userId, response.roomId, error);
//Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
// Open created room
[[AppDelegate theDelegate].masterTabBarController showRoom:response.roomId];
} failure:^(NSError *error) {
NSLog(@"Create room failed: %@", error);
//Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
}];
}
}
// Notify user when his power is too weak
@ -2156,10 +2204,13 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
}
// Set power level
if (userId && powerLevel) {
// FIXME
NSLog(@"Set user power level (/op) is not supported yet (%@)", userId);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"/op is not supported yet" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
// Set user power level
[self.mxRoom setPowerLevelOfUserWithUserID:userId powerLevel:[powerLevel integerValue] success:^{
} failure:^(NSError *error) {
NSLog(@"Set user power (%@) failed: %@", userId, error);
//Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
} else {
// Display cmd usage in text input as placeholder
self.messageTextField.placeholder = @"Usage: /op <userId> <power level>";
@ -2167,10 +2218,12 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
} else if ([cmd isEqualToString:kCmdResetUserPowerLevel]) {
if (userId) {
// Reset user power level
// FIXME
NSLog(@"Reset user power level (/deop) is not supported yet (%@)", userId);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"/deop is not supported yet" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
[self.mxRoom setPowerLevelOfUserWithUserID:userId powerLevel:0 success:^{
} failure:^(NSError *error) {
NSLog(@"Reset user power (%@) failed: %@", userId, error);
//Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
} else {
// Display cmd usage in text input as placeholder
self.messageTextField.placeholder = @"Usage: /deop <userId>";

View file

@ -50,6 +50,7 @@ NSString* const kCommandsDescriptionText = @"The following commands are availabl
UISwitch *allEventsSwitch;
UISwitch *unsupportedMsgSwitch;
UISwitch *sortMembersSwitch;
UISwitch *displayLeftMembersSwitch;
}
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UIView *tableHeader;
@ -105,6 +106,7 @@ NSString* const kCommandsDescriptionText = @"The following commands are availabl
allEventsSwitch = nil;
unsupportedMsgSwitch = nil;
sortMembersSwitch = nil;
displayLeftMembersSwitch = nil;
[[MatrixHandler sharedHandler] removeObserver:self forKeyPath:@"isInitialSyncDone"];
}
@ -371,6 +373,8 @@ NSString* const kCommandsDescriptionText = @"The following commands are availabl
[AppSettings sharedSettings].hideUnsupportedMessages = unsupportedMsgSwitch.on;
} else if (sender == sortMembersSwitch) {
[AppSettings sharedSettings].sortMembersUsingLastSeenTime = sortMembersSwitch.on;
} else if (sender == displayLeftMembersSwitch) {
[AppSettings sharedSettings].displayLeftUsers = displayLeftMembersSwitch.on;
}
}
@ -404,7 +408,7 @@ NSString* const kCommandsDescriptionText = @"The following commands are availabl
}
return 1;
} else if (section == SETTINGS_SECTION_ROOMS_INDEX) {
return 3;
return 4;
} else if (section == SETTINGS_SECTION_CONFIGURATION_INDEX) {
return 1;
} else if (section == SETTINGS_SECTION_COMMANDS_INDEX) {
@ -488,10 +492,14 @@ NSString* const kCommandsDescriptionText = @"The following commands are availabl
roomsSettingCell.settingLabel.text = @"Hide unsupported messages";
roomsSettingCell.settingSwitch.on = [[AppSettings sharedSettings] hideUnsupportedMessages];
unsupportedMsgSwitch = roomsSettingCell.settingSwitch;
} else {
} else if (indexPath.row == 2) {
roomsSettingCell.settingLabel.text = @"Sort members by last seen time";
roomsSettingCell.settingSwitch.on = [[AppSettings sharedSettings] sortMembersUsingLastSeenTime];
sortMembersSwitch = roomsSettingCell.settingSwitch;
} else {
roomsSettingCell.settingLabel.text = @"Display left members";
roomsSettingCell.settingSwitch.on = [[AppSettings sharedSettings] displayLeftUsers];
displayLeftMembersSwitch = roomsSettingCell.settingSwitch;
}
cell = roomsSettingCell;
} else if (indexPath.section == SETTINGS_SECTION_CONFIGURATION_INDEX) {

View file

@ -18,5 +18,7 @@
<true/>
<key>sortMembersUsingLastSeenTime</key>
<true/>
<key>displayLeftUsers</key>
<false/>
</dict>
</plist>