2014-10-02 15:02:47 +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 .
* /
2014-10-03 17:26:39 +00:00
# import "SettingsViewController.h"
2014-10-02 15:02:47 +00:00
2014-10-08 16:55:26 +00:00
# import "AppDelegate.h"
2014-10-29 16:48:11 +00:00
# import "AppSettings.h"
2014-10-18 02:03:07 +00:00
# import "MatrixHandler.h"
# import "MediaManager.h"
2014-10-08 16:55:26 +00:00
2014-10-29 16:48:11 +00:00
# import "SettingsTableViewCell.h"
# define SETTINGS_SECTION _NOTIFICATIONS _INDEX 0
2014-11-05 11:57:24 +00:00
# define SETTINGS_SECTION _ROOMS _INDEX 1
2014-10-29 16:48:11 +00:00
# define SETTINGS_SECTION _CONFIGURATION _INDEX 2
# define SETTINGS_SECTION _COMMANDS _INDEX 3
NSString * const kConfigurationFormatText = @ "Home server: %@\r\nIdentity server: %@\r\nUser ID: %@\r\nAccess token: %@" ;
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" ;
2014-10-18 02:03:07 +00:00
@ interface SettingsViewController ( ) {
2014-10-24 10:06:35 +00:00
id imageLoader ;
2014-10-18 02:03:07 +00:00
NSString * currentDisplayName ;
NSString * currentPictureURL ;
2014-10-31 17:54:32 +00:00
BOOL shouldSavePicture ;
2014-10-29 16:48:11 +00:00
UIButton * logoutBtn ;
UISwitch * notificationsSwitch ;
UISwitch * allEventsSwitch ;
2014-11-05 11:57:24 +00:00
UISwitch * sortMembersSwitch ;
2014-10-31 17:54:32 +00:00
UIImagePickerController * imagePicker ;
2014-10-18 02:03:07 +00:00
}
2014-10-08 16:55:26 +00:00
@ property ( strong , nonatomic ) IBOutlet UITableView * tableView ;
@ property ( weak , nonatomic ) IBOutlet UIView * tableHeader ;
@ property ( weak , nonatomic ) IBOutlet UIButton * userPicture ;
@ property ( weak , nonatomic ) IBOutlet UITextField * userDisplayName ;
@ property ( weak , nonatomic ) IBOutlet UIButton * saveBtn ;
2014-10-31 17:54:32 +00:00
@ property ( strong , nonatomic ) IBOutlet UIActivityIndicatorView * activityIndicator ;
2014-10-08 16:55:26 +00:00
- ( IBAction ) onButtonPressed : ( id ) sender ;
2014-10-02 15:02:47 +00:00
2014-10-03 17:26:39 +00:00
@ end
2014-10-02 15:02:47 +00:00
2014-10-03 17:26:39 +00:00
@ implementation SettingsViewController
2014-10-02 15:02:47 +00:00
2014-10-03 17:26:39 +00:00
- ( void ) viewDidLoad {
[ super viewDidLoad ] ;
// Do any additional setup after loading the view , typically from a nib .
2014-10-24 10:06:35 +00:00
2014-10-29 16:48:11 +00:00
// 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-10-24 10:06:35 +00:00
[ self reset ] ;
2014-10-03 17:26:39 +00:00
}
2014-10-02 15:02:47 +00:00
2014-10-03 17:26:39 +00:00
- ( void ) didReceiveMemoryWarning {
[ super didReceiveMemoryWarning ] ;
// Dispose of any resources that can be recreated .
2014-10-24 10:06:35 +00:00
if ( imageLoader ) {
[ MediaManager cancel : imageLoader ] ;
imageLoader = nil ;
}
}
- ( void ) dealloc {
// Cancel picture loader ( if any )
if ( imageLoader ) {
[ MediaManager cancel : imageLoader ] ;
imageLoader = nil ;
}
2014-10-29 16:48:11 +00:00
logoutBtn = nil ;
notificationsSwitch = nil ;
allEventsSwitch = nil ;
2014-11-05 11:57:24 +00:00
sortMembersSwitch = nil ;
2014-10-03 17:26:39 +00:00
}
2014-10-02 15:02:47 +00:00
2014-10-18 02:03:07 +00:00
- ( void ) viewWillAppear : ( BOOL ) animated {
[ super viewWillAppear : animated ] ;
2014-10-31 17:54:32 +00:00
// Ignore viewWillAppear if it is related to the mediaPicker use
if ( imagePicker = = nil ) {
// Update User information
MatrixHandler * mxHandler = [ MatrixHandler sharedHandler ] ;
// Handle user ' s display name
currentDisplayName = mxHandler . userDisplayName ;
self . userDisplayName . text = mxHandler . userDisplayName ;
[ [ MatrixHandler sharedHandler ] addObserver : self forKeyPath : @ "userDisplayName" options : 0 context : nil ] ;
2014-11-05 14:52:21 +00:00
[ mxHandler . mxRestClient displayName : mxHandler . mxRestClient . credentials . userId success : ^ ( NSString * displayname ) {
2014-10-31 17:54:32 +00:00
mxHandler . userDisplayName = displayname ;
} failure : ^ ( NSError * error ) {
NSLog ( @ "Get displayName failed: %@" , error ) ;
// Alert user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
} ] ;
// Handle user ' s picture url
[ self updateUserPicture : mxHandler . userPictureURL ] ;
[ [ MatrixHandler sharedHandler ] addObserver : self forKeyPath : @ "userPictureURL" options : 0 context : nil ] ;
2014-11-05 14:52:21 +00:00
[ mxHandler . mxRestClient avatarUrl : mxHandler . mxRestClient . credentials . userId success : ^ ( NSString * avatar_url ) {
2014-10-31 17:54:32 +00:00
mxHandler . userPictureURL = avatar_url ;
} failure : ^ ( NSError * error ) {
NSLog ( @ "Get picture url failed: %@" , error ) ;
// Alert user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
} ] ;
// Refresh settings
[ self . tableView reloadData ] ;
}
2014-10-18 02:03:07 +00:00
}
2014-10-30 09:54:57 +00:00
- ( void ) viewWillDisappear : ( BOOL ) animated {
[ super viewWillDisappear : animated ] ;
2014-10-31 17:54:32 +00:00
// Ignore viewWillDisappear if it is related to the mediaPicker use
if ( imagePicker = = nil ) {
[ [ MatrixHandler sharedHandler ] removeObserver : self forKeyPath : @ "userDisplayName" ] ;
[ [ MatrixHandler sharedHandler ] removeObserver : self forKeyPath : @ "userPictureURL" ] ;
shouldSavePicture = NO ;
}
2014-10-30 09:54:57 +00:00
}
# pragma mark - Internal methods
2014-10-08 16:55:26 +00:00
2014-10-31 17:54:32 +00:00
- ( void ) save {
MatrixHandler * mxHandler = [ MatrixHandler sharedHandler ] ;
// Start saving
[ _activityIndicator startAnimating ] ;
_saveBtn . enabled = NO ;
_saveBtn . alpha = 0.5 ;
// Check whether the display name has been changed
NSString * displayname = self . userDisplayName . text ;
if ( [ displayname isEqualToString : currentDisplayName ] = = NO ) {
// Save display name
2014-11-05 14:52:21 +00:00
[ mxHandler . mxRestClient setDisplayName : displayname success : ^ {
2014-10-31 17:54:32 +00:00
currentDisplayName = displayname ;
// Loop to save other changes
[ self save ] ;
} failure : ^ ( NSError * error ) {
// Stop saving
[ _activityIndicator stopAnimating ] ;
_saveBtn . enabled = YES ;
_saveBtn . alpha = 1 ;
NSLog ( @ "Set displayName failed: %@" , error ) ;
// Alert user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
} ] ;
// Wait for the end of this request before pursuing the saving
return ;
}
// Check whether the picture has been changed
if ( shouldSavePicture ) {
2014-11-05 14:52:21 +00:00
[ mxHandler . mxRestClient uploadContent : UIImageJPEGRepresentation ( [ self . userPicture imageForState : UIControlStateNormal ] , 0.5 )
2014-10-31 17:54:32 +00:00
mimeType : @ "image/jpeg"
timeout : 30
success : ^ ( NSString * url ) {
2014-11-05 14:52:21 +00:00
[ mxHandler . mxRestClient setAvatarUrl : url
2014-10-31 17:54:32 +00:00
success : ^ {
shouldSavePicture = NO ;
[ MatrixHandler sharedHandler ] . userPictureURL = url ;
// Loop to save other changes
[ self save ] ;
} failure : ^ ( NSError * error ) {
// Stop saving
[ _activityIndicator stopAnimating ] ;
_saveBtn . enabled = YES ;
_saveBtn . alpha = 1 ;
NSLog ( @ "Set avatar url failed: %@" , error ) ;
// Alert user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
} ] ;
} failure : ^ ( NSError * error ) {
// Stop saving
[ _activityIndicator stopAnimating ] ;
_saveBtn . enabled = YES ;
_saveBtn . alpha = 1 ;
NSLog ( @ "Upload image failed: %@" , error ) ;
// Alert user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
} ] ;
// Wait for the end of this request before pursuing the saving
return ;
}
// Stop saving
[ _activityIndicator stopAnimating ] ;
_saveBtn . enabled = YES ;
_saveBtn . alpha = 1 ;
}
2014-10-24 10:06:35 +00:00
- ( void ) reset {
// Cancel picture loader ( if any )
if ( imageLoader ) {
[ MediaManager cancel : imageLoader ] ;
imageLoader = nil ;
}
currentPictureURL = nil ;
UIImage * image = [ UIImage imageNamed : @ "default-profile" ] ;
[ self . userPicture setImage : image forState : UIControlStateNormal ] ;
[ self . userPicture setImage : image forState : UIControlStateHighlighted ] ;
currentDisplayName = nil ;
self . userDisplayName . text = nil ;
}
2014-10-30 09:54:57 +00:00
- ( void ) updateUserPicture : ( NSString * ) avatar_url {
if ( currentPictureURL = = nil || [ currentPictureURL isEqualToString : avatar_url ] = = NO ) {
// Cancel previous loader ( if any )
if ( imageLoader ) {
[ MediaManager cancel : imageLoader ] ;
imageLoader = nil ;
}
currentPictureURL = [ avatar_url isEqual : [ NSNull null ] ] ? nil : avatar_url ;
if ( currentPictureURL ) {
// Load user ' s picture
imageLoader = [ MediaManager loadPicture : currentPictureURL success : ^ ( UIImage * image ) {
[ self . userPicture setImage : image forState : UIControlStateNormal ] ;
[ self . userPicture setImage : image forState : UIControlStateHighlighted ] ;
} failure : ^ ( NSError * error ) {
// Reset picture URL in order to try next time
currentPictureURL = nil ;
} ] ;
} else {
// Set placeholder
UIImage * image = [ UIImage imageNamed : @ "default-profile" ] ;
[ self . userPicture setImage : image forState : UIControlStateNormal ] ;
[ self . userPicture setImage : image forState : UIControlStateHighlighted ] ;
}
}
}
# pragma mark - KVO
2014-10-31 17:54:32 +00:00
- ( void ) observeValueForKeyPath : ( NSString * ) keyPath ofObject : ( id ) object change : ( NSDictionary * ) change context : ( void * ) context {
if ( [ @ "userDisplayName" isEqualToString : keyPath ] ) {
2014-10-30 09:54:57 +00:00
// Refresh user ' s display name
MatrixHandler * mxHandler = [ MatrixHandler sharedHandler ] ;
if ( [ currentDisplayName isEqualToString : mxHandler . userDisplayName ] = = NO ) {
currentDisplayName = mxHandler . userDisplayName ;
self . userDisplayName . text = mxHandler . userDisplayName ;
}
} else if ( [ @ "userPictureURL" isEqualToString : keyPath ] ) {
// Refresh user ' s picture
MatrixHandler * mxHandler = [ MatrixHandler sharedHandler ] ;
[ self updateUserPicture : mxHandler . userPictureURL ] ;
}
}
2014-10-29 16:48:11 +00:00
# pragma mark - Actions
2014-10-24 10:06:35 +00:00
2014-10-08 16:55:26 +00:00
- ( IBAction ) onButtonPressed : ( id ) sender {
2014-10-24 10:06:35 +00:00
[ self dismissKeyboard ] ;
2014-10-08 16:55:26 +00:00
if ( sender = = _userPicture ) {
2014-10-31 17:54:32 +00:00
// Open picture gallery
imagePicker = [ [ UIImagePickerController alloc ] init ] ;
imagePicker . delegate = self ;
imagePicker . sourceType = UIImagePickerControllerSourceTypePhotoLibrary ;
imagePicker . allowsEditing = NO ;
[ self presentViewController : imagePicker animated : YES completion : nil ] ;
2014-10-18 02:03:07 +00:00
} else if ( sender = = _saveBtn ) {
2014-10-31 17:54:32 +00:00
[ self save ] ;
2014-10-29 16:48:11 +00:00
} else if ( sender = = logoutBtn ) {
2014-10-24 10:06:35 +00:00
[ self reset ] ;
2014-10-08 16:55:26 +00:00
[ [ AppDelegate theDelegate ] logout ] ;
2014-10-29 16:48:11 +00:00
} else if ( sender = = notificationsSwitch ) {
[ AppSettings sharedSettings ] . enableNotifications = notificationsSwitch . on ;
} else if ( sender = = allEventsSwitch ) {
[ AppSettings sharedSettings ] . displayAllEvents = allEventsSwitch . on ;
2014-11-05 11:57:24 +00:00
} else if ( sender = = sortMembersSwitch ) {
[ AppSettings sharedSettings ] . sortMembersUsingLastSeenTime = sortMembersSwitch . on ;
2014-10-08 16:55:26 +00:00
}
}
# pragma mark - keyboard
- ( void ) dismissKeyboard
{
// Hide the keyboard
[ _userDisplayName resignFirstResponder ] ;
}
# pragma mark - UITextField delegate
- ( BOOL ) textFieldShouldReturn : ( UITextField * ) textField
{
// "Done" key has been pressed
[ textField resignFirstResponder ] ;
return YES ;
}
2014-10-29 16:48:11 +00:00
# pragma mark - Table view data source
- ( NSInteger ) numberOfSectionsInTableView : ( UITableView * ) tableView {
return 4 ;
}
- ( NSInteger ) tableView : ( UITableView * ) tableView numberOfRowsInSection : ( NSInteger ) section {
if ( section = = SETTINGS_SECTION _NOTIFICATIONS _INDEX ) {
return 1 ;
2014-11-05 11:57:24 +00:00
} else if ( section = = SETTINGS_SECTION _ROOMS _INDEX ) {
return 2 ;
2014-10-29 16:48:11 +00:00
} else if ( section = = SETTINGS_SECTION _CONFIGURATION _INDEX ) {
return 1 ;
} else if ( section = = SETTINGS_SECTION _COMMANDS _INDEX ) {
return 1 ;
}
return 0 ;
}
- ( CGFloat ) tableView : ( UITableView * ) tableView heightForRowAtIndexPath : ( NSIndexPath * ) indexPath {
if ( indexPath . section = = SETTINGS_SECTION _NOTIFICATIONS _INDEX ) {
return 44 ;
2014-11-05 11:57:24 +00:00
} else if ( indexPath . section = = SETTINGS_SECTION _ROOMS _INDEX ) {
2014-10-29 16:48:11 +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 ] ;
MatrixHandler * mxHandler = [ MatrixHandler sharedHandler ] ;
textView . text = [ NSString stringWithFormat : kConfigurationFormatText , mxHandler . homeServerURL , nil , mxHandler . userId , mxHandler . accessToken ] ;
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 ;
}
- ( CGFloat ) tableView : ( UITableView * ) tableView heightForHeaderInSection : ( NSInteger ) section
{
return 30 ;
}
- ( CGFloat ) tableView : ( UITableView * ) tableView heightForFooterInSection : ( NSInteger ) section
{
return 1 ;
}
- ( UIView * ) tableView : ( UITableView * ) tableView viewForHeaderInSection : ( NSInteger ) section
{
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 ] ;
if ( section = = SETTINGS_SECTION _NOTIFICATIONS _INDEX ) {
sectionHeader . text = @ " Notifications" ;
2014-11-05 11:57:24 +00:00
} else if ( section = = SETTINGS_SECTION _ROOMS _INDEX ) {
sectionHeader . text = @ " Rooms" ;
2014-10-29 16:48:11 +00:00
} 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 {
SettingsTableViewCell * cell = nil ;
if ( indexPath . section = = SETTINGS_SECTION _NOTIFICATIONS _INDEX ) {
SettingsTableCellWithSwitch * notificationsCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithSwitch" forIndexPath : indexPath ] ;
notificationsCell . settingLabel . text = @ "Enable notifications" ;
notificationsCell . settingSwitch . on = [ [ AppSettings sharedSettings ] enableNotifications ] ;
notificationsSwitch = notificationsCell . settingSwitch ;
cell = notificationsCell ;
2014-11-05 11:57:24 +00:00
} else if ( indexPath . section = = SETTINGS_SECTION _ROOMS _INDEX ) {
SettingsTableCellWithSwitch * roomsSettingCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithSwitch" forIndexPath : indexPath ] ;
if ( indexPath . row = = 0 ) {
roomsSettingCell . settingLabel . text = @ "Display all events" ;
roomsSettingCell . settingSwitch . on = [ [ AppSettings sharedSettings ] displayAllEvents ] ;
allEventsSwitch = roomsSettingCell . settingSwitch ;
} else {
roomsSettingCell . settingLabel . text = @ "Sort members by last seen time" ;
roomsSettingCell . settingSwitch . on = [ [ AppSettings sharedSettings ] sortMembersUsingLastSeenTime ] ;
sortMembersSwitch = roomsSettingCell . settingSwitch ;
}
cell = roomsSettingCell ;
2014-10-29 16:48:11 +00:00
} else if ( indexPath . section = = SETTINGS_SECTION _CONFIGURATION _INDEX ) {
SettingsTableCellWithTextView * configCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithTextView" forIndexPath : indexPath ] ;
MatrixHandler * mxHandler = [ MatrixHandler sharedHandler ] ;
configCell . settingTextView . text = [ NSString stringWithFormat : kConfigurationFormatText , mxHandler . homeServerURL , nil , mxHandler . userId , mxHandler . accessToken ] ;
cell = configCell ;
} else if ( indexPath . section = = SETTINGS_SECTION _COMMANDS _INDEX ) {
SettingsTableCellWithTextView * commandsCell = [ tableView dequeueReusableCellWithIdentifier : @ "SettingsCellWithTextView" forIndexPath : indexPath ] ;
commandsCell . settingTextView . text = kCommandsDescriptionText ;
cell = commandsCell ;
}
return cell ;
}
2014-10-31 17:54:32 +00:00
# pragma mark - UIImagePickerControllerDelegate
- ( void ) imagePickerController : ( UIImagePickerController * ) picker didFinishPickingMediaWithInfo : ( NSDictionary * ) info {
UIImage * selectedImage = [ info objectForKey : UIImagePickerControllerOriginalImage ] ;
if ( selectedImage ) {
[ self . userPicture setImage : selectedImage forState : UIControlStateNormal ] ;
[ self . userPicture setImage : selectedImage forState : UIControlStateHighlighted ] ;
shouldSavePicture = YES ;
}
[ self dismissMediaPicker ] ;
}
- ( void ) imagePickerControllerDidCancel : ( UIImagePickerController * ) picker {
[ self dismissMediaPicker ] ;
}
- ( void ) dismissMediaPicker {
if ( imagePicker ) {
[ self dismissViewControllerAnimated : NO completion : nil ] ;
imagePicker . delegate = nil ;
imagePicker = nil ;
}
}
2014-10-03 17:26:39 +00:00
@ end