mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-21 17:12:45 +02:00
Merge MatrixKit develop with commit hash: b85b736313bec0592bd1cabc68035d97f5331137
This commit is contained in:
@@ -0,0 +1,578 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2018 New Vector 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 "MXKRoomCreationView.h"
|
||||
|
||||
#import "MXKConstants.h"
|
||||
|
||||
#import "NSBundle+MatrixKit.h"
|
||||
|
||||
#import "MXKSwiftHeader.h"
|
||||
|
||||
@interface MXKRoomCreationView ()
|
||||
{
|
||||
UIAlertController *mxSessionPicker;
|
||||
|
||||
// Array of homeserver suffix (NSString instance)
|
||||
NSMutableArray *homeServerSuffixArray;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MXKRoomCreationView
|
||||
@synthesize inputAccessoryView;
|
||||
|
||||
+ (UINib *)nib
|
||||
{
|
||||
return [UINib nibWithNibName:NSStringFromClass([MXKRoomCreationView class])
|
||||
bundle:[NSBundle bundleForClass:[MXKRoomCreationView class]]];
|
||||
}
|
||||
|
||||
+ (instancetype)roomCreationView
|
||||
{
|
||||
if ([[self class] nib])
|
||||
{
|
||||
return [[[self class] nib] instantiateWithOwner:nil options:nil].firstObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
return [[self alloc] init];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
|
||||
// Add observer to keep align text fields
|
||||
[_roomNameLabel addObserver:self forKeyPath:@"text" options:0 context:nil];
|
||||
[_roomAliasLabel addObserver:self forKeyPath:@"text" options:0 context:nil];
|
||||
[_participantsLabel addObserver:self forKeyPath:@"text" options:0 context:nil];
|
||||
[self alignTextFields];
|
||||
|
||||
// Finalize setup
|
||||
[self setTranslatesAutoresizingMaskIntoConstraints: NO];
|
||||
|
||||
// Add an accessory view to the text views in order to retrieve keyboard view.
|
||||
inputAccessoryView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
_roomNameTextField.inputAccessoryView = inputAccessoryView;
|
||||
_roomAliasTextField.inputAccessoryView = inputAccessoryView;
|
||||
_participantsTextField.inputAccessoryView = inputAccessoryView;
|
||||
|
||||
// Localize strings
|
||||
_roomNameLabel.text = [MatrixKitL10n roomCreationNameTitle];
|
||||
_roomNameTextField.placeholder = [MatrixKitL10n roomCreationNamePlaceholder];
|
||||
_roomAliasLabel.text = [MatrixKitL10n roomCreationAliasTitle];
|
||||
_roomAliasTextField.placeholder = [MatrixKitL10n roomCreationAliasPlaceholder];
|
||||
_participantsLabel.text = [MatrixKitL10n roomCreationParticipantsTitle];
|
||||
_participantsTextField.placeholder = [MatrixKitL10n roomCreationParticipantsPlaceholder];
|
||||
|
||||
[_roomVisibilityControl setTitle:[MatrixKitL10n public] forSegmentAtIndex:0];
|
||||
[_roomVisibilityControl setTitle:[MatrixKitL10n private] forSegmentAtIndex:1];
|
||||
|
||||
[_createRoomBtn setTitle:[MatrixKitL10n createRoom] forState:UIControlStateNormal];
|
||||
[_createRoomBtn setTitle:[MatrixKitL10n createRoom] forState:UIControlStateHighlighted];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self destroy];
|
||||
|
||||
inputAccessoryView = nil;
|
||||
}
|
||||
|
||||
- (void)setRoomNameFieldHidden:(BOOL)roomNameFieldHidden
|
||||
{
|
||||
_roomNameFieldHidden = _roomNameTextField.hidden = _roomNameLabel.hidden = roomNameFieldHidden;
|
||||
|
||||
if (roomNameFieldHidden)
|
||||
{
|
||||
_roomAliasFieldTopConstraint.constant -= _roomNameTextField.frame.size.height + 8;
|
||||
_participantsFieldTopConstraint.constant -= _roomNameTextField.frame.size.height + 8;
|
||||
_createRoomBtnTopConstraint.constant -= _roomNameTextField.frame.size.height + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
_roomAliasFieldTopConstraint.constant += _roomNameTextField.frame.size.height + 8;
|
||||
_participantsFieldTopConstraint.constant += _roomNameTextField.frame.size.height + 8;
|
||||
_createRoomBtnTopConstraint.constant += _roomNameTextField.frame.size.height + 8;
|
||||
}
|
||||
|
||||
[self alignTextFields];
|
||||
}
|
||||
|
||||
- (void)setRoomAliasFieldHidden:(BOOL)roomAliasFieldHidden
|
||||
{
|
||||
_roomAliasFieldHidden = _roomAliasTextField.hidden = _roomAliasLabel.hidden = roomAliasFieldHidden;
|
||||
|
||||
if (roomAliasFieldHidden)
|
||||
{
|
||||
_participantsFieldTopConstraint.constant -= _roomAliasTextField.frame.size.height + 8;
|
||||
_createRoomBtnTopConstraint.constant -= _roomAliasTextField.frame.size.height + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
_participantsFieldTopConstraint.constant += _roomAliasTextField.frame.size.height + 8;
|
||||
_createRoomBtnTopConstraint.constant += _roomAliasTextField.frame.size.height + 8;
|
||||
}
|
||||
|
||||
[self alignTextFields];
|
||||
}
|
||||
|
||||
- (void)setParticipantsFieldHidden:(BOOL)participantsFieldHidden
|
||||
{
|
||||
_participantsFieldHidden = _participantsTextField.hidden = _participantsLabel.hidden = participantsFieldHidden;
|
||||
|
||||
if (participantsFieldHidden)
|
||||
{
|
||||
_createRoomBtnTopConstraint.constant -= _participantsTextField.frame.size.height + 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
_createRoomBtnTopConstraint.constant += _participantsTextField.frame.size.height + 8;
|
||||
}
|
||||
|
||||
[self alignTextFields];
|
||||
}
|
||||
|
||||
- (CGFloat)actualFrameHeight
|
||||
{
|
||||
return (_createRoomBtnTopConstraint.constant + _createRoomBtn.frame.size.height + 8);
|
||||
}
|
||||
|
||||
- (void)setMxSessions:(NSArray *)mxSessions
|
||||
{
|
||||
_mxSessions = mxSessions;
|
||||
|
||||
if (mxSessions.count)
|
||||
{
|
||||
homeServerSuffixArray = [NSMutableArray array];
|
||||
|
||||
for (MXSession *mxSession in mxSessions)
|
||||
{
|
||||
NSString *homeserverSuffix = mxSession.matrixRestClient.homeserverSuffix;
|
||||
if (homeserverSuffix && [homeServerSuffixArray indexOfObject:homeserverSuffix] == NSNotFound)
|
||||
{
|
||||
[homeServerSuffixArray addObject:homeserverSuffix];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
homeServerSuffixArray = nil;
|
||||
}
|
||||
|
||||
// Update alias placeholder in room creation section
|
||||
if (homeServerSuffixArray.count == 1)
|
||||
{
|
||||
_roomAliasTextField.placeholder = [MatrixKitL10n roomCreationAliasPlaceholderWithHomeserver:homeServerSuffixArray.firstObject];
|
||||
}
|
||||
else
|
||||
{
|
||||
_roomAliasTextField.placeholder = [MatrixKitL10n roomCreationAliasPlaceholder];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dismissKeyboard
|
||||
{
|
||||
// Hide the keyboard
|
||||
[_roomNameTextField resignFirstResponder];
|
||||
[_roomAliasTextField resignFirstResponder];
|
||||
[_participantsTextField resignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
{
|
||||
self.mxSessions = nil;
|
||||
|
||||
// Remove observers
|
||||
[_roomNameLabel removeObserver:self forKeyPath:@"text"];
|
||||
[_roomAliasLabel removeObserver:self forKeyPath:@"text"];
|
||||
[_participantsLabel removeObserver:self forKeyPath:@"text"];
|
||||
}
|
||||
|
||||
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
// UIView will be "transparent" for touch events if we return NO
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Internal methods
|
||||
|
||||
- (void)alignTextFields
|
||||
{
|
||||
CGFloat maxLabelLenght = 0;
|
||||
|
||||
if (!_roomNameLabel.hidden)
|
||||
{
|
||||
maxLabelLenght = _roomNameLabel.frame.size.width;
|
||||
}
|
||||
if (!_roomAliasLabel.hidden && maxLabelLenght < _roomAliasLabel.frame.size.width)
|
||||
{
|
||||
maxLabelLenght = _roomAliasLabel.frame.size.width;
|
||||
}
|
||||
if (!_participantsLabel.hidden && maxLabelLenght < _participantsLabel.frame.size.width)
|
||||
{
|
||||
maxLabelLenght = _participantsLabel.frame.size.width;
|
||||
}
|
||||
|
||||
// Update textField left constraint by adding marging
|
||||
_textFieldLeftConstraint.constant = maxLabelLenght + (2 * 8);
|
||||
|
||||
[self layoutIfNeeded];
|
||||
}
|
||||
|
||||
- (NSString*)alias
|
||||
{
|
||||
// Extract alias name from alias text field
|
||||
NSString *alias = _roomAliasTextField.text;
|
||||
if (alias.length)
|
||||
{
|
||||
// Remove '#' character
|
||||
alias = [alias substringFromIndex:1];
|
||||
|
||||
NSString *actualAlias = nil;
|
||||
for (NSString *homeServerSuffix in homeServerSuffixArray)
|
||||
{
|
||||
// Remove homeserver suffix
|
||||
NSRange range = [alias rangeOfString:homeServerSuffix];
|
||||
if (range.location != NSNotFound)
|
||||
{
|
||||
actualAlias = [alias stringByReplacingCharactersInRange:range withString:@""];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (actualAlias)
|
||||
{
|
||||
alias = actualAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXLogDebug(@"[MXKRoomCreationView] Wrong room alias has been set (%@)", _roomAliasTextField.text);
|
||||
alias = nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (! alias.length)
|
||||
{
|
||||
alias = nil;
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
- (NSArray*)participantsList
|
||||
{
|
||||
NSMutableArray *participants = [NSMutableArray array];
|
||||
|
||||
if (_participantsTextField.text.length)
|
||||
{
|
||||
NSArray *components = [_participantsTextField.text componentsSeparatedByString:@";"];
|
||||
|
||||
for (NSString *component in components)
|
||||
{
|
||||
// Remove white space from both ends
|
||||
NSString *user = [component stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
if (user.length > 1 && [user hasPrefix:@"@"])
|
||||
{
|
||||
[participants addObject:user];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (participants.count == 0)
|
||||
{
|
||||
participants = nil;
|
||||
}
|
||||
|
||||
return participants;
|
||||
}
|
||||
|
||||
- (void)selectMatrixSession:(void (^)(MXSession *selectedSession))onSelection
|
||||
{
|
||||
if (_mxSessions.count == 1)
|
||||
{
|
||||
if (onSelection)
|
||||
{
|
||||
onSelection(_mxSessions.firstObject);
|
||||
}
|
||||
}
|
||||
else if (_mxSessions.count > 1)
|
||||
{
|
||||
if (mxSessionPicker)
|
||||
{
|
||||
[mxSessionPicker dismissViewControllerAnimated:NO completion:nil];
|
||||
}
|
||||
|
||||
mxSessionPicker = [UIAlertController alertControllerWithTitle:[MatrixKitL10n selectAccount] message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
for(MXSession *mxSession in _mxSessions)
|
||||
{
|
||||
[mxSessionPicker addAction:[UIAlertAction actionWithTitle:mxSession.myUser.userId
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->mxSessionPicker = nil;
|
||||
|
||||
if (onSelection)
|
||||
{
|
||||
onSelection(mxSession);
|
||||
}
|
||||
}
|
||||
|
||||
}]];
|
||||
}
|
||||
|
||||
[mxSessionPicker addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->mxSessionPicker = nil;
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[mxSessionPicker popoverPresentationController].sourceView = self;
|
||||
[mxSessionPicker popoverPresentationController].sourceRect = self.bounds;
|
||||
|
||||
if (self.delegate)
|
||||
{
|
||||
[self.delegate roomCreationView:self presentAlertController:mxSessionPicker];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UITextField delegate
|
||||
|
||||
- (IBAction)textFieldEditingChanged:(id)sender
|
||||
{
|
||||
// Update Create Room button
|
||||
NSString *roomName = _roomNameTextField.text;
|
||||
NSString *roomAlias = _roomAliasTextField.text;
|
||||
NSString *participants = _participantsTextField.text;
|
||||
|
||||
// Room alias is required to create public room
|
||||
_createRoomBtn.enabled = ((_roomVisibilityControl.selectedSegmentIndex == 0) ? roomAlias.length : (roomName.length || roomAlias.length || participants.length));
|
||||
}
|
||||
|
||||
- (void)textFieldDidBeginEditing:(UITextField *)textField
|
||||
{
|
||||
if (textField == _participantsTextField)
|
||||
{
|
||||
if (textField.text.length == 0)
|
||||
{
|
||||
textField.text = @"@";
|
||||
}
|
||||
}
|
||||
else if (textField == _roomAliasTextField)
|
||||
{
|
||||
if (textField.text.length == 0)
|
||||
{
|
||||
textField.text = @"#";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)textField
|
||||
{
|
||||
if (textField == _roomAliasTextField)
|
||||
{
|
||||
if (homeServerSuffixArray.count == 1)
|
||||
{
|
||||
// Check whether homeserver suffix should be added
|
||||
NSRange range = [textField.text rangeOfString:@":"];
|
||||
if (range.location == NSNotFound)
|
||||
{
|
||||
textField.text = [textField.text stringByAppendingString:homeServerSuffixArray.firstObject];
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the alias is valid
|
||||
if (!self.alias)
|
||||
{
|
||||
// reset text field
|
||||
textField.text = nil;
|
||||
|
||||
// Update Create button status
|
||||
_createRoomBtn.enabled = ((_roomVisibilityControl.selectedSegmentIndex == 1) && (_roomNameTextField.text.length || _participantsTextField.text.length));
|
||||
}
|
||||
}
|
||||
else if (textField == _participantsTextField)
|
||||
{
|
||||
NSArray *participants = self.participantsList;
|
||||
textField.text = [participants componentsJoinedByString:@"; "];
|
||||
|
||||
// Update Create button status
|
||||
_createRoomBtn.enabled = ((_roomVisibilityControl.selectedSegmentIndex == 0) ? _roomAliasTextField.text.length : (_roomNameTextField.text.length || _roomAliasTextField.text.length || _participantsTextField.text.length));
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
|
||||
{
|
||||
// Auto complete participant IDs
|
||||
if (textField == _participantsTextField)
|
||||
{
|
||||
// Add @ if none
|
||||
if (!textField.text.length || textField.text.length == range.length)
|
||||
{
|
||||
if ([string hasPrefix:@"@"] == NO)
|
||||
{
|
||||
textField.text = [NSString stringWithFormat:@"@%@",string];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
else if (range.location == textField.text.length)
|
||||
{
|
||||
if ([string isEqualToString:@";"])
|
||||
{
|
||||
// Add '@' character
|
||||
textField.text = [textField.text stringByAppendingString:@"; @"];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (textField == _roomAliasTextField)
|
||||
{
|
||||
// Add # if none
|
||||
if (!textField.text.length || textField.text.length == range.length)
|
||||
{
|
||||
if ([string hasPrefix:@"#"] == NO)
|
||||
{
|
||||
if ([string isEqualToString:@":"] && homeServerSuffixArray.count == 1)
|
||||
{
|
||||
textField.text = [NSString stringWithFormat:@"#%@",homeServerSuffixArray.firstObject];
|
||||
}
|
||||
else
|
||||
{
|
||||
textField.text = [NSString stringWithFormat:@"#%@",string];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
else if (homeServerSuffixArray.count == 1)
|
||||
{
|
||||
// Add homeserver automatically when user adds ':' at the end
|
||||
if (range.location == textField.text.length && [string isEqualToString:@":"])
|
||||
{
|
||||
textField.text = [textField.text stringByAppendingString:homeServerSuffixArray.firstObject];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField*) textField
|
||||
{
|
||||
// "Done" key has been pressed
|
||||
[textField resignFirstResponder];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)onButtonPressed:(id)sender
|
||||
{
|
||||
[self dismissKeyboard];
|
||||
|
||||
// Handle multi-sessions here
|
||||
[self selectMatrixSession:^(MXSession *selectedSession)
|
||||
{
|
||||
if (sender == self->_createRoomBtn)
|
||||
{
|
||||
// Disable button to prevent multiple request
|
||||
self->_createRoomBtn.enabled = NO;
|
||||
|
||||
MXRoomCreationParameters *roomCreationParameters = [MXRoomCreationParameters new];
|
||||
|
||||
roomCreationParameters.name = self->_roomNameTextField.text;
|
||||
if (!roomCreationParameters.name.length)
|
||||
{
|
||||
roomCreationParameters.name = nil;
|
||||
}
|
||||
|
||||
// Check whether some users must be invited
|
||||
roomCreationParameters.inviteArray = self.participantsList;
|
||||
|
||||
// Prepare room settings
|
||||
|
||||
if (self->_roomVisibilityControl.selectedSegmentIndex == 0)
|
||||
{
|
||||
roomCreationParameters.visibility = kMXRoomDirectoryVisibilityPublic;
|
||||
}
|
||||
else
|
||||
{
|
||||
roomCreationParameters.visibility = kMXRoomDirectoryVisibilityPrivate;
|
||||
roomCreationParameters.isDirect = (roomCreationParameters.inviteArray.count == 1);
|
||||
}
|
||||
|
||||
// Ensure direct chat are created with equal ops on both sides (the trusted_private_chat preset)
|
||||
roomCreationParameters.preset = (roomCreationParameters.isDirect ? kMXRoomPresetTrustedPrivateChat : nil);
|
||||
|
||||
// Create new room
|
||||
[selectedSession createRoomWithParameters:roomCreationParameters success:^(MXRoom *room) {
|
||||
|
||||
// Reset text fields
|
||||
self->_roomNameTextField.text = nil;
|
||||
self->_roomAliasTextField.text = nil;
|
||||
self->_participantsTextField.text = nil;
|
||||
|
||||
if (self.delegate)
|
||||
{
|
||||
// Open created room
|
||||
[self.delegate roomCreationView:self showRoom:room.roomId withMatrixSession:selectedSession];
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
self->_createRoomBtn.enabled = YES;
|
||||
|
||||
MXLogDebug(@"[MXKRoomCreationView] Create room (%@ %@ (%@)) failed", self->_roomNameTextField.text, self.alias, (self->_roomVisibilityControl.selectedSegmentIndex == 0) ? @"Public":@"Private");
|
||||
|
||||
// Notify MatrixKit user
|
||||
NSString *myUserId = selectedSession.myUser.userId;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
|
||||
|
||||
}];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - KVO
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
// Check whether one label has been updated
|
||||
if ([@"text" isEqualToString:keyPath] && (object == _roomNameLabel || object == _roomAliasLabel || object == _participantsLabel))
|
||||
{
|
||||
// Update left constraint of the text fields
|
||||
[object sizeToFit];
|
||||
[self alignTextFields];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user