mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-05-02 06:06:57 +02:00
Merge branch 'master' of https://github.com/vector-im/element-ios into feature/3269_merge_element_1_8_18
# Conflicts: # Config/AppIdentifiers.xcconfig # Config/AppVersion.xcconfig # Podfile # Podfile.lock # Riot/Assets/de.lproj/Vector.strings # Riot/Generated/Images.swift # Riot/Modules/Analytics/DecryptionFailureTracker.m # Riot/Modules/Application/LegacyAppDelegate.h # Riot/Modules/Onboarding/OnboardingCoordinator.swift # Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift # Riot/Modules/Room/RoomViewController.m # Riot/SupportingFiles/Info.plist # Riot/Utils/EventFormatter.m # Riot/Utils/Tools.h # Riot/Utils/Tools.m # Riot/target.yml # RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift # fastlane/Fastfile # project.yml
This commit is contained in:
@@ -18,6 +18,7 @@ import Foundation
|
||||
import MatrixSDK.MXLog
|
||||
|
||||
public extension NSString {
|
||||
|
||||
/// Gets the first URL contained in the string ignoring any links to hosts defined in
|
||||
/// the `firstURLDetectionIgnoredHosts` property of `MXKAppSettings`.
|
||||
/// - Returns: A URL if detected, otherwise nil.
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
@import UIKit;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UITextView(MatrixKit)
|
||||
|
||||
/**
|
||||
Determine if there is a link near a location point in UITextView bounds.
|
||||
|
||||
@param point The point inside the UITextView bounds
|
||||
@return YES to indicate that a link has been detected near the location point.
|
||||
*/
|
||||
- (BOOL)isThereALinkNearPoint:(CGPoint)point;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "UITextView+MatrixKit.h"
|
||||
|
||||
@implementation UITextView(MatrixKit)
|
||||
|
||||
- (BOOL)isThereALinkNearPoint:(CGPoint)point
|
||||
{
|
||||
if (!CGRectContainsPoint(self.bounds, point))
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
UITextPosition *textPosition = [self closestPositionToPoint:point];
|
||||
|
||||
if (!textPosition)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
UITextRange *textRange = [self.tokenizer rangeEnclosingPosition:textPosition
|
||||
withGranularity:UITextGranularityCharacter
|
||||
inDirection:UITextLayoutDirectionLeft];
|
||||
|
||||
if (!textRange)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSInteger startIndex = [self offsetFromPosition:self.beginningOfDocument toPosition:textRange.start];
|
||||
|
||||
if (startIndex < 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self.attributedText attribute:NSLinkAttributeName atIndex:startIndex effectiveRange:NULL] != nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UITextView {
|
||||
private enum Constants {
|
||||
/// Distance threshold at which linkified text attachment can still be considered as "near" location.
|
||||
static let attachmentLinkHorizontalDistanceThreshold: CGFloat = 16.0
|
||||
}
|
||||
|
||||
/// Determine if there is a link near a location point in UITextView bounds.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - point: The point inside the UITextView bounds
|
||||
/// - Returns: true to indicate that a link has been detected near the location point.
|
||||
@objc func isThereALinkNearLocation(_ point: CGPoint) -> Bool {
|
||||
return urlForLinkAtLocation(point) != nil
|
||||
}
|
||||
|
||||
/// Detect link near a location point in UITextView bounds.
|
||||
///
|
||||
/// - Parameter point: The point inside the UITextView bounds
|
||||
/// - Returns: link detected at given location
|
||||
@objc func urlForLinkAtLocation(_ point: CGPoint) -> URL? {
|
||||
guard bounds.contains(point),
|
||||
let textPosition = closestPosition(to: point)
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
// The value of `NSLinkAttributeName` attribute could be an URL or a String object.
|
||||
func attributeToLink(_ attribute: Any) -> URL? {
|
||||
if let link = attribute as? URL {
|
||||
return link
|
||||
} else if let stringURL = attribute as? String {
|
||||
return URL(string: stringURL)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Depending on cursor position on a character containing both an attachment
|
||||
// and a link (e.g. a mention pill), a positive result can be retrieved either
|
||||
// from textStylingAtPosition or tokenizer's rangeEnclosingPosition.
|
||||
if let attributes = textStyling(at: textPosition, in: .forward),
|
||||
let linkAttribute = attributes[.link] {
|
||||
// Using textStyling shouldn't provide false positives.
|
||||
return attributeToLink(linkAttribute)
|
||||
} else if let textRange = tokenizer.rangeEnclosingPosition(textPosition,
|
||||
with: .character,
|
||||
inDirection: .layout(.left)) {
|
||||
let startIndex = offset(from: beginningOfDocument, to: textRange.start)
|
||||
if let linkAttribute = attributedText.attribute(.link, at: startIndex, effectiveRange: nil) {
|
||||
// Fix false positives from tokenizer's rangeEnclosingPosition.
|
||||
// These occur if given point is located on the same line as a
|
||||
// trailing linkified text attachment. Detected link is
|
||||
// rejected if actual distance from attachment trailing to point
|
||||
// is greater than linkHorizontalDistanceThreshold.
|
||||
let glyphIndex = layoutManager.glyphIndexForCharacter(at: startIndex)
|
||||
let attachmentWidth = layoutManager.attachmentSize(forGlyphAt: glyphIndex).width
|
||||
// Width is -1 when there is no attachment.
|
||||
if attachmentWidth > 0 {
|
||||
let glyphStartX = layoutManager.location(forGlyphAt: glyphIndex).x
|
||||
let start = glyphStartX - Constants.attachmentLinkHorizontalDistanceThreshold
|
||||
let end = glyphStartX + attachmentWidth + Constants.attachmentLinkHorizontalDistanceThreshold
|
||||
let range = (start...end)
|
||||
|
||||
return range.contains(point.x) ? attributeToLink(linkAttribute) : nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,7 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer
|
||||
|
||||
@param credentials user's credentials
|
||||
*/
|
||||
- (instancetype)initWithCredentials:(MXCredentials*)credentials;
|
||||
- (nonnull instancetype)initWithCredentials:(MXCredentials*)credentials;
|
||||
|
||||
/**
|
||||
Create a matrix session based on the provided store.
|
||||
|
||||
@@ -135,7 +135,7 @@ static NSArray<NSNumber*> *initialSyncSilentErrorsHTTPStatusCodes;
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)initWithCredentials:(MXCredentials*)credentials
|
||||
- (nonnull instancetype)initWithCredentials:(MXCredentials*)credentials
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
|
||||
@@ -147,7 +147,9 @@ static NSString *const kMXAppGroupID = @"group.org.matrix";
|
||||
kMXEventTypeStringKeyVerificationCancel,
|
||||
kMXEventTypeStringKeyVerificationDone,
|
||||
kMXEventTypeStringPollStart,
|
||||
kMXEventTypeStringPollStartMSC3381
|
||||
kMXEventTypeStringPollStartMSC3381,
|
||||
kMXEventTypeStringBeaconInfo,
|
||||
kMXEventTypeStringBeaconInfoMSC3672
|
||||
].mutableCopy;
|
||||
|
||||
|
||||
@@ -179,7 +181,9 @@ static NSString *const kMXAppGroupID = @"group.org.matrix";
|
||||
kMXEventTypeStringKeyVerificationCancel,
|
||||
kMXEventTypeStringKeyVerificationDone,
|
||||
kMXEventTypeStringPollStart,
|
||||
kMXEventTypeStringPollStartMSC3381
|
||||
kMXEventTypeStringPollStartMSC3381,
|
||||
kMXEventTypeStringBeaconInfo,
|
||||
kMXEventTypeStringBeaconInfoMSC3672
|
||||
].mutableCopy;
|
||||
|
||||
lastMessageEventTypesAllowList = @[
|
||||
|
||||
@@ -538,7 +538,7 @@
|
||||
// Select the right text view for measurement
|
||||
UITextView *selectedTextView = (removeVerticalInset ? measurementTextViewWithoutInset : measurementTextView);
|
||||
|
||||
selectedTextView.frame = CGRectMake(0, 0, _maxTextViewWidth, MAXFLOAT);
|
||||
selectedTextView.frame = CGRectMake(0, 0, _maxTextViewWidth, 0);
|
||||
selectedTextView.attributedText = attributedText;
|
||||
|
||||
CGSize size = [selectedTextView sizeThatFits:selectedTextView.frame.size];
|
||||
|
||||
@@ -170,6 +170,11 @@ extern NSString *const kMXKRoomDataSourceTimelineErrorErrorKey;
|
||||
*/
|
||||
@property (nonatomic) NSString *partialTextMessage;
|
||||
|
||||
/**
|
||||
The current attributed text message partially typed in text input (use nil to reset it).
|
||||
*/
|
||||
@property (nonatomic) NSAttributedString *partialAttributedTextMessage;
|
||||
|
||||
/**
|
||||
The current thread id for the data source. If provided, data source displays the specified thread, otherwise the whole room messages.
|
||||
*/
|
||||
@@ -471,6 +476,14 @@ extern NSString *const kMXKRoomDataSourceTimelineErrorErrorKey;
|
||||
success:(void (^)(NSString *))success
|
||||
failure:(void (^)(NSError *))failure;
|
||||
|
||||
/**
|
||||
Updates an event with replacement event.
|
||||
@note the original event is defined in the `MXEventContentRelatesTo` object.
|
||||
|
||||
@param replaceEvent the new event to display
|
||||
*/
|
||||
- (void)updateEventWithReplaceEvent:(MXEvent*)replaceEvent;
|
||||
|
||||
/**
|
||||
Indicates if replying to the provided event is supported.
|
||||
Only event of type 'MXEventTypeRoomMessage' are supported for the moment, and for certain msgtype.
|
||||
@@ -735,6 +748,25 @@ extern NSString *const kMXKRoomDataSourceTimelineErrorErrorKey;
|
||||
roomState:(MXRoomState*)roomState
|
||||
direction:(MXTimelineDirection)direction;
|
||||
|
||||
/**
|
||||
Queue an event in order to process its display later.
|
||||
|
||||
@param event the event to process.
|
||||
@param roomState the state of the room when the event fired.
|
||||
@param direction the order of the events in the arrays
|
||||
*/
|
||||
- (void)queueEventForProcessing:(MXEvent*)event
|
||||
withRoomState:(MXRoomState*)roomState
|
||||
direction:(MXTimelineDirection)direction;
|
||||
|
||||
/**
|
||||
Start processing pending events.
|
||||
|
||||
@param onComplete a block called (on the main thread) when the processing has been done. Can be nil.
|
||||
Note this block returns the number of added cells in first and last positions.
|
||||
*/
|
||||
- (void)processQueuedEvents:(void (^)(NSUInteger addedHistoryCellNb, NSUInteger addedLiveCellNb))onComplete;
|
||||
|
||||
#pragma mark - Bubble collapsing
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#import "MXKAppSettings.h"
|
||||
|
||||
#import "MXKSendReplyEventStringLocalizer.h"
|
||||
#import "MXKSlashCommands.h"
|
||||
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
@@ -991,6 +990,16 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
_room.partialTextMessage = partialTextMessage;
|
||||
}
|
||||
|
||||
- (NSAttributedString *)partialAttributedTextMessage
|
||||
{
|
||||
return _room.partialAttributedTextMessage;
|
||||
}
|
||||
|
||||
- (void)setPartialAttributedTextMessage:(NSAttributedString *)partialAttributedTextMessage
|
||||
{
|
||||
_room.partialAttributedTextMessage = partialAttributedTextMessage;
|
||||
}
|
||||
|
||||
- (void)refreshEventListeners:(NSArray *)liveEventTypesFilterForMessages
|
||||
{
|
||||
// Remove the existing listeners
|
||||
@@ -2982,13 +2991,6 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
return processingQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
Queue an event in order to process its display later.
|
||||
|
||||
@param event the event to process.
|
||||
@param roomState the state of the room when the event fired.
|
||||
@param direction the order of the events in the arrays
|
||||
*/
|
||||
- (void)queueEventForProcessing:(MXEvent*)event withRoomState:(MXRoomState*)roomState direction:(MXTimelineDirection)direction
|
||||
{
|
||||
if (event.isLocalEvent)
|
||||
@@ -3166,12 +3168,6 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
return isHighlighted;
|
||||
}
|
||||
|
||||
/**
|
||||
Start processing pending events.
|
||||
|
||||
@param onComplete a block called (on the main thread) when the processing has been done. Can be nil.
|
||||
Note this block returns the number of added cells in first and last positions.
|
||||
*/
|
||||
- (void)processQueuedEvents:(void (^)(NSUInteger addedHistoryCellNb, NSUInteger addedLiveCellNb))onComplete
|
||||
{
|
||||
MXWeakify(self);
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <MatrixSDK/MXSendReplyEventStringLocalizerProtocol.h>
|
||||
|
||||
/**
|
||||
A `MXKSendReplyEventStringLocalizer` instance represents string localizations used when send reply event to a message in a room.
|
||||
*/
|
||||
@interface MXKSendReplyEventStringLocalizer : NSObject<MXSendReplyEventStringLocalizerProtocol>
|
||||
|
||||
@end
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#import "MXKSendReplyEventStringLocalizer.h"
|
||||
#import "MXKSwiftHeader.h"
|
||||
|
||||
@implementation MXKSendReplyEventStringLocalizer
|
||||
|
||||
- (NSString *)senderSentAnImage
|
||||
{
|
||||
return [VectorL10n messageReplyToSenderSentAnImage];
|
||||
}
|
||||
|
||||
- (NSString *)senderSentAVideo
|
||||
{
|
||||
return [VectorL10n messageReplyToSenderSentAVideo];
|
||||
}
|
||||
|
||||
- (NSString *)senderSentAnAudioFile
|
||||
{
|
||||
return [VectorL10n messageReplyToSenderSentAnAudioFile];
|
||||
}
|
||||
|
||||
- (NSString *)senderSentAVoiceMessage
|
||||
{
|
||||
return [VectorL10n messageReplyToSenderSentAVoiceMessage];
|
||||
}
|
||||
|
||||
- (NSString *)senderSentAFile
|
||||
{
|
||||
return [VectorL10n messageReplyToSenderSentAFile];
|
||||
}
|
||||
|
||||
- (NSString *)senderSentTheirLocation
|
||||
{
|
||||
return [VectorL10n messageReplyToSenderSentTheirLocation];
|
||||
}
|
||||
|
||||
- (NSString *)messageToReplyToPrefix
|
||||
{
|
||||
return [VectorL10n messageReplyToMessageToReplyToPrefix];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class MXKSendReplyEventStringLocalizer: NSObject, MXSendReplyEventStringLocalizerProtocol {
|
||||
func senderSentAnImage() -> String {
|
||||
return VectorL10n.messageReplyToSenderSentAnImage
|
||||
}
|
||||
|
||||
func senderSentAVideo() -> String {
|
||||
return VectorL10n.messageReplyToSenderSentAVideo
|
||||
}
|
||||
|
||||
func senderSentAnAudioFile() -> String {
|
||||
return VectorL10n.messageReplyToSenderSentAnAudioFile
|
||||
}
|
||||
|
||||
func senderSentAVoiceMessage() -> String {
|
||||
return VectorL10n.messageReplyToSenderSentAVoiceMessage
|
||||
}
|
||||
|
||||
func senderSentAFile() -> String {
|
||||
return VectorL10n.messageReplyToSenderSentAFile
|
||||
}
|
||||
|
||||
func senderSentTheirLocation() -> String {
|
||||
return VectorL10n.messageReplyToSenderSentTheirLocation
|
||||
}
|
||||
|
||||
func messageToReplyToPrefix() -> String {
|
||||
return VectorL10n.messageReplyToMessageToReplyToPrefix
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,11 @@
|
||||
return roomSummary.avatar;
|
||||
}
|
||||
|
||||
- (NSString *)directUserId
|
||||
{
|
||||
return self.roomSummary.directUserId;
|
||||
}
|
||||
|
||||
- (MXPresence)presence
|
||||
{
|
||||
if (self.roomSummary.isDirect)
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
@property (nonatomic, readonly) NSString *roomIdentifier;
|
||||
@property (nonatomic, readonly) NSString *roomDisplayname;
|
||||
@property (nonatomic, readonly) NSString *avatarUrl;
|
||||
@property (nonatomic, readonly) NSString *directUserId;
|
||||
@property (nonatomic, readonly) MXPresence presence;
|
||||
@property (nonatomic, readonly) NSString *lastEventTextMessage;
|
||||
@property (nonatomic, readonly) NSString *lastEventDate;
|
||||
|
||||
@@ -228,6 +228,18 @@ typedef enum : NSUInteger {
|
||||
*/
|
||||
- (NSAttributedString*)renderHTMLString:(NSString*)htmlString forEvent:(MXEvent*)event withRoomState:(MXRoomState*)roomState;
|
||||
|
||||
/**
|
||||
Render a random html string into an attributed string with the font and the text color
|
||||
that correspond to the passed event.
|
||||
|
||||
@param htmlString the HTLM string to render.
|
||||
@param event the event associated to the string.
|
||||
@param roomState the room state right before the event.
|
||||
@param isEditMode wether string will be used for edition in the composer
|
||||
@return an attributed string.
|
||||
*/
|
||||
- (NSAttributedString*)renderHTMLString:(NSString*)htmlString forEvent:(MXEvent*)event withRoomState:(MXRoomState*)roomState isEditMode:(BOOL)isEditMode;
|
||||
|
||||
/**
|
||||
Same as [self renderString:forEvent:] but add a prefix.
|
||||
The prefix will be rendered with 'prefixTextFont' and 'prefixTextColor'.
|
||||
|
||||
@@ -1751,11 +1751,17 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=\"(.*?)\">([^<]*)</a>";
|
||||
}
|
||||
|
||||
- (NSAttributedString*)renderHTMLString:(NSString*)htmlString forEvent:(MXEvent*)event withRoomState:(MXRoomState*)roomState
|
||||
{
|
||||
return [self renderHTMLString:htmlString forEvent:event withRoomState:roomState isEditMode:NO];
|
||||
}
|
||||
|
||||
- (NSAttributedString*)renderHTMLString:(NSString*)htmlString forEvent:(MXEvent*)event withRoomState:(MXRoomState*)roomState isEditMode:(BOOL)isEditMode
|
||||
{
|
||||
NSString *html = htmlString;
|
||||
|
||||
// Special treatment for "In reply to" message
|
||||
if (event.isReplyEvent || (!RiotSettings.shared.enableThreads && event.isInThread))
|
||||
// Note: `isEditMode` fixes an issue where editing a reply would display an "In reply to" span instead of a mention.
|
||||
if (!isEditMode && (event.isReplyEvent || (!RiotSettings.shared.enableThreads && event.isInThread)))
|
||||
{
|
||||
html = [self renderReplyTo:html withRoomState:roomState];
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
*/
|
||||
|
||||
#import "MXKAuthenticationRecaptchaWebView.h"
|
||||
#import "ThemeService.h"
|
||||
|
||||
NSString *kMXKRecaptchaHTMLString = @"<html> \
|
||||
<head> \
|
||||
<meta name='viewport' content='initial-scale=1.0' /> \
|
||||
<style>@media (prefers-color-scheme: dark) { body { background-color: #15191E; } }</style> \
|
||||
<script type=\"text/javascript\"> \
|
||||
var verifyCallback = function(response) { \
|
||||
/* Generic method to make a bridge between JS and the WKWebView*/ \
|
||||
@@ -33,7 +35,8 @@ var verifyCallback = function(response) { \
|
||||
var onloadCallback = function() { \
|
||||
grecaptcha.render('recaptcha_widget', { \
|
||||
'sitekey' : '%@', \
|
||||
'callback': verifyCallback \
|
||||
'callback': verifyCallback, \
|
||||
'theme': '%@' \
|
||||
}); \
|
||||
}; \
|
||||
</script> \
|
||||
@@ -78,7 +81,9 @@ var onloadCallback = function() { \
|
||||
[self addSubview:activityIndicator];
|
||||
[activityIndicator startAnimating];
|
||||
|
||||
NSString *htmlString = [NSString stringWithFormat:kMXKRecaptchaHTMLString, siteKey];
|
||||
NSString *theme = ThemeService.shared.isCurrentThemeDark ? @"dark" : @"light";
|
||||
|
||||
NSString *htmlString = [NSString stringWithFormat:kMXKRecaptchaHTMLString, siteKey, theme];
|
||||
|
||||
[self loadHTMLString:htmlString baseURL:[NSURL URLWithString:homeServer]];
|
||||
}
|
||||
|
||||
@@ -26,6 +26,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// The last hit test location received by the view.
|
||||
@property (nonatomic, readonly) CGPoint lastHitTestLocation;
|
||||
|
||||
|
||||
/// Register a view that has been added as a pill to this text view.
|
||||
/// This is needed in order to flush pills that are not always removed properly by the system.
|
||||
/// All registered views will be manually removed from hierarchy on attributedText or text updates.
|
||||
///
|
||||
/// @param pillView pill view to register
|
||||
- (void)registerPillView:(UIView *)pillView API_AVAILABLE(ios(15));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
|
||||
#import "MXKMessageTextView.h"
|
||||
#import "UITextView+MatrixKit.h"
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
@interface MXKMessageTextView()
|
||||
|
||||
@property (nonatomic, readwrite) CGPoint lastHitTestLocation;
|
||||
@property (nonatomic) NSHashTable *pillViews;
|
||||
|
||||
@end
|
||||
|
||||
@@ -51,7 +52,41 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self isThereALinkNearPoint:point];
|
||||
return [self isThereALinkNearLocation:point];
|
||||
}
|
||||
|
||||
#pragma mark - Pills Flushing
|
||||
|
||||
- (void)setText:(NSString *)text
|
||||
{
|
||||
if (@available(iOS 15.0, *)) {
|
||||
[self flushPills];
|
||||
}
|
||||
[super setText:text];
|
||||
}
|
||||
|
||||
- (void)setAttributedText:(NSAttributedString *)attributedText
|
||||
{
|
||||
if (@available(iOS 15.0, *)) {
|
||||
[self flushPills];
|
||||
}
|
||||
[super setAttributedText:attributedText];
|
||||
}
|
||||
|
||||
- (void)registerPillView:(UIView *)pillView
|
||||
{
|
||||
[self.pillViews addObject:pillView];
|
||||
}
|
||||
|
||||
/// Flushes all previously registered Pills from their hierarchy.
|
||||
- (void)flushPills API_AVAILABLE(ios(15))
|
||||
{
|
||||
for (UIView* view in self.pillViews)
|
||||
{
|
||||
view.alpha = 0.0;
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
self.pillViews = [NSHashTable weakObjectsHashTable];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -269,6 +269,11 @@ typedef enum : NSUInteger
|
||||
*/
|
||||
- (IBAction)onTouchUpInside:(UIButton*)button;
|
||||
|
||||
/**
|
||||
Send message currently displayed inside toolbar's ` UITextView`.
|
||||
*/
|
||||
- (void)sendCurrentMessage;
|
||||
|
||||
/**
|
||||
Handle image attachment
|
||||
Save the image in user's photos library when 'isPhotoLibraryAsset' flag is NO and auto saving is enabled.
|
||||
@@ -355,4 +360,9 @@ typedef enum : NSUInteger
|
||||
*/
|
||||
- (void)pasteText:(NSString*)text;
|
||||
|
||||
/**
|
||||
The current attributed text message in message composer.
|
||||
*/
|
||||
@property (nonatomic) NSAttributedString *attributedTextMessage;
|
||||
|
||||
@end
|
||||
|
||||
@@ -277,22 +277,27 @@
|
||||
}
|
||||
else if (button == self.rightInputToolbarButton && self.textMessage.length)
|
||||
{
|
||||
// This forces an autocorrect event to happen when "Send" is pressed, which is necessary to accept a pending correction on send
|
||||
self.textMessage = [NSString stringWithFormat:@"%@ ", self.textMessage];
|
||||
self.textMessage = [self.textMessage substringToIndex:[self.textMessage length]-1];
|
||||
[self sendCurrentMessage];
|
||||
}
|
||||
}
|
||||
|
||||
NSString *message = self.textMessage;
|
||||
|
||||
// Reset message, disable view animation during the update to prevent placeholder distorsion.
|
||||
[UIView setAnimationsEnabled:NO];
|
||||
self.textMessage = nil;
|
||||
[UIView setAnimationsEnabled:YES];
|
||||
|
||||
// Send button has been pressed
|
||||
if (message.length && [self.delegate respondsToSelector:@selector(roomInputToolbarView:sendTextMessage:)])
|
||||
{
|
||||
[self.delegate roomInputToolbarView:self sendTextMessage:message];
|
||||
}
|
||||
- (void)sendCurrentMessage
|
||||
{
|
||||
// This forces an autocorrect event to happen when "Send" is pressed, which is necessary to accept a pending correction on send
|
||||
self.textMessage = [NSString stringWithFormat:@"%@ ", self.textMessage];
|
||||
self.textMessage = [self.textMessage substringToIndex:[self.textMessage length]-1];
|
||||
|
||||
NSString *message = self.textMessage;
|
||||
|
||||
// Reset message, disable view animation during the update to prevent placeholder distorsion.
|
||||
[UIView setAnimationsEnabled:NO];
|
||||
self.textMessage = nil;
|
||||
[UIView setAnimationsEnabled:YES];
|
||||
|
||||
// Send button has been pressed
|
||||
if (message.length && [self.delegate respondsToSelector:@selector(roomInputToolbarView:sendTextMessage:)])
|
||||
{
|
||||
[self.delegate roomInputToolbarView:self sendTextMessage:message];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user