2014-11-24 09:38:23 +00:00
/ *
Copyright 2014 OpenMarket Ltd
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : // www . apache . org / licenses / LICENSE -2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
# import "SettingsViewController.h"
# import "AppDelegate.h"
# import "AppSettings.h"
2014-12-12 13:18:34 +00:00
# import "APNSHandler.h"
2015-01-23 14:36:05 +00:00
# import "MatrixSDKHandler.h"
2014-11-24 09:38:23 +00:00
# import "MediaManager.h"
2015-01-27 16:24:55 +00:00
# import "MXC3PID.h"
2014-11-24 09:38:23 +00:00
# import "SettingsTableViewCell.h"
2015-01-23 17:45:13 +00:00
# define SETTINGS_SECTION _LINKED _EMAILS _INDEX 0
# define SETTINGS_SECTION _NOTIFICATIONS _INDEX 1
2015-01-26 17:06:13 +00:00
# define SETTINGS_SECTION _CONTACTS _INDEX 2
# define SETTINGS_SECTION _ROOMS _INDEX 3
# define SETTINGS_SECTION _CONFIGURATION _INDEX 4
# define SETTINGS_SECTION _COMMANDS _INDEX 5
# define SETTINGS_SECTION _COUNT 6
2014-11-24 09:38:23 +00:00
2014-12-19 09:02:09 +00:00
# define SETTINGS_SECTION _ROOMS _DISPLAY _ALL _EVENTS _INDEX 0
2015-01-28 17:39:23 +00:00
# define SETTINGS_SECTION _ROOMS _HIDE _REDACTED _INFO _INDEX 1
# define SETTINGS_SECTION _ROOMS _HIDE _UNSUPPORTED _EVENTS _INDEX 2
# define SETTINGS_SECTION _ROOMS _SORT _MEMBERS _INDEX 3
# define SETTINGS_SECTION _ROOMS _DISPLAY _LEFT _MEMBERS _INDEX 4
# define SETTINGS_SECTION _ROOMS _SET _CACHE _SIZE _INDEX 5
# define SETTINGS_SECTION _ROOMS _CLEAR _CACHE _INDEX 6
# define SETTINGS_SECTION _ROOMS _INDEX _COUNT 7
2014-12-19 09:02:09 +00:00
2015-01-14 13:22:07 +00:00
NSString * const kConfigurationFormatText = @ "matrixConsole version: %@\r\nSDK version: %@\r\n\r\nHome server: %@\r\nIdentity server: %@\r\nUser ID: %@\r\nAccess token: %@" ;
2014-11-24 09:38:23 +00:00
NSString * const kCommandsDescriptionText = @ "The following commands are available in the room chat:\r\n\r\n /nick <display_name>: change your display name\r\n /me <action>: send the action you are doing. /me will be replaced by your display name\r\n /join <room_alias>: join a room\r\n /kick <user_id> [<reason>]: kick the user\r\n /ban <user_id> [<reason>]: ban the user\r\n /unban <user_id>: unban the user\r\n /op <user_id> <power_level>: set user power level\r\n /deop <user_id>: reset user power level to the room default value" ;
@ interface SettingsViewController ( ) {
2015-01-26 15:51:34 +00:00
NSMutableArray * alertsArray ;
2015-01-23 17:45:13 +00:00
// Navigation Bar button
UIButton * logoutBtn ;
2014-11-24 09:38:23 +00:00
2015-01-23 17:45:13 +00:00
// User ' s profile
MediaLoader * imageLoader ;
2014-11-24 09:38:23 +00:00
NSString * currentDisplayName ;
NSString * currentPictureURL ;
2015-01-14 17:30:00 +00:00
NSString * currentPictureThumbURL ;
2014-11-24 09:38:23 +00:00
NSString * uploadedPictureURL ;
2015-01-26 15:51:34 +00:00
// Local changes
BOOL isAvatarUpdated ;
BOOL isSavingInProgress ;
// Listen user ' s profile changes
2014-12-11 13:52:04 +00:00
id userUpdateListener ;
2015-01-23 17:45:13 +00:00
// Linked emails
NSMutableArray * linkedEmails ;
2015-01-27 16:24:55 +00:00
MXC3PID * submittedEmail ;
SettingsCellWithTextFieldAndButton * submittedEmailCell ;
2015-01-27 09:25:36 +00:00
SettingsCellWithLabelTextFieldAndButton * emailTokenCell ;
// Dynamic rows in the Linked emails section
int submittedEmailRowIndex ;
int emailTokenRowIndex ;
2014-11-24 09:38:23 +00:00
2015-01-26 17:06:13 +00:00
// contacts
UISwitch * contactsSyncSwitch ;
2015-01-23 17:45:13 +00:00
// Notifications
2014-12-12 13:18:34 +00:00
UISwitch * apnsNotificationsSwitch ;
UISwitch * inAppNotificationsSwitch ;
2015-01-27 09:25:36 +00:00
SettingsCellWithLabelAndTextField * inAppNotificationsRulesCell ;
2015-01-23 17:45:13 +00:00
// Dynamic rows in the Notifications section
2015-01-27 09:25:36 +00:00
int enablePushNotifRowIndex ;
int enableInAppNotifRowIndex ;
int inAppNotifRulesRowIndex ;
2015-01-23 17:45:13 +00:00
// Rooms settings
2014-11-24 09:38:23 +00:00
UISwitch * allEventsSwitch ;
2015-01-28 17:39:23 +00:00
UISwitch * redactedInfoSwitch ;
UISwitch * unsupportedEventsSwitch ;
2014-11-24 09:38:23 +00:00
UISwitch * sortMembersSwitch ;
2014-12-17 13:40:39 +00:00
UISwitch * displayLeftMembersSwitch ;
2015-01-23 17:45:13 +00:00
SettingsCellWithLabelAndSlider * maxCacheSizeCell ;
2015-01-27 16:24:55 +00:00
// Configuration
SettingsCellWithTextView * configurationCell ;
// Commands
SettingsCellWithTextView * commandsCell ;
2014-11-24 09:38:23 +00:00
}
@ property ( strong , nonatomic ) IBOutlet UITableView * tableView ;
@ property ( weak , nonatomic ) IBOutlet UIView * tableHeader ;
2015-01-23 17:45:13 +00:00
@ property ( weak , nonatomic ) IBOutlet UIButton * userPictureButton ;
2014-11-24 09:38:23 +00:00
@ property ( weak , nonatomic ) IBOutlet UITextField * userDisplayName ;
2015-01-05 13:25:11 +00:00
@ property ( weak , nonatomic ) IBOutlet UIButton * saveUserInfoButton ;
@ property ( strong , nonatomic ) IBOutlet UIView * activityIndicatorBackgroundView ;
2014-11-24 09:38:23 +00:00
@ property ( strong , nonatomic ) IBOutlet UIActivityIndicatorView * activityIndicator ;
- ( IBAction ) onButtonPressed : ( id ) sender ;
@ end
@ implementation SettingsViewController
- ( void ) viewDidLoad {
[ super viewDidLoad ] ;
// Do any additional setup after loading the view , typically from a nib .
// Add logout button in nav bar
logoutBtn = [ UIButton buttonWithType : UIButtonTypeSystem ] ;
logoutBtn . frame = CGRectMake ( 0 , 0 , 60 , 44 ) ;
[ logoutBtn setTitle : @ "Logout" forState : UIControlStateNormal ] ;
[ logoutBtn setTitle : @ "Logout" forState : UIControlStateHighlighted ] ;
[ logoutBtn addTarget : self action : @ selector ( onButtonPressed : ) forControlEvents : UIControlEventTouchUpInside ] ;
self . navigationItem . rightBarButtonItem = [ [ UIBarButtonItem alloc ] initWithCustomView : logoutBtn ] ;
2014-12-16 07:47:48 +00:00
// keep the aspect ratio of the contact thumbnail
2014-12-16 07:49:19 +00:00
// scale it to fit the button frame
2015-01-23 17:45:13 +00:00
[ [ self . userPictureButton imageView ] setContentMode : UIViewContentModeScaleAspectFill ] ;
[ [ self . userPictureButton imageView ] setClipsToBounds : YES ] ;
2014-12-16 07:47:48 +00:00
2015-01-26 15:51:34 +00:00
alertsArray = [ NSMutableArray array ] ;
2015-01-23 14:36:05 +00:00
[ [ MatrixSDKHandler sharedHandler ] addObserver : self forKeyPath : @ "status" options : 0 context : nil ] ;
2015-01-05 13:25:11 +00:00
isAvatarUpdated = NO ;
2015-01-26 15:51:34 +00:00
isSavingInProgress = NO ;
2015-01-05 15:53:41 +00:00
2015-01-05 13:25:11 +00:00
_saveUserInfoButton . enabled = NO ;
_activityIndicatorBackgroundView . hidden = YES ;
2014-11-24 09:38:23 +00:00
}
- ( void ) didReceiveMemoryWarning {
[ super didReceiveMemoryWarning ] ;
// Dispose of any resources that can be recreated .
if ( imageLoader ) {
2015-01-08 20:23:49 +00:00
[ imageLoader cancel ] ;
2014-11-24 09:38:23 +00:00
imageLoader = nil ;
}
}
- ( void ) dealloc {
2014-12-11 13:52:04 +00:00
[ self reset ] ;
2015-01-26 15:51:34 +00:00
alertsArray = nil ;
2014-11-24 09:38:23 +00:00
logoutBtn = nil ;
2015-01-27 09:25:36 +00:00
2015-01-23 14:36:05 +00:00
[ [ MatrixSDKHandler sharedHandler ] removeObserver : self forKeyPath : @ "status" ] ;
2014-11-24 09:38:23 +00:00
}
- ( void ) viewWillAppear : ( BOOL ) animated {
[ super viewWillAppear : animated ] ;
2014-12-11 13:52:04 +00:00
// Refresh display
2015-01-26 15:51:34 +00:00
[ self startActivityIndicator ] ;
2014-12-11 13:52:04 +00:00
[ self configureView ] ;
2015-01-23 14:36:05 +00:00
[ [ MatrixSDKHandler sharedHandler ] addObserver : self forKeyPath : @ "isResumeDone" options : 0 context : nil ] ;
2014-12-12 13:18:34 +00:00
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( onAPNSHandlerHasBeenUpdated ) name : kAPNSHandlerHasBeenUpdated object : nil ] ;
2014-11-24 09:38:23 +00:00
}
- ( void ) viewWillDisappear : ( BOOL ) animated {
[ super viewWillDisappear : animated ] ;
2015-01-05 15:53:41 +00:00
2015-01-23 14:36:05 +00:00
[ [ MatrixSDKHandler sharedHandler ] removeObserver : self forKeyPath : @ "isResumeDone" ] ;
2014-12-12 13:18:34 +00:00
[ [ NSNotificationCenter defaultCenter ] removeObserver : self name : kAPNSHandlerHasBeenUpdated object : nil ] ;
2014-11-24 09:38:23 +00:00
}
2015-01-26 15:51:34 +00:00
- ( BOOL ) shouldLeave : ( blockSettings_onReadyToLeave ) handler {
// Check whether some local changes have not been saved
if ( _saveUserInfoButton . enabled ) {
2015-01-05 15:53:41 +00:00
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
2015-01-26 15:51:34 +00:00
MXCAlert * alert = [ [ MXCAlert alloc ] initWithTitle : nil message : @ "Changes will be discarded" style : MXCAlertStyleAlert ] ;
[ alertsArray addObject : alert ] ;
alert . cancelButtonIndex = [ alert addActionWithTitle : @ "Discard" style : MXCAlertActionStyleDefault handler : ^ ( MXCAlert * alert ) {
[ alertsArray removeObject : alert ] ;
// Discard changes
self . userDisplayName . text = currentDisplayName ;
[ self updateUserPicture : [ MatrixSDKHandler sharedHandler ] . mxSession . myUser . avatarUrl force : YES ] ;
// Ready to leave
if ( handler ) {
handler ( ) ;
}
2015-01-05 15:53:41 +00:00
} ] ;
2015-01-26 15:51:34 +00:00
[ alert addActionWithTitle : @ "Save" style : MXCAlertActionStyleDefault handler : ^ ( MXCAlert * alert ) {
[ alertsArray removeObject : alert ] ;
// Start saving
[ self saveUserInfo ] ;
// Ready to leave
if ( handler ) {
handler ( ) ;
}
2015-01-05 15:53:41 +00:00
} ] ;
2015-01-26 15:51:34 +00:00
[ alert showInViewController : self ] ;
2015-01-05 15:53:41 +00:00
} ) ;
2015-01-26 15:51:34 +00:00
return NO ;
2015-01-05 15:53:41 +00:00
}
2015-01-26 15:51:34 +00:00
return YES ;
2015-01-05 15:53:41 +00:00
}
2014-11-24 09:38:23 +00:00
# pragma mark - Internal methods
2014-12-12 13:18:34 +00:00
- ( void ) onAPNSHandlerHasBeenUpdated {
2015-01-29 17:06:37 +00:00
apnsNotificationsSwitch . enabled = YES ;
2014-12-12 13:18:34 +00:00
// Force table reload to update notifications section
apnsNotificationsSwitch = nil ;
[ self . tableView reloadData ] ;
}
2014-11-24 09:38:23 +00:00
- ( void ) reset {
2015-01-08 17:20:34 +00:00
// Remove observers
[ [ NSNotificationCenter defaultCenter ] removeObserver : self ] ;
2014-11-24 09:38:23 +00:00
// Cancel picture loader ( if any )
if ( imageLoader ) {
2015-01-08 20:23:49 +00:00
[ imageLoader cancel ] ;
2014-11-24 09:38:23 +00:00
imageLoader = nil ;
}
2015-01-26 15:51:34 +00:00
// Cancel potential alerts
for ( MXCAlert * alert in alertsArray ) {
2014-11-24 09:38:23 +00:00
[ alert dismiss : NO ] ;
}
2014-12-11 13:52:04 +00:00
// Remove listener
if ( userUpdateListener ) {
2015-01-23 14:36:05 +00:00
[ [ MatrixSDKHandler sharedHandler ] . mxSession . myUser removeListener : userUpdateListener ] ;
2014-12-11 13:52:04 +00:00
userUpdateListener = nil ;
}
2014-11-24 09:38:23 +00:00
currentPictureURL = nil ;
2015-01-14 17:30:00 +00:00
currentPictureThumbURL = nil ;
2014-11-24 09:38:23 +00:00
uploadedPictureURL = nil ;
2015-01-26 15:51:34 +00:00
isAvatarUpdated = NO ;
2015-01-23 17:45:13 +00:00
[ self updateUserPictureButton : [ UIImage imageNamed : @ "default-profile" ] ] ;
2014-11-24 09:38:23 +00:00
currentDisplayName = nil ;
self . userDisplayName . text = nil ;
2015-01-23 17:45:13 +00:00
2015-01-26 15:51:34 +00:00
_saveUserInfoButton . enabled = NO ;
2015-01-23 17:45:13 +00:00
linkedEmails = nil ;
2015-01-27 16:24:55 +00:00
submittedEmail = nil ;
submittedEmailCell = nil ;
emailTokenCell = nil ;
contactsSyncSwitch = nil ;
apnsNotificationsSwitch = nil ;
inAppNotificationsSwitch = nil ;
inAppNotificationsRulesCell = nil ;
allEventsSwitch = nil ;
2015-01-28 17:39:23 +00:00
unsupportedEventsSwitch = nil ;
2015-01-27 16:24:55 +00:00
sortMembersSwitch = nil ;
displayLeftMembersSwitch = nil ;
maxCacheSizeCell = nil ;
configurationCell = nil ;
commandsCell = nil ;
2014-11-24 09:38:23 +00:00
}
2015-01-26 15:51:34 +00:00
- ( void ) startActivityIndicator {
2015-01-05 13:25:11 +00:00
if ( _activityIndicatorBackgroundView . hidden ) {
_activityIndicatorBackgroundView . hidden = NO ;
[ _activityIndicator startAnimating ] ;
}
2015-01-26 15:51:34 +00:00
_userPictureButton . enabled = NO ;
_userDisplayName . enabled = NO ;
2015-01-05 13:25:11 +00:00
_saveUserInfoButton . enabled = NO ;
}
2015-01-26 15:51:34 +00:00
- ( void ) stopActivityIndicator {
2015-01-05 13:25:11 +00:00
if ( ! _activityIndicatorBackgroundView . hidden ) {
_activityIndicatorBackgroundView . hidden = YES ;
[ _activityIndicator stopAnimating ] ;
}
2015-01-26 15:51:34 +00:00
_userPictureButton . enabled = YES ;
_userDisplayName . enabled = YES ;
[ self updateSaveUserInfoButtonStatus ] ;
2015-01-05 13:25:11 +00:00
}
2014-12-11 13:52:04 +00:00
- ( void ) configureView {
2015-01-26 15:51:34 +00:00
// Ignore any refresh when saving is in progress
if ( isSavingInProgress ) {
2015-01-05 15:53:41 +00:00
return ;
}
2015-01-23 14:36:05 +00:00
MatrixSDKHandler * mxHandler = [ MatrixSDKHandler sharedHandler ] ;
2014-12-11 13:52:04 +00:00
2014-11-24 09:38:23 +00:00
// Disable user ' s interactions
2015-01-23 17:45:13 +00:00
_userPictureButton . enabled = NO ;
2014-11-24 09:38:23 +00:00
_userDisplayName . enabled = NO ;
2015-01-23 14:36:05 +00:00
if ( mxHandler . status = = MatrixSDKHandlerStatusServerSyncDone ) {
2014-12-11 13:52:04 +00:00
if ( ! userUpdateListener ) {
// Set current user ' s information and add observers
2015-01-26 15:51:34 +00:00
[ self updateUserPicture : mxHandler . mxSession . myUser . avatarUrl force : YES ] ;
2014-12-11 13:52:04 +00:00
currentDisplayName = mxHandler . mxSession . myUser . displayname ;
self . userDisplayName . text = currentDisplayName ;
2014-11-24 09:38:23 +00:00
2015-01-26 15:51:34 +00:00
[ self stopActivityIndicator ] ;
2015-01-05 13:25:11 +00:00
2014-12-11 13:52:04 +00:00
// Register listener to update user ' s information
userUpdateListener = [ mxHandler . mxSession . myUser listenToUserUpdate : ^ ( MXEvent * event ) {
// Update displayName
if ( ! [ currentDisplayName isEqualToString : mxHandler . mxSession . myUser . displayname ] ) {
currentDisplayName = mxHandler . mxSession . myUser . displayname ;
self . userDisplayName . text = mxHandler . mxSession . myUser . displayname ;
}
// Update user ' s avatar
2015-01-26 15:51:34 +00:00
[ self updateUserPicture : mxHandler . mxSession . myUser . avatarUrl force : NO ] ;
// Update button management
[ self updateSaveUserInfoButtonStatus ] ;
2015-01-05 13:25:11 +00:00
2014-12-11 13:52:04 +00:00
// TODO display user ' s presence
} ] ;
}
2015-01-23 14:36:05 +00:00
} else if ( mxHandler . status = = MatrixSDKHandlerStatusStoreDataReady ) {
2015-01-05 14:11:40 +00:00
// Set local user ' s information ( the data may not be up - to - date )
2015-01-26 15:51:34 +00:00
[ self updateUserPicture : mxHandler . mxSession . myUser . avatarUrl force : NO ] ;
2015-01-05 14:11:40 +00:00
currentDisplayName = mxHandler . mxSession . myUser . displayname ;
self . userDisplayName . text = currentDisplayName ;
2015-01-23 14:36:05 +00:00
} else if ( mxHandler . status = = MatrixSDKHandlerStatusLoggedOut ) {
2014-12-11 13:52:04 +00:00
[ self reset ] ;
}
2014-11-24 09:38:23 +00:00
2014-12-11 13:52:04 +00:00
if ( [ mxHandler isResumeDone ] ) {
2015-01-26 15:51:34 +00:00
[ self stopActivityIndicator ] ;
2014-12-11 13:52:04 +00:00
}
2015-01-26 15:51:34 +00:00
// Restore user ' s interactions
_userPictureButton . enabled = YES ;
_userDisplayName . enabled = YES ;
2014-11-24 09:38:23 +00:00
[ self . tableView reloadData ] ;
}
2015-01-26 15:51:34 +00:00
- ( void ) saveUserInfo {
MatrixSDKHandler * mxHandler = [ MatrixSDKHandler sharedHandler ] ;
[ self startActivityIndicator ] ;
isSavingInProgress = YES ;
2014-11-24 09:38:23 +00:00
// Check whether the display name has been changed
NSString * displayname = self . userDisplayName . text ;
2014-12-16 23:59:57 +00:00
if ( ( displayname . length || currentDisplayName . length ) && [ displayname isEqualToString : currentDisplayName ] = = NO ) {
2014-11-24 09:38:23 +00:00
// Save display name
2014-12-11 13:52:04 +00:00
[ mxHandler . mxSession . myUser setDisplayName : displayname success : ^ {
2015-01-26 15:51:34 +00:00
// Update the current displayname
2014-11-24 09:38:23 +00:00
currentDisplayName = displayname ;
2015-01-26 15:51:34 +00:00
// Go to the next change saving step
[ self saveUserInfo ] ;
2014-11-24 09:38:23 +00:00
} failure : ^ ( NSError * error ) {
NSLog ( @ "Set displayName failed: %@" , error ) ;
// Alert user
NSString * title = [ error . userInfo valueForKey : NSLocalizedFailureReasonErrorKey ] ;
if ( ! title ) {
title = @ "Display name change failed" ;
}
NSString * msg = [ error . userInfo valueForKey : NSLocalizedDescriptionKey ] ;
2015-01-23 12:46:27 +00:00
MXCAlert * alert = [ [ MXCAlert alloc ] initWithTitle : title message : msg style : MXCAlertStyleAlert ] ;
2015-01-26 15:51:34 +00:00
[ alertsArray addObject : alert ] ;
alert . cancelButtonIndex = [ alert addActionWithTitle : @ "Abort" style : MXCAlertActionStyleDefault handler : ^ ( MXCAlert * alert ) {
[ alertsArray removeObject : alert ] ;
// Discard changes
2014-11-24 09:38:23 +00:00
self . userDisplayName . text = currentDisplayName ;
2015-01-26 15:51:34 +00:00
[ self updateUserPicture : [ MatrixSDKHandler sharedHandler ] . mxSession . myUser . avatarUrl force : YES ] ;
// Loop to end saving
[ self saveUserInfo ] ;
2014-11-24 09:38:23 +00:00
} ] ;
2015-01-23 12:46:27 +00:00
[ alert addActionWithTitle : @ "Retry" style : MXCAlertActionStyleDefault handler : ^ ( MXCAlert * alert ) {
2015-01-26 15:51:34 +00:00
[ alertsArray removeObject : alert ] ;
// Loop to retry saving
[ self saveUserInfo ] ;
2014-11-24 09:38:23 +00:00
} ] ;
[ alert showInViewController : self ] ;
} ] ;
2015-01-26 15:51:34 +00:00
return ;
2014-11-24 09:38:23 +00:00
}
2015-01-26 15:51:34 +00:00
// Check whether avatar has been updated
if ( isAvatarUpdated ) {
if ( uploadedPictureURL = = nil ) {
// Upload picture
MediaLoader * uploader = [ [ MediaLoader alloc ] initWithUploadId : nil initialRange : 0 andRange : 1.0 folder : kMediaManagerThumbnailFolder ] ;
[ uploader uploadData : UIImageJPEGRepresentation ( [ self . userPictureButton imageForState : UIControlStateNormal ] , 0.5 ) mimeType : @ "image/jpeg" success : ^ ( NSString * url ) {
// Store uploaded picture url and trigger picture saving
uploadedPictureURL = url ;
[ self saveUserInfo ] ;
} failure : ^ ( NSError * error ) {
NSLog ( @ "Upload image failed: %@" , error ) ;
[ self handleErrorDuringPictureSaving : error ] ;
} ] ;
} else {
[ mxHandler . mxSession . myUser setAvatarUrl : uploadedPictureURL
success : ^ {
// uploadedPictureURL becomes the user ' s picture
[ self updateUserPicture : uploadedPictureURL force : YES ] ;
// Loop to end saving
[ self saveUserInfo ] ;
} failure : ^ ( NSError * error ) {
NSLog ( @ "Set avatar url failed: %@" , error ) ;
[ self handleErrorDuringPictureSaving : error ] ;
} ] ;
}
return ;
}
// Backup is complete
isSavingInProgress = NO ;
// Stop animation ( except if the app is resuming )
if ( [ [ MatrixSDKHandler sharedHandler ] isResumeDone ] ) {
[ self stopActivityIndicator ] ;
2014-11-24 09:38:23 +00:00
}
}
- ( void ) handleErrorDuringPictureSaving : ( NSError * ) error {
NSString * title = [ error . userInfo valueForKey : NSLocalizedFailureReasonErrorKey ] ;
if ( ! title ) {
title = @ "Picture change failed" ;
}
NSString * msg = [ error . userInfo valueForKey : NSLocalizedDescriptionKey ] ;
2015-01-23 12:46:27 +00:00
MXCAlert * alert = [ [ MXCAlert alloc ] initWithTitle : title message : msg style : MXCAlertStyleAlert ] ;
2015-01-26 15:51:34 +00:00
[ alertsArray addObject : alert ] ;
alert . cancelButtonIndex = [ alert addActionWithTitle : @ "Abort" style : MXCAlertActionStyleDefault handler : ^ ( MXCAlert * alert ) {
[ alertsArray removeObject : alert ] ;
2014-11-24 09:38:23 +00:00
// Remove change
2015-01-26 15:51:34 +00:00
self . userDisplayName . text = currentDisplayName ;
[ self updateUserPicture : [ MatrixSDKHandler sharedHandler ] . mxSession . myUser . avatarUrl force : YES ] ;
// Loop to end saving
[ self saveUserInfo ] ;
2014-11-24 09:38:23 +00:00
} ] ;
2015-01-23 12:46:27 +00:00
[ alert addActionWithTitle : @ "Retry" style : MXCAlertActionStyleDefault handler : ^ ( MXCAlert * alert ) {
2015-01-26 15:51:34 +00:00
[ alertsArray removeObject : alert ] ;
// Loop to retry saving
[ self saveUserInfo ] ;
2014-11-24 09:38:23 +00:00
} ] ;
[ alert showInViewController : self ] ;
}
2015-01-26 15:51:34 +00:00
- ( void ) updateUserPicture : ( NSString * ) avatar_url force : ( BOOL ) force {
if ( force || currentPictureURL = = nil || [ currentPictureURL isEqualToString : avatar_url ] = = NO ) {
2015-01-08 17:20:34 +00:00
// Remove any pending observers
[ [ NSNotificationCenter defaultCenter ] removeObserver : self ] ;
2014-11-24 09:38:23 +00:00
// Cancel previous loader ( if any )
if ( imageLoader ) {
2015-01-08 20:23:49 +00:00
[ imageLoader cancel ] ;
2014-11-24 09:38:23 +00:00
imageLoader = nil ;
}
2015-01-26 15:51:34 +00:00
// Cancel any local change
isAvatarUpdated = NO ;
uploadedPictureURL = nil ;
2014-11-24 09:38:23 +00:00
currentPictureURL = [ avatar_url isEqual : [ NSNull null ] ] ? nil : avatar_url ;
if ( currentPictureURL ) {
2015-01-14 17:30:00 +00:00
// Suppose this url is a matrix content uri , we use SDK to get the well adapted thumbnail from server
2015-01-23 14:36:05 +00:00
MatrixSDKHandler * mxHandler = [ MatrixSDKHandler sharedHandler ] ;
2015-01-23 17:45:13 +00:00
currentPictureThumbURL = [ mxHandler thumbnailURLForContent : currentPictureURL inViewSize : self . userPictureButton . frame . size withMethod : MXThumbnailingMethodCrop ] ;
2015-01-14 17:30:00 +00:00
2015-01-08 17:20:34 +00:00
// Check whether the image download is in progress
2015-01-19 13:33:57 +00:00
id loader = [ MediaManager existingDownloaderForURL : currentPictureThumbURL inFolder : kMediaManagerThumbnailFolder ] ;
2015-01-08 17:20:34 +00:00
if ( loader ) {
// Add observers
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( onMediaDownloadEnd : ) name : kMediaDownloadDidFinishNotification object : nil ] ;
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( onMediaDownloadEnd : ) name : kMediaDownloadDidFailNotification object : nil ] ;
} else {
// Retrieve the image from cache
2015-01-19 13:33:57 +00:00
UIImage * image = [ MediaManager loadCachePictureForURL : currentPictureThumbURL inFolder : kMediaManagerThumbnailFolder ] ;
2015-01-08 17:20:34 +00:00
if ( image ) {
2015-01-23 17:45:13 +00:00
[ self updateUserPictureButton : image ] ;
2015-01-08 17:20:34 +00:00
} else {
// Cancel potential download in progress
if ( imageLoader ) {
2015-01-08 20:23:49 +00:00
[ imageLoader cancel ] ;
2015-01-08 17:20:34 +00:00
}
// Add observers
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( onMediaDownloadEnd : ) name : kMediaDownloadDidFinishNotification object : nil ] ;
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( onMediaDownloadEnd : ) name : kMediaDownloadDidFailNotification object : nil ] ;
2015-01-19 13:33:57 +00:00
imageLoader = [ MediaManager downloadMediaFromURL : currentPictureThumbURL withType : @ "image/jpeg" inFolder : kMediaManagerThumbnailFolder ] ;
2015-01-08 17:20:34 +00:00
}
}
2014-11-24 09:38:23 +00:00
} else {
// Set placeholder
2015-01-23 17:45:13 +00:00
[ self updateUserPictureButton : [ UIImage imageNamed : @ "default-profile" ] ] ;
}
}
}
- ( void ) updateUserPictureButton : ( UIImage * ) image {
[ self . userPictureButton setImage : image forState : UIControlStateNormal ] ;
[ self . userPictureButton setImage : image forState : UIControlStateHighlighted ] ;
[ self . userPictureButton setImage : image forState : UIControlStateDisabled ] ;
}
2015-01-26 15:51:34 +00:00
- ( void ) updateSaveUserInfoButtonStatus {
// Check whether display name has been changed
2015-01-23 17:45:13 +00:00
NSString * displayname = self . userDisplayName . text ;
2015-01-26 15:51:34 +00:00
BOOL isDisplayNameUpdated = ( ( displayname . length || currentDisplayName . length ) && [ displayname isEqualToString : currentDisplayName ] = = NO ) ;
2015-01-23 17:45:13 +00:00
_saveUserInfoButton . enabled = isDisplayNameUpdated || isAvatarUpdated ;
}
// remove trailing spaces
- ( NSString * ) removeUselessSpaceChars : ( NSString * ) text {
NSMutableString * cleanedText = [ text mutableCopy ] ;
while ( [ cleanedText hasPrefix : @ " " ] ) {
cleanedText = [ [ cleanedText substringFromIndex : 1 ] mutableCopy ] ;
}
while ( [ cleanedText hasSuffix : @ " " ] ) {
cleanedText = [ [ cleanedText substringToIndex : cleanedText . length -1 ] mutableCopy ] ;
}
return cleanedText ;
}
// split the words list provided by the user
// check if they are valid , not duplicated
- ( void ) manageWordsList {
2015-01-27 09:25:36 +00:00
NSArray * words = [ inAppNotificationsRulesCell . settingTextField . text componentsSeparatedByString : @ "," ] ;
2015-01-23 17:45:13 +00:00
NSMutableArray * fiteredWords = [ [ NSMutableArray alloc ] init ] ;
MatrixSDKHandler * mxHandler = [ MatrixSDKHandler sharedHandler ] ;
// theses both items are implicitly checked
NSString * displayname = nil ;
if ( mxHandler . mxSession . myUser . displayname . length ) {
displayname = mxHandler . mxSession . myUser . displayname ;
}
NSString * userID = nil ;
if ( mxHandler . localPartFromUserId . length ) {
userID = mxHandler . localPartFromUserId ;
}
// checked word by word
for ( NSString * word in words ) {
NSString * cleanWord = [ self removeUselessSpaceChars : word ] ;
// if they are valid ( not null , not implicit and does not already added
if ( ( cleanWord . length > 0 ) && ! [ cleanWord isEqualToString : displayname ] && ! [ cleanWord isEqualToString : userID ] && ( [ fiteredWords indexOfObject : cleanWord ] = = NSNotFound ) ) {
[ fiteredWords addObject : cleanWord ] ;
2014-11-24 09:38:23 +00:00
}
}
2015-01-23 17:45:13 +00:00
[ [ AppSettings sharedSettings ] setSpecificWordsToAlertOn : fiteredWords ] ;
[ self refreshWordsList ] ;
}
- ( void ) refreshWordsList {
NSMutableString * wordsList = [ [ NSMutableString alloc ] init ] ;
NSArray * patterns = [ AppSettings sharedSettings ] . specificWordsToAlertOn ;
2015-01-27 09:25:36 +00:00
for ( NSString * string in patterns ) {
2015-01-23 17:45:13 +00:00
[ wordsList appendFormat : @ "%@," , string ] ;
}
if ( wordsList . length > 0 ) {
2015-01-27 09:25:36 +00:00
inAppNotificationsRulesCell . settingTextField . text = [ wordsList substringToIndex : wordsList . length - 1 ] ;
2015-01-23 17:45:13 +00:00
}
else {
2015-01-27 09:25:36 +00:00
inAppNotificationsRulesCell . settingTextField . text = nil ;
2015-01-23 17:45:13 +00:00
}
2014-11-24 09:38:23 +00:00
}
2015-01-08 17:20:34 +00:00
- ( void ) onMediaDownloadEnd : ( NSNotification * ) notif {
// sanity check
if ( [ notif . object isKindOfClass : [ NSString class ] ] ) {
NSString * url = notif . object ;
2015-01-14 17:30:00 +00:00
if ( [ url isEqualToString : currentPictureThumbURL ] ) {
2015-01-08 17:20:34 +00:00
// update the image
2015-01-19 13:33:57 +00:00
UIImage * image = [ MediaManager loadCachePictureForURL : currentPictureThumbURL inFolder : kMediaManagerThumbnailFolder ] ;
2015-01-08 17:20:34 +00:00
if ( image = = nil ) {
image = [ UIImage imageNamed : @ "default-profile" ] ;
}
2015-01-23 17:45:13 +00:00
[ self updateUserPictureButton : image ] ;
2015-01-08 17:20:34 +00:00
// remove the observers
[ [ NSNotificationCenter defaultCenter ] removeObserver : self ] ;
imageLoader = nil ;
if ( [ notif . name isEqualToString : kMediaDownloadDidFailNotification ] ) {
// Reset picture URL in order to try next time
currentPictureURL = nil ;
}
}
}
}
2014-11-24 09:38:23 +00:00
# pragma mark - KVO
- ( void ) observeValueForKeyPath : ( NSString * ) keyPath ofObject : ( id ) object change : ( NSDictionary * ) change context : ( void * ) context {
2015-01-05 14:11:40 +00:00
if ( [ @ "status" isEqualToString : keyPath ] ) {
2014-12-11 13:52:04 +00:00
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ self configureView ] ;
} ) ;
} else if ( [ @ "isResumeDone" isEqualToString : keyPath ] ) {
2015-01-26 15:51:34 +00:00
if ( [ [ MatrixSDKHandler sharedHandler ] isResumeDone ] && ! isSavingInProgress ) {
[ self stopActivityIndicator ] ;
2014-12-11 13:52:04 +00:00
} else {
2015-01-26 15:51:34 +00:00
[ self startActivityIndicator ] ;
2014-11-24 09:38:23 +00:00
}
}
}
# pragma mark - Actions
- ( IBAction ) onButtonPressed : ( id ) sender {
[ self dismissKeyboard ] ;
2015-01-05 13:25:11 +00:00
if ( sender = = _saveUserInfoButton ) {
2015-01-26 15:51:34 +00:00
[ self saveUserInfo ] ;
2015-01-23 17:45:13 +00:00
} else if ( sender = = _userPictureButton ) {
2014-11-24 09:38:23 +00:00
// Open picture gallery
UIImagePickerController * mediaPicker = [ [ UIImagePickerController alloc ] init ] ;
mediaPicker . delegate = self ;
mediaPicker . sourceType = UIImagePickerControllerSourceTypePhotoLibrary ;
mediaPicker . allowsEditing = NO ;
[ [ AppDelegate theDelegate ] . masterTabBarController presentMediaPicker : mediaPicker ] ;
} else if ( sender = = logoutBtn ) {
[ [ AppDelegate theDelegate ] logout ] ;
2015-01-27 16:24:55 +00:00
} else if ( sender = = submittedEmailCell . settingButton ) {
if ( ! submittedEmail || ! [ submittedEmail . address isEqualToString : submittedEmailCell . settingTextField . text ] ) {
submittedEmail = [ [ MXC3PID alloc ] initWithMedium : kMX3PIDMediumEmail andAddress : submittedEmailCell . settingTextField . text ] ;
}
submittedEmailCell . settingButton . enabled = NO ;
[ submittedEmail requestValidationToken : ^ {
// Reset email field
submittedEmailCell . settingTextField . text = nil ;
[ self . tableView reloadData ] ;
} failure : ^ ( NSError * error ) {
NSLog ( @ "Request email token failed: %@" , error ) ;
// Alert user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
submittedEmailCell . settingButton . enabled = YES ;
} ] ;
} else if ( sender = = emailTokenCell . settingButton ) {
emailTokenCell . settingButton . enabled = NO ;
[ submittedEmail validateWithToken : emailTokenCell . settingTextField . text success : ^ ( BOOL success ) {
if ( success ) {
// The email has been "Authenticated"
// Link the email with user ' s account
MatrixSDKHandler * mxHandler = [ MatrixSDKHandler sharedHandler ] ;
[ submittedEmail bindWithUserId : mxHandler . userId success : ^ {
// Add new linked email
if ( ! linkedEmails ) {
linkedEmails = [ NSMutableArray array ] ;
}
[ linkedEmails addObject : submittedEmail . address ] ;
// Release pending email and refresh table to remove related cell
submittedEmail = nil ;
[ self . tableView reloadData ] ;
} failure : ^ ( NSError * error ) {
NSLog ( @ "Link email failed: %@" , error ) ;
// Alert user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
// Release the pending email ( even if it is Authenticated )
submittedEmail = nil ;
[ self . tableView reloadData ] ;
} ] ;
} else {
NSLog ( @ "Failed to link email" ) ;
MXCAlert * alert = [ [ MXCAlert alloc ] initWithTitle : nil message : @ "Failed to link email" style : MXCAlertStyleAlert ] ;
[ alertsArray addObject : alert ] ;
alert . cancelButtonIndex = [ alert addActionWithTitle : @ "OK" style : MXCAlertActionStyleDefault handler : ^ ( MXCAlert * alert ) {
[ alertsArray removeObject : alert ] ;
} ] ;
[ alert showInViewController : self ] ;
// Reset wrong token
emailTokenCell . settingTextField . text = nil ;
}
} failure : ^ ( NSError * error ) {
NSLog ( @ "Submitted email token failed: %@" , error ) ;
// Alert user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
emailTokenCell . settingButton . enabled = YES ;
} ] ;
2014-12-12 13:18:34 +00:00
} else if ( sender = = apnsNotificationsSwitch ) {
[ APNSHandler sharedHandler ] . isActive = apnsNotificationsSwitch . on ;
2015-01-29 17:06:37 +00:00
apnsNotificationsSwitch . enabled = NO ;
2014-12-12 13:18:34 +00:00
} else if ( sender = = inAppNotificationsSwitch ) {
[ AppSettings sharedSettings ] . enableInAppNotifications = inAppNotificationsSwitch . on ;
2015-01-09 14:58:15 +00:00
[ self . tableView reloadData ] ;
2014-11-24 09:38:23 +00:00
} else if ( sender = = allEventsSwitch ) {
[ AppSettings sharedSettings ] . displayAllEvents = allEventsSwitch . on ;
2015-01-28 17:39:23 +00:00
} else if ( sender = = redactedInfoSwitch ) {
[ AppSettings sharedSettings ] . hideRedactedInformation = redactedInfoSwitch . on ;
} else if ( sender = = unsupportedEventsSwitch ) {
[ AppSettings sharedSettings ] . hideUnsupportedEvents = unsupportedEventsSwitch . on ;
2014-11-24 09:38:23 +00:00
} else if ( sender = = sortMembersSwitch ) {
[ AppSettings sharedSettings ] . sortMembersUsingLastSeenTime = sortMembersSwitch . on ;
2014-12-17 13:40:39 +00:00
} else if ( sender = = displayLeftMembersSwitch ) {
[ AppSettings sharedSettings ] . displayLeftUsers = displayLeftMembersSwitch . on ;
2015-01-26 17:06:13 +00:00
} else if ( sender = = contactsSyncSwitch ) {
[ AppSettings sharedSettings ] . syncLocalContacts = contactsSyncSwitch . on ;
2014-11-24 09:38:23 +00:00
}
}
2015-01-19 07:58:45 +00:00
- ( IBAction ) onSliderValueChange : ( id ) sender {
if ( sender = = maxCacheSizeCell . settingSlider ) {
2015-01-23 14:36:05 +00:00
MatrixSDKHandler * mxHandler = [ MatrixSDKHandler sharedHandler ] ;
2015-01-21 14:08:29 +00:00
UISlider * slider = maxCacheSizeCell . settingSlider ;
// check if the upper bounds have been updated
if ( slider . maximumValue ! = mxHandler . maxAllowedCachesSize ) {
slider . maximumValue = mxHandler . maxAllowedCachesSize ;
}
// check if the value does not exceed the bounds
if ( slider . value < mxHandler . minCachesSize ) {
slider . value = mxHandler . minCachesSize ;
}
2015-01-23 14:36:05 +00:00
[ [ MatrixSDKHandler sharedHandler ] setCurrentMaxCachesSize : slider . value ] ;
2015-01-21 14:08:29 +00:00
maxCacheSizeCell . settingLabel . text = [ NSString stringWithFormat : @ "Maximum cache size (%@)" , [ NSByteCountFormatter stringFromByteCount : mxHandler . currentMaxCachesSize countStyle : NSByteCountFormatterCountStyleFile ] ] ;
2015-01-19 07:58:45 +00:00
}
}
2014-11-24 09:38:23 +00:00
# pragma mark - keyboard
2014-12-16 23:59:57 +00:00
- ( void ) dismissKeyboard {
2015-01-09 14:58:15 +00:00
if ( [ _userDisplayName isFirstResponder ] ) {
// Hide the keyboard
[ _userDisplayName resignFirstResponder ] ;
2015-01-26 15:51:34 +00:00
[ self updateSaveUserInfoButtonStatus ] ;
2015-01-27 09:25:36 +00:00
} else if ( inAppNotificationsRulesCell && [ inAppNotificationsRulesCell . settingTextField isFirstResponder ] ) {
2015-01-09 14:58:15 +00:00
[ self manageWordsList ] ;
2015-01-27 09:25:36 +00:00
[ inAppNotificationsRulesCell . settingTextField resignFirstResponder ] ;
2015-01-27 16:24:55 +00:00
} else if ( [ submittedEmailCell . settingTextField isFirstResponder ] ) {
[ submittedEmailCell . settingTextField resignFirstResponder ] ;
} else if ( [ emailTokenCell . settingTextField isFirstResponder ] ) {
[ emailTokenCell . settingTextField resignFirstResponder ] ;
2015-01-09 14:58:15 +00:00
}
2014-11-24 09:38:23 +00:00
}
# pragma mark - UITextField delegate
2015-01-05 13:25:11 +00:00
- ( BOOL ) textFieldShouldReturn : ( UITextField * ) textField {
2015-01-23 17:45:13 +00:00
// "Done" key has been pressed
[ self dismissKeyboard ] ;
2014-11-24 09:38:23 +00:00
return YES ;
}
2015-01-05 13:25:11 +00:00
- ( IBAction ) textFieldDidChange : ( id ) sender {
if ( sender = = _userDisplayName ) {
2015-01-26 15:51:34 +00:00
[ self updateSaveUserInfoButtonStatus ] ;
2015-01-27 16:24:55 +00:00
} else if ( sender = = submittedEmailCell . settingTextField ) {
submittedEmailCell . settingButton . enabled = ( submittedEmailCell . settingTextField . text . length ! = 0 ) ;
} else if ( sender = = emailTokenCell . settingTextField ) {
emailTokenCell . settingButton . enabled = ( emailTokenCell . settingTextField . text . length ! = 0 ) ;
2015-01-05 13:25:11 +00:00
}
}
2015-01-23 17:45:13 +00:00
# pragma mark - UITableView data source
2014-11-24 09:38:23 +00:00
- ( NSInteger ) numberOfSectionsInTableView : ( UITableView * ) tableView {
2015-01-23 17:45:13 +00:00
return SETTINGS_SECTION _COUNT ;
2014-11-24 09:38:23 +00:00
}
- ( NSInteger ) tableView : ( UITableView * ) tableView numberOfRowsInSection : ( NSInteger ) section {
2015-01-27 16:24:55 +00:00
NSInteger count = 0 ;
2015-01-23 17:45:13 +00:00
if ( section = = SETTINGS_SECTION _LINKED _EMAILS _INDEX ) {
2015-01-27 16:24:55 +00:00
submittedEmailRowIndex = emailTokenRowIndex = -1 ;
2015-01-09 14:58:15 +00:00
2015-01-27 16:24:55 +00:00
count = linkedEmails . count ;
submittedEmailRowIndex = count + + ;
if ( submittedEmail && submittedEmail . validationState >= MXC3PIDAuthStateTokenReceived ) {
emailTokenRowIndex = count + + ;
} else {
emailTokenCell = nil ;
}
} else if ( section = = SETTINGS_SECTION _NOTIFICATIONS _INDEX ) {
2015-01-27 09:25:36 +00:00
enableInAppNotifRowIndex = inAppNotifRulesRowIndex = enablePushNotifRowIndex = -1 ;
2015-01-09 14:58:15 +00:00
2015-01-27 09:25:36 +00:00
if ( [ APNSHandler sharedHandler ] . isAvailable ) {
enablePushNotifRowIndex = count + + ;
2015-01-09 14:58:15 +00:00
}
2015-01-27 09:25:36 +00:00
enableInAppNotifRowIndex = count + + ;
if ( [ [ AppSettings sharedSettings ] enableInAppNotifications ] ) {
inAppNotifRulesRowIndex = count + + ;
2014-12-12 13:18:34 +00:00
}
2015-01-26 17:06:13 +00:00
} else if ( section = = SETTINGS_SECTION _CONTACTS _INDEX ) {
2015-01-27 16:24:55 +00:00
count = 1 ;
2014-11-24 09:38:23 +00:00
} else if ( section = = SETTINGS_SECTION _ROOMS _INDEX ) {
2015-01-27 16:24:55 +00:00
count = SETTINGS_SECTION _ROOMS _INDEX _COUNT ;
2014-11-24 09:38:23 +00:00
} else if ( section = = SETTINGS_SECTION _CONFIGURATION _INDEX ) {
2015-01-27 16:24:55 +00:00
count = 1 ;
2014-11-24 09:38:23 +00:00
} else if ( section = = SETTINGS_SECTION _COMMANDS _INDEX ) {
2015-01-27 16:24:55 +00:00
count = 1 ;
2014-11-24 09:38:23 +00:00
}
2015-01-27 16:24:55 +00:00
return count ;
2014-11-24 09:38:23 +00:00
}
- ( CGFloat ) tableView : ( UITableView * ) tableView heightForRowAtIndexPath : ( NSIndexPath * ) indexPath {
2015-01-23 17:45:13 +00:00
if ( indexPath . section = = SETTINGS_SECTION _LINKED _EMAILS _INDEX ) {
2015-01-27 16:24:55 +00:00
if ( indexPath . row = = emailTokenRowIndex ) {
return 70 ;
}
2015-01-23 17:45:13 +00:00
return 44 ;
} else if ( indexPath . section = = SETTINGS_SECTION _NOTIFICATIONS _INDEX ) {
2015-01-27 09:25:36 +00:00
if ( indexPath . row = = inAppNotifRulesRowIndex ) {
2015-01-09 14:58:15 +00:00
return 110 ;
}
2014-11-24 09:38:23 +00:00
return 44 ;
2015-01-26 17:06:13 +00:00
} else if ( indexPath . section = = SETTINGS_SECTION _CONTACTS _INDEX ) {
return 44 ;
2014-11-24 09:38:23 +00:00
} else if ( indexPath . section = = SETTINGS_SECTION _ROOMS _INDEX ) {
2015-01-19 07:58:45 +00:00
if ( indexPath . row = = SETTINGS_SECTION _ROOMS _SET _CACHE _SIZE _INDEX ) {
2015-01-21 14:08:29 +00:00
return 88 ;
2015-01-19 07:58:45 +00:00
}
2014-11-24 09:38:23 +00:00
return 44 ;
} else if ( indexPath . section = = SETTINGS_SECTION _CONFIGURATION _INDEX ) {
UITextView * textView = [ [ UITextView alloc ] initWithFrame : CGRectMake ( 0 , 0 , tableView . frame . size . width , MAXFLOAT ) ] ;
textView . font = [ UIFont systemFontOfSize : 14 ] ;
2015-01-14 13:22:07 +00:00
NSString * appVersion = [ [ NSBundle mainBundle ] objectForInfoDictionaryKey : @ "CFBundleShortVersionString" ] ;
2015-01-23 14:36:05 +00:00
MatrixSDKHandler * mxHandler = [ MatrixSDKHandler sharedHandler ] ;
2015-01-14 13:22:07 +00:00
textView . text = [ NSString stringWithFormat : kConfigurationFormatText , appVersion , MatrixSDKVersion , mxHandler . homeServerURL , nil , mxHandler . userId , mxHandler . accessToken ] ;
2014-11-24 09:38:23 +00:00
CGSize contentSize = [ textView sizeThatFits : textView . frame . size ] ;
return contentSize . height + 1 ;
} else if ( indexPath . section = = SETTINGS_SECTION _COMMANDS _INDEX ) {
UITextView * textView = [ [ UITextView alloc ] initWithFrame : CGRectMake ( 0 , 0 , tableView . frame . size . width , MAXFLOAT ) ] ;
textView . font = [ UIFont systemFontOfSize : 14 ] ;
textView . text = kCommandsDescriptionText ;
CGSize contentSize = [ textView sizeThatFits : textView . frame . size ] ;
return contentSize . height + 1 ;
}
return 44 ;
}
2014-12-12 13:18:34 +00:00
- ( CGFloat ) tableView : ( UITableView * ) tableView heightForHeaderInSection : ( NSInteger ) section {
2014-11-24 09:38:23 +00:00
return 30 ;
}
2014-12-12 13:18:34 +00:00
- ( CGFloat ) tableView : ( UITableView * ) tableView heightForFooterInSection : ( NSInteger ) section {
2014-11-24 09:38:23 +00:00
return 1 ;
}
2014-12-12 13:18:34 +00:00
- ( UIView * ) tableView : ( UITableView * ) tableView viewForHeaderInSection : ( NSInteger ) section {
2014-11-24 09:38:23 +00:00
UILabel * sectionHeader = [ [ UILabel alloc ] initWithFrame : [ tableView rectForHeaderInSection : section ] ] ;
sectionHeader . font = [ UIFont boldSystemFontOfSize : 16 ] ;
sectionHeader . backgroundColor = [ UIColor colorWithRed : 0.9 green : 0.9 blue : 0.9 alpha : 1.0 ] ;
2015-01-23 17:45:13 +00:00
if ( section = = SETTINGS_SECTION _LINKED _EMAILS _INDEX ) {
sectionHeader . text = @ " Linked emails" ;
} else if ( section = = SETTINGS_SECTION _NOTIFICATIONS _INDEX ) {
2014-11-24 09:38:23 +00:00
sectionHeader . text = @ " Notifications" ;
2015-01-26 17:06:13 +00:00
} else if ( section = = SETTINGS_SECTION _CONTACTS _INDEX ) {
sectionHeader . text = @ " Contacts" ;
2014-11-24 09:38:23 +00:00
} else if ( section = = SETTINGS_SECTION _ROOMS _INDEX ) {
sectionHeader . text = @ " Rooms" ;
} else if ( section = = SETTINGS_SECTION _CONFIGURATION _INDEX ) {
sectionHeader . text = @ " Configuration" ;
} else if ( section = = SETTINGS_SECTION _COMMANDS _INDEX ) {
sectionHeader . text = @ " Commands" ;
} else {
sectionHeader = nil ;
}
return sectionHeader ;
}
- ( UITableViewCell * ) tableView : ( UITableView * ) tableView cellForRowAtIndexPath : ( NSIndexPath * ) indexPath {
2015-01-27 08:28:49 +00:00
MatrixSDKHandler * mxHandler = [ MatrixSDKHandler sharedHandler ] ;
2014-12-19 09:02:09 +00:00
UITableViewCell * cell = nil ;
2014-11-24 09:38:23 +00:00
2015-01-23 17:45:13 +00:00
if ( indexPath . section = = SETTINGS_SECTION _LINKED _EMAILS _INDEX ) {
2015-01-27 16:24:55 +00:00
if ( indexPath . row < linkedEmails . count ) {
cell = [ [ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier : @ "LinkedEmailCell" ] ;
if ( ! cell ) {
cell = [ [ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier : @ "LinkedEmailCell" ] ;
}
cell . selectionStyle = UITableViewCellSelectionStyleNone ;
cell . textLabel . text = [ linkedEmails objectAtIndex : indexPath . row ] ;
} else if ( indexPath . row = = submittedEmailRowIndex ) {
// Report the current email value ( if any )
NSString * currentEmail = nil ;
if ( submittedEmailCell ) {
currentEmail = submittedEmailCell . settingTextField . text ;
}
submittedEmailCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithTextFieldAndButton" forIndexPath : indexPath ] ;
submittedEmailCell . settingTextField . text = currentEmail ;
submittedEmailCell . settingButton . enabled = ( currentEmail . length ! = 0 ) ;
[ submittedEmailCell . settingButton setTitle : @ "Link Email" forState : UIControlStateNormal ] ;
[ submittedEmailCell . settingButton setTitle : @ "Link Email" forState : UIControlStateHighlighted ] ;
if ( emailTokenRowIndex ! = -1 ) {
// Hide the separator
CGSize screenSize = [ [ UIScreen mainScreen ] bounds ] . size ;
CGFloat rightInset = ( screenSize . width < screenSize . height ) ? screenSize . height : screenSize . width ;
submittedEmailCell . separatorInset = UIEdgeInsetsMake ( 0. f , 0. f , 0. f , rightInset ) ;
}
cell = submittedEmailCell ;
} else if ( indexPath . row = = emailTokenRowIndex ) {
// Report the current token value ( if any )
NSString * currentToken = nil ;
if ( emailTokenCell ) {
currentToken = emailTokenCell . settingTextField . text ;
}
emailTokenCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithLabelTextFieldAndButton" forIndexPath : indexPath ] ;
emailTokenCell . settingLabel . text = [ NSString stringWithFormat : @ "Enter validation token for %@:" , submittedEmail . address ] ;
emailTokenCell . settingTextField . text = currentToken ;
emailTokenCell . settingButton . enabled = ( currentToken . length ! = 0 ) ;
[ emailTokenCell . settingButton setTitle : @ "Submit code" forState : UIControlStateNormal ] ;
[ emailTokenCell . settingButton setTitle : @ "Submit code" forState : UIControlStateHighlighted ] ;
cell = emailTokenCell ;
2015-01-23 17:45:13 +00:00
}
} else if ( indexPath . section = = SETTINGS_SECTION _NOTIFICATIONS _INDEX ) {
2015-01-27 09:25:36 +00:00
if ( indexPath . row = = inAppNotifRulesRowIndex ) {
2015-01-27 16:24:55 +00:00
// Report the current value ( if any )
2015-01-27 09:25:36 +00:00
NSString * currentRules = nil ;
BOOL isFirstResponder = NO ;
if ( inAppNotificationsRulesCell ) {
currentRules = inAppNotificationsRulesCell . settingTextField . text ;
isFirstResponder = inAppNotificationsRulesCell . settingTextField . isFirstResponder ;
}
inAppNotificationsRulesCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithLabelAndTextField" forIndexPath : indexPath ] ;
inAppNotificationsRulesCell . settingLabel . text = @ "If blank, all messages will trigger an alert.Your username & display name always alerts." ;
inAppNotificationsRulesCell . settingTextField . text = currentRules ;
2015-01-09 14:58:15 +00:00
2015-01-27 09:25:36 +00:00
// If the current rules are empty , reload rules from settings except if the textField was the first responder
if ( ! currentRules . length && ! isFirstResponder ) {
2015-01-09 14:58:15 +00:00
[ self refreshWordsList ] ;
}
2015-01-27 09:25:36 +00:00
cell = inAppNotificationsRulesCell ;
2015-01-23 17:45:13 +00:00
} else {
SettingsCellWithSwitch * notificationsCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithSwitch" forIndexPath : indexPath ] ;
2015-01-27 09:25:36 +00:00
if ( indexPath . row = = enableInAppNotifRowIndex ) {
2015-01-09 14:58:15 +00:00
notificationsCell . settingLabel . text = @ "Enable In-App notifications" ;
notificationsCell . settingSwitch . on = [ [ AppSettings sharedSettings ] enableInAppNotifications ] ;
inAppNotificationsSwitch = notificationsCell . settingSwitch ;
} else / * SETTINGS_SECTION _NOTIFICATIONS _PUSH _NOTIFICATION _INDEX * / {
notificationsCell . settingLabel . text = @ "Enable push notifications" ;
notificationsCell . settingSwitch . on = [ [ APNSHandler sharedHandler ] isActive ] ;
apnsNotificationsSwitch = notificationsCell . settingSwitch ;
}
cell = notificationsCell ;
2014-12-12 13:18:34 +00:00
}
2015-01-26 17:06:13 +00:00
} else if ( indexPath . section = = SETTINGS_SECTION _CONTACTS _INDEX ) {
SettingsCellWithSwitch * contactsCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithSwitch" forIndexPath : indexPath ] ;
contactsCell . settingLabel . text = @ "Sync local contacts" ;
contactsCell . settingSwitch . on = [ [ AppSettings sharedSettings ] syncLocalContacts ] ;
contactsSyncSwitch = contactsCell . settingSwitch ;
cell = contactsCell ;
2014-11-24 09:38:23 +00:00
} else if ( indexPath . section = = SETTINGS_SECTION _ROOMS _INDEX ) {
2014-12-19 09:02:09 +00:00
if ( indexPath . row = = SETTINGS_SECTION _ROOMS _CLEAR _CACHE _INDEX ) {
cell = [ [ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier : @ "ClearCacheCell" ] ;
if ( ! cell ) {
cell = [ [ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier : @ "ClearCacheCell" ] ;
}
2015-01-27 08:28:49 +00:00
cell . textLabel . text = [ NSString stringWithFormat : @ "Clear cache (%@)" , [ NSByteCountFormatter stringFromByteCount : mxHandler . cachesSize countStyle : NSByteCountFormatterCountStyleFile ] ] ;
2014-12-19 09:02:09 +00:00
cell . textLabel . textAlignment = NSTextAlignmentCenter ;
cell . textLabel . textColor = [ AppDelegate theDelegate ] . masterTabBarController . tabBar . tintColor ;
2015-01-19 07:58:45 +00:00
} else if ( indexPath . row = = SETTINGS_SECTION _ROOMS _SET _CACHE _SIZE _INDEX ) {
2015-01-27 16:24:55 +00:00
maxCacheSizeCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithLabelAndSilder" forIndexPath : indexPath ] ;
2015-01-21 14:08:29 +00:00
maxCacheSizeCell . settingSlider . minimumValue = 0 ;
2015-01-27 08:28:49 +00:00
maxCacheSizeCell . settingSlider . maximumValue = mxHandler . maxAllowedCachesSize ;
maxCacheSizeCell . settingSlider . value = mxHandler . currentMaxCachesSize ;
2015-01-19 07:58:45 +00:00
2015-01-21 14:08:29 +00:00
[ self onSliderValueChange : maxCacheSizeCell . settingSlider ] ;
2015-01-27 16:24:55 +00:00
cell = maxCacheSizeCell ;
2014-12-17 13:40:39 +00:00
} else {
2015-01-23 17:45:13 +00:00
SettingsCellWithSwitch * roomsSettingCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithSwitch" forIndexPath : indexPath ] ;
2014-12-19 09:02:09 +00:00
if ( indexPath . row = = SETTINGS_SECTION _ROOMS _DISPLAY _ALL _EVENTS _INDEX ) {
roomsSettingCell . settingLabel . text = @ "Display all events" ;
roomsSettingCell . settingSwitch . on = [ [ AppSettings sharedSettings ] displayAllEvents ] ;
allEventsSwitch = roomsSettingCell . settingSwitch ;
2015-01-28 17:39:23 +00:00
} else if ( indexPath . row = = SETTINGS_SECTION _ROOMS _HIDE _REDACTED _INFO _INDEX ) {
roomsSettingCell . settingLabel . text = @ "Hide redacted information" ;
roomsSettingCell . settingSwitch . on = [ [ AppSettings sharedSettings ] hideRedactedInformation ] ;
redactedInfoSwitch = roomsSettingCell . settingSwitch ;
} else if ( indexPath . row = = SETTINGS_SECTION _ROOMS _HIDE _UNSUPPORTED _EVENTS _INDEX ) {
roomsSettingCell . settingLabel . text = @ "Hide unsupported events" ;
roomsSettingCell . settingSwitch . on = [ [ AppSettings sharedSettings ] hideUnsupportedEvents ] ;
unsupportedEventsSwitch = roomsSettingCell . settingSwitch ;
2014-12-19 09:02:09 +00:00
} else if ( indexPath . row = = SETTINGS_SECTION _ROOMS _SORT _MEMBERS _INDEX ) {
roomsSettingCell . settingLabel . text = @ "Sort members by last seen time" ;
roomsSettingCell . settingSwitch . on = [ [ AppSettings sharedSettings ] sortMembersUsingLastSeenTime ] ;
sortMembersSwitch = roomsSettingCell . settingSwitch ;
} else if ( indexPath . row = = SETTINGS_SECTION _ROOMS _DISPLAY _LEFT _MEMBERS _INDEX ) {
roomsSettingCell . settingLabel . text = @ "Display left members" ;
roomsSettingCell . settingSwitch . on = [ [ AppSettings sharedSettings ] displayLeftUsers ] ;
displayLeftMembersSwitch = roomsSettingCell . settingSwitch ;
}
cell = roomsSettingCell ;
2014-11-24 09:38:23 +00:00
}
} else if ( indexPath . section = = SETTINGS_SECTION _CONFIGURATION _INDEX ) {
2015-01-27 16:24:55 +00:00
if ( ! configurationCell ) {
configurationCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithTextView" forIndexPath : indexPath ] ;
NSString * appVersion = [ [ NSBundle mainBundle ] objectForInfoDictionaryKey : @ "CFBundleShortVersionString" ] ;
configurationCell . settingTextView . text = [ NSString stringWithFormat : kConfigurationFormatText , appVersion , MatrixSDKVersion , mxHandler . homeServerURL , nil , mxHandler . userId , mxHandler . accessToken ] ;
}
cell = configurationCell ;
2014-11-24 09:38:23 +00:00
} else if ( indexPath . section = = SETTINGS_SECTION _COMMANDS _INDEX ) {
2015-01-27 16:24:55 +00:00
if ( ! commandsCell ) {
commandsCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithTextView" forIndexPath : indexPath ] ;
commandsCell . settingTextView . text = kCommandsDescriptionText ;
}
2014-11-24 09:38:23 +00:00
cell = commandsCell ;
}
return cell ;
}
2015-01-23 17:45:13 +00:00
# pragma mark - UITableView delegate
- ( void ) tableView : ( UITableView * ) aTableView didSelectRowAtIndexPath : ( NSIndexPath * ) indexPath {
if ( self . tableView = = aTableView ) {
// tap on clear application cache
if ( ( indexPath . section = = SETTINGS_SECTION _ROOMS _INDEX ) && ( indexPath . row = = SETTINGS_SECTION _ROOMS _CLEAR _CACHE _INDEX ) ) {
// clear caches
[ [ MatrixSDKHandler sharedHandler ] forceInitialSync : YES ] ;
}
[ aTableView deselectRowAtIndexPath : indexPath animated : YES ] ;
}
}
2014-11-24 09:38:23 +00:00
# pragma mark - UIImagePickerControllerDelegate
- ( void ) imagePickerController : ( UIImagePickerController * ) picker didFinishPickingMediaWithInfo : ( NSDictionary * ) info {
UIImage * selectedImage = [ info objectForKey : UIImagePickerControllerOriginalImage ] ;
if ( selectedImage ) {
2015-01-23 17:45:13 +00:00
[ self updateUserPictureButton : selectedImage ] ;
2015-01-05 13:25:11 +00:00
isAvatarUpdated = YES ;
_saveUserInfoButton . enabled = YES ;
2014-11-24 09:38:23 +00:00
}
[ self dismissMediaPicker ] ;
}
- ( void ) imagePickerControllerDidCancel : ( UIImagePickerController * ) picker {
[ self dismissMediaPicker ] ;
}
- ( void ) dismissMediaPicker {
[ [ AppDelegate theDelegate ] . masterTabBarController dismissMediaPicker ] ;
}
@ end