Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefill Email Field on Registrations #3173

Merged
merged 5 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Improvements:
* Verification requests: Hide incoming request modal when it is no more pending (#3033).
* Self-verification: Do not display incoming self verification requests at the top of the Complete Security screen.
* Verification: Do not talk about QR code if only emoji is possible (#3035).
* Registration: Prefill email field when opened with universal link (PR #3173).

Bug fix:
* AuthenticationViewController: Remove fallback to matrix.org when authentication failed (PR #3165).
Expand Down
6 changes: 6 additions & 0 deletions Riot.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
6E6F1CB1244E00FD0068B78B /* LocalContactsSectionHeaderContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E6F1CAF244E00FD0068B78B /* LocalContactsSectionHeaderContainerView.m */; };
6E6F1CB324506EC50068B78B /* UITableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E6F1CB224506EC50068B78B /* UITableViewCell.swift */; };
6E6F1CB524506FA40068B78B /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E6F1CB424506FA40068B78B /* UITableView.swift */; };
6E75C3E32458797D00AF497D /* UniversalLink.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E75C3E22458797D00AF497D /* UniversalLink.m */; };
6E7A9E9C243E10E700FD039E /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E7A9E9B243E10E700FD039E /* UIDevice.swift */; };
926FA53F1F4C132000F826C2 /* MXSession+Riot.m in Sources */ = {isa = PBXBuildFile; fileRef = 926FA53E1F4C132000F826C2 /* MXSession+Riot.m */; };
92726A471F58737A004AD26F /* IntentHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 92726A461F58737A004AD26F /* IntentHandler.m */; };
Expand Down Expand Up @@ -913,6 +914,8 @@
6E6F1CB0244E00FD0068B78B /* LocalContactsSectionHeaderContainerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalContactsSectionHeaderContainerView.h; sourceTree = "<group>"; };
6E6F1CB224506EC50068B78B /* UITableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableViewCell.swift; sourceTree = "<group>"; };
6E6F1CB424506FA40068B78B /* UITableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UITableView.swift; sourceTree = "<group>"; };
6E75C3E12458797D00AF497D /* UniversalLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UniversalLink.h; sourceTree = "<group>"; };
6E75C3E22458797D00AF497D /* UniversalLink.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UniversalLink.m; sourceTree = "<group>"; };
6E7A9E9B243E10E700FD039E /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = "<group>"; };
926FA53D1F4C132000F826C2 /* MXSession+Riot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MXSession+Riot.h"; sourceTree = "<group>"; };
926FA53E1F4C132000F826C2 /* MXSession+Riot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MXSession+Riot.m"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4339,6 +4342,8 @@
F083BC151E7009EC00A9B29C /* Tools.m */,
B1DB4F0D22316FFF0065DBFA /* UserNameColorGenerator.swift */,
B197B7C5243DE947005ABBF3 /* EncryptionTrustLevelBadgeImageHelper.swift */,
6E75C3E12458797D00AF497D /* UniversalLink.h */,
6E75C3E22458797D00AF497D /* UniversalLink.m */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -5127,6 +5132,7 @@
3232ABC2225B996200AD6A5C /* Themable.swift in Sources */,
32A6001B22C661100042C1D9 /* EditHistoryViewAction.swift in Sources */,
3232ABA7225730E100AD6A5C /* DeviceVerificationStartCoordinator.swift in Sources */,
6E75C3E32458797D00AF497D /* UniversalLink.m in Sources */,
B1D4752721EE4E630067973F /* KeyboardAvoider.swift in Sources */,
B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */,
B1D1BDA622BBAFB500831367 /* ReactionsMenuView.swift in Sources */,
Expand Down
11 changes: 11 additions & 0 deletions Riot/AppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#import "Analytics.h"

#import "ThemeService.h"
#import "UniversalLink.h"

#pragma mark - Notifications
/**
Expand All @@ -42,6 +43,11 @@ extern NSString *const AppDelegateDidValidateEmailNotification;
extern NSString *const AppDelegateDidValidateEmailNotificationSIDKey;
extern NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey;

/**
Posted when the property 'lastHandledUniversalLink' has changed. Notification object and userInfo will be nil.
*/
extern NSString *const AppDelegateUniversalLinkDidChangeNotification;

@interface AppDelegate : UIResponder <UIApplicationDelegate, MXKCallViewControllerDelegate, UISplitViewControllerDelegate, UINavigationControllerDelegate, JitsiViewControllerDelegate, UNUserNotificationCenterDelegate>
{
BOOL isPushRegistered;
Expand Down Expand Up @@ -87,6 +93,11 @@ extern NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey;
// Current selected room id. nil if no room is presently visible.
@property (strong, nonatomic) NSString *visibleRoomId;

/**
Last handled universal link (url will be formatted for several hash keys).
*/
@property (nonatomic, readonly) UniversalLink *lastHandledUniversalLink;

// New message sound id.
@property (nonatomic, readonly) SystemSoundID messageSound;

Expand Down
22 changes: 16 additions & 6 deletions Riot/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@
NSString *const AppDelegateDidValidateEmailNotificationSIDKey = @"AppDelegateDidValidateEmailNotificationSIDKey";
NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey = @"AppDelegateDidValidateEmailNotificationClientSecretKey";

NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUniversalLinkDidChangeNotification";

@interface AppDelegate () <PKPushRegistryDelegate, GDPRConsentViewControllerDelegate, KeyVerificationCoordinatorBridgePresenterDelegate, ServiceTermsModalCoordinatorBridgePresenterDelegate>
{
/**
Expand Down Expand Up @@ -2038,6 +2040,19 @@ - (BOOL)handleUniversalLink:(NSUserActivity*)userActivity
// iOS Patch: fix vector.im urls before using it
webURL = [Tools fixURLWithSeveralHashKeys:webURL];

// Extract required parameters from the link
NSArray<NSString*> *pathParams;
NSMutableDictionary *queryParams;
[self parseUniversalLinkFragment:webURL.absoluteString outPathParams:&pathParams outQueryParams:&queryParams];

UniversalLink *newLink = [[UniversalLink alloc] initWithUrl:webURL pathParams:pathParams queryParams:queryParams];
if (![_lastHandledUniversalLink isEqual:newLink])
{
_lastHandledUniversalLink = [[UniversalLink alloc] initWithUrl:webURL pathParams:pathParams queryParams:queryParams];
// notify this change
[[NSNotificationCenter defaultCenter] postNotificationName:AppDelegateUniversalLinkDidChangeNotification object:nil];
}

if ([webURL.path hasPrefix:@"/config"])
{
return [self handleServerProvionningLink:webURL];
Expand Down Expand Up @@ -2098,12 +2113,7 @@ - (BOOL)handleUniversalLink:(NSUserActivity*)userActivity
}

MXIdentityService *identityService = [[MXIdentityService alloc] initWithIdentityServer:identityServer accessToken:nil andHomeserverRestClient:homeserverRestClient];

// Extract required parameters from the link
NSArray<NSString*> *pathParams;
NSMutableDictionary *queryParams;
[self parseUniversalLinkFragment:webURL.absoluteString outPathParams:&pathParams outQueryParams:&queryParams];


NSString *clientSecret = queryParams[@"client_secret"];
NSString *sid = queryParams[@"sid"];

Expand Down
31 changes: 31 additions & 0 deletions Riot/Modules/Authentication/AuthenticationViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ @interface AuthenticationViewController () <AuthFallBackViewControllerDelegate,
*/
id kThemeServiceDidChangeThemeNotificationObserver;

/**
Observe AppDelegateUniversalLinkDidChangeNotification to handle universal link changes.
*/
id universalLinkDidChangeNotificationObserver;

/**
Server discovery.
*/
Expand Down Expand Up @@ -143,7 +148,12 @@ - (void)viewDidLoad
[self userInterfaceThemeDidChange];

}];
universalLinkDidChangeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:AppDelegateUniversalLinkDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) {
[self updateUniversalLink];
}];

[self userInterfaceThemeDidChange];
[self updateUniversalLink];
}

- (void)userInterfaceThemeDidChange
Expand Down Expand Up @@ -218,6 +228,20 @@ - (void)userInterfaceThemeDidChange
[self setNeedsStatusBarAppearanceUpdate];
}

- (void)updateUniversalLink
{
UniversalLink *link = [AppDelegate theDelegate].lastHandledUniversalLink;
if (link)
{
NSString *emailAddress = link.queryParams[@"email"];
if (emailAddress && self.authInputsView)
{
AuthInputsView *inputsView = (AuthInputsView *)self.authInputsView;
inputsView.emailTextField.text = emailAddress;
}
}
}

- (UIStatusBarStyle)preferredStatusBarStyle
{
return ThemeService.shared.theme.statusBarStyle;
Expand Down Expand Up @@ -264,6 +288,12 @@ - (void)destroy
kThemeServiceDidChangeThemeNotificationObserver = nil;
}

if (universalLinkDidChangeNotificationObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:universalLinkDidChangeNotificationObserver];
universalLinkDidChangeNotificationObserver = nil;
}

autoDiscovery = nil;
_keyVerificationCoordinatorBridgePresenter = nil;
}
Expand Down Expand Up @@ -668,6 +698,7 @@ - (void)handleAuthenticationSession:(MXAuthenticationSession *)authSession
if ([self.authInputsView isKindOfClass:AuthInputsView.class])
{
authInputsview = (AuthInputsView*)self.authInputsView;
[self updateUniversalLink];
}

// Hide "Forgot password" and "Log in" buttons in case of SSO
Expand Down
35 changes: 35 additions & 0 deletions Riot/Utils/UniversalLink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
Copyright 2020 Vector Creations 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 <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface UniversalLink : NSObject

@property (nonatomic, copy, readonly) NSURL *url;

@property (nonatomic, copy, readonly) NSArray<NSString*> *pathParams;

@property (nonatomic, copy, readonly) NSDictionary<NSString*, NSString*> *queryParams;

- (id)initWithUrl:(NSURL *)url
pathParams:(NSArray<NSString*> *)pathParams
queryParams:(NSDictionary<NSString*, NSString*> *)queryParams;

@end

NS_ASSUME_NONNULL_END
60 changes: 60 additions & 0 deletions Riot/Utils/UniversalLink.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
Copyright 2020 Vector Creations 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 "UniversalLink.h"

@implementation UniversalLink

- (id)initWithUrl:(NSURL *)url pathParams:(NSArray<NSString *> *)pathParams queryParams:(NSDictionary<NSString *,NSString *> *)queryParams
{
self = [super init];
if (self)
{
_url = url;
_pathParams = pathParams;
_queryParams = queryParams;
}
return self;
}

- (BOOL)isEqual:(id)other
{
if (other == self)
return YES;

if (![other isKindOfClass:UniversalLink.class])
return NO;

UniversalLink *otherLink = (UniversalLink *)other;

return [_url isEqual:otherLink.url]
&& [_pathParams isEqualToArray:otherLink.pathParams]
&& [_queryParams isEqualToDictionary:otherLink.queryParams];
}

- (NSUInteger)hash
{
NSUInteger prime = 31;
NSUInteger result = 1;

result = prime * result + [_url hash];
result = prime * result + [_pathParams hash];
result = prime * result + [_queryParams hash];

return result;
}

@end