-
Notifications
You must be signed in to change notification settings - Fork 503
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
Target SiriIntents
: Split IntentHandler
into smaller files (#6203)
#6365
Merged
pixlwave
merged 18 commits into
element-hq:develop
from
wtimme:feature/6203-Split-IntentHandler-into-smaller-files
Jul 6, 2022
Merged
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
2c44e1b
Add protocol `ContactResolving`
wtimme 0fda5d7
Let the `IntentHandler` implement `ContactResolving` (#6203)
wtimme 02a56db
Prepare the separation of the contact resolver from the intents handl…
wtimme f414324
Move the implementation of `ContactResolving` to a dedicated class (#…
wtimme c21e8e3
Move `ContactResolver` to a dedicated file (#6203)
wtimme 0880e91
Prepare the separation of the `StartAudioCallIntentHandler` from `Int…
wtimme 6977afb
Move the implementation of `INStartAudioCallIntentHandling` to a dedi…
wtimme 6abb4ff
Prepare the separation of the `StartVideoCallIntentHandler` from `Int…
wtimme 6ca57b6
Move the implementation of `INStartVideoCallIntentHandling` to a dedi…
wtimme 52114cc
Prepare the separation of the `SendMessageIntentHandler` from `Intent…
wtimme 4507b66
Move the implementation of `INSendMessageIntentHandling` to a dedicat…
wtimme e4b12b9
Remove unused property (#6203)
wtimme 3a3b1a9
Return `nil` if the requested intent cannot be handled (#6203)
wtimme b6ff75b
Initialize the intent handlers _after_ everything else is configured …
wtimme 5a63be1
Add changelog entry
wtimme 3ac7f0a
Move curly braces in Objective-C to dedicated lines
wtimme 4cf16e9
Inject the `ContactResolver` into the intent handlers during initiali…
wtimme 6e761f8
Prefer forward-declaration over import in Objective-C header files
wtimme File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// | ||
// Copyright 2022 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 <Foundation/Foundation.h> | ||
#import "GeneratedInterface-Swift.h" | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface ContactResolver: NSObject <ContactResolving> | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// | ||
// Copyright 2022 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 "ContactResolver.h" | ||
@import Intents; | ||
#import "MXKAccountManager.h" | ||
|
||
@implementation ContactResolver | ||
|
||
- (void)resolveContacts:(nullable NSArray<INPerson *> *)contacts | ||
withCompletion:(void (^)(NSArray<INPersonResolutionResult *> * _Nonnull))completion { | ||
if (contacts.count == 0) | ||
{ | ||
completion(@[[INPersonResolutionResult needsValue]]); | ||
return; | ||
} | ||
else | ||
{ | ||
// We don't iterate over array of contacts from passed intent | ||
// since it's hard to imagine scenario with several callee | ||
// so we just extract the first one | ||
INPerson *callee = contacts.firstObject; | ||
|
||
// If this method is called after selection of the appropriate user, it will hold userId of an user to whom we must call | ||
NSString *selectedUserId; | ||
|
||
// Check if the user has selected right room among several direct rooms from previous resolution process run | ||
if (callee.customIdentifier.length) | ||
{ | ||
// If callee will have the same name as one of the contact in the system contacts app | ||
// Siri will pass us this contact in the intent.contacts array and we must provide the same count of | ||
// resolution results as elements count in the intent.contact. | ||
// So we just pass the same result at all iterations | ||
NSMutableArray *resolutionResults = [NSMutableArray array]; | ||
for (NSInteger i = 0; i < contacts.count; ++i) | ||
[resolutionResults addObject:[INPersonResolutionResult successWithResolvedPerson:callee]]; | ||
completion(resolutionResults); | ||
return; | ||
} | ||
else | ||
{ | ||
// This resolution process run after selecting appropriate user among suggested user list | ||
selectedUserId = callee.personHandle.value; | ||
} | ||
|
||
MXKAccount *account = [MXKAccountManager sharedManager].activeAccounts.firstObject; | ||
if (account) | ||
{ | ||
MXFileStore *fileStore = [[MXFileStore alloc] initWithCredentials:account.mxCredentials]; | ||
[fileStore.roomSummaryStore fetchAllSummaries:^(NSArray<id<MXRoomSummaryProtocol>> * _Nonnull summaries) { | ||
|
||
// Contains userIds of all users with whom the current user has direct chats | ||
// Use set to avoid duplicates | ||
NSMutableSet<NSString *> *directUserIds = [NSMutableSet set]; | ||
|
||
// Contains room summaries for all direct rooms connected with particular userId | ||
NSMutableDictionary<NSString *, NSMutableArray<id<MXRoomSummaryProtocol>> *> *roomSummaries = [NSMutableDictionary dictionary]; | ||
|
||
for (id<MXRoomSummaryProtocol> summary in summaries) | ||
{ | ||
// TODO: We also need to check if joined room members count equals 2 | ||
// It is pointlessly to save rooms with 1 joined member or room with more than 2 joined members | ||
if (summary.isDirect) | ||
{ | ||
NSString *directUserId = summary.directUserId; | ||
|
||
// Collect room summaries only for specified user | ||
if (selectedUserId && ![directUserId isEqualToString:selectedUserId]) | ||
continue; | ||
|
||
// Save userId | ||
[directUserIds addObject:directUserId]; | ||
|
||
// Save associated with diretUserId room summary | ||
NSMutableArray<id<MXRoomSummaryProtocol>> *userRoomSummaries = roomSummaries[directUserId]; | ||
if (userRoomSummaries) | ||
[userRoomSummaries addObject:summary]; | ||
else | ||
roomSummaries[directUserId] = [NSMutableArray arrayWithObject:summary]; | ||
} | ||
} | ||
|
||
[fileStore asyncUsersWithUserIds:directUserIds.allObjects success:^(NSArray<MXUser *> * _Nonnull users) { | ||
|
||
// Find users whose display name contains string presented us by Siri | ||
NSMutableArray<MXUser *> *matchingUsers = [NSMutableArray array]; | ||
for (MXUser *user in users) | ||
{ | ||
if (!user.displayname) | ||
continue; | ||
|
||
if (!NSEqualRanges([callee.displayName rangeOfString:user.displayname options:NSCaseInsensitiveSearch], (NSRange){NSNotFound,0})) | ||
{ | ||
[matchingUsers addObject:user]; | ||
} | ||
} | ||
|
||
NSMutableArray<INPerson *> *persons = [NSMutableArray array]; | ||
|
||
if (matchingUsers.count == 1) | ||
{ | ||
MXUser *user = matchingUsers.firstObject; | ||
|
||
// Provide to the user a list of direct rooms to choose from | ||
NSArray<id<MXRoomSummaryProtocol>> *summaries = roomSummaries[user.userId]; | ||
for (id<MXRoomSummaryProtocol> summary in summaries) | ||
{ | ||
INPersonHandle *personHandle = [[INPersonHandle alloc] initWithValue:user.userId type:INPersonHandleTypeUnknown]; | ||
|
||
// For rooms we try to use room display name | ||
NSString *displayName = summary.displayname ? summary.displayname : user.displayname; | ||
|
||
INPerson *person = [[INPerson alloc] initWithPersonHandle:personHandle | ||
nameComponents:nil | ||
displayName:displayName | ||
image:nil | ||
contactIdentifier:nil | ||
customIdentifier:summary.roomId]; | ||
|
||
[persons addObject:person]; | ||
} | ||
} | ||
else if (matchingUsers.count > 1) | ||
{ | ||
// Provide to the user a list of users to choose from | ||
// This is the case when there are several users with the same name | ||
for (MXUser *user in matchingUsers) | ||
{ | ||
INPersonHandle *personHandle = [[INPersonHandle alloc] initWithValue:user.userId type:INPersonHandleTypeUnknown]; | ||
INPerson *person = [[INPerson alloc] initWithPersonHandle:personHandle | ||
nameComponents:nil | ||
displayName:user.displayname | ||
image:nil | ||
contactIdentifier:nil | ||
customIdentifier:nil]; | ||
|
||
[persons addObject:person]; | ||
} | ||
} | ||
|
||
if (persons.count == 0) | ||
{ | ||
completion(@[[INPersonResolutionResult unsupported]]); | ||
} | ||
else if (persons.count == 1) | ||
{ | ||
completion(@[[INPersonResolutionResult successWithResolvedPerson:persons.firstObject]]); | ||
} | ||
else | ||
{ | ||
completion(@[[INPersonResolutionResult disambiguationWithPeopleToDisambiguate:persons]]); | ||
} | ||
} failure:nil]; | ||
}]; | ||
} | ||
else | ||
{ | ||
completion(@[[INPersonResolutionResult notRequired]]); | ||
} | ||
} | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// | ||
// Copyright 2022 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 Intents | ||
|
||
@objc protocol ContactResolving { | ||
func resolveContacts(_ contacts: [INPerson]?, | ||
withCompletion completion: @escaping ([INPersonResolutionResult]) -> Void) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our objc style is to have
{
on the next line.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing that out! Nowadays, I do not spend time thinking about code formatting, since the projects that I am working on usually have automatic code formatting set up. Maybe that's something that could be incorporated into this repository, even though the Objective-C code will likely be discarded once Element-X sees mass adoption.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that would be nice. We're currently adding swiftformat to ElementX which should make life much better over there!
BTW, I don't think this one was resolved by your last commit.