diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift
index b9c639f158..377a4b80ff 100644
--- a/Config/BuildSettings.swift
+++ b/Config/BuildSettings.swift
@@ -256,6 +256,7 @@ final class BuildSettings: NSObject {
static let homeScreenShowFavouritesTab: Bool = true
static let homeScreenShowPeopleTab: Bool = true
static let homeScreenShowRoomsTab: Bool = true
+ static let homeScreenShowCallsTab: Bool = true
static let homeScreenShowCommunitiesTab: Bool = true
// MARK: - General Settings Screen
diff --git a/Riot/Assets/Base.lproj/Main.storyboard b/Riot/Assets/Base.lproj/Main.storyboard
index 885be7db74..e155910177 100644
--- a/Riot/Assets/Base.lproj/Main.storyboard
+++ b/Riot/Assets/Base.lproj/Main.storyboard
@@ -122,7 +122,7 @@
-
+
@@ -147,6 +147,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -231,6 +250,7 @@
+
@@ -497,12 +517,14 @@
-
+
+
-
+
+
@@ -511,5 +533,8 @@
+
+
+
diff --git a/Riot/Assets/Images.xcassets/Common/start_call.imageset/Contents.json b/Riot/Assets/Images.xcassets/Common/start_call.imageset/Contents.json
new file mode 100644
index 0000000000..cf4d858ce9
--- /dev/null
+++ b/Riot/Assets/Images.xcassets/Common/start_call.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "start_call.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "start_call@2x.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "start_call@3x.png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Riot/Assets/Images.xcassets/Common/start_call.imageset/start_call.png b/Riot/Assets/Images.xcassets/Common/start_call.imageset/start_call.png
new file mode 100644
index 0000000000..a8540b165d
Binary files /dev/null and b/Riot/Assets/Images.xcassets/Common/start_call.imageset/start_call.png differ
diff --git a/Riot/Assets/Images.xcassets/Common/start_call.imageset/start_call@2x.png b/Riot/Assets/Images.xcassets/Common/start_call.imageset/start_call@2x.png
new file mode 100644
index 0000000000..0281abca30
Binary files /dev/null and b/Riot/Assets/Images.xcassets/Common/start_call.imageset/start_call@2x.png differ
diff --git a/Riot/Assets/Images.xcassets/Common/start_call.imageset/start_call@3x.png b/Riot/Assets/Images.xcassets/Common/start_call.imageset/start_call@3x.png
new file mode 100644
index 0000000000..920d3f8fa6
Binary files /dev/null and b/Riot/Assets/Images.xcassets/Common/start_call.imageset/start_call@3x.png differ
diff --git a/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/Contents.json b/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/Contents.json
new file mode 100644
index 0000000000..5ce068333f
--- /dev/null
+++ b/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/Contents.json
@@ -0,0 +1,26 @@
+{
+ "images" : [
+ {
+ "filename" : "tab_calls.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "tab_calls@2x.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "tab_calls@3x.png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+}
diff --git a/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/tab_calls.png b/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/tab_calls.png
new file mode 100644
index 0000000000..53fe67a863
Binary files /dev/null and b/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/tab_calls.png differ
diff --git a/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/tab_calls@2x.png b/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/tab_calls@2x.png
new file mode 100644
index 0000000000..e286a99a3b
Binary files /dev/null and b/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/tab_calls@2x.png differ
diff --git a/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/tab_calls@3x.png b/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/tab_calls@3x.png
new file mode 100644
index 0000000000..989b1bcca0
Binary files /dev/null and b/Riot/Assets/Images.xcassets/TabBar/tab_calls.imageset/tab_calls@3x.png differ
diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings
index 4ddccf8948..cae9c345ce 100644
--- a/Riot/Assets/de.lproj/Vector.strings
+++ b/Riot/Assets/de.lproj/Vector.strings
@@ -12,6 +12,7 @@
"title_favourites" = "Favoriten";
"title_people" = "Personen";
"title_rooms" = "Räume";
+"title_calls" = "Anrufe";
"warning" = "Warnung";
"remove" = "Entferne";
"start" = "Starte";
@@ -82,6 +83,7 @@
"room_recents_favourites_section" = "FAVORITEN";
"room_recents_people_section" = "PERSONEN";
"room_recents_conversations_section" = "RÄUME";
+"room_recents_calls_section" = "ANRUFE";
"room_recents_no_conversation" = "Keine Räume";
"room_recents_low_priority_section" = "NIEDRIGE PRIORITÄT";
"room_recents_invites_section" = "EINLADUNGEN";
@@ -1245,6 +1247,8 @@
"rooms_empty_view_title" = "Räume";
"people_empty_view_information" = "Sicher kommunizieren mit allen. Drücke + um Leute hinzuzufügen.";
"people_empty_view_title" = "Leute";
+"calls_empty_view_title" = "Anrufe";
+"calls_empty_view_information" = "Eingehende und ausgehende Anrufe werden hier gelistet. Drücke + um einen Anruf von der Wähltastatur zu starten.";
// MARK: - Favourites
diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings
index ef355b1838..ea52b52fb7 100644
--- a/Riot/Assets/en.lproj/Vector.strings
+++ b/Riot/Assets/en.lproj/Vector.strings
@@ -26,6 +26,7 @@
"title_people" = "People";
"title_rooms" = "Rooms";
"title_groups" = "Communities";
+"title_calls" = "Calls";
"warning" = "Warning";
// Actions
@@ -213,6 +214,7 @@
"room_recents_favourites_section" = "FAVOURITES";
"room_recents_people_section" = "PEOPLE";
"room_recents_conversations_section" = "ROOMS";
+"room_recents_calls_section" = "CALLS";
"room_recents_no_conversation" = "No rooms";
"room_recents_low_priority_section" = "LOW PRIORITY";
"room_recents_server_notice_section" = "SYSTEM ALERTS";
@@ -234,6 +236,10 @@
"people_empty_view_information" = "Chat securely with anyone.
Tap the + to start adding people.";
+// Calls tab
+"calls_empty_view_title" = "Calls";
+"calls_empty_view_information" = "Incoming and outgoing calls are listed here. Tap the + to start a call from the dial pad";
+
// Rooms tab
"room_directory_no_public_room" = "No public rooms available";
diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift
index 65511e31cd..485d893078 100644
--- a/Riot/Generated/Images.swift
+++ b/Riot/Generated/Images.swift
@@ -77,6 +77,7 @@ internal class Asset: NSObject {
internal static let shareActionButton = ImageAsset(name: "share_action_button")
internal static let shrinkIcon = ImageAsset(name: "shrink_icon")
internal static let smartphone = ImageAsset(name: "smartphone")
+ internal static let startCall = ImageAsset(name: "start_call")
internal static let startChat = ImageAsset(name: "start_chat")
internal static let touchidIcon = ImageAsset(name: "touchid_icon")
internal static let addGroupParticipant = ImageAsset(name: "add_group_participant")
@@ -242,6 +243,7 @@ internal class Asset: NSObject {
internal static let spaceTypeIcon = ImageAsset(name: "space_type_icon")
internal static let spaceUserIcon = ImageAsset(name: "space_user_icon")
internal static let spacesMore = ImageAsset(name: "spaces_more")
+ internal static let tabCalls = ImageAsset(name: "tab_calls")
internal static let tabFavourites = ImageAsset(name: "tab_favourites")
internal static let tabGroups = ImageAsset(name: "tab_groups")
internal static let tabHome = ImageAsset(name: "tab_home")
diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift
index 755555512c..9394459873 100644
--- a/Riot/Generated/Strings.swift
+++ b/Riot/Generated/Strings.swift
@@ -799,6 +799,14 @@ public class VectorL10n: NSObject {
public static var callbarReturn: String {
return VectorL10n.tr("Vector", "callbar_return")
}
+ /// Incoming and outgoing calls are listed here. Tap the + to start a call from the dial pad
+ public static var callsEmptyViewInformation: String {
+ return VectorL10n.tr("Vector", "calls_empty_view_information")
+ }
+ /// Calls
+ public static var callsEmptyViewTitle: String {
+ return VectorL10n.tr("Vector", "calls_empty_view_title")
+ }
/// Camera
public static var camera: String {
return VectorL10n.tr("Vector", "camera")
@@ -5351,6 +5359,10 @@ public class VectorL10n: NSObject {
public static var roomPromptResend: String {
return VectorL10n.tr("Vector", "room_prompt_resend")
}
+ /// CALLS
+ public static var roomRecentsCallsSection: String {
+ return VectorL10n.tr("Vector", "room_recents_calls_section")
+ }
/// ROOMS
public static var roomRecentsConversationsSection: String {
return VectorL10n.tr("Vector", "room_recents_conversations_section")
@@ -7107,6 +7119,10 @@ public class VectorL10n: NSObject {
public static var `switch`: String {
return VectorL10n.tr("Vector", "switch")
}
+ /// Calls
+ public static var titleCalls: String {
+ return VectorL10n.tr("Vector", "title_calls")
+ }
/// Copy link to thread
public static var threadCopyLinkToThread: String {
return VectorL10n.tr("Vector", "thread_copy_link_to_thread")
diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift
index e034f28f51..61ad3240ba 100644
--- a/Riot/Managers/Settings/RiotSettings.swift
+++ b/Riot/Managers/Settings/RiotSettings.swift
@@ -269,6 +269,9 @@ final class RiotSettings: NSObject {
@UserDefault(key: "homeScreenShowRoomsTab", defaultValue: BuildSettings.homeScreenShowRoomsTab, storage: defaults)
var homeScreenShowRoomsTab
+ @UserDefault(key: "homeScreenShowCallsTab", defaultValue: BuildSettings.homeScreenShowCallsTab, storage: defaults)
+ var homeScreenShowCallsTab
+
@UserDefault(key: "homeScreenShowCommunitiesTab", defaultValue: BuildSettings.homeScreenShowCommunitiesTab, storage: defaults)
var homeScreenShowCommunitiesTab
diff --git a/Riot/Modules/Calls/CallsViewController.h b/Riot/Modules/Calls/CallsViewController.h
new file mode 100644
index 0000000000..d894834238
--- /dev/null
+++ b/Riot/Modules/Calls/CallsViewController.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 CallsViewController_h
+#define CallsViewController_h
+
+#import "RecentsViewController.h"
+
+/**
+ 'CallsViewController' instance is used to display/filter the direct rooms and a list of contacts.
+ */
+@interface CallsViewController : RecentsViewController
+
++ (instancetype)instantiate;
+
+/**
+ Scroll the next room with missed notifications to the top.
+ */
+- (void)scrollToNextRoomWithMissedNotifications;
+
+@end
+
+
+#endif /* CallsViewController_h */
diff --git a/Riot/Modules/Calls/CallsViewController.m b/Riot/Modules/Calls/CallsViewController.m
new file mode 100644
index 0000000000..7a99412488
--- /dev/null
+++ b/Riot/Modules/Calls/CallsViewController.m
@@ -0,0 +1,171 @@
+//
+// 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
+
+#import "CallsViewController.h"
+
+#import "UIViewController+RiotSearch.h"
+
+#import "RageShakeManager.h"
+
+#import "RecentsDataSource.h"
+#import "RecentTableViewCell.h"
+
+#import "Riot-Swift.h"
+
+@interface CallsViewController ()
+{
+ NSInteger callRoomsSectionNumber;
+ RecentsDataSource *recentsDataSource;
+}
+
+@property(nonatomic) SpaceMembersCoordinatorBridgePresenter *spaceMembersCoordinatorBridgePresenter;
+
+@end
+
+@implementation CallsViewController
+
++ (instancetype)instantiate
+{
+ UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
+ CallsViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"CallsViewController"];
+ return viewController;
+}
+
+- (void)finalizeInit
+{
+ [super finalizeInit];
+
+ callRoomsSectionNumber = 0;
+
+ self.screenName = @"Calls";
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ // Do any additional setup after loading the view, typically from a nib.
+
+ self.view.accessibilityIdentifier = @"CallsVCView";
+ self.recentsTableView.accessibilityIdentifier = @"CallsVCTableView";
+
+ // Tag the recents table with the its recents data source mode.
+ // This will be used by the shared RecentsDataSource instance for sanity checks (see UITableViewDataSource methods).
+ self.recentsTableView.tag = RecentsDataSourceModeSipCalls;
+
+ // Add the (+) button programmatically
+ plusButtonImageView = [self vc_addFABWithImage:[UIImage imageNamed:@"start_call"]
+ target:self
+ action:@selector(onPlusButtonPressed)];
+}
+
+- (void)didReceiveMemoryWarning
+{
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+ [super viewWillAppear:animated];
+
+ [AppDelegate theDelegate].masterTabBarController.navigationItem.title = [VectorL10n titleCalls];
+ [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.shared.theme.tintColor;
+
+ if ([self.dataSource isKindOfClass:RecentsDataSource.class])
+ {
+ // Take the lead on the shared data source.
+ recentsDataSource = (RecentsDataSource*)self.dataSource;
+ recentsDataSource.areSectionsShrinkable = NO;
+ [recentsDataSource setDelegate:self andRecentsDataSourceMode:RecentsDataSourceModeSipCalls];
+ }
+}
+
+#pragma mark - UITableView delegate
+
+- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
+{
+ return 0.0;
+}
+
+- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
+{
+ return nil;
+}
+
+#pragma mark - Override RecentsViewController
+
+- (void)refreshCurrentSelectedCell:(BOOL)forceVisible
+{
+ // Check whether the recents data source is correctly configured.
+ if (recentsDataSource.recentsDataSourceMode != RecentsDataSourceModeSipCalls)
+ {
+ return;
+ }
+
+ [super refreshCurrentSelectedCell:forceVisible];
+}
+
+- (void)onPlusButtonPressed
+{
+ [super openDialpad];
+}
+
+#pragma mark -
+
+- (void)scrollToNextRoomWithMissedNotifications
+{
+ // Check whether the recents data source is correctly configured.
+ if (recentsDataSource.recentsDataSourceMode == RecentsDataSourceModeSipCalls)
+ {
+ [self scrollToTheTopTheNextRoomWithMissedNotificationsInSection:recentsDataSource.callsSection];
+ }
+}
+
+#pragma mark - Empty view management
+
+- (void)updateEmptyView
+{
+ [self.emptyView fillWith:[self emptyViewArtwork]
+ title:[VectorL10n callsEmptyViewTitle]
+ informationText:[VectorL10n callsEmptyViewInformation]];
+}
+
+- (UIImage*)emptyViewArtwork
+{
+ if (ThemeService.shared.isCurrentThemeDark)
+ {
+ // TODO: replace with picture calls_empty_screen_artwork_dark
+ return [UIImage imageNamed:@"rooms_empty_screen_artwork_dark"];
+ }
+ else
+ {
+ // TODO: replace with picture calls_empty_screen_artwork
+ return [UIImage imageNamed:@"rooms_empty_screen_artwork"];
+ }
+}
+
+#pragma mark - SpaceMembersCoordinatorBridgePresenterDelegate
+
+- (void)spaceMembersCoordinatorBridgePresenterDelegateDidComplete:(SpaceMembersCoordinatorBridgePresenter *)coordinatorBridgePresenter
+{
+ [coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
+ self.spaceMembersCoordinatorBridgePresenter = nil;
+ }];
+}
+
+@end
diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h
index cf6329d0f7..c0c0802cab 100644
--- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h
+++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h
@@ -33,7 +33,8 @@ typedef NS_ENUM(NSInteger, RecentsDataSourceMode)
RecentsDataSourceModeHome = 1,
RecentsDataSourceModeFavourites,
RecentsDataSourceModePeople,
- RecentsDataSourceModeRooms
+ RecentsDataSourceModeRooms,
+ RecentsDataSourceModeSipCalls
};
/**
@@ -77,6 +78,7 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
@property (nonatomic) NSInteger lowPrioritySection;
@property (nonatomic) NSInteger serverNoticeSection;
@property (nonatomic) NSInteger suggestedRoomsSection;
+@property (nonatomic) NSInteger callsSection;
@property (nonatomic, readonly) NSInteger totalVisibleItemCount;
@@ -95,6 +97,11 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
*/
@property (nonatomic, readonly) DiscussionsCount *groupMissedDiscussionsCount;
+/**
+ Counts for call rooms.
+ */
+@property (nonatomic, readonly) DiscussionsCount *callsMissedDiscussionsCount;
+
@property (nonatomic, readonly) SecureBackupBannerDisplay secureBackupBannerDisplay;
@property (nonatomic, readonly) CrossSigningBannerDisplay crossSigningBannerDisplay;
diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m
index 0430b3304c..0cdbbde730 100644
--- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m
+++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m
@@ -36,6 +36,7 @@
#define RECENTSDATASOURCE_SECTION_SERVERNOTICE 0x20
#define RECENTSDATASOURCE_SECTION_PEOPLE 0x40
#define RECENTSDATASOURCE_SECTION_SUGGESTED 0x80
+#define RECENTSDATASOURCE_SECTION_CALLS 0x0100
#define RECENTSDATASOURCE_DEFAULT_SECTION_HEADER_HEIGHT 30.0
@@ -63,7 +64,7 @@ @interface RecentsDataSource() > *)callCellDataArray
+{
+ return self.recentsListService.callRoomListData.rooms;
+}
- (NSInteger)totalVisibleItemCount
{
@@ -165,6 +171,11 @@ - (DiscussionsCount *)groupMissedDiscussionsCount
return self.recentsListService.conversationMissedDiscussionsCount;
}
+- (DiscussionsCount *)callsMissedDiscussionsCount
+{
+ return self.recentsListService.callsMissedDiscussionsCount;
+}
+
#pragma mark -
- (void)setDelegate:(id)delegate andRecentsDataSourceMode:(RecentsDataSourceMode)recentsDataSourceMode
@@ -517,6 +528,11 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
suggestedRoomsSection = sectionsCount++;
}
+
+ if (self.callCellDataArray.count > 0)
+ {
+ callsSection = sectionsCount++;
+ }
}
return sectionsCount;
@@ -573,7 +589,11 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger
{
count = self.suggestedRoomCellDataArray.count;
}
-
+ else if (section == callsSection && !(shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_CALLS))
+ {
+ count = self.callCellDataArray.count;
+ }
+
// Adjust this count according to the potential dragged cell.
if ([self isMovingCellSection:section])
{
@@ -659,6 +679,11 @@ - (NSAttributedString *)attributedStringForHeaderTitleInSection:(NSInteger)secti
count = self.recentsListService.suggestedRoomListData.counts.total.numberOfRooms;
title = [VectorL10n roomRecentsSuggestedRoomsSection];
}
+ else if (section == callsSection)
+ {
+ count = self.callCellDataArray.count;
+ title = [VectorL10n roomRecentsCallsSection];
+ }
if (count && !(section == invitesSection))
{
@@ -717,6 +742,10 @@ - (UIView *)badgeViewForHeaderTitleInSection:(NSInteger)section
{
counts = self.recentsListService.suggestedRoomListData.counts;
}
+ else if (section == callsSection)
+ {
+ counts = self.recentsListService.callRoomListData.counts;
+ }
// Invites are counted as highlights for the badge view display.
NSUInteger numberOfNotifications = counts.total.numberOfNotifications + counts.total.numberOfInvitedRooms;
@@ -810,6 +839,10 @@ - (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame in
{
sectionBitwise = RECENTSDATASOURCE_SECTION_SUGGESTED;
}
+ else if (section == callsSection)
+ {
+ sectionBitwise = RECENTSDATASOURCE_SECTION_CALLS;
+ }
}
if (sectionBitwise)
@@ -943,7 +976,30 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
return tableViewCell;
}
-
+ else if (indexPath.section == callsSection && !self.callCellDataArray.count)
+ {
+ MXKTableViewCell *tableViewCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCell defaultReuseIdentifier]];
+ if (!tableViewCell)
+ {
+ tableViewCell = [[MXKTableViewCell alloc] init];
+ tableViewCell.textLabel.textColor = ThemeService.shared.theme.textSecondaryColor;
+ tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0];
+ tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone;
+ }
+
+ // Check whether a search session is in progress
+ if (self.searchPatternsList)
+ {
+ tableViewCell.textLabel.text = [VectorL10n searchNoResult];
+ }
+ else
+ {
+ tableViewCell.textLabel.text = [VectorL10n roomRecentsNoConversation];
+ }
+
+ return tableViewCell;
+ }
+
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
@@ -1012,7 +1068,14 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
summary = self.suggestedRoomCellDataArray[cellDataIndex];
}
}
-
+ else if (tableSection == callsSection)
+ {
+ if (cellDataIndex < self.callCellDataArray.count)
+ {
+ summary = self.callCellDataArray[cellDataIndex];
+ }
+ }
+
if (summary)
{
return [[MXKRecentCellData alloc] initWithRoomSummary:summary dataSource:self];
@@ -1035,7 +1098,11 @@ - (CGFloat)cellHeightAtIndexPath:(NSIndexPath *)indexPath
{
return 50.0;
}
-
+ if (indexPath.section == callsSection && !self.callCellDataArray.count)
+ {
+ return 50.0;
+ }
+
// Override this method here to use our own cellDataAtIndexPath
id cellData = [self cellDataAtIndexPath:indexPath];
@@ -1184,6 +1251,21 @@ - (NSIndexPath*)cellIndexPathWithRoomId:(NSString*)roomId andMatrixSession:(MXSe
indexPath = [NSIndexPath indexPathForRow:index inSection:serverNoticeSection];
}
}
+
+ if (!indexPath && (callsSection >= 0))
+ {
+ index = [self cellIndexPosWithRoomId:roomId andMatrixSession:matrixSession within:self.callCellDataArray];
+
+ if (index != NSNotFound)
+ {
+ // Check whether the low priority rooms are shrinked
+ if (shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_CALLS)
+ {
+ return nil;
+ }
+ indexPath = [NSIndexPath indexPathForRow:index inSection:callsSection];
+ }
+ }
return indexPath;
}
@@ -1310,6 +1392,10 @@ - (BOOL)isDraggableCellAt:(NSIndexPath*)path
{
return NO;
}
+ if (_recentsDataSourceMode == RecentsDataSourceModeSipCalls)
+ {
+ return NO;
+ }
return (path && ((path.section == favoritesSection) || (path.section == peopleSection) || (path.section == lowPrioritySection) || (path.section == serverNoticeSection) || (path.section == conversationSection)));
}
diff --git a/Riot/Modules/Common/Recents/RecentsViewController.h b/Riot/Modules/Common/Recents/RecentsViewController.h
index a9f46c8ff4..117caaff32 100644
--- a/Riot/Modules/Common/Recents/RecentsViewController.h
+++ b/Riot/Modules/Common/Recents/RecentsViewController.h
@@ -162,6 +162,11 @@ FOUNDATION_EXPORT NSString *const RecentsViewControllerDataReadyNotification;
*/
- (void)leaveEditedRoom;
+/**
+ Make this function accessible to subclass
+ */
+- (void)openDialpad;
+
/**
Update the selected room tag.
*/
diff --git a/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift b/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift
index f37ad11ae3..357368fc65 100644
--- a/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift
+++ b/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift
@@ -40,6 +40,8 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
return invitedRoomListDataFetcherForPeople
case .rooms:
return invitedRoomListDataFetcherForRooms
+ case .sipCalls:
+ return invitedRoomListDataFetcherForCalls
default:
return nil
}
@@ -51,6 +53,8 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
return directRoomListDataFetcherForHome
case .people:
return directRoomListDataFetcherForPeople
+ case .sipCalls:
+ return directRoomListDataFetcherForCalls
default:
return nil
}
@@ -73,9 +77,11 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
private var conversationRoomListDataFetcherForRooms: MXRoomListDataFetcher?
private var directRoomListDataFetcherForHome: MXRoomListDataFetcher?
private var directRoomListDataFetcherForPeople: MXRoomListDataFetcher?
+ private var directRoomListDataFetcherForCalls: MXRoomListDataFetcher?
private var invitedRoomListDataFetcherForHome: MXRoomListDataFetcher?
private var invitedRoomListDataFetcherForPeople: MXRoomListDataFetcher?
private var invitedRoomListDataFetcherForRooms: MXRoomListDataFetcher?
+ private var invitedRoomListDataFetcherForCalls: MXRoomListDataFetcher?
// MARK: - Private
@@ -83,7 +89,8 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
.home: [.invited, .favorited, .directHome, .conversationHome, .lowPriority, .serverNotice, .suggested],
.favourites: [.favorited],
.people: [.invited, .directPeople],
- .rooms: [.invited, .conversationRooms, .suggested]
+ .rooms: [.invited, .conversationRooms, .suggested],
+ .sipCalls: [.invited, .sipCalls]
]
private var allFetchers: [MXRoomListDataFetcher] {
@@ -91,9 +98,11 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
invitedRoomListDataFetcherForHome,
invitedRoomListDataFetcherForPeople,
invitedRoomListDataFetcherForRooms,
+ invitedRoomListDataFetcherForCalls,
favoritedRoomListDataFetcher,
directRoomListDataFetcherForHome,
directRoomListDataFetcherForPeople,
+ directRoomListDataFetcherForCalls,
conversationRoomListDataFetcherForHome,
conversationRoomListDataFetcherForRooms,
lowPriorityRoomListDataFetcher,
@@ -119,6 +128,9 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
if let fetcher = directRoomListDataFetcherForPeople, fetcherTypes.contains(.directPeople) {
result.append(fetcher)
}
+ if let fetcher = directRoomListDataFetcherForCalls, fetcherTypes.contains(.sipCalls) {
+ result.append(fetcher)
+ }
if let fetcher = conversationRoomListDataFetcherForHome, fetcherTypes.contains(.conversationHome) {
result.append(fetcher)
}
@@ -215,7 +227,11 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
guard shouldShowSuggested else { return nil }
return suggestedRoomListDataFetcher?.data
}
-
+ public var callRoomListData: MXRoomListData? {
+ guard shouldShowCalls else { return nil }
+ return directRoomListDataFetcherForCalls?.data
+ }
+
public var favoritedMissedDiscussionsCount: DiscussionsCount {
guard let totalCounts = favoritedRoomListDataFetcher?.data?.counts.total else {
return .zero
@@ -236,6 +252,13 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
let totalCounts = [invitesCount, conversationCount].compactMap { $0 }
return DiscussionsCount(withRoomListDataCounts: totalCounts)
}
+
+ public var callsMissedDiscussionsCount: DiscussionsCount {
+ let invitesCount = invitedRoomListDataFetcherForCalls?.data?.counts.total
+ let callsCount = directRoomListDataFetcherForCalls?.data?.counts.total
+ let totalCounts = [invitesCount, callsCount].compactMap { $0 }
+ return DiscussionsCount(withRoomListDataCounts: totalCounts)
+ }
public var totalVisibleItemCount: Int {
return visibleFetchers.reduce(0, { $0 + ($1.data?.counts.numberOfRooms ?? 0) })
@@ -288,9 +311,11 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
invitedRoomListDataFetcherForHome = nil
invitedRoomListDataFetcherForPeople = nil
invitedRoomListDataFetcherForRooms = nil
+ invitedRoomListDataFetcherForCalls = nil
favoritedRoomListDataFetcher = nil
directRoomListDataFetcherForHome = nil
directRoomListDataFetcherForPeople = nil
+ directRoomListDataFetcherForCalls = nil
conversationRoomListDataFetcherForHome = nil
conversationRoomListDataFetcherForRooms = nil
lowPriorityRoomListDataFetcher = nil
@@ -413,6 +438,10 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
return fetcherTypesForMode[mode]?.contains(.suggested) ?? false
}
+ private var shouldShowCalls: Bool {
+ return fetcherTypesForMode[mode]?.contains(.sipCalls) ?? false
+ }
+
private func fetcher(forSection section: RecentsListServiceSection) -> MXRoomListDataFetcher? {
switch section {
case .invited:
@@ -421,6 +450,8 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
return favoritedRoomListDataFetcher
case .people:
return directRoomListDataFetcher
+ case .sipCalls:
+ return directRoomListDataFetcherForCalls
case .conversation:
return conversationRoomListDataFetcher
case .lowPriority:
@@ -439,6 +470,8 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
return .favorited
} else if fetcher === directRoomListDataFetcher {
return .people
+ } else if fetcher === directRoomListDataFetcherForCalls {
+ return .sipCalls
} else if fetcher === conversationRoomListDataFetcher {
return .conversation
} else if fetcher === lowPriorityRoomListDataFetcher {
@@ -492,6 +525,14 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
return fetcher
}
+ private func createInvitedRoomListDataFetcherForCalls() -> MXRoomListDataFetcher {
+ let fetcher = createCommonRoomListDataFetcher(withDataTypes: [.invited, .sipCall], paginate: false, strictMatches: true)
+ updateInvitedFetcher(fetcher, for: .sipCalls)
+ fetcher.addDelegate(self)
+ fetcher.paginate()
+ return fetcher
+ }
+
private func createDirectRoomListDataFetcherForHome() -> MXRoomListDataFetcher {
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [.direct], paginate: false)
updateDirectFetcher(fetcher, for: .home)
@@ -508,6 +549,14 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
return fetcher
}
+ private func createDirectRoomListDataFetcherForCalls() -> MXRoomListDataFetcher {
+ let fetcher = createCommonRoomListDataFetcher(withDataTypes: [.sipCall], paginate: false)
+ updateDirectFetcher(fetcher, for: .sipCalls)
+ fetcher.addDelegate(self)
+ fetcher.paginate()
+ return fetcher
+ }
+
private func createConversationRoomListDataFetcherForHome() -> MXRoomListDataFetcher {
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [], paginate: false)
updateConversationFetcher(fetcher, for: .home)
@@ -539,10 +588,12 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
invitedRoomListDataFetcherForHome = createCommonRoomListDataFetcher(withDataTypes: [.invited])
invitedRoomListDataFetcherForPeople = createInvitedRoomListDataFetcherForPeople()
invitedRoomListDataFetcherForRooms = createInvitedRoomListDataFetcherForRooms()
+ invitedRoomListDataFetcherForCalls = createInvitedRoomListDataFetcherForCalls()
}
favoritedRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.favorited])
directRoomListDataFetcherForHome = createDirectRoomListDataFetcherForHome()
directRoomListDataFetcherForPeople = createDirectRoomListDataFetcherForPeople()
+ directRoomListDataFetcherForCalls = createDirectRoomListDataFetcherForCalls()
conversationRoomListDataFetcherForHome = createConversationRoomListDataFetcherForHome()
conversationRoomListDataFetcherForRooms = createConversationRoomListDataFetcherForRooms()
lowPriorityRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.lowPriority])
@@ -557,9 +608,12 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
var notDataTypes: MXRoomSummaryDataTypes = [.hidden, .conferenceUser, .space, .invited, .lowPriority]
switch mode {
case .home:
- notDataTypes.insert(.favorited)
+ notDataTypes.insert([.favorited, .sipCall])
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
case .people:
+ notDataTypes.insert([.sipCall])
+ fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
+ case .sipCalls:
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
default:
break
@@ -570,9 +624,12 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
var notDataTypes: MXRoomSummaryDataTypes = [.hidden, .conferenceUser, .lowPriority, .serverNotice, .space]
switch mode {
case .people:
+ notDataTypes.insert([.sipCall])
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
case .rooms:
- notDataTypes.insert([.direct])
+ notDataTypes.insert([.direct, .sipCall])
+ fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
+ case .sipCalls:
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
default:
break
@@ -650,8 +707,9 @@ private struct FetcherTypes: OptionSet {
static let lowPriority = FetcherTypes(rawValue: 1 << 6)
static let serverNotice = FetcherTypes(rawValue: 1 << 7)
static let suggested = FetcherTypes(rawValue: 1 << 8)
+ static let sipCalls = FetcherTypes(rawValue: 1 << 9)
static let none: FetcherTypes = []
static let all: FetcherTypes = [
- .invited, .favorited, .directHome, .directPeople, .conversationHome, .conversationRooms, .lowPriority, .serverNotice, .suggested]
+ .invited, .favorited, .directHome, .directPeople, .sipCalls, .conversationHome, .conversationRooms, .lowPriority, .serverNotice, .suggested]
}
diff --git a/Riot/Modules/Common/Recents/Service/Mock/MockRecentsListService.swift b/Riot/Modules/Common/Recents/Service/Mock/MockRecentsListService.swift
index 7cb3ca4ab1..df6c4bd252 100644
--- a/Riot/Modules/Common/Recents/Service/Mock/MockRecentsListService.swift
+++ b/Riot/Modules/Common/Recents/Service/Mock/MockRecentsListService.swift
@@ -27,7 +27,8 @@ public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
private var _conversationRoomListData: MXRoomListData?
private var _lowPriorityRoomListData: MXRoomListData?
private var _serverNoticeRoomListData: MXRoomListData?
-
+ private var _callRoomListData: MXRoomListData?
+
// swiftlint:disable weak_delegate
private let multicastDelegate: MXMulticastDelegate = MXMulticastDelegate()
// swiftlint:enable weak_delegate
@@ -41,7 +42,8 @@ public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
var conversation: [MockRoomSummary] = []
var lowPriority: [MockRoomSummary] = []
var serverNotice: [MockRoomSummary] = []
-
+ var calls: [MockRoomSummary] = []
+
rooms.forEach { summary in
if summary.isTyped(.invited) {
invited.append(summary)
@@ -72,7 +74,8 @@ public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
_conversationRoomListData = MockRoomListData(withRooms: conversation)
_lowPriorityRoomListData = MockRoomListData(withRooms: lowPriority)
_serverNoticeRoomListData = MockRoomListData(withRooms: serverNotice)
-
+ _callRoomListData = MockRoomListData(withRooms: calls)
+
super.init()
}
@@ -90,6 +93,8 @@ public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
room.dataTypes = .invited
} else if i % 11 == 0 {
room.dataTypes = .serverNotice
+ } else if i % 13 == 0 {
+ room.dataTypes = .sipCall
}
room.displayname = "Room \(i+1)"
if let event = MXEvent(fromJSON: [
@@ -147,6 +152,11 @@ public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
return _serverNoticeRoomListData
}
+ public var callRoomListData: MXRoomListData? {
+ guard mode == .sipCalls else { return nil }
+ return _callRoomListData
+ }
+
public var suggestedRoomListData: MXRoomListData?
public var favoritedMissedDiscussionsCount: DiscussionsCount = .zero
@@ -154,7 +164,9 @@ public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
public var peopleMissedDiscussionsCount: DiscussionsCount = .zero
public var conversationMissedDiscussionsCount: DiscussionsCount = .zero
-
+
+ public var callsMissedDiscussionsCount: DiscussionsCount = .zero
+
public var totalVisibleItemCount: Int {
switch mode {
case .home:
@@ -165,6 +177,8 @@ public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
return peopleRoomListData?.counts.numberOfRooms ?? 0
case .rooms:
return conversationRoomListData?.counts.numberOfRooms ?? 0
+ case .sipCalls:
+ return callRoomListData?.counts.numberOfRooms ?? 0
@unknown default:
return 0
}
@@ -198,6 +212,7 @@ public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
_conversationRoomListData = nil
_lowPriorityRoomListData = nil
_serverNoticeRoomListData = nil
+ _callRoomListData = nil
removeAllDelegates()
}
diff --git a/Riot/Modules/Common/Recents/Service/Mock/MockRoomSummary.swift b/Riot/Modules/Common/Recents/Service/Mock/MockRoomSummary.swift
index c211db025b..8dc2242882 100644
--- a/Riot/Modules/Common/Recents/Service/Mock/MockRoomSummary.swift
+++ b/Riot/Modules/Common/Recents/Service/Mock/MockRoomSummary.swift
@@ -44,6 +44,8 @@ public class MockRoomSummary: NSObject, MXRoomSummaryProtocol {
public var isConferenceUserRoom: Bool = false
+ public var isSipCallRoom: Bool = false
+
public var hiddenFromUser: Bool = false
public var storedHash: UInt = 0
diff --git a/Riot/Modules/Common/Recents/Service/RecentsListServiceProtocol.swift b/Riot/Modules/Common/Recents/Service/RecentsListServiceProtocol.swift
index 72ab08f08d..e2ff99da21 100644
--- a/Riot/Modules/Common/Recents/Service/RecentsListServiceProtocol.swift
+++ b/Riot/Modules/Common/Recents/Service/RecentsListServiceProtocol.swift
@@ -53,6 +53,9 @@ public protocol RecentsListServiceProtocol {
/// Suggested rooms for current mode
var suggestedRoomListData: MXRoomListData? { get }
+ /// Call list
+ var callRoomListData: MXRoomListData? { get }
+
// MARK: Discussion counts
/// Counts for favorite screen
@@ -63,7 +66,10 @@ public protocol RecentsListServiceProtocol {
/// Counts for rooms screen
var conversationMissedDiscussionsCount: DiscussionsCount { get }
-
+
+ /// Counts for rooms screen
+ var callsMissedDiscussionsCount: DiscussionsCount { get }
+
/// Total number of rooms visible in one screen. Can be used to display an empty view
var totalVisibleItemCount: Int { get }
diff --git a/Riot/Modules/Common/Recents/Service/RecentsListServiceSection.swift b/Riot/Modules/Common/Recents/Service/RecentsListServiceSection.swift
index 99ef113532..c6567a64e3 100644
--- a/Riot/Modules/Common/Recents/Service/RecentsListServiceSection.swift
+++ b/Riot/Modules/Common/Recents/Service/RecentsListServiceSection.swift
@@ -21,6 +21,7 @@ public enum RecentsListServiceSection: Int {
case invited
case favorited
case people
+ case sipCalls
case conversation
case lowPriority
case serverNotice
diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m
index c627650af2..5630cf2227 100644
--- a/Riot/Modules/Home/HomeViewController.m
+++ b/Riot/Modules/Home/HomeViewController.m
@@ -392,7 +392,11 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
{
return [recentsDataSource tableView:tableView cellForRowAtIndexPath:indexPath];
}
-
+ if (indexPath.section == recentsDataSource.callsSection && !recentsDataSource.recentsListService.callRoomListData.counts.numberOfRooms)
+ {
+ return [recentsDataSource tableView:tableView cellForRowAtIndexPath:indexPath];
+ }
+
TableViewCellWithCollectionView *tableViewCell = [tableView dequeueReusableCellWithIdentifier:TableViewCellWithCollectionView.defaultReuseIdentifier forIndexPath:indexPath];
tableViewCell.collectionView.tag = indexPath.section;
[tableViewCell.collectionView registerClass:RoomCollectionViewCell.class forCellWithReuseIdentifier:RoomCollectionViewCell.defaultReuseIdentifier];
@@ -481,6 +485,10 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa
{
return [recentsDataSource cellHeightAtIndexPath:indexPath];
}
+ else if (indexPath.section == recentsDataSource.callsSection && !recentsDataSource.recentsListService.callRoomListData.counts.numberOfRooms)
+ {
+ return [recentsDataSource cellHeightAtIndexPath:indexPath];
+ }
else if (indexPath.section == recentsDataSource.secureBackupBannerSection || indexPath.section == recentsDataSource.crossSigningBannerSection)
{
CGFloat height = 0.0;
diff --git a/Riot/Modules/TabBar/MasterTabBarController.h b/Riot/Modules/TabBar/MasterTabBarController.h
index c9948baf9a..80f32d18fd 100644
--- a/Riot/Modules/TabBar/MasterTabBarController.h
+++ b/Riot/Modules/TabBar/MasterTabBarController.h
@@ -23,20 +23,23 @@
#import "PeopleViewController.h"
#import "RoomsViewController.h"
#import "GroupsViewController.h"
+#import "CallsViewController.h"
#define TABBAR_HOME_INDEX 0
#define TABBAR_FAVOURITES_INDEX 1
#define TABBAR_PEOPLE_INDEX 2
#define TABBAR_ROOMS_INDEX 3
#define TABBAR_GROUPS_INDEX 4
-#define TABBAR_COUNT 5
+#define TABBAR_CALLS_INDEX 5
+#define TABBAR_COUNT 6
typedef NS_ENUM(NSUInteger, MasterTabBarIndex) {
MasterTabBarIndexHome = TABBAR_HOME_INDEX,
MasterTabBarIndexFavourites = TABBAR_FAVOURITES_INDEX,
MasterTabBarIndexPeople = TABBAR_PEOPLE_INDEX,
MasterTabBarIndexRooms = TABBAR_ROOMS_INDEX,
- MasterTabBarIndexGroups = TABBAR_GROUPS_INDEX
+ MasterTabBarIndexGroups = TABBAR_GROUPS_INDEX,
+ MasterTabBarIndexCalls = TABBAR_CALLS_INDEX
};
@protocol MasterTabBarControllerDelegate;
@@ -158,6 +161,7 @@ typedef NS_ENUM(NSUInteger, MasterTabBarIndex) {
@property (nonatomic, readonly) PeopleViewController *peopleViewController;
@property (nonatomic, readonly) RoomsViewController *roomsViewController;
@property (nonatomic, readonly) GroupsViewController *groupsViewController;
+@property (nonatomic, readonly) CallsViewController *callsViewController;
// References on the currently selected room
diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m
index bc306b757f..bbce9e82a0 100644
--- a/Riot/Modules/TabBar/MasterTabBarController.m
+++ b/Riot/Modules/TabBar/MasterTabBarController.m
@@ -105,6 +105,11 @@ - (GroupsViewController *)groupsViewController
return (GroupsViewController*)[self viewControllerForClass:GroupsViewController.class];
}
+- (CallsViewController *)callsViewController
+{
+ return (CallsViewController*)[self viewControllerForClass:CallsViewController.class];
+}
+
#pragma mark - Life cycle
- (void)viewDidLoad
@@ -345,7 +350,8 @@ - (void)initializeDataSources
[self.favouritesViewController displayList:recentsDataSource];
[self.peopleViewController displayList:recentsDataSource];
[self.roomsViewController displayList:recentsDataSource];
-
+ [self.callsViewController displayList:recentsDataSource];
+
// Restore the right delegate of the shared recent data source.
id recentsDataSourceDelegate = self.homeViewController;
RecentsDataSourceMode recentsDataSourceMode = RecentsDataSourceModeHome;
@@ -368,7 +374,11 @@ - (void)initializeDataSources
recentsDataSourceDelegate = self.roomsViewController;
recentsDataSourceMode = RecentsDataSourceModeRooms;
break;
-
+ case TABBAR_CALLS_INDEX:
+ recentsDataSourceDelegate = self.callsViewController;
+ recentsDataSourceMode = RecentsDataSourceModeSipCalls;
+ break;
+
default:
break;
}
@@ -459,7 +469,8 @@ - (void)removeMatrixSession:(MXSession *)mxSession
[self.favouritesViewController displayList:nil];
[self.peopleViewController displayList:nil];
[self.roomsViewController displayList:nil];
-
+ [self.callsViewController displayList:nil];
+
[recentsDataSource destroy];
recentsDataSource = nil;
}
@@ -857,6 +868,13 @@ - (void)refreshTabBarBadges
withBadgeColor:(recentsDataSource.groupMissedDiscussionsCount.hasHighlight ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)];
}
}
+
+ if (RiotSettings.shared.homeScreenShowCallsTab)
+ {
+ [self setMissedDiscussionsCount:recentsDataSource.callsMissedDiscussionsCount.numberOfNotified
+ onTabBarItem:TABBAR_CALLS_INDEX
+ withBadgeColor:ThemeService.shared.theme.noticeSecondaryColor];
+ }
}
- (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor
@@ -1084,6 +1102,10 @@ - (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
[self.favouritesViewController scrollToNextRoomWithMissedNotifications];
}
+ else if (item.tag == TABBAR_CALLS_INDEX)
+ {
+ [self.callsViewController scrollToNextRoomWithMissedNotifications];
+ }
}
}
diff --git a/Riot/Modules/TabBar/TabBarCoordinator.swift b/Riot/Modules/TabBar/TabBarCoordinator.swift
index 3e43f7f415..ab67533472 100644
--- a/Riot/Modules/TabBar/TabBarCoordinator.swift
+++ b/Riot/Modules/TabBar/TabBarCoordinator.swift
@@ -268,6 +268,13 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
return groupsViewController
}
+ private func createCallsViewController() -> CallsViewController {
+ let callsViewController: CallsViewController = CallsViewController.instantiate()
+ callsViewController.tabBarItem.tag = Int(TABBAR_CALLS_INDEX)
+ callsViewController.accessibilityLabel = VectorL10n.titleCalls
+ return callsViewController
+ }
+
private func createUnifiedSearchController() -> UnifiedSearchViewController {
let viewController: UnifiedSearchViewController = UnifiedSearchViewController.instantiate()
@@ -340,6 +347,11 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
viewControllers.append(groupsViewController)
}
+ if RiotSettings.shared.homeScreenShowCallsTab {
+ let callsViewController = self.createCallsViewController()
+ viewControllers.append(callsViewController)
+ }
+
tabBarController.updateViewControllers(viewControllers)
}
diff --git a/changelog.d/5782.feature b/changelog.d/5782.feature
new file mode 100644
index 0000000000..e2139887af
--- /dev/null
+++ b/changelog.d/5782.feature
@@ -0,0 +1 @@
+HomeViewController: Tab for list of calls with bridged users.
\ No newline at end of file