Merge branch 'release/1.6.8/master'

This commit is contained in:
Doug 2021-11-17 16:49:01 +00:00
commit a14d82fb9b
54 changed files with 1057 additions and 654 deletions

View file

@ -64,9 +64,9 @@ body:
- type: dropdown
id: rageshake
attributes:
label: Have you submitted a rageshake?
label: Will you send logs?
description: |
Did you know that you can shake your phone to submit logs for this issue? Trigger the defect, then shake your phone and you will see a popup asking if you would like to open the bug report screen. Click YES, and describe the issue, mentioning that you have also filed a bug. Submit the report to send anonymous logs to the developers.
Did you know that you can shake your phone to submit logs for this issue? Trigger the defect, then shake your phone and you will see a popup asking if you would like to open the bug report screen. Click YES, and describe the issue, mentioning that you have also filed a bug (it's helpful if you can include a link to the bug). Send the report to submit anonymous logs to the developers.
options:
- 'Yes'
- 'No'

View file

@ -1,3 +1,35 @@
## Changes in 1.6.8 (2021-11-17)
🙌 Improvements
- Upgrade MatrixKit version ([v0.16.10](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.16.10)).
- Using mutable room list fetch sort options after chaning them to be a structure. ([#4384](https://github.com/vector-im/element-ios/issues/4384))
- Share Extension: Remove the image compression prompt when the showMediaSizeSelection setting is disabled. ([#4815](https://github.com/vector-im/element-ios/issues/4815))
- Replaced GrowingTextView with simpler, custom implementation. Cleaned up the RoomInputToolbar header. ([#4976](https://github.com/vector-im/element-ios/issues/4976))
- Settings: Update about section footer text. ([#5090](https://github.com/vector-im/element-ios/issues/5090))
- MXSession: Add logs to track if E2EE is enabled by default on the current HS. ([#5129](https://github.com/vector-im/element-ios/issues/5129))
🐛 Bugfixes
- Fixed share extension and message forwarding room list accessory view icon. ([#5041](https://github.com/vector-im/element-ios/issues/5041))
- Fixed message composer not following keyboard when swiping to dismiss. ([#5042](https://github.com/vector-im/element-ios/issues/5042))
- RoomVC: Fix retain cycles that prevents `RoomViewController` to be deallocated. ([#5055](https://github.com/vector-im/element-ios/issues/5055))
- Share Extension: Fix missing avatars and don't list spaces as rooms. ([#5057](https://github.com/vector-im/element-ios/issues/5057))
- Fix retain cycles that prevents deallocation in several classes. ([#5058](https://github.com/vector-im/element-ios/issues/5058))
- Fixed retain cycles between the user suggestion coordinator and the suggestion service, and in the suggestion service currentTextTrigger subject sink. ([#5063](https://github.com/vector-im/element-ios/issues/5063))
- Ensure alerts with weak references are retained until they've been presented. ([#5071](https://github.com/vector-im/element-ios/issues/5071))
- Message Composer: Ensure there is no text view when the user isn't allowed to send messages. ([#5079](https://github.com/vector-im/element-ios/issues/5079))
- Home: Fix bug where favourited DM would be shown in both Favourites and People section. ([#5081](https://github.com/vector-im/element-ios/issues/5081))
- Fix a crash when selected space is not home and a clear cache or logout is performed. ([#5082](https://github.com/vector-im/element-ios/issues/5082))
- Room Previews: Fix room previews not loading. ([#5083](https://github.com/vector-im/element-ios/issues/5083))
- Do not make the placeholder appearing when leaving a room on iPhone. ([#5084](https://github.com/vector-im/element-ios/issues/5084))
- Fix room ordering when switching between Home and People/Rooms/Favourites. ([#5105](https://github.com/vector-im/element-ios/issues/5105))
Others
- Improve wording around rageshakes in the defect issue template. ([#4987](https://github.com/vector-im/element-ios/issues/4987))
## Changes in 1.6.6 (2021-10-21)
✨ Features

View file

@ -15,5 +15,5 @@
//
// Version
MARKETING_VERSION = 1.6.6
CURRENT_PROJECT_VERSION = 1.6.6
MARKETING_VERSION = 1.6.8
CURRENT_PROJECT_VERSION = 1.6.8

View file

@ -13,7 +13,7 @@ use_frameworks!
# - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI
#
# Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
$matrixKitVersion = '= 0.16.9'
$matrixKitVersion = '= 0.16.10'
# $matrixKitVersion = :local
# $matrixKitVersion = {'develop' => 'develop'}
@ -73,7 +73,6 @@ abstract_target 'RiotPods' do
pod 'SideMenu', '~> 6.5'
pod 'DSWaveformImage', '~> 6.1.1'
pod 'ffmpeg-kit-ios-audio', '~> 4.5'
pod 'GrowingTextView', '~> 0.7.2'
pod 'FLEX', '~> 4.5.0', :configurations => ['Debug']

View file

@ -43,7 +43,6 @@ PODS:
- GBDeviceInfo (6.6.0):
- GBDeviceInfo/Core (= 6.6.0)
- GBDeviceInfo/Core (6.6.0)
- GrowingTextView (0.7.2)
- GZIP (1.3.0)
- HPGrowingTextView (1.1)
- JitsiMeetSDK (3.10.2)
@ -59,29 +58,29 @@ PODS:
- MatomoTracker (7.4.1):
- MatomoTracker/Core (= 7.4.1)
- MatomoTracker/Core (7.4.1)
- MatrixKit (0.16.9):
- MatrixKit (0.16.10):
- Down (~> 0.11.0)
- DTCoreText (~> 1.6.25)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixKit/Core (= 0.16.9)
- MatrixSDK (= 0.20.9)
- MatrixKit/Core (0.16.9):
- MatrixKit/Core (= 0.16.10)
- MatrixSDK (= 0.20.10)
- MatrixKit/Core (0.16.10):
- Down (~> 0.11.0)
- DTCoreText (~> 1.6.25)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.20.9)
- MatrixSDK (0.20.9):
- MatrixSDK/Core (= 0.20.9)
- MatrixSDK/Core (0.20.9):
- MatrixSDK (= 0.20.10)
- MatrixSDK (0.20.10):
- MatrixSDK/Core (= 0.20.10)
- MatrixSDK/Core (0.20.10):
- AFNetworking (~> 4.0.0)
- GZIP (~> 1.3.0)
- libbase58 (~> 0.1.4)
- OLMKit (~> 3.2.5)
- Realm (= 10.16.0)
- SwiftyBeaver (= 1.9.5)
- MatrixSDK/JingleCallStack (0.20.9):
- MatrixSDK/JingleCallStack (0.20.10):
- JitsiMeetSDK (= 3.10.2)
- MatrixSDK/Core
- OLMKit (3.2.5):
@ -122,11 +121,10 @@ DEPENDENCIES:
- FLEX (~> 4.5.0)
- FlowCommoniOS (~> 1.12.0)
- GBDeviceInfo (~> 6.6.0)
- GrowingTextView (~> 0.7.2)
- KeychainAccess (~> 4.2.2)
- KTCenterFlowLayout (~> 1.3.1)
- MatomoTracker (~> 7.4.1)
- MatrixKit (= 0.16.9)
- MatrixKit (= 0.16.10)
- MatrixSDK
- MatrixSDK/JingleCallStack
- OLMKit
@ -156,7 +154,6 @@ SPEC REPOS:
- FLEX
- FlowCommoniOS
- GBDeviceInfo
- GrowingTextView
- GZIP
- HPGrowingTextView
- JitsiMeetSDK
@ -198,7 +195,6 @@ SPEC CHECKSUMS:
FLEX: e51461dd6f0bfb00643c262acdfea5d5d12c596b
FlowCommoniOS: e9ecbc97fb9ce5c593fb3da0e1073b65a3902026
GBDeviceInfo: ed0db16230d2fa280e1cbb39a5a7f60f6946aaec
GrowingTextView: 876bf42005b5e4a4fd740597db12caaf41f0fe6c
GZIP: 416858efbe66b41b206895ac6dfd5493200d95b3
HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19
JitsiMeetSDK: 2f118fa770f23e518f3560fc224fae3ac7062223
@ -210,8 +206,8 @@ SPEC CHECKSUMS:
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
Logging: beeb016c9c80cf77042d62e83495816847ef108b
MatomoTracker: 24a846c9d3aa76933183fe9d47fd62c9efa863fb
MatrixKit: ed209774b5c3408974c52cfe2aaba4d2e8b4b05b
MatrixSDK: 9e312e3874027bf9eab61be7d0779102f8bd323a
MatrixKit: c3f0bb056ceeb015e2f1688543ac4dbcf88bef2f
MatrixSDK: 0e2ed8fc6f004cac4b4ab46f038a86fe49ce4007
OLMKit: 9fb4799c4a044dd2c06bda31ec31a12191ad30b5
ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d
Realm: b6027801398f3743fc222f096faa85281b506e6c
@ -226,6 +222,6 @@ SPEC CHECKSUMS:
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
PODFILE CHECKSUM: 2740772a9b2d32e17876526875dfc58f67240ba0
PODFILE CHECKSUM: 675c24e5fcaf580998f32fde709fc3be1b2bde22
COCOAPODS: 1.11.2

View file

@ -4,7 +4,8 @@
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
buildImplicitDependencies = "YES"
runPostActionsOnFailure = "NO">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"

View file

@ -19,5 +19,8 @@
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View file

@ -19,5 +19,8 @@
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View file

@ -1016,6 +1016,9 @@ Tap the + to start adding people.";
// Share extension
"share_extension_auth_prompt" = "Login in the main app to share content";
"share_extension_failed_to_encrypt" = "Failed to send. Check in the main app the encryption settings for this room";
"share_extension_low_quality_video_title" = "Video will be sent in low quality";
"share_extension_low_quality_video_message" = "Send in %@ for better quality, or send in low quality below.";
"share_extension_send_now" = "Send now";
// Room key request dialog
"e2e_room_key_request_title" = "Encryption key request";

View file

@ -65,6 +65,7 @@
}
else
{
MXLogWarning(@"[MXSession] E2EE is disabled by default on this homeserver.\nWellknown content: %@", self.homeserverWellknown.JSONDictionary);
success(NO);
return [MXHTTPOperation new];
}

View file

@ -4775,6 +4775,18 @@ public class VectorL10n: NSObject {
public static var shareExtensionFailedToEncrypt: String {
return VectorL10n.tr("Vector", "share_extension_failed_to_encrypt")
}
/// Send in %@ for better quality, or send in low quality below.
public static func shareExtensionLowQualityVideoMessage(_ p1: String) -> String {
return VectorL10n.tr("Vector", "share_extension_low_quality_video_message", p1)
}
/// Video will be sent in low quality
public static var shareExtensionLowQualityVideoTitle: String {
return VectorL10n.tr("Vector", "share_extension_low_quality_video_title")
}
/// Send now
public static var shareExtensionSendNow: String {
return VectorL10n.tr("Vector", "share_extension_send_now")
}
/// Feedback
public static var sideMenuActionFeedback: String {
return VectorL10n.tr("Vector", "side_menu_action_feedback")

View file

@ -32,7 +32,7 @@
/**
The delegate object to receive analytics events.
*/
@property (nonatomic) id<MXAnalyticsDelegate> delegate;
@property (nonatomic, weak) id<MXAnalyticsDelegate> delegate;
/**
Report an event unable to decrypt.

View file

@ -143,7 +143,7 @@ final class RiotSettings: NSObject {
@UserDefault(key: "roomsAllowToJoinPublicRooms", defaultValue: BuildSettings.roomsAllowToJoinPublicRooms, storage: defaults)
var roomsAllowToJoinPublicRooms
@UserDefault(key: UserDefaultsKeys.showAllRoomsInHomeSpace, defaultValue: false, storage: defaults)
@UserDefault(key: UserDefaultsKeys.showAllRoomsInHomeSpace, defaultValue: true, storage: defaults)
var showAllRoomsInHomeSpace
// MARK: - Room Screen

View file

@ -228,7 +228,7 @@ extension AppCoordinator: LegacyAppDelegateDelegate {
}
func legacyAppDelegateRestoreEmptyDetailsViewController(_ legacyAppDelegate: LegacyAppDelegate!) {
self.splitViewCoordinator?.restorePlaceholderDetails()
self.splitViewCoordinator?.resetDetails(animated: false)
}
func legacyAppDelegate(_ legacyAppDelegate: LegacyAppDelegate!, didAddMatrixSession session: MXSession!) {

View file

@ -40,7 +40,7 @@ FOUNDATION_EXPORT NSString *const RecentsViewControllerDataReadyNotification;
/**
Current alert (if any).
*/
UIAlertController *currentAlert;
__weak UIAlertController *currentAlert;
/**
The list of the section headers currently displayed in the recents table.

View file

@ -50,13 +50,13 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
NSIndexPath* lastPotentialCellPath;
// Observe UIApplicationDidEnterBackgroundNotification to cancel editing mode when app leaves the foreground state.
id UIApplicationDidEnterBackgroundNotificationObserver;
__weak id UIApplicationDidEnterBackgroundNotificationObserver;
// Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar.
id kAppDelegateDidTapStatusBarNotificationObserver;
__weak id kAppDelegateDidTapStatusBarNotificationObserver;
// Observe kMXNotificationCenterDidUpdateRules to update missed messages counts.
id kMXNotificationCenterDidUpdateRulesObserver;
__weak id kMXNotificationCenterDidUpdateRulesObserver;
MXHTTPOperation *currentRequest;
@ -65,7 +65,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
UISearchBar *tableSearchBar;
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
id kThemeServiceDidChangeThemeNotificationObserver;
__weak id kThemeServiceDidChangeThemeNotificationObserver;
}
@property (nonatomic, strong) CreateRoomCoordinatorBridgePresenter *createRoomCoordinatorBridgePresenter;
@ -156,11 +156,15 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
// Apply dragging settings
self.enableDragging = _enableDragging;
MXWeakify(self);
// Observe UIApplicationDidEnterBackgroundNotification to refresh bubbles when app leaves the foreground state.
UIApplicationDidEnterBackgroundNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
// Leave potential editing mode
[self cancelEditionMode:isRefreshPending];
[self cancelEditionMode:self->isRefreshPending];
}];
@ -170,6 +174,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self userInterfaceThemeDidChange];
}];
@ -268,9 +274,13 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
[self.recentsTableView deselectRowAtIndexPath:indexPath animated:NO];
}
MXWeakify(self);
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self scrollToTop:YES];
}];
@ -278,6 +288,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
// Observe kMXNotificationCenterDidUpdateRules to refresh missed messages counts
kMXNotificationCenterDidUpdateRulesObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXNotificationCenterDidUpdateRules object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
MXStrongifyAndReturnIfNil(self);
[self refreshRecentsTable];
}];
@ -527,11 +539,13 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
[self->currentAlert dismissViewControllerAnimated:NO completion:nil];
self->currentAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n roomErrorJoinFailedTitle] message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *errorAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n roomErrorJoinFailedTitle]
message:msg
preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[errorAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
@ -541,7 +555,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}
}]];
[self presentViewController:self->currentAlert animated:YES completion:nil];
[self presentViewController:errorAlert animated:YES completion:nil];
currentAlert = errorAlert;
}
#pragma mark - Sticky Headers
@ -1190,13 +1205,13 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}
// confirm leave
currentAlert = [UIAlertController alertControllerWithTitle:title
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *leavePrompt = [UIAlertController alertControllerWithTitle:title
message:message
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
[leavePrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -1206,8 +1221,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n leave]
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[leavePrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n leave]
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -1268,8 +1283,9 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}]];
[currentAlert mxk_setAccessibilityIdentifier:@"LeaveEditedRoomAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[leavePrompt mxk_setAccessibilityIdentifier:@"LeaveEditedRoomAlert"];
[self presentViewController:leavePrompt animated:YES completion:nil];
currentAlert = leavePrompt;
}
}
@ -1824,11 +1840,11 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
[currentAlert dismissViewControllerAnimated:NO completion:nil];
currentAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomRecentsStartChatWith]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionSheet addAction:[UIAlertAction actionWithTitle:[VectorL10n roomRecentsStartChatWith]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -1840,9 +1856,9 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomRecentsCreateEmptyRoom]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionSheet addAction:[UIAlertAction actionWithTitle:[VectorL10n roomRecentsCreateEmptyRoom]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -1854,9 +1870,9 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomRecentsJoinRoom]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionSheet addAction:[UIAlertAction actionWithTitle:[VectorL10n roomRecentsJoinRoom]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -1870,10 +1886,9 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
if (self.mainSession.callManager.supportsPSTN)
{
[currentAlert addAction:[UIAlertAction
actionWithTitle:[VectorL10n roomOpenDialpad]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionSheet addAction:[UIAlertAction actionWithTitle:[VectorL10n roomOpenDialpad]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -1886,9 +1901,9 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}]];
}
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
[actionSheet addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -1898,11 +1913,12 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}]];
[currentAlert popoverPresentationController].sourceView = plusButtonImageView;
[currentAlert popoverPresentationController].sourceRect = plusButtonImageView.bounds;
[actionSheet popoverPresentationController].sourceView = plusButtonImageView;
[actionSheet popoverPresentationController].sourceRect = plusButtonImageView.bounds;
[currentAlert mxk_setAccessibilityIdentifier:@"RecentsVCCreateRoomAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[actionSheet mxk_setAccessibilityIdentifier:@"RecentsVCCreateRoomAlert"];
[self presentViewController:actionSheet animated:YES completion:nil];
currentAlert = actionSheet;
}
- (void)openDialpad
@ -1996,7 +2012,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}
// Check whether the user has already joined the selected public room
if ([self.recentsDataSource.publicRoomsDirectoryDataSource.mxSession roomWithRoomId:publicRoom.roomId])
if ([self.recentsDataSource.publicRoomsDirectoryDataSource.mxSession isJoinedOnRoom:publicRoom.roomId])
{
// Open the public room
[self showRoomWithRoomId:publicRoom.roomId

View file

@ -20,7 +20,12 @@ import Foundation
public class RecentsListService: NSObject, RecentsListServiceProtocol {
private weak var session: MXSession?
public private(set) var mode: RecentsDataSourceMode
public private(set) var mode: RecentsDataSourceMode {
didSet {
refresh()
}
}
public private(set) var query: String?
public private(set) var space: MXSpace?
@ -427,7 +432,7 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
private func updateDirectFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) {
switch mode {
case .home:
fetcher.fetchOptions.filterOptions.notDataTypes = [.invited, .lowPriority]
fetcher.fetchOptions.filterOptions.notDataTypes = [.invited, .favorited, .lowPriority]
case .people:
fetcher.fetchOptions.filterOptions.notDataTypes = [.lowPriority]
default:
@ -440,7 +445,7 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
case .home:
fetcher.fetchOptions.sortOptions = sortOptions
case .favourites:
let newSortOptions = sortOptions
var newSortOptions = sortOptions
newSortOptions.favoriteTag = true
fetcher.fetchOptions.sortOptions = newSortOptions
default:

View file

@ -60,6 +60,18 @@ public class MockRoomSummary: NSObject, MXRoomSummaryProtocol {
public var highlightCount: UInt = 0
public var hasAnyUnread: Bool {
return localUnreadEventCount > 0
}
public var hasAnyNotification: Bool {
return notificationCount > 0
}
public var hasAnyHighlight: Bool {
return highlightCount > 0
}
public var isDirect: Bool {
return isTyped(.direct)
}

View file

@ -50,7 +50,7 @@
NSLayoutConstraint *leftMarkerViewConstraint;
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
id kThemeServiceDidChangeThemeNotificationObserver;
__weak id kThemeServiceDidChangeThemeNotificationObserver;
}
@end
@ -183,9 +183,13 @@
[self createSegmentedViews];
MXWeakify(self);
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self userInterfaceThemeDidChange];
}];

View file

@ -27,10 +27,10 @@
BOOL isRefreshPending;
// Observe UIApplicationDidEnterBackgroundNotification to cancel editing mode when app leaves the foreground state.
id UIApplicationDidEnterBackgroundNotificationObserver;
__weak id UIApplicationDidEnterBackgroundNotificationObserver;
// Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar.
id kAppDelegateDidTapStatusBarNotificationObserver;
__weak id kAppDelegateDidTapStatusBarNotificationObserver;
MXHTTPOperation *currentRequest;
@ -39,7 +39,7 @@
UISearchBar *tableSearchBar;
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
id kThemeServiceDidChangeThemeNotificationObserver;
__weak id kThemeServiceDidChangeThemeNotificationObserver;
}
@end
@ -98,11 +98,15 @@
self.groupsTableView.estimatedSectionHeaderHeight = 30;
self.groupsTableView.estimatedSectionFooterHeight = 0;
MXWeakify(self);
// Observe UIApplicationDidEnterBackgroundNotification to refresh bubbles when app leaves the foreground state.
UIApplicationDidEnterBackgroundNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
// Leave potential editing mode
[self cancelEditionMode:isRefreshPending];
[self cancelEditionMode:self->isRefreshPending];
}];
@ -117,6 +121,8 @@
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self userInterfaceThemeDidChange];
}];
@ -207,9 +213,13 @@
[self.groupsTableView deselectRowAtIndexPath:indexPath animated:NO];
}
MXWeakify(self);
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self scrollToTop:YES];
}];

View file

@ -43,6 +43,10 @@ final class GroupDetailsCoordinator: GroupDetailsCoordinatorProtocol {
self.groupDetailsViewController = groupDetailsViewController
}
deinit {
groupDetailsViewController.destroy()
}
// MARK: - Public
func start() {

View file

@ -122,7 +122,7 @@
/**
The delegate for the view controller.
*/
@property (nonatomic) id<ContactsTableViewControllerDelegate> contactsTableViewControllerDelegate;
@property (nonatomic, weak) id<ContactsTableViewControllerDelegate> contactsTableViewControllerDelegate;
@end

View file

@ -33,12 +33,12 @@
/**
Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar.
*/
id kAppDelegateDidTapStatusBarNotificationObserver;
__weak id kAppDelegateDidTapStatusBarNotificationObserver;
/**
Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
*/
id kThemeServiceDidChangeThemeNotificationObserver;
__weak id kThemeServiceDidChangeThemeNotificationObserver;
}
@property (nonatomic, strong) FindYourContactsFooterView *findYourContactsFooterView;
@ -102,9 +102,13 @@
self.contactsTableView.tableFooterView = [[UIView alloc] init];
self.contactsAreFilteredWithSearch = NO;
MXWeakify(self);
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self userInterfaceThemeDidChange];
}];
@ -158,10 +162,14 @@
// Screen tracking
[[Analytics sharedInstance] trackScreen:_screenName];
MXWeakify(self);
// Observe kAppDelegateDidTapStatusBarNotification.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self.contactsTableView setContentOffset:CGPointMake(-self.contactsTableView.adjustedContentInset.left, -self.contactsTableView.adjustedContentInset.top) animated:YES];
}];

View file

@ -47,12 +47,12 @@
/**
Observe UIApplicationWillChangeStatusBarOrientationNotification to hide/show bubbles bg.
*/
id UIApplicationWillChangeStatusBarOrientationNotificationObserver;
__weak id UIApplicationWillChangeStatusBarOrientationNotificationObserver;
/**
The observer of the presence for matrix user.
*/
id mxPresenceObserver;
__weak id mxPresenceObserver;
/**
List of the basic actions on this contact.
@ -79,7 +79,7 @@
/**
Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
*/
id kThemeServiceDidChangeThemeNotificationObserver;
__weak id kThemeServiceDidChangeThemeNotificationObserver;
/**
The current visibility of the status bar in this view controller.
@ -182,9 +182,13 @@
self.bottomImageView.hidden = (orientation.integerValue == UIInterfaceOrientationLandscapeLeft || orientation.integerValue == UIInterfaceOrientationLandscapeRight);
}];
MXWeakify(self);
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self userInterfaceThemeDidChange];
}];
@ -379,9 +383,13 @@
// Be warned when the thumbnail is updated
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onThumbnailUpdate:) name:kMXKContactThumbnailUpdateNotification object:nil];
MXWeakify(self);
// Observe contact presence change
mxPresenceObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKContactManagerMatrixUserPresenceChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
NSString* matrixId = self.firstMatrixId;
if (matrixId && [matrixId isEqualToString:notif.object])

View file

@ -105,8 +105,8 @@ final class EnterNewRoomDetailsViewController: UIViewController {
var section3: Section?
if RiotSettings.shared.roomCreationScreenAllowEncryptionConfiguration {
let row_3_0 = Row(type: .withSwitch(isOn: viewModel.roomCreationParameters.isEncrypted, onValueChanged: { (theSwitch) in
self.viewModel.roomCreationParameters.isEncrypted = theSwitch.isOn
let row_3_0 = Row(type: .withSwitch(isOn: viewModel.roomCreationParameters.isEncrypted, onValueChanged: { [weak self] (theSwitch) in
self?.viewModel.roomCreationParameters.isEncrypted = theSwitch.isOn
}), text: VectorL10n.createRoomEnableEncryption, accessoryType: .none) {
// no-op
}
@ -117,11 +117,20 @@ final class EnterNewRoomDetailsViewController: UIViewController {
var section4: Section?
if RiotSettings.shared.roomCreationScreenAllowRoomTypeConfiguration {
let row_4_0 = Row(type: .default, text: VectorL10n.createRoomTypePrivate, accessoryType: viewModel.roomCreationParameters.isPublic ? .none : .checkmark) {
let row_4_0 = Row(type: .default, text: VectorL10n.createRoomTypePrivate, accessoryType: viewModel.roomCreationParameters.isPublic ? .none : .checkmark) { [weak self] in
guard let self = self else {
return
}
self.viewModel.roomCreationParameters.isPublic = false
self.updateSections()
}
let row_4_1 = Row(type: .default, text: VectorL10n.createRoomTypePublic, accessoryType: viewModel.roomCreationParameters.isPublic ? .checkmark : .none) {
let row_4_1 = Row(type: .default, text: VectorL10n.createRoomTypePublic, accessoryType: viewModel.roomCreationParameters.isPublic ? .checkmark : .none) { [weak self] in
guard let self = self else {
return
}
self.viewModel.roomCreationParameters.isPublic = true
self.updateSections()
// scroll bottom to show user new fields
@ -149,8 +158,8 @@ final class EnterNewRoomDetailsViewController: UIViewController {
}
if viewModel.roomCreationParameters.isPublic {
let row_5_0 = Row(type: .withSwitch(isOn: viewModel.roomCreationParameters.showInDirectory, onValueChanged: { (theSwitch) in
self.viewModel.roomCreationParameters.showInDirectory = theSwitch.isOn
let row_5_0 = Row(type: .withSwitch(isOn: viewModel.roomCreationParameters.showInDirectory, onValueChanged: { [weak self] (theSwitch) in
self?.viewModel.roomCreationParameters.showInDirectory = theSwitch.isOn
}), text: VectorL10n.createRoomShowInDirectory, accessoryType: .none) {
// no-op
}
@ -389,7 +398,10 @@ extension EnterNewRoomDetailsViewController: UITableViewDataSource {
cell.mxkLabel.text = row.text
cell.mxkSwitch.isOn = isOn
cell.mxkSwitch.removeTarget(nil, action: nil, for: .valueChanged)
cell.mxkSwitch.vc_addAction(for: .valueChanged) {
cell.mxkSwitch.vc_addAction(for: .valueChanged) { [weak cell] in
guard let cell = cell else {
return
}
onValueChanged?(cell.mxkSwitch)
}
cell.mxkLabelLeadingConstraint.constant = cell.vc_separatorInset.left

View file

@ -190,7 +190,7 @@
MXPublicRoom *publicRoom = [dataSource roomAtIndexPath:indexPath];
// Check whether the user has already joined the selected public room
if ([dataSource.mxSession roomWithRoomId:publicRoom.roomId])
if ([dataSource.mxSession isJoinedOnRoom:publicRoom.roomId])
{
// Open the public room.
[self showRoomWithId:publicRoom.roomId inMatrixSession:dataSource.mxSession];

View file

@ -81,7 +81,7 @@
/**
The delegate for the view controller.
*/
@property (nonatomic) id<JitsiViewControllerDelegate> delegate;
@property (nonatomic, weak) id<JitsiViewControllerDelegate> delegate;
@end

View file

@ -44,7 +44,7 @@ const CGFloat kTypingCellHeight = 24;
// Timer used to debounce cells refresh
@property (nonatomic, strong) NSTimer *refreshCellsTimer;
@property (nonatomic, readonly) id<RoomDataSourceDelegate> roomDataSourceDelegate;
@property (nonatomic, weak, readonly) id<RoomDataSourceDelegate> roomDataSourceDelegate;
@property(nonatomic, readwrite) RoomEncryptionTrustLevel encryptionTrustLevel;

View file

@ -54,6 +54,6 @@
/**
The delegate.
*/
@property (nonatomic) id<RoomMemberTitleViewDelegate> delegate;
@property (nonatomic, weak) id<RoomMemberTitleViewDelegate> delegate;
@end

View file

@ -90,7 +90,7 @@
/**
The delegate for the view controller.
*/
@property (nonatomic) id<RoomParticipantsViewControllerDelegate> delegate;
@property (nonatomic, weak) id<RoomParticipantsViewControllerDelegate> delegate;
/**
Returns the `UINib` object initialized for a `RoomParticipantsViewController`.

View file

@ -77,6 +77,10 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
super.init()
}
deinit {
roomViewController.destroy()
}
// MARK: - Public
@ -90,9 +94,12 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
self.roomViewController.delegate = self
// Detect when view controller has been dismissed by gesture when presented modally (not in full screen).
self.roomViewController.presentationController?.delegate = self
// FIXME: Find a better way to manage modal dismiss. This makes the `roomViewController` to never be released
// self.roomViewController.presentationController?.delegate = self
if let eventId = self.selectedEventId {
if let previewData = self.parameters.previewData {
self.loadRoomPreview(withData: previewData, completion: completion)
} else if let eventId = self.selectedEventId {
self.loadRoom(withId: self.parameters.roomId, and: eventId, completion: completion)
} else {
self.loadRoom(withId: self.parameters.roomId, completion: completion)
@ -178,6 +185,13 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol {
completion?()
}
}
private func loadRoomPreview(withData previewData: RoomPreviewData, completion: (() -> Void)?) {
self.roomViewController.displayRoomPreview(previewData)
completion?()
}
}
// MARK: - RoomIdentifiable

View file

@ -152,11 +152,10 @@ final class RoomInfoCoordinator: NSObject, RoomInfoCoordinatorType {
case .search:
MXKRoomDataSourceManager.sharedManager(forMatrixSession: session)?.roomDataSource(forRoom: self.room.roomId, create: false, onComplete: { (roomDataSource) in
guard let dataSource = roomDataSource else { return }
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let search = storyboard.instantiateViewController(withIdentifier: "RoomSearch") as? RoomSearchViewController {
search.roomDataSource = dataSource
self.navigationRouter.push(search, animated: animated, popCompletion: nil)
}
let roomSearchViewController: RoomSearchViewController = RoomSearchViewController.instantiate()
roomSearchViewController.loadViewIfNeeded()
roomSearchViewController.roomDataSource = dataSource
self.navigationRouter.push(roomSearchViewController, animated: animated, popCompletion: nil)
})
case .notifications:
let coordinator = createRoomNotificationSettingsCoordinator()

View file

@ -50,8 +50,8 @@ final class RoomInfoListViewController: UIViewController {
private lazy var basicInfoView: RoomInfoBasicView = {
let view = RoomInfoBasicView.loadFromNib()
view.onTopicSizeChange = { _ in
self.view.setNeedsLayout()
view.onTopicSizeChange = { [weak self] _ in
self?.view.setNeedsLayout()
}
return view
}()

View file

@ -144,7 +144,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
{
// The preview header
PreviewRoomTitleView *previewHeader;
__weak PreviewRoomTitleView *previewHeader;
// The customized room data source for Vector
RoomDataSource *customizedRoomDataSource;
@ -156,7 +156,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
NSArray *currentTypingUsers;
// Typing notifications listener.
id typingNotifListener;
__weak id typingNotifListener;
// The position of the first touch down event stored in case of scrolling when the expanded header is visible.
CGPoint startScrollingPoint;
@ -168,33 +168,33 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
UIView *missedDiscussionsDotView;
// Potential encryption details view.
EncryptionInfoView *encryptionInfoView;
__weak EncryptionInfoView *encryptionInfoView;
// The list of unknown devices that prevent outgoing messages from being sent
MXUsersDevicesMap<MXDeviceInfo*> *unknownDevices;
// Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar.
id kAppDelegateDidTapStatusBarNotificationObserver;
__weak id kAppDelegateDidTapStatusBarNotificationObserver;
// Observe kAppDelegateNetworkStatusDidChangeNotification to handle network status change.
id kAppDelegateNetworkStatusDidChangeNotificationObserver;
__weak id kAppDelegateNetworkStatusDidChangeNotificationObserver;
// Observers to manage MXSession state (and sync errors)
id kMXSessionStateDidChangeObserver;
__weak id kMXSessionStateDidChangeObserver;
// Observers to manage ongoing conference call banner
id kMXCallStateDidChangeObserver;
id kMXCallManagerConferenceStartedObserver;
id kMXCallManagerConferenceFinishedObserver;
__weak id kMXCallStateDidChangeObserver;
__weak id kMXCallManagerConferenceStartedObserver;
__weak id kMXCallManagerConferenceFinishedObserver;
// Observers to manage widgets
id kMXKWidgetManagerDidUpdateWidgetObserver;
__weak id kMXKWidgetManagerDidUpdateWidgetObserver;
// Observer kMXRoomSummaryDidChangeNotification to keep updated the missed discussion count
id mxRoomSummaryDidChangeObserver;
__weak id mxRoomSummaryDidChangeObserver;
// Observer for removing the re-request explanation/waiting dialog
id mxEventDidDecryptNotificationObserver;
__weak id mxEventDidDecryptNotificationObserver;
// The table view cell in which the read marker is displayed (nil by default).
MXKRoomBubbleTableViewCell *readMarkerTableViewCell;
@ -209,13 +209,13 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
NSArray<UIBarButtonItem *> *rightBarButtonItems;
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
id kThemeServiceDidChangeThemeNotificationObserver;
__weak id kThemeServiceDidChangeThemeNotificationObserver;
// Observe URL preview updates to refresh cells.
id URLPreviewDidUpdateNotificationObserver;
__weak id URLPreviewDidUpdateNotificationObserver;
// Listener for `m.room.tombstone` event type
id tombstoneEventNotificationsListener;
__weak id tombstoneEventNotificationsListener;
// Homeserver notices
MXServerNotices *serverNotices;
@ -454,9 +454,13 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
self.jumpToLastUnreadLabel.text = [VectorL10n roomJumpToFirstUnread];
MXWeakify(self);
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self userInterfaceThemeDidChange];
}];
@ -587,9 +591,13 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self listenTombstoneEventNotifications];
[self listenMXSessionStateChangeNotifications];
MXWeakify(self);
// Observe kAppDelegateDidTapStatusBarNotification.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self setBubbleTableViewContentOffset:CGPointMake(-self.bubblesTableView.adjustedContentInset.left, -self.bubblesTableView.adjustedContentInset.top) animated:YES];
}];
@ -661,9 +669,13 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[AppDelegate theDelegate].visibleRoomId = self.roomDataSource.roomId;
}
MXWeakify(self);
// Observe network reachability
kAppDelegateNetworkStatusDidChangeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateNetworkStatusDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self refreshActivitiesViewDisplay];
}];
@ -673,6 +685,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Observe missed notifications
mxRoomSummaryDidChangeObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXRoomSummaryDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
MXRoomSummary *roomSummary = notif.object;
if ([roomSummary.roomId isEqualToString:self.roomDataSource.roomId])
@ -1084,16 +1098,12 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (self.roomDataSource)
{
// Restore tool bar view and room activities view if none
if (!self.inputToolbarView)
{
[self updateRoomInputToolbarViewClassIfNeeded];
[self refreshRoomInputToolbar];
self.inputToolbarView.hidden = (self.roomDataSource.state != MXKDataSourceStateReady);
}
// Update the input toolbar class and update the layout
[self updateRoomInputToolbarViewClassIfNeeded];
self.inputToolbarView.hidden = (self.roomDataSource.state != MXKDataSourceStateReady);
// Restore room activities view if none
if (!self.activitiesView)
{
// And the extra area
@ -1178,6 +1188,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
[self updateInputToolBarViewHeight];
[self refreshRoomInputToolbar];
}
}
@ -1398,8 +1409,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
if (URLPreviewDidUpdateNotificationObserver)
{
[NSNotificationCenter.defaultCenter removeObserver:URLPreviewDidUpdateNotificationObserver];
URLPreviewDidUpdateNotificationObserver = nil;
[NSNotificationCenter.defaultCenter removeObserver:URLPreviewDidUpdateNotificationObserver];
}
[self removeCallNotificationsListeners];
@ -1555,8 +1565,12 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
- (void)registerURLPreviewNotifications
{
MXWeakify(self);
URLPreviewDidUpdateNotificationObserver = [NSNotificationCenter.defaultCenter addObserverForName:URLPreviewDidUpdateNotification object:nil queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull notification) {
MXStrongifyAndReturnIfNil(self);
// Ensure this is the correct room
if (![(NSString*)notification.userInfo[@"roomId"] isEqualToString:self.roomDataSource.roomId])
{
@ -2045,20 +2059,22 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[VectorL10n widgetStickerPickerNoStickerpacksAlert],
[VectorL10n widgetStickerPickerNoStickerpacksAlertAddNow]];
currentAlert = [UIAlertController alertControllerWithTitle:nil message:alertMessage preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *installPrompt = [UIAlertController alertControllerWithTitle:nil
message:alertMessage
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n no]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action)
[installPrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n no]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action)
{
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n yes]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
[installPrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n yes]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
@ -2073,8 +2089,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self presentViewController:modularVC animated:NO completion:nil];
}]];
[currentAlert mxk_setAccessibilityIdentifier:@"RoomVCStickerPickerAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[installPrompt mxk_setAccessibilityIdentifier:@"RoomVCStickerPickerAlert"];
[self presentViewController:installPrompt animated:YES completion:nil];
currentAlert = installPrompt;
}
}
@ -2240,6 +2257,12 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
UIViewController *suggestionsViewController = self.userSuggestionCoordinator.toPresentable;
if (!suggestionsViewController)
{
return;
}
[suggestionsViewController.view setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addChildViewController:suggestionsViewController];
@ -2336,11 +2359,14 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (isVisible)
{
previewHeader = [PreviewRoomTitleView roomTitleView];
PreviewRoomTitleView *previewHeader = [PreviewRoomTitleView roomTitleView];
previewHeader.delegate = self;
previewHeader.tapGestureDelegate = self;
previewHeader.translatesAutoresizingMaskIntoConstraints = NO;
[self.previewHeaderContainer addSubview:previewHeader];
self->previewHeader = previewHeader;
// Force preview header in full width
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:previewHeader
attribute:NSLayoutAttributeLeading
@ -3119,14 +3145,14 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
__weak __typeof(self) weakSelf = self;
currentAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertController *actionsMenu = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
// Add actions for a failed event
if (selectedEvent.sentState == MXEventSentStateFailed)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n retry]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n retry]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3140,9 +3166,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionDelete]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionDelete]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3177,9 +3203,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
selectedEvent.sentState == MXEventSentStateEncrypting ||
selectedEvent.sentState == MXEventSentStateSending)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionCancelSend]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionCancelSend]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
if (weakSelf)
{
@ -3197,9 +3223,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
}
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionForward]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionForward]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
self.shareManager = [[ShareManager alloc] initWithShareItemProvider:[[SimpleShareItemProvider alloc] initWithTextMessage:selectedComponent.textMessage]
type:ShareManagerTypeForward];
@ -3216,9 +3242,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (!isJitsiCallEvent)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionQuote]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionQuote]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3238,9 +3264,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (!isJitsiCallEvent && BuildSettings.messageDetailsAllowShare)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionShare]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionShare]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3272,9 +3298,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
attachment.type == MXKAttachmentTypeVideo ||
attachment.type == MXKAttachmentTypeVoiceMessage) {
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionForward]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionForward]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
self.shareManager = [[ShareManager alloc] initWithShareItemProvider:[[SimpleShareItemProvider alloc] initWithAttachment:attachment]
type:ShareManagerTypeForward];
@ -3294,9 +3320,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
{
if (attachment.type == MXKAttachmentTypeImage || attachment.type == MXKAttachmentTypeVideo)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionSave]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionSave]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3339,9 +3365,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
NSString *uploadId = roomBubbleTableViewCell.bubbleData.attachment.contentURL;
if ([MXMediaManager existingUploaderWithId:uploadId])
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionCancelSend]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionCancelSend]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
// Get again the loader
MXMediaLoader *loader = [MXMediaManager existingUploaderWithId:uploadId];
@ -3377,9 +3403,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
{
if (BuildSettings.messageDetailsAllowShare)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionShare]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionShare]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3427,9 +3453,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
NSString *downloadId = roomBubbleTableViewCell.bubbleData.attachment.downloadId;
if ([MXMediaManager existingDownloaderWithIdentifier:downloadId])
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionCancelDownload]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionCancelDownload]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3455,9 +3481,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// because it breaks everything
if (selectedEvent.eventType != MXEventTypeRoomEncryption)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionRedact]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionRedact]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3489,9 +3515,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (BuildSettings.messageDetailsAllowPermalink)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionPermalink]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionPermalink]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3518,9 +3544,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Add reaction history if event contains reactions
if (roomBubbleTableViewCell.bubbleData.reactions[selectedEvent.eventId].aggregatedReactionsWithNonZeroCount)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionReactionHistory]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionReactionHistory]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[self cancelEventSelection];
@ -3531,9 +3557,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (BuildSettings.messageDetailsAllowViewSource)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionViewSource]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionViewSource]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3551,9 +3577,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Add "View Decrypted Source" for e2ee event we can decrypt
if (selectedEvent.isEncrypted && selectedEvent.clearEvent)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionViewDecryptedSource]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionViewDecryptedSource]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3571,9 +3597,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (![selectedEvent.sender isEqualToString:self.mainSession.myUser.userId] && RiotSettings.shared.roomContextualMenuShowReportContentOption)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionReport]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionReport]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3582,15 +3608,15 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self cancelEventSelection];
// Prompt user to enter a description of the problem content.
self->currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionReportPromptReason] message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *reportReasonAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionReportPromptReason] message:nil preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
[reportReasonAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.secureTextEntry = NO;
textField.placeholder = nil;
textField.keyboardType = UIKeyboardTypeDefault;
}];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[reportReasonAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3606,9 +3632,11 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self stopActivityIndicator];
// Prompt user to ignore content from this user
self->currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionReportPromptIgnoreUser] message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *ignoreUserAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionReportPromptIgnoreUser]
message:nil
preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n yes] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[ignoreUserAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n yes] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3637,7 +3665,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n no] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[ignoreUserAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n no] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3647,7 +3675,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[self presentViewController:self->currentAlert animated:YES completion:nil];
[self presentViewController:ignoreUserAlert animated:YES completion:nil];
self->currentAlert = ignoreUserAlert;
} failure:^(NSError *error) {
@ -3663,7 +3692,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
[reportReasonAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3673,7 +3702,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[self presentViewController:self->currentAlert animated:YES completion:nil];
[self presentViewController:reportReasonAlert animated:YES completion:nil];
self->currentAlert = reportReasonAlert;
}
}]];
@ -3681,9 +3711,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (!isJitsiCallEvent && self.roomDataSource.room.summary.isEncrypted)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionViewEncryption]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionViewEncryption]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3698,9 +3728,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
}
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
[actionsMenu addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3711,20 +3741,17 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
// Do not display empty action sheet
if (currentAlert.actions.count > 1)
if (actionsMenu.actions.count > 1)
{
NSInteger bubbleComponentIndex = [roomBubbleTableViewCell.bubbleData bubbleComponentIndexForEventId:selectedEvent.eventId];
CGRect sourceRect = [roomBubbleTableViewCell componentFrameInContentViewForIndex:bubbleComponentIndex];
[currentAlert mxk_setAccessibilityIdentifier:@"RoomVCEventMenuAlert"];
[currentAlert popoverPresentationController].sourceView = roomBubbleTableViewCell;
[currentAlert popoverPresentationController].sourceRect = sourceRect;
[self presentViewController:currentAlert animated:animated completion:nil];
}
else
{
currentAlert = nil;
[actionsMenu mxk_setAccessibilityIdentifier:@"RoomVCEventMenuAlert"];
[actionsMenu popoverPresentationController].sourceView = roomBubbleTableViewCell;
[actionsMenu popoverPresentationController].sourceRect = sourceRect;
[self presentViewController:actionsMenu animated:animated completion:nil];
currentAlert = actionsMenu;
}
}
@ -4097,14 +4124,14 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
- (void)showVoiceCallActionSheet
{
// Ask the user the kind of the call: voice or dialpad?
currentAlert = [UIAlertController alertControllerWithTitle:nil
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertController *callActionSheet = [UIAlertController alertControllerWithTitle:nil
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
__weak typeof(self) weakSelf = self;
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomPlaceVoiceCall]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[callActionSheet addAction:[UIAlertAction actionWithTitle:[VectorL10n roomPlaceVoiceCall]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -4116,9 +4143,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomOpenDialpad]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[callActionSheet addAction:[UIAlertAction actionWithTitle:[VectorL10n roomOpenDialpad]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -4130,9 +4157,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
[callActionSheet addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -4142,9 +4169,10 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[currentAlert popoverPresentationController].barButtonItem = self.navigationItem.rightBarButtonItems.firstObject;
[currentAlert popoverPresentationController].permittedArrowDirections = UIPopoverArrowDirectionUp;
[self presentViewController:currentAlert animated:YES completion:nil];
[callActionSheet popoverPresentationController].barButtonItem = self.navigationItem.rightBarButtonItems.firstObject;
[callActionSheet popoverPresentationController].permittedArrowDirections = UIPopoverArrowDirectionUp;
[self presentViewController:callActionSheet animated:YES completion:nil];
currentAlert = callActionSheet;
}
- (void)placeCallWithVideo2:(BOOL)video
@ -4196,20 +4224,21 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
MXWeakify(self);
[currentAlert dismissViewControllerAnimated:NO completion:nil];
currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomNoPrivilegesToCreateGroupCall]
message:nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *unprivilegedAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomNoPrivilegesToCreateGroupCall]
message:nil
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
[unprivilegedAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
}]];
[currentAlert mxk_setAccessibilityIdentifier:@"RoomVCCallAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[unprivilegedAlert mxk_setAccessibilityIdentifier:@"RoomVCCallAlert"];
[self presentViewController:unprivilegedAlert animated:YES completion:nil];
currentAlert = unprivilegedAlert;
}
}
}
@ -4768,10 +4797,14 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
- (void)listenCallNotifications
{
MXWeakify(self);
kMXCallStateDidChangeObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXCallStateDidChange object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
MXCall *call = notif.object;
if ([call.room.roomId isEqualToString:customizedRoomDataSource.roomId])
if ([call.room.roomId isEqualToString:self->customizedRoomDataSource.roomId])
{
[self refreshActivitiesViewDisplay];
[self refreshRoomInputToolbar];
@ -4779,16 +4812,20 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}];
kMXCallManagerConferenceStartedObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXCallManagerConferenceStarted object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
NSString *roomId = notif.object;
if ([roomId isEqualToString:customizedRoomDataSource.roomId])
if ([roomId isEqualToString:self->customizedRoomDataSource.roomId])
{
[self refreshActivitiesViewDisplay];
}
}];
kMXCallManagerConferenceFinishedObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXCallManagerConferenceFinished object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
NSString *roomId = notif.object;
if ([roomId isEqualToString:customizedRoomDataSource.roomId])
if ([roomId isEqualToString:self->customizedRoomDataSource.roomId])
{
[self refreshActivitiesViewDisplay];
[self refreshRoomInputToolbar];
@ -5129,6 +5166,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[VectorL10n roomUnsentMessagesUnknownDevicesNotification] :
[VectorL10n roomUnsentMessagesNotification];
MXWeakify(self);
RoomActivitiesView *roomActivitiesView = (RoomActivitiesView*) self.activitiesView;
self.activitiesViewExpanded = YES;
[roomActivitiesView displayUnsentMessagesNotification:notification withResendLink:^{
@ -5140,57 +5178,53 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self cancelAllUnsentMessages];
} andIconTapGesture:^{
MXStrongifyAndReturnIfNil(self);
if (currentAlert)
if (self->currentAlert)
{
[currentAlert dismissViewControllerAnimated:NO completion:nil];
[self->currentAlert dismissViewControllerAnimated:NO completion:nil];
}
__weak __typeof(self) weakSelf = self;
currentAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
MXWeakify(self);
UIAlertController *resendAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomResendUnsentMessages]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[resendAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomResendUnsentMessages]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
[self resendAllUnsentMessages];
self->currentAlert = nil;
}
MXStrongifyAndReturnIfNil(self);
[self resendAllUnsentMessages];
self->currentAlert = nil;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomDeleteUnsentMessages]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[resendAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomDeleteUnsentMessages]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
[self cancelAllUnsentMessages];
self->currentAlert = nil;
}
MXStrongifyAndReturnIfNil(self);
[self cancelAllUnsentMessages];
self->currentAlert = nil;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
[resendAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->currentAlert = nil;
}
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
}]];
[currentAlert mxk_setAccessibilityIdentifier:@"RoomVCUnsentMessagesMenuAlert"];
[currentAlert popoverPresentationController].sourceView = roomActivitiesView;
[currentAlert popoverPresentationController].sourceRect = roomActivitiesView.bounds;
[self presentViewController:currentAlert animated:YES completion:nil];
[resendAlert mxk_setAccessibilityIdentifier:@"RoomVCUnsentMessagesMenuAlert"];
[resendAlert popoverPresentationController].sourceView = roomActivitiesView;
[resendAlert popoverPresentationController].sourceRect = roomActivitiesView.bounds;
[self presentViewController:resendAlert animated:YES completion:nil];
self->currentAlert = resendAlert;
}];
}
@ -5230,13 +5264,13 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
}
currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n unknownDevicesAlertTitle]
message:[VectorL10n unknownDevicesAlert]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *unknownDevicesAlert = [UIAlertController alertControllerWithTitle:[VectorL10n unknownDevicesAlertTitle]
message:[VectorL10n unknownDevicesAlert]
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n unknownDevicesVerify]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[unknownDevicesAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n unknownDevicesVerify]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -5248,9 +5282,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n unknownDevicesSendAnyway]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[unknownDevicesAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n unknownDevicesSendAnyway]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -5271,8 +5305,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[currentAlert mxk_setAccessibilityIdentifier:@"RoomVCUnknownDevicesAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[unknownDevicesAlert mxk_setAccessibilityIdentifier:@"RoomVCUnknownDevicesAlert"];
[self presentViewController:unknownDevicesAlert animated:YES completion:nil];
currentAlert = unknownDevicesAlert;
}
}
@ -5334,15 +5369,17 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
- (void)cancelAllUnsentMessages
{
currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomUnsentMessagesCancelTitle] message:[VectorL10n roomUnsentMessagesCancelMessage] preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *cancelAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomUnsentMessagesCancelTitle]
message:[VectorL10n roomUnsentMessagesCancelMessage]
preferredStyle:UIAlertControllerStyleAlert];
MXWeakify(self);
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
[cancelAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n delete] style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) {
[cancelAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n delete] style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
// Remove unsent event ids
for (NSUInteger index = 0; index < self.roomDataSource.room.outgoingMessages.count;)
@ -5359,9 +5396,11 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
[self refreshActivitiesViewDisplay];
self->currentAlert = nil;
}]];
[self presentViewController:currentAlert animated:YES completion:nil];
[self presentViewController:cancelAlert animated:YES completion:nil];
currentAlert = cancelAlert;
}
# pragma mark - Encryption Information view
@ -5373,7 +5412,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Remove potential existing subviews
[self dismissTemporarySubViews];
encryptionInfoView = [[EncryptionInfoView alloc] initWithEvent:event andMatrixSession:self.roomDataSource.mxSession];
EncryptionInfoView *encryptionInfoView = [[EncryptionInfoView alloc] initWithEvent:event andMatrixSession:self.roomDataSource.mxSession];
// Add shadow on added view
encryptionInfoView.layer.cornerRadius = 5;
@ -5383,6 +5422,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Add the view and define edge constraints
[self.view addSubview:encryptionInfoView];
self->encryptionInfoView = encryptionInfoView;
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:encryptionInfoView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
@ -5588,11 +5629,11 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Invite ?
NSString *promptMsg = [VectorL10n roomParticipantsInvitePromptMsg:contact.displayName];
currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomParticipantsInvitePromptTitle]
message:promptMsg
preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *invitePrompt = [UIAlertController alertControllerWithTitle:[VectorL10n roomParticipantsInvitePromptTitle]
message:promptMsg
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
[invitePrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
@ -5604,7 +5645,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n invite]
[invitePrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n invite]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
@ -5699,8 +5740,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}]];
[currentAlert mxk_setAccessibilityIdentifier:@"RoomVCInviteAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[invitePrompt mxk_setAccessibilityIdentifier:@"RoomVCInviteAlert"];
[self presentViewController:invitePrompt animated:YES completion:nil];
currentAlert = invitePrompt;
}
#pragma mark - Re-request encryption keys
@ -5744,8 +5786,6 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
alert = [UIAlertController alertControllerWithTitle:VectorL10n.rerequestKeysAlertTitle
message:[VectorL10n e2eRoomKeyRequestMessage:AppInfo.current.displayName]
preferredStyle:UIAlertControllerStyleAlert];
currentAlert = alert;
[alert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
@ -5759,7 +5799,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
self->currentAlert = nil;
}]];
[self presentViewController:currentAlert animated:YES completion:nil];
[self presentViewController:alert animated:YES completion:nil];
currentAlert = alert;
}
- (void)presentReviewUnverifiedSessionsAlert
@ -5839,8 +5880,12 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
- (void)listenMXSessionStateChangeNotifications
{
MXWeakify(self);
kMXSessionStateDidChangeObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionStateDidChangeNotification object:self.roomDataSource.mxSession queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
if (self.roomDataSource.mxSession.state == MXSessionStateSyncError
|| self.roomDataSource.mxSession.state == MXSessionStateRunning)
{
@ -6029,18 +6074,19 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self hideContextualMenuAnimated:YES cancelEventSelection:YES completion:^{
MXStrongifyAndReturnIfNil(self);
self->currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionDeleteConfirmationTitle]
message:[VectorL10n roomEventActionDeleteConfirmationMessage]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *deleteConfirmation = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionDeleteConfirmationTitle]
message:[VectorL10n roomEventActionDeleteConfirmationMessage]
preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[deleteConfirmation addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
}]];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n delete] style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) {
[deleteConfirmation addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n delete] style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) {
[self.roomDataSource removeEventWithEventId:event.eventId];
}]];
[self presentViewController:self->currentAlert animated:YES completion:nil];
[self presentViewController:deleteConfirmation animated:YES completion:nil];
self->currentAlert = deleteConfirmation;
}];
};

View file

@ -163,7 +163,7 @@
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oni-F4-X1U" userLabel="User suggestion container">
<rect key="frame" x="0.0" y="626" width="375" height="0.0"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" placeholder="YES" id="1Cd-cT-gOr"/>
</constraints>

View file

@ -25,4 +25,6 @@
*/
@property (nonatomic) MXKRoomDataSource *roomDataSource;
+ (instancetype)instantiate;
@end

View file

@ -37,6 +37,13 @@
@implementation RoomSearchViewController
+ (instancetype)instantiate
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
RoomSearchViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"RoomSearch"];
return viewController;
}
- (void)finalizeInit
{
[super finalizeInit];

View file

@ -14,26 +14,100 @@
// limitations under the License.
//
import GrowingTextView
@objc protocol RoomInputToolbarTextViewDelegate: AnyObject {
func textView(_ textView: RoomInputToolbarTextView, didChangeHeight height: CGFloat)
func textView(_ textView: RoomInputToolbarTextView, didReceivePasteForMediaFromSender sender: Any?)
}
class RoomInputToolbarTextView: GrowingTextView {
@objcMembers
class RoomInputToolbarTextView: UITextView {
@objc weak var toolbarDelegate: RoomInputToolbarTextViewDelegate?
override var keyCommands: [UIKeyCommand]? {
return [UIKeyCommand(input: "\r", modifierFlags: [], action: #selector(keyCommandSelector(_:)))]
private var heightConstraint: NSLayoutConstraint!
weak var toolbarDelegate: RoomInputToolbarTextViewDelegate?
var placeholder: String? {
didSet {
setNeedsDisplay()
}
}
@objc private func keyCommandSelector(_ keyCommand: UIKeyCommand) {
guard keyCommand.input == "\r", let delegate = (self.delegate as? RoomInputToolbarView) else {
var placeholderColor: UIColor = UIColor(white: 0.8, alpha: 1.0) {
didSet {
setNeedsDisplay()
}
}
var minHeight: CGFloat = 30.0 {
didSet {
updateUI()
}
}
var maxHeight: CGFloat = 0.0 {
didSet {
updateUI()
}
}
override var text: String! {
didSet {
updateUI()
}
}
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
contentMode = .redraw
NotificationCenter.default.addObserver(self, selector: #selector(textDidChange), name: UITextView.textDidChangeNotification, object: self)
if let heightConstraint = constraints.filter({ $0.firstAttribute == .height && $0.relation == .equal }).first {
self.heightConstraint = heightConstraint
} else {
heightConstraint = self.heightAnchor.constraint(equalToConstant: minHeight)
addConstraint(heightConstraint)
}
}
// MARK: - Overrides
override func layoutSubviews() {
super.layoutSubviews()
updateUI()
}
override func draw(_ rect: CGRect) {
super.draw(rect)
guard text.isEmpty, let placeholder = placeholder else {
return
}
delegate.onTouchUp(inside: delegate.rightInputToolbarButton)
var attributes: [NSAttributedString.Key: Any] = [.foregroundColor: placeholderColor]
if let font = font {
attributes[.font] = font
}
let frame = rect.inset(by: .init(top: textContainerInset.top,
left: textContainerInset.left + textContainer.lineFragmentPadding,
bottom: textContainerInset.bottom,
right: textContainerInset.right))
placeholder.draw(in: frame, withAttributes: attributes)
}
override var keyCommands: [UIKeyCommand]? {
return [UIKeyCommand(input: "\r", modifierFlags: [], action: #selector(keyCommandSelector(_:)))]
}
/// Overrides paste to handle images pasted from Safari, passing them up to the input toolbar.
@ -49,4 +123,36 @@ class RoomInputToolbarTextView: GrowingTextView {
super.paste(sender)
}
}
// MARK: - Private
@objc private func textDidChange(notification: Notification) {
if let sender = notification.object as? RoomInputToolbarTextView, sender == self {
updateUI()
}
}
private func updateUI() {
var height = sizeThatFits(CGSize(width: bounds.size.width, height: CGFloat.greatestFiniteMagnitude)).height
height = minHeight > 0 ? max(height, minHeight) : height
height = maxHeight > 0 ? min(height, maxHeight) : height
// Update placeholder
self.setNeedsDisplay()
guard height != heightConstraint.constant else {
return
}
heightConstraint.constant = height
toolbarDelegate?.textView(self, didChangeHeight: height)
}
@objc private func keyCommandSelector(_ keyCommand: UIKeyCommand) {
guard keyCommand.input == "\r", let delegate = (self.delegate as? RoomInputToolbarView) else {
return
}
delegate.onTouchUp(inside: delegate.rightInputToolbarButton)
}
}

View file

@ -60,28 +60,10 @@ typedef enum : NSUInteger
*/
@property (nonatomic, weak) id<RoomInputToolbarViewDelegate> delegate;
@property (weak, nonatomic) IBOutlet UIView *mainToolbarView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *mainToolbarMinHeightConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *mainToolbarHeightConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *messageComposerContainerTrailingConstraint;
@property (weak, nonatomic) IBOutlet UIButton *attachMediaButton;
@property (weak, nonatomic) IBOutlet UIImageView *inputTextBackgroundView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputContextViewHeightConstraint;
@property (weak, nonatomic) IBOutlet UIImageView *inputContextImageView;
@property (weak, nonatomic) IBOutlet UILabel *inputContextLabel;
@property (weak, nonatomic) IBOutlet UIButton *inputContextButton;
@property (weak, nonatomic) IBOutlet RoomActionsBar *actionsBar;
@property (weak, nonatomic) UIView *voiceMessageToolbarView;
/**
Tell whether the filled data will be sent encrypted. NO by default.
*/
@property (nonatomic) BOOL isEncryptionEnabled;
@property (nonatomic, assign) BOOL isEncryptionEnabled;
/**
Sender of the event being edited / replied.
@ -91,11 +73,31 @@ typedef enum : NSUInteger
/**
Destination of the message in the composer.
*/
@property (nonatomic) RoomInputToolbarViewSendMode sendMode;
@property (nonatomic, assign) RoomInputToolbarViewSendMode sendMode;
/**
YES if action menu is opened. NO otherwise
*/
@property (nonatomic, getter=isActionMenuOpened) BOOL actionMenuOpened;
@property (nonatomic, assign) BOOL actionMenuOpened;
/**
The input toolbar's main height constraint
*/
@property (nonatomic, weak, readonly) NSLayoutConstraint *mainToolbarHeightConstraint;
/**
The input toolbar's action bar
*/
@property (nonatomic, weak, readonly) RoomActionsBar *actionsBar;
/**
The attach media button
*/
@property (nonatomic, weak, readonly) UIButton *attachMediaButton;
/**
Adds a voice message toolbar view to be displayed inside this input toolbar
*/
- (void)setVoiceMessageToolbarView:(UIView *)toolbarView;
@end

View file

@ -17,34 +17,40 @@
#import "RoomInputToolbarView.h"
#import "ThemeService.h"
#import "Riot-Swift.h"
#import "GBDeviceInfo_iOS.h"
#import "UINavigationController+Riot.h"
static const CGFloat kContextBarHeight = 24;
static const CGFloat kActionMenuAttachButtonSpringVelocity = 7;
static const CGFloat kActionMenuAttachButtonSpringDamping = .45;
#import "WidgetManager.h"
#import "IntegrationManagerViewController.h"
static const NSTimeInterval kSendModeAnimationDuration = .15;
static const NSTimeInterval kActionMenuAttachButtonAnimationDuration = .4;
static const NSTimeInterval kActionMenuContentAlphaAnimationDuration = .2;
static const NSTimeInterval kActionMenuComposerHeightAnimationDuration = .3;
@import GrowingTextView;
@interface RoomInputToolbarView() <UITextViewDelegate, RoomInputToolbarTextViewDelegate>
const double kContextBarHeight = 24;
const NSTimeInterval kSendModeAnimationDuration = .15;
const NSTimeInterval kActionMenuAttachButtonAnimationDuration = .4;
const CGFloat kActionMenuAttachButtonSpringVelocity = 7;
const CGFloat kActionMenuAttachButtonSpringDamping = .45;
const NSTimeInterval kActionMenuContentAlphaAnimationDuration = .2;
const NSTimeInterval kActionMenuComposerHeightAnimationDuration = .3;
const CGFloat kComposerContainerTrailingPadding = 12;
@property (nonatomic, weak) IBOutlet UIView *mainToolbarView;
@interface RoomInputToolbarView() <GrowingTextViewDelegate, RoomInputToolbarTextViewDelegate>
{
// The intermediate action sheet
UIAlertController *actionSheet;
}
@property (nonatomic, weak) IBOutlet UIButton *attachMediaButton;
@property (nonatomic, weak) IBOutlet RoomInputToolbarTextView *textView;
@property (nonatomic, weak) IBOutlet UIImageView *inputTextBackgroundView;
@property (nonatomic, weak) IBOutlet UIImageView *inputContextImageView;
@property (nonatomic, weak) IBOutlet UILabel *inputContextLabel;
@property (nonatomic, weak) IBOutlet UIButton *inputContextButton;
@property (nonatomic, weak) IBOutlet RoomActionsBar *actionsBar;
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *mainToolbarMinHeightConstraint;
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *mainToolbarHeightConstraint;
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *messageComposerContainerTrailingConstraint;
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *inputContextViewHeightConstraint;
@property (nonatomic, weak) UIView *voiceMessageToolbarView;
@property (nonatomic, assign) CGFloat expandedMainToolbarHeight;
@end
@ -52,22 +58,10 @@ const CGFloat kComposerContainerTrailingPadding = 12;
@implementation RoomInputToolbarView
@dynamic delegate;
+ (UINib *)nib
{
return [UINib nibWithNibName:NSStringFromClass([RoomInputToolbarView class])
bundle:[NSBundle bundleForClass:[RoomInputToolbarView class]]];
}
+ (instancetype)roomInputToolbarView
{
if ([[self class] nib])
{
return [[[self class] nib] instantiateWithOwner:nil options:nil].firstObject;
}
else
{
return [[self alloc] init];
}
UINib *nib = [UINib nibWithNibName:NSStringFromClass([RoomInputToolbarView class]) bundle:nil];
return [nib instantiateWithOwner:nil options:nil].firstObject;
}
- (void)awakeFromNib
@ -85,6 +79,10 @@ const CGFloat kComposerContainerTrailingPadding = 12;
[self updateUIWithTextMessage:nil animated:NO];
self.textView.toolbarDelegate = self;
// Add an accessory view to the text view in order to retrieve keyboard view.
inputAccessoryView = [[UIView alloc] initWithFrame:CGRectZero];
self.textView.inputAccessoryView = inputAccessoryView;
}
- (void)setVoiceMessageToolbarView:(UIView *)voiceMessageToolbarView
@ -311,6 +309,11 @@ const CGFloat kComposerContainerTrailingPadding = 12;
self.textView.placeholder = inPlaceholder;
}
- (void)pasteText:(NSString *)text
{
self.textMessage = [self.textView.text stringByReplacingCharactersInRange:self.textView.selectedRange withString:text];
}
#pragma mark - Actions
- (IBAction)cancelAction:(id)sender
@ -321,7 +324,7 @@ const CGFloat kComposerContainerTrailingPadding = 12;
}
}
#pragma mark - GrowingTextViewDelegate
#pragma mark - UITextViewDelegate
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
@ -347,7 +350,9 @@ const CGFloat kComposerContainerTrailingPadding = 12;
[self.delegate roomInputToolbarViewDidChangeTextMessage:self];
}
- (void)textViewDidChangeHeight:(GrowingTextView *)textView height:(CGFloat)height
#pragma mark - RoomInputToolbarTextViewDelegate
- (void)textView:(RoomInputToolbarTextView *)textView didChangeHeight:(CGFloat)height
{
// Update height of the main toolbar (message composer)
CGFloat updatedHeight = height + (self.messageComposerContainerTopConstraint.constant + self.messageComposerContainerBottomConstraint.constant) + self.inputContextViewHeightConstraint.constant;
@ -372,13 +377,18 @@ const CGFloat kComposerContainerTrailingPadding = 12;
}
}
- (void)textView:(RoomInputToolbarTextView *)textView didReceivePasteForMediaFromSender:(id)sender
{
[self paste:sender];
}
#pragma mark - Override MXKRoomInputToolbarView
- (IBAction)onTouchUpInside:(UIButton*)button
{
if (button == self.attachMediaButton)
{
self.actionMenuOpened = !self.isActionMenuOpened;
self.actionMenuOpened = !self.actionMenuOpened;
}
[super onTouchUpInside:button];
@ -396,12 +406,6 @@ const CGFloat kComposerContainerTrailingPadding = 12;
- (void)destroy
{
if (actionSheet)
{
[actionSheet dismissViewControllerAnimated:NO completion:nil];
actionSheet = nil;
}
[super destroy];
}
@ -458,20 +462,6 @@ const CGFloat kComposerContainerTrailingPadding = 12;
}
}
#pragma mark - Clipboard - Handle image/data paste from general pasteboard
- (void)paste:(id)sender
{
// TODO Custom here the validation screen for each available item
[super paste:sender];
}
- (void)textView:(GrowingTextView *)textView didReceivePasteForMediaFromSender:(id)sender
{
[self paste:sender];
}
#pragma mark - Private
- (void)updateUIWithTextMessage:(NSString *)textMessage animated:(BOOL)animated

View file

@ -178,16 +178,16 @@ ServiceTermsModalCoordinatorBridgePresenterDelegate,
TableViewSectionsDelegate>
{
// Current alert (if any).
UIAlertController *currentAlert;
__weak UIAlertController *currentAlert;
// listener
id removedAccountObserver;
id accountUserInfoObserver;
id pushInfoUpdateObserver;
__weak id removedAccountObserver;
__weak id accountUserInfoObserver;
__weak id pushInfoUpdateObserver;
id notificationCenterWillUpdateObserver;
id notificationCenterDidUpdateObserver;
id notificationCenterDidFailObserver;
__weak id notificationCenterWillUpdateObserver;
__weak id notificationCenterDidUpdateObserver;
__weak id notificationCenterDidFailObserver;
// profile updates
// avatar
@ -216,10 +216,10 @@ TableViewSectionsDelegate>
GroupsDataSource *groupsDataSource;
// Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar.
id kAppDelegateDidTapStatusBarNotificationObserver;
__weak id kAppDelegateDidTapStatusBarNotificationObserver;
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
id kThemeServiceDidChangeThemeNotificationObserver;
__weak id kThemeServiceDidChangeThemeNotificationObserver;
// Postpone destroy operation when saving, pwd reset or email binding is in progress
BOOL isSavingInProgress;
@ -541,13 +541,8 @@ TableViewSectionsDelegate>
sectionAbout.headerTitle = VectorL10n.settingsAbout;
if (BuildSettings.settingsScreenShowAdvancedSettings)
{
sectionAbout.footerTitle = [NSString stringWithFormat:@"Element %@ (%@) / Olm %@\n%@\n%@",
AppInfo.current.appVersion.bundleShortVersion,
AppInfo.current.appVersion.bundleVersion,
[OLMKit versionString],
[MatrixKitL10n settingsConfigUserId:account.mxCredentials.userId],
[MatrixKitL10n settingsConfigHomeServer:account.mxCredentials.homeServer]];
{
sectionAbout.footerTitle = [self buildAboutSectionFooterTitleWithAccount:account];
}
[tmpSections addObject:sectionAbout];
@ -612,9 +607,13 @@ TableViewSectionsDelegate>
self.tableView.sectionFooterHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionFooterHeight = 50;
MXWeakify(self);
// Add observer to handle removed accounts
removedAccountObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountManagerDidRemoveAccountNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
if ([MXKAccountManager sharedManager].accounts.count)
{
// Refresh table to remove this account
@ -626,6 +625,8 @@ TableViewSectionsDelegate>
// Add observer to handle accounts update
accountUserInfoObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountUserInfoDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self stopActivityIndicator];
[self refreshSettings];
@ -635,6 +636,8 @@ TableViewSectionsDelegate>
// Add observer to push settings
pushInfoUpdateObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountAPNSActivityDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self stopActivityIndicator];
[self refreshSettings];
@ -663,6 +666,8 @@ TableViewSectionsDelegate>
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self userInterfaceThemeDidChange];
}];
@ -777,10 +782,14 @@ TableViewSectionsDelegate>
// Refresh linked emails and phone numbers in parallel
[self loadAccount3PIDs];
MXWeakify(self);
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
[self.tableView setContentOffset:CGPointMake(-self.tableView.adjustedContentInset.left, -self.tableView.adjustedContentInset.top) animated:YES];
}];
@ -977,9 +986,11 @@ TableViewSectionsDelegate>
{
MXWeakify(self);
[currentAlert dismissViewControllerAnimated:NO completion:nil];
currentAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n accountEmailValidationTitle] message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *validationAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n accountEmailValidationTitle]
message:message
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[validationAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
[self stopActivityIndicator];
@ -988,14 +999,15 @@ TableViewSectionsDelegate>
self.newEmailEditingEnabled = NO;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n continue] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[validationAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n continue] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
[self tryFinaliseAddEmailSession:threePidAddSession withAuthenticationParameters:authenticationParameters
threePidAddManager:threePidAddManager];
}]];
[currentAlert mxk_setAccessibilityIdentifier:@"SettingsVCEmailValidationAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[validationAlert mxk_setAccessibilityIdentifier:@"SettingsVCEmailValidationAlert"];
[self presentViewController:validationAlert animated:YES completion:nil];
currentAlert = validationAlert;
}
- (void)tryFinaliseAddEmailSession:(MX3PidAddSession*)threePidAddSession withAuthenticationParameters:(NSDictionary*)authParams threePidAddManager:(MX3PidAddManager*)threePidAddManager
@ -1035,11 +1047,13 @@ TableViewSectionsDelegate>
MXLogDebug(@"[SettingsViewController] tryFinaliseAddEmailSession: Wrong credentials");
// Ask password again
self->currentAlert = [UIAlertController alertControllerWithTitle:nil
message:[VectorL10n settingsAdd3pidInvalidPasswordMessage]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *passwordPrompt = [UIAlertController alertControllerWithTitle:nil
message:[VectorL10n settingsAdd3pidInvalidPasswordMessage]
preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n retry] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXWeakify(self);
[passwordPrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n retry] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
[self showAuthenticationIfNeededForAdding:kMX3PIDMediumEmail withSession:self.mainSession completion:^(NSDictionary *authParams) {
@ -1047,7 +1061,8 @@ TableViewSectionsDelegate>
}];
}]];
[self presentViewController:self->currentAlert animated:YES completion:nil];
[self presentViewController:passwordPrompt animated:YES completion:nil];
self->currentAlert = passwordPrompt;
return;
}
@ -1088,9 +1103,11 @@ TableViewSectionsDelegate>
MXWeakify(self);
[currentAlert dismissViewControllerAnimated:NO completion:nil];
currentAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n accountMsisdnValidationTitle] message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *validationAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n accountMsisdnValidationTitle]
message:message
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[validationAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
@ -1101,13 +1118,13 @@ TableViewSectionsDelegate>
self.newPhoneEditingEnabled = NO;
}]];
[currentAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
[validationAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.secureTextEntry = NO;
textField.placeholder = nil;
textField.keyboardType = UIKeyboardTypeDecimalPad;
}];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n submit] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
[validationAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n submit] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
@ -1126,8 +1143,9 @@ TableViewSectionsDelegate>
}
}]];
[currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCMsisdnValidationAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[validationAlert mxk_setAccessibilityIdentifier: @"SettingsVCMsisdnValidationAlert"];
[self presentViewController:validationAlert animated:YES completion:nil];
currentAlert = validationAlert;
}
- (void)finaliseAddPhoneNumberSession:(MX3PidAddSession*)threePidAddSession withToken:(NSString*)token andAuthenticationParameters:(NSDictionary*)authParams message:(NSString*)message threePidAddManager:(MX3PidAddManager*)threePidAddManager
@ -1166,11 +1184,13 @@ TableViewSectionsDelegate>
MXLogDebug(@"[SettingsViewController] finaliseAddPhoneNumberSession: Wrong authentication credentials");
// Ask password again
self->currentAlert = [UIAlertController alertControllerWithTitle:nil
message:[VectorL10n settingsAdd3pidInvalidPasswordMessage]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *passwordPrompt = [UIAlertController alertControllerWithTitle:nil
message:[VectorL10n settingsAdd3pidInvalidPasswordMessage]
preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n retry] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXWeakify(self);
[passwordPrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n retry] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
[self showAuthenticationIfNeededForAdding:kMX3PIDMediumMSISDN withSession:self.mainSession completion:^(NSDictionary *authParams) {
@ -1178,7 +1198,8 @@ TableViewSectionsDelegate>
}];
}]];
[self presentViewController:self->currentAlert animated:YES completion:nil];
[self presentViewController:passwordPrompt animated:YES completion:nil];
self->currentAlert = passwordPrompt;
return;
}
@ -1218,17 +1239,20 @@ TableViewSectionsDelegate>
}
self->currentAlert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *errorAlert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXWeakify(self);
[errorAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
// Ask again the sms token
[self showValidationMsisdnDialogWithMessage:message for3PidAddSession:threePidAddSession threePidAddManager:threePidAddManager authenticationParameters:authParams];
}]];
[self->currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCErrorAlert"];
[self presentViewController:self->currentAlert animated:YES completion:nil];
[errorAlert mxk_setAccessibilityIdentifier: @"SettingsVCErrorAlert"];
[self presentViewController:errorAlert animated:YES completion:nil];
self->currentAlert = errorAlert;
}
}];
}
@ -1396,6 +1420,35 @@ TableViewSectionsDelegate>
}
}
- (NSString*)buildAboutSectionFooterTitleWithAccount:(MXKAccount*)account
{
NSMutableString *footerText = [NSMutableString new];
AppInfo *appInfo = AppInfo.current;
NSString *appName = appInfo.displayName;
NSString *appVersion = appInfo.appVersion.bundleShortVersion;
NSString *buildVersion = appInfo.appVersion.bundleVersion;
NSString *appVersionInfo = [NSString stringWithFormat:@"%@ %@ (%@)", appName, appVersion, buildVersion];
NSString *loggedUserInfo = [MatrixKitL10n settingsConfigUserId:account.mxCredentials.userId];
NSString *homeserverInfo = [MatrixKitL10n settingsConfigHomeServer:account.mxCredentials.homeServer];
NSString *sdkVersionInfo = [NSString stringWithFormat:@"Matrix SDK %@", MatrixSDKVersion];
NSString *olmVersionInfo = [NSString stringWithFormat:@"OLM %@", [OLMKit versionString]];
[footerText appendFormat:@"%@\n", loggedUserInfo];
[footerText appendFormat:@"%@\n", homeserverInfo];
[footerText appendFormat:@"%@\n", appVersionInfo];
[footerText appendFormat:@"%@\n", sdkVersionInfo];
[footerText appendFormat:@"%@", olmVersionInfo];
return [footerText copy];
}
#pragma mark - 3Pid Add
- (void)showAuthenticationIfNeededForAdding:(MX3PIDMedium)medium withSession:(MXSession*)session completion:(void (^)(NSDictionary* authParams))completion
@ -2592,11 +2645,11 @@ TableViewSectionsDelegate>
__weak typeof(self) weakSelf = self;
currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n settingsUnignoreUser:ignoredUserId] message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *unignorePrompt = [UIAlertController alertControllerWithTitle:[VectorL10n settingsUnignoreUser:ignoredUserId] message:nil preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n yes]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[unignorePrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n yes]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -2625,9 +2678,9 @@ TableViewSectionsDelegate>
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n no]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[unignorePrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n no]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -2637,8 +2690,9 @@ TableViewSectionsDelegate>
}]];
[currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCUnignoreAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[unignorePrompt mxk_setAccessibilityIdentifier: @"SettingsVCUnignoreAlert"];
[self presentViewController:unignorePrompt animated:YES completion:nil];
currentAlert = unignorePrompt;
}
}
else if (section == SECTION_TAG_ABOUT)
@ -2824,9 +2878,9 @@ TableViewSectionsDelegate>
}
// Remove ?
currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n settingsRemovePromptTitle] message:promptMsg preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *removePrompt = [UIAlertController alertControllerWithTitle:[VectorL10n settingsRemovePromptTitle] message:promptMsg preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
[removePrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
@ -2838,7 +2892,7 @@ TableViewSectionsDelegate>
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n remove]
[removePrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n remove]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
@ -2878,8 +2932,9 @@ TableViewSectionsDelegate>
}]];
[currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCRemove3PIDAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[removePrompt mxk_setAccessibilityIdentifier: @"SettingsVCRemove3PIDAlert"];
[self presentViewController:removePrompt animated:YES completion:nil];
currentAlert = removePrompt;
}
}
}
@ -2901,9 +2956,9 @@ TableViewSectionsDelegate>
NSString *title = [VectorL10n settingsNotificationsDisabledAlertTitle];
NSString *message = [VectorL10n settingsNotificationsDisabledAlertMessage];
currentAlert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *showSettingsPrompt = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
[showSettingsPrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
@ -2927,13 +2982,14 @@ TableViewSectionsDelegate>
}
}];
[currentAlert addAction:settingsAction];
currentAlert.preferredAction = settingsAction;
[showSettingsPrompt addAction:settingsAction];
showSettingsPrompt.preferredAction = settingsAction;
[currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCPushNotificationsAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[showSettingsPrompt mxk_setAccessibilityIdentifier: @"SettingsVCPushNotificationsAlert"];
[self presentViewController:showSettingsPrompt animated:YES completion:nil];
currentAlert = showSettingsPrompt;
// Keep off the switch
// Keep the the switch off.
sender.on = NO;
}
else if ([MXKAccountManager sharedManager].activeAccounts.count)
@ -3322,11 +3378,11 @@ TableViewSectionsDelegate>
[currentAlert dismissViewControllerAnimated:NO completion:nil];
currentAlert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *errorAlert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[errorAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3347,9 +3403,9 @@ TableViewSectionsDelegate>
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n retry]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[errorAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n retry]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3363,8 +3419,9 @@ TableViewSectionsDelegate>
}]];
[currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCSaveChangesFailedAlert"];
[rootViewController presentViewController:currentAlert animated:YES completion:nil];
[errorAlert mxk_setAccessibilityIdentifier: @"SettingsVCSaveChangesFailedAlert"];
[rootViewController presentViewController:errorAlert animated:YES completion:nil];
currentAlert = errorAlert;
}
}
@ -3385,13 +3442,13 @@ TableViewSectionsDelegate>
[currentAlert dismissViewControllerAnimated:NO completion:nil];
currentAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n accountErrorEmailWrongTitle]
message:[MatrixKitL10n accountErrorEmailWrongDescription]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *errorAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n accountErrorEmailWrongTitle]
message:[MatrixKitL10n accountErrorEmailWrongDescription]
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[errorAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
@ -3402,8 +3459,9 @@ TableViewSectionsDelegate>
}]];
[currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCAddEmailAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[errorAlert mxk_setAccessibilityIdentifier: @"SettingsVCAddEmailAlert"];
[self presentViewController:errorAlert animated:YES completion:nil];
currentAlert = errorAlert;
return;
}
@ -3495,11 +3553,11 @@ TableViewSectionsDelegate>
[currentAlert dismissViewControllerAnimated:NO completion:nil];
__weak typeof(self) weakSelf = self;
currentAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n accountErrorMsisdnWrongTitle]
message:[MatrixKitL10n accountErrorMsisdnWrongDescription]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *errorAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n accountErrorMsisdnWrongTitle]
message:[MatrixKitL10n accountErrorMsisdnWrongDescription]
preferredStyle:UIAlertControllerStyleAlert];
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
[errorAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
@ -3511,8 +3569,9 @@ TableViewSectionsDelegate>
}]];
[currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCAddMsisdnAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
[errorAlert mxk_setAccessibilityIdentifier: @"SettingsVCAddMsisdnAlert"];
[self presentViewController:errorAlert animated:YES completion:nil];
currentAlert = errorAlert;
return;
}
@ -3868,9 +3927,9 @@ TableViewSectionsDelegate>
{
[self->currentAlert dismissViewControllerAnimated:NO completion:nil];
self->currentAlert = [UIAlertController alertControllerWithTitle:nil message:[VectorL10n settingsPasswordUpdated] preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *successAlert = [UIAlertController alertControllerWithTitle:nil message:[VectorL10n settingsPasswordUpdated] preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
[successAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
@ -3890,8 +3949,9 @@ TableViewSectionsDelegate>
}]];
[self->currentAlert mxk_setAccessibilityIdentifier:@"SettingsVCOnPasswordUpdatedAlert"];
[self presentViewController:self->currentAlert animated:YES completion:nil];
[successAlert mxk_setAccessibilityIdentifier:@"SettingsVCOnPasswordUpdatedAlert"];
[self presentViewController:successAlert animated:YES completion:nil];
self->currentAlert = successAlert;
}
else
{
@ -3916,9 +3976,9 @@ TableViewSectionsDelegate>
{
[self->currentAlert dismissViewControllerAnimated:NO completion:nil];
self->currentAlert = [UIAlertController alertControllerWithTitle:nil message:[VectorL10n settingsFailToUpdatePassword] preferredStyle:UIAlertControllerStyleAlert];
UIAlertController *errorAlert = [UIAlertController alertControllerWithTitle:nil message:[VectorL10n settingsFailToUpdatePassword] preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
[errorAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
@ -3939,8 +3999,9 @@ TableViewSectionsDelegate>
}]];
[self->currentAlert mxk_setAccessibilityIdentifier:@"SettingsVCPasswordChangeFailedAlert"];
[rootViewController presentViewController:self->currentAlert animated:YES completion:nil];
[errorAlert mxk_setAccessibilityIdentifier:@"SettingsVCPasswordChangeFailedAlert"];
[rootViewController presentViewController:errorAlert animated:YES completion:nil];
self->currentAlert = errorAlert;
}
}

View file

@ -131,6 +131,9 @@ final class SpaceListViewModel: SpaceListViewModelType {
private func loadData() {
guard let session = self.userSessionsService.mainUserSession?.matrixSession else {
// If there is no main session, reset current selection and give an empty section list
// It can happen when the user make a clear cache or logout
self.resetList()
return
}
@ -243,4 +246,15 @@ final class SpaceListViewModel: SpaceListViewModelType {
return spaceViewData.spaceId
}
}
private func resetList() {
self.sections = []
let selectedIndexPath = IndexPath(row: 0, section: 0)
self.selectedIndexPath = selectedIndexPath
self.homeIndexPath = selectedIndexPath
self.update(viewState: .loaded([]))
}
}

View file

@ -125,20 +125,20 @@ final class SplitViewCoordinator: NSObject, SplitViewCoordinatorType {
}
// TODO: Do not expose publicly this method
func restorePlaceholderDetails() {
func resetDetails(animated: Bool) {
// Be sure that the primary is then visible too.
if splitViewController.displayMode == .primaryHidden {
splitViewController.preferredDisplayMode = .allVisible
}
self.resetDetailNavigationControllerWithPlaceholder(animated: false)
self.resetDetailNavigationController(animated: animated)
// Release the current selected item (room/contact/group...).
self.tabBarCoordinator?.releaseSelectedItems()
}
}
func popToHome(animated: Bool, completion: (() -> Void)?) {
self.resetDetailNavigationControllerWithPlaceholder(animated: animated)
self.resetDetails(animated: animated)
// Force back to the main screen if this is not the one that is displayed
self.tabBarCoordinator?.popToHome(animated: animated, completion: completion)
@ -172,6 +172,17 @@ final class SplitViewCoordinator: NSObject, SplitViewCoordinatorType {
// Set placeholder screen as root controller of detail navigation controller
let placeholderDetailsVC = self.createPlaceholderDetailsViewController()
detailNavigationRouter.setRootModule(placeholderDetailsVC, hideNavigationBar: false, animated: animated, popCompletion: nil)
}
private func resetDetailNavigationController(animated: Bool) {
if self.splitViewController.isCollapsed {
if let topMostNavigationController = self.selectedNavigationRouter?.modules.last as? UINavigationController, topMostNavigationController == self.detailNavigationController {
self.selectedNavigationRouter?.popModule(animated: animated)
}
} else {
self.resetDetailNavigationControllerWithPlaceholder(animated: animated)
}
}
private func isPlaceholderShown(from secondaryViewController: UIViewController) -> Bool {
@ -270,7 +281,7 @@ extension SplitViewCoordinator: UISplitViewControllerDelegate {
}
// Restore detail navigation controller with placeholder as root
self.resetDetailNavigationControllerWithPlaceholder(animated: false)
self.resetDetailNavigationController(animated: false)
// Return up to date detail navigation controller
// In any cases `detailNavigationController` will be used as secondary view of the split view controller.
@ -353,6 +364,6 @@ extension SplitViewCoordinator: SplitViewMasterPresentableDelegate {
}
func splitViewMasterPresentableWantsToResetDetail(_ presentable: Presentable) {
self.resetDetailNavigationControllerWithPlaceholder(animated: false)
self.resetDetails(animated: false)
}
}

View file

@ -30,8 +30,10 @@ protocol SplitViewCoordinatorType: Coordinator, Presentable {
/// - Parameter spaceId: The id of the Space to use.
func start(with spaceId: String?)
/// Restore navigation stack and show home screen
func popToHome(animated: Bool, completion: (() -> Void)?)
// TODO: Do not expose publicly this method
func restorePlaceholderDetails()
/// Remove detail screens and display placeholder if needed
func resetDetails(animated: Bool)
}

View file

@ -41,7 +41,8 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
private let masterNavigationController: UINavigationController
private var currentSpaceId: String?
private var homeViewControllerWrapperViewController: HomeViewControllerWithBannerWrapperViewController?
private weak var versionCheckCoordinator: VersionCheckCoordinator?
private var currentMatrixSession: MXSession? {
return parameters.userSessionsService.mainUserSession?.matrixSession
@ -77,8 +78,7 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
}
func start(with spaceId: String?) {
self.currentSpaceId = spaceId
// If start has been done once do not setup view controllers again
if self.hasStartedOnce == false {
let masterTabBarController = self.createMasterTabBarController()
@ -98,16 +98,12 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
self.registerUserSessionsServiceNotifications()
self.registerSessionChange()
if let homeViewController = homeViewControllerWrapperViewController {
let versionCheckCoordinator = VersionCheckCoordinator(rootViewController: masterTabBarController,
bannerPresenter: homeViewController,
themeService: ThemeService.shared())
versionCheckCoordinator.start()
add(childCoordinator: versionCheckCoordinator)
}
self.updateMasterTabBarController(with: spaceId, forceReload: true)
} else {
self.updateMasterTabBarController(with: spaceId)
}
self.updateMasterTabBarController(with: spaceId)
self.currentSpaceId = spaceId
}
func toPresentable() -> UIViewController {
@ -211,21 +207,25 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
}
searchBarButtonItem.accessibilityLabel = VectorL10n.searchDefaultPlaceholder
tabBarController.navigationItem.rightBarButtonItem = searchBarButtonItem
self.updateTabControllers(for: tabBarController, showCommunities: true)
tabBarController.navigationItem.rightBarButtonItem = searchBarButtonItem
return tabBarController
}
private func createHomeViewController() -> UIViewController {
private func createVersionCheckCoordinator(withRootViewController rootViewController: UIViewController, bannerPresentrer: BannerPresentationProtocol) -> VersionCheckCoordinator {
let versionCheckCoordinator = VersionCheckCoordinator(rootViewController: rootViewController,
bannerPresenter: bannerPresentrer,
themeService: ThemeService.shared())
return versionCheckCoordinator
}
private func createHomeViewController() -> HomeViewControllerWithBannerWrapperViewController {
let homeViewController: HomeViewController = HomeViewController.instantiate()
homeViewController.tabBarItem.tag = Int(TABBAR_HOME_INDEX)
homeViewController.tabBarItem.image = homeViewController.tabBarItem.image
homeViewController.accessibilityLabel = VectorL10n.titleHome
let wrapperViewController = HomeViewControllerWithBannerWrapperViewController(viewController: homeViewController)
homeViewControllerWrapperViewController = wrapperViewController
let wrapperViewController = HomeViewControllerWithBannerWrapperViewController(viewController: homeViewController)
return wrapperViewController
}
@ -280,18 +280,35 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
gesture.delegate = self
}
private func updateMasterTabBarController(with spaceId: String?) {
private func updateMasterTabBarController(with spaceId: String?, forceReload: Bool = false) {
guard forceReload || spaceId != self.currentSpaceId else { return }
self.updateTabControllers(for: self.masterTabBarController, showCommunities: spaceId == nil)
self.masterTabBarController.filterRooms(withParentId: spaceId, inMatrixSession: self.currentMatrixSession)
}
// TODO: Avoid to reinstantiate controllers everytime
private func updateTabControllers(for tabBarController: MasterTabBarController, showCommunities: Bool) {
var viewControllers: [UIViewController] = []
let homeViewController = self.createHomeViewController()
viewControllers.append(homeViewController)
if let existingVersionCheckCoordinator = self.versionCheckCoordinator {
self.remove(childCoordinator: existingVersionCheckCoordinator)
}
if let masterTabBarController = self.masterTabBarController {
let versionCheckCoordinator = self.createVersionCheckCoordinator(withRootViewController: masterTabBarController, bannerPresentrer: homeViewController)
versionCheckCoordinator.start()
self.add(childCoordinator: versionCheckCoordinator)
self.versionCheckCoordinator = versionCheckCoordinator
}
if RiotSettings.shared.homeScreenShowFavouritesTab {
let favouritesViewController = self.createFavouritesViewController()
viewControllers.append(favouritesViewController)

View file

@ -299,13 +299,12 @@ final class NavigationRouter: NSObject, NavigationRouterType {
self.postNotification(withName: NavigationRouter.willPopModule, for: viewController)
}
private func didPopViewController(_ viewController: UIViewController) {
private func didPopViewController(_ viewController: UIViewController) {
self.postNotification(withName: NavigationRouter.didPopModule, for: viewController)
// Call completion closure associated to the view controller
// So associated coordinator can be deallocated
runCompletion(for: viewController)
self.postNotification(withName: NavigationRouter.didPopModule, for: viewController)
self.removeModule(for: viewController)
}

View file

@ -86,7 +86,7 @@
for (MXRoomSummary *roomSummary in roomsSummaries)
{
if (!roomSummary.hiddenFromUser)
if (!roomSummary.hiddenFromUser && roomSummary.roomType == MXRoomTypeRoom)
{
[roomSummary setMatrixSession:session];

View file

@ -32,6 +32,8 @@
static const CGFloat kLargeImageSizeMaxDimension = 2048.0;
static const CGSize kThumbnailSize = {800.0, 600.0};
/// A safe maximum file size for an image to send the original.
static const NSUInteger kImageMaxFileSize = 20 * 1024 * 1024;
typedef NS_ENUM(NSInteger, ImageCompressionMode)
{
@ -314,30 +316,43 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
if ([self.shareItemProvider areAllItemsImages])
{
// When all items are images, they're processed together from the
// pending list, immediately after the final image has been loaded.
[self.pendingImages addObject:imageData];
}
else
{
CGSize imageSize = [self imageSizeFromImageData:imageData];
// Otherwise, the image is sent as is, without prompting for a resize
// as that wouldn't make much sense with multiple content types.
self.imageCompressionMode = ImageCompressionModeNone;
self.actualLargeSize = MAX(imageSize.width, imageSize.height);
[self sendImageData:imageData toRooms:rooms success:requestSuccess failure:requestFailure];
}
// Only prompt for image resize if all items are images
// Ignore showMediaCompressionPrompt setting due to memory constraints with full size images.
// When there are multiple content types the image will have been sent above.
// Otherwise, if we have loaded all of the images we can send them all together.
if ([self.shareItemProvider areAllItemsImages])
{
if ([self.shareItemProvider areAllItemsLoaded])
{
UIAlertController *compressionPrompt = [self compressionPromptForPendingImagesWithShareBlock:^{
MXWeakify(self);
void (^sendPendingImages)(void) = ^void() {
MXStrongifyAndReturnIfNil(self);
[self sendImageDatas:self.pendingImages.copy toRooms:rooms success:requestSuccess failure:requestFailure];
}];
};
if (compressionPrompt)
if (RiotSettings.shared.showMediaCompressionPrompt)
{
[self presentCompressionPrompt:compressionPrompt];
// Create a compression prompt which will be nil when the sizes can't be determined or if there are no pending images.
UIAlertController *compressionPrompt = [self compressionPromptForPendingImagesWithShareBlock:sendPendingImages];
if (compressionPrompt)
{
[self presentCompressionPrompt:compressionPrompt];
}
}
else
{
self.imageCompressionMode = ImageCompressionModeNone;
sendPendingImages();
}
}
else
@ -410,26 +425,26 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
}
}
- (void)resetPendingData
- (BOOL)roomsContainEncryptedRoom:(NSArray<MXRoom *> *)rooms
{
[self.pendingImages removeAllObjects];
[self.imageUploadProgresses removeAllObjects];
}
- (BOOL)isAPendingImageNotOrientedUp
{
BOOL isAPendingImageNotOrientedUp = NO;
BOOL foundEncryptedRoom = NO;
for (NSData *imageData in self.pendingImages)
for (MXRoom *room in rooms)
{
if ([self isImageOrientationNotUpOrUndeterminedForImageData:imageData])
if (room.summary.isEncrypted)
{
isAPendingImageNotOrientedUp = YES;
foundEncryptedRoom = YES;
break;
}
}
return isAPendingImageNotOrientedUp;
return foundEncryptedRoom;
}
- (void)resetPendingData
{
[self.pendingImages removeAllObjects];
[self.imageUploadProgresses removeAllObjects];
}
// TODO: When select multiple images:
@ -442,8 +457,6 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
return nil;
}
BOOL isAPendingImageNotOrientedUp = [self isAPendingImageNotOrientedUp];
NSData *firstImageData = self.pendingImages.firstObject;
UIImage *firstImage = [UIImage imageWithData:firstImageData];
@ -451,16 +464,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
if (compressionSizes.small.fileSize == 0 && compressionSizes.medium.fileSize == 0 && compressionSizes.large.fileSize == 0)
{
if (isAPendingImageNotOrientedUp && self.pendingImages.count > 1)
{
self.imageCompressionMode = ImageCompressionModeSmall;
}
else
{
self.imageCompressionMode = ImageCompressionModeNone;
}
MXLogDebug(@"[ShareManager] Send %lu image(s) without compression prompt using compression mode: %ld", (unsigned long)self.pendingImages.count, (long)self.imageCompressionMode);
self.imageCompressionMode = ImageCompressionModeNone;
MXLogDebug(@"[ShareManager] Bypass compression prompt and send originals for %lu image(s) due to undetermined file sizes", (unsigned long)self.pendingImages.count);
shareBlock();
@ -480,7 +485,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
MXStrongifyAndReturnIfNil(self);
self.imageCompressionMode = ImageCompressionModeSmall;
[self logCompressionSizeChoice:compressionSizes.large];
[self logCompressionSizeChoice:compressionSizes.small];
shareBlock();
}]];
@ -495,7 +500,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
MXStrongifyAndReturnIfNil(self);
self.imageCompressionMode = ImageCompressionModeMedium;
[self logCompressionSizeChoice:compressionSizes.large];
[self logCompressionSizeChoice:compressionSizes.medium];
shareBlock();
}]];
@ -520,8 +525,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
}]];
}
// To limit memory consumption, we suggest the original resolution only if the image orientation is up, or if the image size is moderate
if (!isAPendingImageNotOrientedUp || !compressionSizes.large.fileSize)
// To limit memory consumption when encrypting, we suggest the original resolution only if the image size is moderate
if (compressionSizes.original.fileSize < kImageMaxFileSize)
{
NSString *fileSizeString = [MXTools fileSizeToString:compressionSizes.original.fileSize];
@ -532,7 +537,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
MXStrongifyAndReturnIfNil(self);
self.imageCompressionMode = ImageCompressionModeNone;
[self logCompressionSizeChoice:compressionSizes.large];
[self logCompressionSizeChoice:compressionSizes.original];
shareBlock();
}]];
@ -626,46 +631,6 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
return CGSizeMake(width, height);
}
- (NSNumber*)cgImageimageOrientationNumberFromImageData:(NSData*)imageData
{
NSNumber *orientationNumber;
CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
CFRelease(imageSource);
if (imageProperties != NULL)
{
CFNumberRef orientationNum = CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation);
// Check orientation and flip size if required
if (orientationNum != NULL)
{
orientationNumber = (__bridge NSNumber *)orientationNum;
}
CFRelease(imageProperties);
}
return orientationNumber;
}
- (BOOL)isImageOrientationNotUpOrUndeterminedForImageData:(NSData*)imageData
{
BOOL isImageNotOrientedUp = YES;
NSNumber *cgImageOrientationNumber = [self cgImageimageOrientationNumberFromImageData:imageData];
if (cgImageOrientationNumber && cgImageOrientationNumber.unsignedIntegerValue == (NSUInteger)kCGImagePropertyOrientationUp)
{
isImageNotOrientedUp = NO;
}
return isImageNotOrientedUp;
}
- (void)logCompressionSizeChoice:(MXKImageCompressionSize)compressionSize
{
NSString *fileSize = [MXTools fileSizeToString:compressionSize.fileSize round:NO];
@ -826,19 +791,9 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
MXWeakify(self);
// Ignore showMediaCompressionPrompt setting due to memory constraints when encrypting large videos.
UIAlertController *compressionPrompt = [MXKTools videoConversionPromptForVideoAsset:videoAsset withCompletion:^(NSString *presetName) {
void (^sendVideo)(void) = ^void() {
MXStrongifyAndReturnIfNil(self);
// If the preset name is nil, the user cancelled.
if (!presetName)
{
return;
}
// Set the chosen video conversion preset.
[MXSDKOptions sharedInstance].videoConversionPresetName = presetName;
[self didStartSending];
if (!videoLocalUrl)
{
@ -876,9 +831,57 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
success();
}
});
}];
};
[self presentCompressionPrompt:compressionPrompt];
BOOL allRoomsAreUnencrypted = ![self roomsContainEncryptedRoom:rooms];
// When rooms are unencrypted convert the video according to the user's normal preferences
if (allRoomsAreUnencrypted)
{
if (!RiotSettings.shared.showMediaCompressionPrompt)
{
[MXSDKOptions sharedInstance].videoConversionPresetName = AVCaptureSessionPreset1920x1080;
sendVideo();
}
else
{
UIAlertController *compressionPrompt = [MXKTools videoConversionPromptForVideoAsset:videoAsset withCompletion:^(NSString *presetName) {
// If the preset name is nil, the user cancelled.
if (!presetName)
{
return;
}
// Set the chosen video conversion preset.
[MXSDKOptions sharedInstance].videoConversionPresetName = presetName;
sendVideo();
}];
[self presentCompressionPrompt:compressionPrompt];
}
}
else
{
// When rooms are encrypted we quickly run out of memory encrypting the video
// Prompt the user if they're happy to send a low quality video (320p).
UIAlertController *lowQualityPrompt = [UIAlertController alertControllerWithTitle:VectorL10n.shareExtensionLowQualityVideoTitle
message:[VectorL10n shareExtensionLowQualityVideoMessage:AppInfo.current.displayName]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:MatrixKitL10n.cancel style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
// Do nothing
}];
UIAlertAction *sendAction = [UIAlertAction actionWithTitle:VectorL10n.shareExtensionSendNow style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[MXSDKOptions sharedInstance].videoConversionPresetName = AVAssetExportPresetMediumQuality;
sendVideo();
}];
[lowQualityPrompt addAction:cancelAction];
[lowQualityPrompt addAction:sendAction];
[lowQualityPrompt setPreferredAction:sendAction];
[self presentCompressionPrompt:lowQualityPrompt];
}
}
- (void)sendVoiceMessage:(NSURL *)fileUrl
@ -1021,17 +1024,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
break;
}
if (CGSizeEqualToSize(newImageSize, CGSizeZero))
{
// No resize to make
// Make sure the uploaded image orientation is up
if ([self isImageOrientationNotUpOrUndeterminedForImageData:imageData])
{
UIImage *image = [UIImage imageWithData:imageData];
convertedImage = [MXKTools forceImageOrientationUp:image];
}
}
else
if (!CGSizeEqualToSize(newImageSize, CGSizeZero))
{
// Resize the image and set image in right orientation too
convertedImage = [MXKTools resizeImageWithData:imageData toFitInSize:newImageSize];

View file

@ -57,6 +57,7 @@
self.roomTitleLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
self.contentView.backgroundColor = ThemeService.shared.theme.backgroundColor;
self.selectionButton.tintColor = ThemeService.shared.theme.tintColor;
[self.selectionButton setImage:[UIImage imageNamed:@"radio-button-default"] forState:UIControlStateNormal];
[self.selectionButton setImage:[UIImage imageNamed:@"radio-button-selected"] forState:UIControlStateSelected];
@ -85,7 +86,7 @@
[self.avatarImageView vc_setRoomAvatarImageWith:roomCellData.avatarUrl
roomId:roomCellData.roomIdentifier
displayName:roomCellData.roomDisplayname
mediaManager:roomCellData.mxSession.mediaManager];
mediaManager:roomCellData.roomSummary.mxSession.mediaManager];
self.roomTitleLabel.text = roomCellData.roomDisplayname;
if (!self.roomTitleLabel.text.length)

View file

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -40,14 +40,15 @@
<constraint firstAttribute="width" constant="11" id="Mai-xD-TqV"/>
</constraints>
</imageView>
<button opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="m0f-of-6xq">
<button opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="m0f-of-6xq">
<rect key="frame" x="562" y="29" width="16" height="16"/>
<constraints>
<constraint firstAttribute="height" constant="16" id="Wue-Ih-eVg"/>
<constraint firstAttribute="width" constant="16" id="s5a-PW-58p"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="plain" image="radio-button-selected"/>
<state key="normal" image="radio-button-selected">
<color key="titleColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
</button>
</subviews>
<constraints>

View file

@ -28,18 +28,18 @@ private class ShareExtensionItem: ShareItemProtocol {
}
var type: ShareItemType {
if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.text.rawValue) {
return .text
} else if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.url.rawValue) {
return .URL
} else if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.fileUrl.rawValue) {
return .fileURL
} else if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.image.rawValue) {
if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.image.rawValue) {
return .image
} else if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.video.rawValue) {
return .video
} else if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.movie.rawValue) {
return .movie
} else if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.fileUrl.rawValue) {
return .fileURL
} else if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.url.rawValue) {
return .URL
} else if itemProvider.hasItemConformingToTypeIdentifier(MXKUTI.text.rawValue) {
return .text
}
return .unknown

View file

@ -34,11 +34,10 @@ final class UserSuggestionCoordinator: Coordinator {
private let parameters: UserSuggestionCoordinatorParameters
private var userSuggestionHostingController: UIViewController!
private var userSuggestionService: UserSuggestionServiceProtocol!
private var userSuggestionViewModel: UserSuggestionViewModelProtocol!
private var roomMembers: [MXRoomMember] = []
private var userSuggestionHostingController: UIViewController
private var userSuggestionService: UserSuggestionServiceProtocol
private var userSuggestionViewModel: UserSuggestionViewModelProtocol
private var roomMemberProvider: UserSuggestionCoordinatorRoomMemberProvider
// MARK: Public
@ -54,9 +53,10 @@ final class UserSuggestionCoordinator: Coordinator {
init(parameters: UserSuggestionCoordinatorParameters) {
self.parameters = parameters
userSuggestionService = UserSuggestionService(roomMembersProvider: self)
roomMemberProvider = UserSuggestionCoordinatorRoomMemberProvider(room: parameters.room)
userSuggestionService = UserSuggestionService(roomMemberProvider: roomMemberProvider)
userSuggestionViewModel = UserSuggestionViewModel.makeUserSuggestionViewModel(userSuggestionService: userSuggestionService)
let view = UserSuggestionList(viewModel: userSuggestionViewModel.context)
.addDependency(AvatarService.instantiate(mediaManager: parameters.mediaManager))
@ -69,7 +69,7 @@ final class UserSuggestionCoordinator: Coordinator {
switch result {
case .selectedItemWithIdentifier(let identifier):
guard let member = self.roomMembers.filter({ $0.userId == identifier }).first else {
guard let member = self.roomMemberProvider.roomMembers.filter({ $0.userId == identifier }).first else {
return
}
@ -93,9 +93,18 @@ final class UserSuggestionCoordinator: Coordinator {
}
@available(iOS 14.0, *)
extension UserSuggestionCoordinator: RoomMembersProviderProtocol {
private class UserSuggestionCoordinatorRoomMemberProvider: RoomMembersProviderProtocol {
private let room: MXRoom
var roomMembers: [MXRoomMember] = []
init(room: MXRoom) {
self.room = room;
}
func fetchMembers(_ members: @escaping ([RoomMembersProviderMember]) -> Void) {
parameters.room.members({ [weak self] roomMembers in
room.members({ [weak self] roomMembers in
guard let self = self, let joinedMembers = roomMembers?.joinedMembers else {
return
}
@ -108,7 +117,7 @@ extension UserSuggestionCoordinator: RoomMembersProviderProtocol {
self.roomMembers = joinedMembers
members(self.roomMembersToProviderMembers(joinedMembers))
}, failure: { error in
MXLog.error("[UserSuggestionCoordinator] Failed loading room with error: \(String(describing: error))")
MXLog.error("[UserSuggestionCoordinatorRoomMemberProvider] Failed loading room with error: \(String(describing: error))")
})
}

View file

@ -30,7 +30,7 @@ enum MockUserSuggestionScreenState: MockScreenState, CaseIterable {
}
var screenView: ([Any], AnyView) {
let service = UserSuggestionService(roomMembersProvider: self)
let service = UserSuggestionService(roomMemberProvider: self)
let listViewModel = UserSuggestionViewModel.makeUserSuggestionViewModel(userSuggestionService: service)
let viewModel = UserSuggestionListWithInputViewModel(listViewModel: listViewModel) { textMessage in

View file

@ -45,7 +45,7 @@ class UserSuggestionService: UserSuggestionServiceProtocol {
// MARK: Private
private let roomMembersProvider: RoomMembersProviderProtocol
private let roomMemberProvider: RoomMembersProviderProtocol
private var suggestionItems: [UserSuggestionItemProtocol] = []
private let currentTextTriggerSubject = CurrentValueSubject<String?, Never>(nil)
@ -61,13 +61,13 @@ class UserSuggestionService: UserSuggestionServiceProtocol {
// MARK: - Setup
init(roomMembersProvider: RoomMembersProviderProtocol) {
self.roomMembersProvider = roomMembersProvider
init(roomMemberProvider: RoomMembersProviderProtocol) {
self.roomMemberProvider = roomMemberProvider
currentTextTriggerSubject
.debounce(for: 0.5, scheduler: RunLoop.main)
.removeDuplicates()
.sink { self.fetchAndFilterMembersForTextTrigger($0) }
.sink { [weak self] in self?.fetchAndFilterMembersForTextTrigger($0) }
.store(in: &cancellables)
}
@ -96,7 +96,7 @@ class UserSuggestionService: UserSuggestionServiceProtocol {
partialName.removeFirst() // remove the '@' prefix
roomMembersProvider.fetchMembers { [weak self] members in
roomMemberProvider.fetchMembers { [weak self] members in
guard let self = self else {
return
}