diff --git a/Riot/Generated/InfoPlist.swift b/Riot/Generated/InfoPlist.swift index b9784e4003..a2d4e486e5 100644 --- a/Riot/Generated/InfoPlist.swift +++ b/Riot/Generated/InfoPlist.swift @@ -35,6 +35,7 @@ internal enum InfoPlist { internal static let nsMicrophoneUsageDescription: String = _document["NSMicrophoneUsageDescription"] internal static let nsPhotoLibraryUsageDescription: String = _document["NSPhotoLibraryUsageDescription"] internal static let nsSiriUsageDescription: String = _document["NSSiriUsageDescription"] + internal static let nsUserActivityTypes: [String] = _document["NSUserActivityTypes"] internal static let uiBackgroundModes: [String] = _document["UIBackgroundModes"] internal static let uiLaunchStoryboardName: String = _document["UILaunchStoryboardName"] internal static let uiRequiredDeviceCapabilities: [String] = _document["UIRequiredDeviceCapabilities"] diff --git a/Riot/Managers/Activities/UserActivities.h b/Riot/Managers/Activities/UserActivities.h new file mode 100644 index 0000000000..f283af7e1f --- /dev/null +++ b/Riot/Managers/Activities/UserActivities.h @@ -0,0 +1,37 @@ +// +// Copyright 2021 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. +// + +#ifndef UserActivities_h +#define UserActivities_h + +#import + +/** + NSUserActivity types for rooms + */ +FOUNDATION_EXPORT NSString *const kUserActivityTypeMatrixRoom; + +/** + UserInfo field for the room id + */ +FOUNDATION_EXPORT NSString *const kUserActivityInfoRoomId; + +/** + UserInfo field for the user id + */ +FOUNDATION_EXPORT NSString *const kUserActivityInfoUserId; + +#endif /* UserActivities_h */ diff --git a/Riot/Managers/Activities/UserActivities.m b/Riot/Managers/Activities/UserActivities.m new file mode 100644 index 0000000000..1c86f8b5d1 --- /dev/null +++ b/Riot/Managers/Activities/UserActivities.m @@ -0,0 +1,21 @@ +// +// Copyright 2021 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 "UserActivities.h" + +NSString *const kUserActivityTypeMatrixRoom = @"org.matrix.room"; +NSString *const kUserActivityInfoRoomId = @"roomID"; +NSString *const kUserActivityInfoUserId = @"userID"; diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 179bcbbc13..b1b224fd2a 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -58,6 +58,8 @@ #import "Riot-Swift.h" #import "PushNotificationService.h" +#import "UserActivities.h" + //#define MX_CALL_STACK_OPENWEBRTC #ifdef MX_CALL_STACK_OPENWEBRTC #import @@ -748,13 +750,22 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserAct { continueUserActivity = [self handleUniversalLink:userActivity]; } + else if ([userActivity.activityType isEqualToString:kUserActivityTypeMatrixRoom]) + { + NSString *roomID = userActivity.userInfo[kUserActivityInfoRoomId]; + if (!roomID) + return continueUserActivity; + + [self navigateToRoomById:roomID]; + continueUserActivity = YES; + } else if ([userActivity.activityType isEqualToString:INStartAudioCallIntentIdentifier] || [userActivity.activityType isEqualToString:INStartVideoCallIntentIdentifier]) { INInteraction *interaction = userActivity.interaction; // roomID provided by Siri intent - NSString *roomID = userActivity.userInfo[@"roomID"]; + NSString *roomID = userActivity.userInfo[kUserActivityInfoRoomId]; // We've launched from calls history list if (!roomID) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 301c568ba8..947e2ed585 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -16,6 +16,8 @@ limitations under the License. */ +@import CoreSpotlight; + #import "RoomViewController.h" #import "RoomDataSource.h" @@ -128,6 +130,8 @@ #import "MXSDKOptions.h" +#import "UserActivities.h" + #import "Riot-Swift.h" NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNotification"; @@ -588,6 +592,8 @@ - (void)viewWillAppear:(BOOL)animated notificationTaskProfile = [MXSDKOptions.sharedInstance.profiler startMeasuringTaskWithName:AnalyticsNoficationsTimeToDisplayContent category:AnalyticsNoficationsCategory]; } + + [self becomeCurrentActivity]; } - (void)viewWillDisappear:(BOOL)animated @@ -1991,6 +1997,50 @@ - (void)setupActions { roomInputView.actionsBar.actionItems = actionItems; } +- (void)becomeCurrentActivity +{ + if (!self.userActivity) { + self.userActivity = [[NSUserActivity alloc] initWithActivityType:kUserActivityTypeMatrixRoom]; + } + + self.userActivity.title = self.roomDataSource.room.summary.displayname; + self.userActivity.requiredUserInfoKeys = [[NSSet alloc] initWithObjects:kUserActivityInfoRoomId, nil]; + + // user info + NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init]; + [userInfo setObject:self.roomDataSource.roomId forKey:kUserActivityInfoRoomId]; + if ([self.roomDataSource.room isDirect]) { + [userInfo setObject:self.roomDataSource.room.directUserId forKey:kUserActivityInfoUserId]; + } + self.userActivity.userInfo = userInfo; + + // TODO: add a NSUserActivityDelegate to save the current text in the userinfo of the activity + // self.userActivity.delegate = self; + // self.userActivity.needsSave = true; + self.userActivity.persistentIdentifier = self.roomDataSource.roomId; + + self.userActivity.eligibleForHandoff = true; + self.userActivity.eligibleForSearch = true; + self.userActivity.eligibleForPrediction = true; + + CSSearchableItemAttributeSet *contentAttribute; + if (@available(iOS 14.0, *)) { + contentAttribute = [[CSSearchableItemAttributeSet alloc] initWithContentType:UTTypeItem]; + } else { + contentAttribute = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:@"public.item"]; + } + + contentAttribute.title = self.roomDataSource.room.summary.displayname; + contentAttribute.displayName = self.roomDataSource.room.summary.displayname; + contentAttribute.contentDescription = self.roomDataSource.room.summary.lastMessage.text; + + // TODO: contentAttribute.thumbnailURL = + // TODO: accountHandles of everyone in the room + contentAttribute.instantMessageAddresses = [[NSArray alloc] initWithObjects:self.roomDataSource.roomId, nil]; + + self.userActivity.contentAttributeSet = contentAttribute; +} + - (void)roomInputToolbarViewPresentStickerPicker { // Search for the sticker picker widget in the user account diff --git a/Riot/SupportingFiles/Info.plist b/Riot/SupportingFiles/Info.plist index 5bcda43e69..7accfad9e3 100644 --- a/Riot/SupportingFiles/Info.plist +++ b/Riot/SupportingFiles/Info.plist @@ -65,6 +65,10 @@ The photo library is used to send photos and videos. NSSiriUsageDescription Siri is used to perform calls even from the lock screen. + NSUserActivityTypes + + org.matrix.room + UIBackgroundModes audio