mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
Merge develop into steve/5020_matrixkit_merge
This commit is contained in:
commit
3d0c77ef30
15 changed files with 155 additions and 117 deletions
2
.github/workflows/triage-move-labelled.yml
vendored
2
.github/workflows/triage-move-labelled.yml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
|||
- uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338
|
||||
with:
|
||||
action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}"
|
||||
project-url: "https://github.com/vector-im/element-android/projects/4"
|
||||
project-url: "https://github.com/vector-im/element-ios/projects/12"
|
||||
column-name: "Need info"
|
||||
label-name: "X-Needs-Info"
|
||||
|
||||
|
|
|
@ -264,6 +264,15 @@ Matrix session observer used to detect new opened sessions.
|
|||
- (void)configurePushKit
|
||||
{
|
||||
MXLogDebug(@"[PushNotificationService] configurePushKit")
|
||||
NSData* token = [_pushRegistry pushTokenForType:PKPushTypeVoIP];
|
||||
if (token) {
|
||||
// If the token is available, store it. This can happen if you sign out and back in.
|
||||
// i.e We are registered, but we have cleared it from the the store on logout and the
|
||||
// _pushRegistry lives through signin/signout as PushNotificationService is a singleton
|
||||
// on app delegate.
|
||||
_pushNotificationStore.pushKitToken = token;
|
||||
MXLogDebug(@"[PushNotificationService] configurePushKit: Restored pushKit token")
|
||||
}
|
||||
|
||||
_pushRegistry.delegate = self;
|
||||
_pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
*/
|
||||
|
||||
#import "RoomPreviewData.h"
|
||||
#import <MatrixSDK-Swift.h>
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@implementation RoomPreviewData
|
||||
|
||||
|
|
|
@ -2497,17 +2497,17 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
|
||||
- (void)checkLocalPrivateKeysInSession:(MXSession*)mxSession
|
||||
{
|
||||
id<MXCryptoStore> cryptoStore = mxSession.crypto.store;
|
||||
MXRecoveryService *recoveryService = mxSession.crypto.recoveryService;
|
||||
NSUInteger keysCount = 0;
|
||||
if ([cryptoStore secretWithSecretId:MXSecretId.keyBackup])
|
||||
if ([recoveryService hasSecretWithSecretId:MXSecretId.keyBackup])
|
||||
{
|
||||
keysCount++;
|
||||
}
|
||||
if ([cryptoStore secretWithSecretId:MXSecretId.crossSigningUserSigning])
|
||||
if ([recoveryService hasSecretWithSecretId:MXSecretId.crossSigningUserSigning])
|
||||
{
|
||||
keysCount++;
|
||||
}
|
||||
if ([cryptoStore secretWithSecretId:MXSecretId.crossSigningSelfSigning])
|
||||
if ([recoveryService hasSecretWithSecretId:MXSecretId.crossSigningSelfSigning])
|
||||
{
|
||||
keysCount++;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
|
||||
#import "MatrixKit.h"
|
||||
|
||||
@interface AuthInputsView : MXKAuthInputsView
|
||||
@class TermsView;
|
||||
|
||||
@interface AuthInputsView : MXKAuthInputsView
|
||||
@property (weak, nonatomic) IBOutlet UITextField *userLoginTextField;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *passWordTextField;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *repeatPasswordTextField;
|
||||
|
|
|
@ -430,15 +430,18 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
|
|||
}
|
||||
|
||||
private func updateDirectFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) {
|
||||
switch mode {
|
||||
case .home:
|
||||
fetcher.fetchOptions.filterOptions.notDataTypes = [.invited, .favorited, .lowPriority]
|
||||
case .people:
|
||||
fetcher.fetchOptions.filterOptions.notDataTypes = [.lowPriority]
|
||||
default:
|
||||
break
|
||||
var notDataTypes: MXRoomSummaryDataTypes = [.hidden, .conferenceUser, .space]
|
||||
switch mode {
|
||||
case .home:
|
||||
notDataTypes.insert([.invited, .favorited, .lowPriority])
|
||||
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
|
||||
case .people:
|
||||
notDataTypes.insert([.lowPriority])
|
||||
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func updateFavoritedFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) {
|
||||
switch mode {
|
||||
|
|
|
@ -40,11 +40,14 @@
|
|||
|
||||
// The options used to load long description html content.
|
||||
NSDictionary *options;
|
||||
NSString *sanitisedGroupLongDescription;
|
||||
NSString *groupLongDescription;
|
||||
|
||||
// The current pushed view controller
|
||||
UIViewController *pushedViewController;
|
||||
}
|
||||
|
||||
@property (nonatomic, readonly) DTHTMLAttributedStringBuilderWillFlushCallback longDescriptionSanitizationCallback;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GroupHomeViewController
|
||||
|
@ -75,6 +78,23 @@
|
|||
|
||||
// Keep visible the status bar by default.
|
||||
isStatusBarHidden = NO;
|
||||
|
||||
// Set up sanitization for the long description
|
||||
NSArray<NSString *> *allowedHTMLTags = @[
|
||||
@"font", // custom to matrix for IRC-style font coloring
|
||||
@"del", // for markdown
|
||||
@"body", // added internally by DTCoreText
|
||||
@"h1", @"h2", @"h3", @"h4", @"h5", @"h6", @"blockquote", @"p", @"a", @"ul", @"ol",
|
||||
@"nl", @"li", @"b", @"i", @"u", @"strong", @"em", @"strike", @"code", @"hr", @"br", @"div",
|
||||
@"table", @"thead", @"caption", @"tbody", @"tr", @"th", @"td", @"pre",
|
||||
@"img"
|
||||
];
|
||||
|
||||
MXWeakify(self);
|
||||
_longDescriptionSanitizationCallback = ^(DTHTMLElement *element) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[element sanitizeWith:allowedHTMLTags bodyFont:self->_groupLongDescription.font imageHandler:[self groupLongDescriptionImageHandler]];
|
||||
};
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
|
@ -154,7 +174,7 @@
|
|||
font-size: small; \
|
||||
}", (unsigned long)bgColor];
|
||||
|
||||
// Apply the css style
|
||||
// Apply the css style with some sanitisation.
|
||||
options = @{
|
||||
DTUseiOS6Attributes: @(YES), // Enable it to be able to display the attributed string in a UITextView
|
||||
DTDefaultFontFamily: _groupLongDescription.font.familyName,
|
||||
|
@ -162,7 +182,8 @@
|
|||
DTDefaultFontSize: @(_groupLongDescription.font.pointSize),
|
||||
DTDefaultTextColor: _groupLongDescription.textColor,
|
||||
DTDefaultLinkDecoration: @(NO),
|
||||
DTDefaultStyleSheet: [[DTCSSStylesheet alloc] initWithStyleBlock:defaultCSS]
|
||||
DTDefaultStyleSheet: [[DTCSSStylesheet alloc] initWithStyleBlock:defaultCSS],
|
||||
DTWillFlushBlockCallBack: self.longDescriptionSanitizationCallback
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -489,94 +510,11 @@
|
|||
{
|
||||
if (_group.summary.profile.longDescription.length)
|
||||
{
|
||||
// Render this html content in a text view.
|
||||
NSArray <NSString*>* allowedHTMLTags = @[
|
||||
@"font", // custom to matrix for IRC-style font coloring
|
||||
@"del", // for markdown
|
||||
@"h1", @"h2", @"h3", @"h4", @"h5", @"h6", @"blockquote", @"p", @"a", @"ul", @"ol",
|
||||
@"nl", @"li", @"b", @"i", @"u", @"strong", @"em", @"strike", @"code", @"hr", @"br", @"div",
|
||||
@"table", @"thead", @"caption", @"tbody", @"tr", @"th", @"td", @"pre",
|
||||
@"img"
|
||||
];
|
||||
|
||||
// Do some sanitisation by handling the potential image
|
||||
MXWeakify(self);
|
||||
sanitisedGroupLongDescription = [MXKTools sanitiseHTML:_group.summary.profile.longDescription withAllowedHTMLTags:allowedHTMLTags imageHandler:^NSString *(NSString *sourceURL, CGFloat width, CGFloat height) {
|
||||
|
||||
MXStrongifyAndReturnValueIfNil(self, nil);
|
||||
NSString *localSourcePath;
|
||||
|
||||
if (width != -1 && height != -1)
|
||||
{
|
||||
CGSize size = CGSizeMake(width, height);
|
||||
// Build the cache path for the a thumbnail of this image.
|
||||
NSString *cacheFilePath = [MXMediaManager thumbnailCachePathForMatrixContentURI:sourceURL
|
||||
andType:nil
|
||||
inFolder:kMXMediaManagerDefaultCacheFolder
|
||||
toFitViewSize:size
|
||||
withMethod:MXThumbnailingMethodScale];
|
||||
// Check whether the provided URL is a valid Matrix Content URI.
|
||||
if (cacheFilePath)
|
||||
{
|
||||
// Download the thumbnail if it is not already stored in the cache.
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:cacheFilePath])
|
||||
{
|
||||
MXWeakify(self);
|
||||
[self.mxSession.mediaManager downloadThumbnailFromMatrixContentURI:sourceURL
|
||||
withType:nil
|
||||
inFolder:kMXMediaManagerDefaultCacheFolder
|
||||
toFitViewSize:size
|
||||
withMethod:MXThumbnailingMethodScale
|
||||
success:^(NSString *outputFilePath) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self refreshGroupLongDescription];
|
||||
}
|
||||
failure:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the local path
|
||||
localSourcePath = [NSString stringWithFormat:@"file://%@", cacheFilePath];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Build the cache path for this image.
|
||||
NSString* cacheFilePath = [MXMediaManager cachePathForMatrixContentURI:sourceURL
|
||||
andType:nil
|
||||
inFolder:kMXMediaManagerDefaultCacheFolder];
|
||||
|
||||
// Check whether the provided URL is a valid Matrix Content URI.
|
||||
if (cacheFilePath)
|
||||
{
|
||||
// Download the image if it is not already stored in the cache.
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:cacheFilePath])
|
||||
{
|
||||
MXWeakify(self);
|
||||
[self.mxSession.mediaManager downloadMediaFromMatrixContentURI:sourceURL
|
||||
withType:nil
|
||||
inFolder:kMXMediaManagerDefaultCacheFolder
|
||||
success:^(NSString *outputFilePath) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self refreshGroupLongDescription];
|
||||
}
|
||||
failure:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the local path
|
||||
localSourcePath = [NSString stringWithFormat:@"file://%@", cacheFilePath];
|
||||
}
|
||||
}
|
||||
}
|
||||
return localSourcePath;
|
||||
|
||||
}];
|
||||
groupLongDescription = _group.summary.profile.longDescription;
|
||||
}
|
||||
else
|
||||
{
|
||||
sanitisedGroupLongDescription = nil;
|
||||
groupLongDescription = nil;
|
||||
}
|
||||
|
||||
[self renderGroupLongDescription];
|
||||
|
@ -584,12 +522,13 @@
|
|||
|
||||
- (void)renderGroupLongDescription
|
||||
{
|
||||
if (sanitisedGroupLongDescription)
|
||||
if (groupLongDescription)
|
||||
{
|
||||
// Using DTCoreText, which renders static string, helps to avoid code injection attacks
|
||||
// that could happen with the default HTML renderer of NSAttributedString which is a
|
||||
// webview.
|
||||
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTMLData:[sanitisedGroupLongDescription dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:NULL];
|
||||
// The supplied options include a callback to sanitize html tags and load image data.
|
||||
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTMLData:[groupLongDescription dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:NULL];
|
||||
|
||||
// Apply additional treatments
|
||||
NSInteger mxIdsBitMask = (MXKTOOLS_USER_IDENTIFIER_BITWISE | MXKTOOLS_ROOM_IDENTIFIER_BITWISE | MXKTOOLS_ROOM_ALIAS_BITWISE | MXKTOOLS_EVENT_IDENTIFIER_BITWISE | MXKTOOLS_GROUP_IDENTIFIER_BITWISE);
|
||||
|
@ -605,6 +544,83 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (NSURL *(^)(NSString *sourceURL, CGFloat width, CGFloat height))groupLongDescriptionImageHandler
|
||||
{
|
||||
MXWeakify(self);
|
||||
return ^NSURL *(NSString *sourceURL, CGFloat width, CGFloat height) {
|
||||
|
||||
MXStrongifyAndReturnValueIfNil(self, nil);
|
||||
NSURL *localSourceURL;
|
||||
|
||||
if (width != -1 && height != -1)
|
||||
{
|
||||
CGSize size = CGSizeMake(width, height);
|
||||
// Build the cache path for the a thumbnail of this image.
|
||||
NSString *cacheFilePath = [MXMediaManager thumbnailCachePathForMatrixContentURI:sourceURL
|
||||
andType:nil
|
||||
inFolder:kMXMediaManagerDefaultCacheFolder
|
||||
toFitViewSize:size
|
||||
withMethod:MXThumbnailingMethodScale];
|
||||
// Check whether the provided URL is a valid Matrix Content URI.
|
||||
if (cacheFilePath)
|
||||
{
|
||||
// Download the thumbnail if it is not already stored in the cache.
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:cacheFilePath])
|
||||
{
|
||||
MXWeakify(self);
|
||||
[self.mxSession.mediaManager downloadThumbnailFromMatrixContentURI:sourceURL
|
||||
withType:nil
|
||||
inFolder:kMXMediaManagerDefaultCacheFolder
|
||||
toFitViewSize:size
|
||||
withMethod:MXThumbnailingMethodScale
|
||||
success:^(NSString *outputFilePath) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self refreshGroupLongDescription];
|
||||
}
|
||||
failure:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the local url
|
||||
localSourceURL = [NSURL fileURLWithPath:cacheFilePath];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Build the cache path for this image.
|
||||
NSString* cacheFilePath = [MXMediaManager cachePathForMatrixContentURI:sourceURL
|
||||
andType:nil
|
||||
inFolder:kMXMediaManagerDefaultCacheFolder];
|
||||
|
||||
// Check whether the provided URL is a valid Matrix Content URI.
|
||||
if (cacheFilePath)
|
||||
{
|
||||
// Download the image if it is not already stored in the cache.
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:cacheFilePath])
|
||||
{
|
||||
MXWeakify(self);
|
||||
[self.mxSession.mediaManager downloadMediaFromMatrixContentURI:sourceURL
|
||||
withType:nil
|
||||
inFolder:kMXMediaManagerDefaultCacheFolder
|
||||
success:^(NSString *outputFilePath) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self refreshGroupLongDescription];
|
||||
}
|
||||
failure:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the local path
|
||||
localSourceURL = [NSURL fileURLWithPath:cacheFilePath];
|
||||
}
|
||||
}
|
||||
}
|
||||
return localSourceURL;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
- (void)didSelectRoomId:(NSString*)roomId
|
||||
{
|
||||
// Check first if the user already joined this room.
|
||||
|
|
|
@ -167,9 +167,8 @@ TableViewSectionsDelegate>
|
|||
|
||||
if (self.mainSession.crypto.backup)
|
||||
{
|
||||
MXDeviceInfo *deviceInfo = [self.mainSession.crypto.deviceList storedDevice:self.mainSession.matrixRestClient.credentials.userId
|
||||
deviceId:self.mainSession.matrixRestClient.credentials.deviceId];
|
||||
|
||||
MXDeviceInfo *deviceInfo = [self.mainSession.crypto deviceWithDeviceId:self.mainSession.myDeviceId ofUser:self.mainSession.myUserId];
|
||||
|
||||
if (deviceInfo)
|
||||
{
|
||||
secureBackupSection = [[SettingsSecureBackupTableViewSection alloc] initWithRecoveryService:self.mainSession.crypto.recoveryService keyBackup:self.mainSession.crypto.backup userDevice:deviceInfo];
|
||||
|
|
|
@ -1021,7 +1021,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
NSArray<MXDeviceInfo*> *devices = [session.crypto.store devicesForUser:session.myUserId].allValues;
|
||||
NSArray<MXDeviceInfo*> *devices = [session.crypto devicesForUser:session.myUserId].allValues;
|
||||
|
||||
BOOL isUserHasOneUnverifiedDevice = NO;
|
||||
|
||||
|
|
|
@ -342,6 +342,9 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
|||
white-space: pre; \
|
||||
-coretext-fontname: Menlo-Regular; \
|
||||
font-size: small; \
|
||||
} \
|
||||
h1,h2 { \
|
||||
font-size: 1.2em; \
|
||||
}", (unsigned long)bgColor];
|
||||
|
||||
self.defaultTextColor = ThemeService.shared.theme.textPrimaryColor;
|
||||
|
|
|
@ -65,7 +65,7 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
}()
|
||||
private var pushNotificationStore: PushNotificationStore = PushNotificationStore()
|
||||
private let localAuthenticationService = LocalAuthenticationService(pinCodePreferences: .shared)
|
||||
|
||||
private static let backgroundServiceInitQueue = DispatchQueue(label: "io.element.NotificationService.backgroundServiceInitQueue")
|
||||
// MARK: - Method Overrides
|
||||
|
||||
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
||||
|
@ -168,14 +168,16 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
MXKAccountManager.shared()?.forceReloadAccounts()
|
||||
self.userAccount = MXKAccountManager.shared()?.activeAccounts.first
|
||||
if let userAccount = userAccount {
|
||||
if NotificationService.backgroundSyncService?.credentials != userAccount.mxCredentials {
|
||||
MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: BEFORE")
|
||||
self.logMemory()
|
||||
NotificationService.backgroundSyncService = MXBackgroundSyncService(withCredentials: userAccount.mxCredentials)
|
||||
MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: AFTER")
|
||||
self.logMemory()
|
||||
Self.backgroundServiceInitQueue.sync {
|
||||
if NotificationService.backgroundSyncService?.credentials != userAccount.mxCredentials {
|
||||
MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: BEFORE")
|
||||
self.logMemory()
|
||||
NotificationService.backgroundSyncService = MXBackgroundSyncService(withCredentials: userAccount.mxCredentials)
|
||||
MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: AFTER")
|
||||
self.logMemory()
|
||||
}
|
||||
completion()
|
||||
}
|
||||
completion()
|
||||
} else {
|
||||
MXLog.debug("[NotificationService] setup: No active accounts")
|
||||
fallbackToBestAttemptContent(forEventId: eventId)
|
||||
|
|
1
changelog.d/5165.change
Normal file
1
changelog.d/5165.change
Normal file
|
@ -0,0 +1 @@
|
|||
Use DTCoreText's callback option to sanitise formatted messages
|
1
changelog.d/5185.bugfix
Normal file
1
changelog.d/5185.bugfix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix rooms that should be hidden(such as virtual rooms) from showing.
|
1
changelog.d/5194.bugfix
Normal file
1
changelog.d/5194.bugfix
Normal file
|
@ -0,0 +1 @@
|
|||
Improve generated Swift header imports.
|
1
changelog.d/5199.bugfix
Normal file
1
changelog.d/5199.bugfix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix bug where VoIP calls would not connect reliably after signout/signin.
|
Loading…
Reference in a new issue