element-ios/Riot/Modules/MatrixKit/Controllers/MXKNotificationSettingsView...

629 lines
23 KiB
Objective-C

/*
Copyright 2018-2024 New Vector Ltd.
Copyright 2015 OpenMarket Ltd
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
#import "MXKNotificationSettingsViewController.h"
#import "MXKTableViewCellWithButton.h"
#import "MXKPushRuleTableViewCell.h"
#import "MXKPushRuleCreationTableViewCell.h"
#import "MXKTableViewCellWithTextView.h"
#import "MXKConstants.h"
#import "NSBundle+MatrixKit.h"
#import "MXKSwiftHeader.h"
#define MXKNOTIFICATIONSETTINGS_SECTION_INTRO_INDEX 0
#define MXKNOTIFICATIONSETTINGS_SECTION_PER_WORD_INDEX 1
#define MXKNOTIFICATIONSETTINGS_SECTION_PER_ROOM_INDEX 2
#define MXKNOTIFICATIONSETTINGS_SECTION_PER_SENDER_INDEX 3
#define MXKNOTIFICATIONSETTINGS_SECTION_OTHERS_INDEX 4
#define MXKNOTIFICATIONSETTINGS_SECTION_DEFAULT_INDEX 5
#define MXKNOTIFICATIONSETTINGS_SECTION_COUNT 6
@interface MXKNotificationSettingsViewController ()
{
/**
Handle master rule state
*/
UIButton *ruleMasterButton;
BOOL areAllDisabled;
/**
*/
NSInteger contentRuleCreationIndex;
NSInteger roomRuleCreationIndex;
NSInteger senderRuleCreationIndex;
/**
Predefined rules index
*/
NSInteger ruleContainsUserNameIndex;
NSInteger ruleContainsDisplayNameIndex;
NSInteger ruleOneToOneRoomIndex;
NSInteger ruleInviteForMeIndex;
NSInteger ruleMemberEventIndex;
NSInteger ruleCallIndex;
NSInteger ruleSuppressBotsNotificationsIndex;
/**
Notification center observers
*/
id notificationCenterWillUpdateObserver;
id notificationCenterDidUpdateObserver;
id notificationCenterDidFailObserver;
}
@end
@implementation MXKNotificationSettingsViewController
- (void)finalizeInit
{
[super finalizeInit];
}
- (void)dealloc
{
ruleMasterButton = nil;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)destroy
{
if (notificationCenterWillUpdateObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:notificationCenterWillUpdateObserver];
notificationCenterWillUpdateObserver = nil;
}
if (notificationCenterDidUpdateObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:notificationCenterDidUpdateObserver];
notificationCenterDidUpdateObserver = nil;
}
if (notificationCenterDidFailObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:notificationCenterDidFailObserver];
notificationCenterDidFailObserver = nil;
}
[super destroy];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (_mxAccount)
{
[self startActivityIndicator];
// Refresh existing notification rules
[_mxAccount.mxSession.notificationCenter refreshRules:^{
[self stopActivityIndicator];
[self.tableView reloadData];
} failure:^(NSError *error) {
[self stopActivityIndicator];
}];
notificationCenterWillUpdateObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXNotificationCenterWillUpdateRules object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[self startActivityIndicator];
}];
notificationCenterDidUpdateObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXNotificationCenterDidUpdateRules object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[self stopActivityIndicator];
[self.tableView reloadData];
}];
notificationCenterDidFailObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXNotificationCenterDidFailRulesUpdate object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[self stopActivityIndicator];
// Notify MatrixKit user
NSString *myUserId = self.mxAccount.mxCredentials.userId;
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:note.userInfo[kMXNotificationCenterErrorKey] userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
}];
}
// Refresh display
[self.tableView reloadData];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if (notificationCenterWillUpdateObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:notificationCenterWillUpdateObserver];
notificationCenterWillUpdateObserver = nil;
}
if (notificationCenterDidUpdateObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:notificationCenterDidUpdateObserver];
notificationCenterDidUpdateObserver = nil;
}
if (notificationCenterDidFailObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:notificationCenterDidFailObserver];
notificationCenterDidFailObserver = nil;
}
}
#pragma mark - Actions
- (IBAction)onButtonPressed:(id)sender
{
if (sender == ruleMasterButton)
{
// Swap enable state for all noticiations
MXPushRule *pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterDisableAllNotificationsRuleID];
if (pushRule)
{
[_mxAccount.mxSession.notificationCenter enableRule:pushRule isEnabled:!areAllDisabled completion:nil];
}
}
}
#pragma mark - UITableView data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Check master rule state
MXPushRule *pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterDisableAllNotificationsRuleID];
if (pushRule.enabled)
{
areAllDisabled = YES;
return 1;
}
else
{
areAllDisabled = NO;
return MXKNOTIFICATIONSETTINGS_SECTION_COUNT;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger count = 0;
if (section == MXKNOTIFICATIONSETTINGS_SECTION_INTRO_INDEX)
{
count = 2;
}
else if (section == MXKNOTIFICATIONSETTINGS_SECTION_PER_WORD_INDEX)
{
// A first cell will display a user information
count = 1;
// Only removable content rules are listed in this section (we ignore here predefined rules)
for (MXPushRule *pushRule in _mxAccount.mxSession.notificationCenter.rules.global.content)
{
if (!pushRule.isDefault)
{
count++;
}
}
// Add one item to suggest new rule creation
contentRuleCreationIndex = count ++;
}
else if (section == MXKNOTIFICATIONSETTINGS_SECTION_PER_ROOM_INDEX)
{
count = _mxAccount.mxSession.notificationCenter.rules.global.room.count;
// Add one item to suggest new rule creation
roomRuleCreationIndex = count ++;
}
else if (section == MXKNOTIFICATIONSETTINGS_SECTION_PER_SENDER_INDEX)
{
count = _mxAccount.mxSession.notificationCenter.rules.global.sender.count;
// Add one item to suggest new rule creation
senderRuleCreationIndex = count ++;
}
else if (section == MXKNOTIFICATIONSETTINGS_SECTION_OTHERS_INDEX)
{
ruleContainsUserNameIndex = ruleContainsDisplayNameIndex = ruleOneToOneRoomIndex = ruleInviteForMeIndex = ruleMemberEventIndex = ruleCallIndex = ruleSuppressBotsNotificationsIndex = -1;
// Check whether each predefined rule is supported
if ([_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterContainUserNameRuleID])
{
ruleContainsUserNameIndex = count++;
}
if ([_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterContainDisplayNameRuleID])
{
ruleContainsDisplayNameIndex = count++;
}
if ([_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterOneToOneRoomRuleID])
{
ruleOneToOneRoomIndex = count++;
}
if ([_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterInviteMeRuleID])
{
ruleInviteForMeIndex = count++;
}
if ([_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterMemberEventRuleID])
{
ruleMemberEventIndex = count++;
}
if ([_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterCallRuleID])
{
ruleCallIndex = count++;
}
if ([_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterSuppressBotsNotificationsRuleID])
{
ruleSuppressBotsNotificationsIndex = count++;
}
}
else if (section == MXKNOTIFICATIONSETTINGS_SECTION_DEFAULT_INDEX)
{
if ([_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterAllOtherRoomMessagesRuleID])
{
count = 1;
}
}
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
NSInteger rowIndex = indexPath.row;
if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_INTRO_INDEX)
{
if (indexPath.row == 0)
{
MXKTableViewCellWithButton *masterBtnCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithButton defaultReuseIdentifier]];
if (!masterBtnCell)
{
masterBtnCell = [[MXKTableViewCellWithButton alloc] init];
}
if (areAllDisabled)
{
[masterBtnCell.mxkButton setTitle:[VectorL10n notificationSettingsEnableNotifications] forState:UIControlStateNormal];
[masterBtnCell.mxkButton setTitle:[VectorL10n notificationSettingsEnableNotifications] forState:UIControlStateHighlighted];
}
else
{
[masterBtnCell.mxkButton setTitle:[VectorL10n notificationSettingsDisableAll] forState:UIControlStateNormal];
[masterBtnCell.mxkButton setTitle:[VectorL10n notificationSettingsDisableAll] forState:UIControlStateHighlighted];
}
[masterBtnCell.mxkButton addTarget:self action:@selector(onButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
ruleMasterButton = masterBtnCell.mxkButton;
cell = masterBtnCell;
}
else
{
MXKTableViewCellWithTextView *introCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithTextView defaultReuseIdentifier]];
if (!introCell)
{
introCell = [[MXKTableViewCellWithTextView alloc] init];
}
if (areAllDisabled)
{
introCell.mxkTextView.text = [VectorL10n notificationSettingsEnableNotificationsWarning];
introCell.mxkTextView.backgroundColor = [UIColor redColor];
}
else
{
introCell.mxkTextView.text = [VectorL10n notificationSettingsGlobalInfo];
introCell.mxkTextView.backgroundColor = [UIColor clearColor];
}
introCell.mxkTextView.font = [UIFont systemFontOfSize:14];
cell = introCell;
}
}
else if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_PER_WORD_INDEX)
{
if (rowIndex == 0)
{
MXKTableViewCellWithTextView *introCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithTextView defaultReuseIdentifier]];
if (!introCell)
{
introCell = [[MXKTableViewCellWithTextView alloc] init];
}
introCell.mxkTextView.text = [VectorL10n notificationSettingsPerWordInfo];
introCell.mxkTextView.font = [UIFont systemFontOfSize:14];
cell = introCell;
}
else if (rowIndex == contentRuleCreationIndex)
{
MXKPushRuleCreationTableViewCell *pushRuleCreationCell = [tableView dequeueReusableCellWithIdentifier:[MXKPushRuleCreationTableViewCell defaultReuseIdentifier]];
if (!pushRuleCreationCell)
{
pushRuleCreationCell = [[MXKPushRuleCreationTableViewCell alloc] init];
}
pushRuleCreationCell.mxSession = _mxAccount.mxSession;
pushRuleCreationCell.mxPushRuleKind = MXPushRuleKindContent;
cell = pushRuleCreationCell;
}
else
{
// Only removable content rules are listed in this section
NSInteger count = 0;
for (MXPushRule *pushRule in _mxAccount.mxSession.notificationCenter.rules.global.content)
{
if (!pushRule.isDefault)
{
count++;
if (count == rowIndex)
{
MXKPushRuleTableViewCell *pushRuleCell = [tableView dequeueReusableCellWithIdentifier:[MXKPushRuleTableViewCell defaultReuseIdentifier]];
if (!pushRuleCell)
{
pushRuleCell = [[MXKPushRuleTableViewCell alloc] init];
}
pushRuleCell.mxSession = _mxAccount.mxSession;
pushRuleCell.mxPushRule = pushRule;
cell = pushRuleCell;
break;
}
}
}
}
}
else if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_PER_ROOM_INDEX)
{
if (rowIndex == roomRuleCreationIndex)
{
MXKPushRuleCreationTableViewCell *pushRuleCreationCell = [tableView dequeueReusableCellWithIdentifier:[MXKPushRuleCreationTableViewCell defaultReuseIdentifier]];
if (!pushRuleCreationCell)
{
pushRuleCreationCell = [[MXKPushRuleCreationTableViewCell alloc] init];
}
pushRuleCreationCell.mxSession = _mxAccount.mxSession;
pushRuleCreationCell.mxPushRuleKind = MXPushRuleKindRoom;
cell = pushRuleCreationCell;
}
else if (rowIndex < _mxAccount.mxSession.notificationCenter.rules.global.room.count)
{
MXKPushRuleTableViewCell *pushRuleCell = [tableView dequeueReusableCellWithIdentifier:[MXKPushRuleTableViewCell defaultReuseIdentifier]];
if (!pushRuleCell)
{
pushRuleCell = [[MXKPushRuleTableViewCell alloc] init];
}
pushRuleCell.mxSession = _mxAccount.mxSession;
pushRuleCell.mxPushRule = [_mxAccount.mxSession.notificationCenter.rules.global.room objectAtIndex:rowIndex];
cell = pushRuleCell;
}
}
else if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_PER_SENDER_INDEX)
{
if (rowIndex == senderRuleCreationIndex)
{
MXKPushRuleCreationTableViewCell *pushRuleCreationCell = [tableView dequeueReusableCellWithIdentifier:[MXKPushRuleCreationTableViewCell defaultReuseIdentifier]];
if (!pushRuleCreationCell)
{
pushRuleCreationCell = [[MXKPushRuleCreationTableViewCell alloc] init];
}
pushRuleCreationCell.mxSession = _mxAccount.mxSession;
pushRuleCreationCell.mxPushRuleKind = MXPushRuleKindSender;
cell = pushRuleCreationCell;
}
else if (rowIndex < _mxAccount.mxSession.notificationCenter.rules.global.sender.count)
{
MXKPushRuleTableViewCell *pushRuleCell = [tableView dequeueReusableCellWithIdentifier:[MXKPushRuleTableViewCell defaultReuseIdentifier]];
if (!pushRuleCell)
{
pushRuleCell = [[MXKPushRuleTableViewCell alloc] init];
}
pushRuleCell.mxSession = _mxAccount.mxSession;
pushRuleCell.mxPushRule = [_mxAccount.mxSession.notificationCenter.rules.global.sender objectAtIndex:rowIndex];
cell = pushRuleCell;
}
}
else if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_OTHERS_INDEX)
{
MXPushRule *pushRule;
NSString *ruleDescription;
if (rowIndex == ruleContainsUserNameIndex)
{
pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterContainUserNameRuleID];
ruleDescription = [VectorL10n notificationSettingsContainMyUserName];
}
if (rowIndex == ruleContainsDisplayNameIndex)
{
pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterContainDisplayNameRuleID];
ruleDescription = [VectorL10n notificationSettingsContainMyDisplayName];
}
if (rowIndex == ruleOneToOneRoomIndex)
{
pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterOneToOneRoomRuleID];
ruleDescription = [VectorL10n notificationSettingsJustSentToMe];
}
if (rowIndex == ruleInviteForMeIndex)
{
pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterInviteMeRuleID];
ruleDescription = [VectorL10n notificationSettingsInviteToANewRoom];
}
if (rowIndex == ruleMemberEventIndex)
{
pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterMemberEventRuleID];
ruleDescription = [VectorL10n notificationSettingsPeopleJoinLeaveRooms];
}
if (rowIndex == ruleCallIndex)
{
pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterCallRuleID];
ruleDescription = [VectorL10n notificationSettingsReceiveACall];
}
if (rowIndex == ruleSuppressBotsNotificationsIndex)
{
pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterSuppressBotsNotificationsRuleID];
ruleDescription = [VectorL10n notificationSettingsSuppressFromBots];
}
if (pushRule)
{
MXKPushRuleTableViewCell *pushRuleCell = [tableView dequeueReusableCellWithIdentifier:[MXKPushRuleTableViewCell defaultReuseIdentifier]];
if (!pushRuleCell)
{
pushRuleCell = [[MXKPushRuleTableViewCell alloc] init];
}
pushRuleCell.mxSession = _mxAccount.mxSession;
pushRuleCell.mxPushRule = pushRule;
pushRuleCell.ruleDescription.text = ruleDescription;
cell = pushRuleCell;
}
}
else if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_DEFAULT_INDEX)
{
MXPushRule *pushRule = [_mxAccount.mxSession.notificationCenter ruleById:kMXNotificationCenterAllOtherRoomMessagesRuleID];
if (pushRule)
{
MXKPushRuleTableViewCell *pushRuleCell = [tableView dequeueReusableCellWithIdentifier:[MXKPushRuleTableViewCell defaultReuseIdentifier]];
if (!pushRuleCell)
{
pushRuleCell = [[MXKPushRuleTableViewCell alloc] init];
}
pushRuleCell.mxSession = _mxAccount.mxSession;
pushRuleCell.mxPushRule = pushRule;
pushRuleCell.ruleDescription.text = [VectorL10n notificationSettingsNotifyAllOther];
cell = pushRuleCell;
}
}
else
{
// Return a fake cell to prevent app from crashing.
cell = [[UITableViewCell alloc] init];
}
return cell;
}
#pragma mark - UITableView delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_INTRO_INDEX && indexPath.row == 1)
{
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, MAXFLOAT)];
textView.font = [UIFont systemFontOfSize:14];
textView.text = areAllDisabled ? [VectorL10n notificationSettingsEnableNotificationsWarning] : [VectorL10n notificationSettingsGlobalInfo];
CGSize contentSize = [textView sizeThatFits:textView.frame.size];
return contentSize.height + 1;
}
if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_PER_WORD_INDEX)
{
if (indexPath.row == 0)
{
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, MAXFLOAT)];
textView.font = [UIFont systemFontOfSize:14];
textView.text = [VectorL10n notificationSettingsPerWordInfo];
CGSize contentSize = [textView sizeThatFits:textView.frame.size];
return contentSize.height + 1;
}
else if (indexPath.row == contentRuleCreationIndex)
{
return 120;
}
}
if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_PER_ROOM_INDEX && indexPath.row == roomRuleCreationIndex)
{
return 120;
}
if (indexPath.section == MXKNOTIFICATIONSETTINGS_SECTION_PER_SENDER_INDEX && indexPath.row == senderRuleCreationIndex)
{
return 120;
}
return 50;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (section != MXKNOTIFICATIONSETTINGS_SECTION_INTRO_INDEX)
{
return 30;
}
return 0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *sectionHeader = [[UIView alloc] initWithFrame:[tableView rectForHeaderInSection:section]];
sectionHeader.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
UILabel *sectionLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, sectionHeader.frame.size.width - 10, sectionHeader.frame.size.height - 10)];
sectionLabel.font = [UIFont boldSystemFontOfSize:16];
sectionLabel.backgroundColor = [UIColor clearColor];
[sectionHeader addSubview:sectionLabel];
if (section == MXKNOTIFICATIONSETTINGS_SECTION_PER_WORD_INDEX)
{
sectionLabel.text = [VectorL10n notificationSettingsPerWordNotifications];
}
else if (section == MXKNOTIFICATIONSETTINGS_SECTION_PER_ROOM_INDEX)
{
sectionLabel.text = [VectorL10n notificationSettingsPerRoomNotifications];
}
else if (section == MXKNOTIFICATIONSETTINGS_SECTION_PER_SENDER_INDEX)
{
sectionLabel.text = [VectorL10n notificationSettingsPerSenderNotifications];
}
else if (section == MXKNOTIFICATIONSETTINGS_SECTION_OTHERS_INDEX)
{
sectionLabel.text = [VectorL10n notificationSettingsOtherAlerts];
}
else if (section == MXKNOTIFICATIONSETTINGS_SECTION_DEFAULT_INDEX)
{
sectionLabel.text = [VectorL10n notificationSettingsByDefault];
}
return sectionHeader;
}
@end