mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-26 19:34:25 +02:00
Merge commit 'a8c505c2f9175ae0bece1f62708e6fc31e587897' into feature/3746_merge_element_1.9.10
# Conflicts: # Config/AppConfiguration.swift # Config/AppVersion.xcconfig # Podfile.lock # Riot/Modules/Application/AppCoordinator.swift # Riot/Modules/Common/Avatar/AvatarView.swift # Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellProvider.m # Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellProvider.m # Riot/Modules/Settings/Security/SecurityViewController.m # Riot/Modules/Settings/SettingsViewController.m # Riot/Modules/TabBar/TabBarCoordinator.swift # Riot/target.yml # fastlane/Fastfile # project.yml
This commit is contained in:
@@ -100,7 +100,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
@interface RoomViewController () <UISearchBarDelegate, UIGestureRecognizerDelegate, UIScrollViewAccessibilityDelegate, RoomTitleViewTapGestureDelegate, MXKRoomMemberDetailsViewControllerDelegate, ContactsTableViewControllerDelegate, MXServerNoticesDelegate, RoomContextualMenuViewControllerDelegate,
|
||||
ReactionsMenuViewModelCoordinatorDelegate, EditHistoryCoordinatorBridgePresenterDelegate, MXKDocumentPickerPresenterDelegate, EmojiPickerCoordinatorBridgePresenterDelegate,
|
||||
ReactionHistoryCoordinatorBridgePresenterDelegate, CameraPresenterDelegate, MediaPickerCoordinatorBridgePresenterDelegate,
|
||||
RoomDataSourceDelegate, RoomCreationModalCoordinatorBridgePresenterDelegate, RoomInfoCoordinatorBridgePresenterDelegate, DialpadViewControllerDelegate, RemoveJitsiWidgetViewDelegate, VoiceMessageControllerDelegate, SpaceDetailPresenterDelegate, UserSuggestionCoordinatorBridgeDelegate, ThreadsCoordinatorBridgePresenterDelegate, ThreadsBetaCoordinatorBridgePresenterDelegate, MXThreadingServiceDelegate, RoomParticipantsInviteCoordinatorBridgePresenterDelegate>
|
||||
RoomDataSourceDelegate, RoomCreationModalCoordinatorBridgePresenterDelegate, RoomInfoCoordinatorBridgePresenterDelegate, DialpadViewControllerDelegate, RemoveJitsiWidgetViewDelegate, VoiceMessageControllerDelegate, SpaceDetailPresenterDelegate, UserSuggestionCoordinatorBridgeDelegate, ThreadsCoordinatorBridgePresenterDelegate, ThreadsBetaCoordinatorBridgePresenterDelegate, MXThreadingServiceDelegate, RoomParticipantsInviteCoordinatorBridgePresenterDelegate, RoomInputToolbarViewDelegate, ComposerCreateActionListBridgePresenterDelegate>
|
||||
{
|
||||
|
||||
// The preview header
|
||||
@@ -198,6 +198,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
@property (nonatomic, strong) RoomContextualMenuPresenter *roomContextualMenuPresenter;
|
||||
@property (nonatomic, strong) MXKErrorAlertPresentation *errorPresenter;
|
||||
@property (nonatomic, strong) NSAttributedString *textMessageBeforeEditing;
|
||||
@property (nonatomic, strong) NSString *htmlTextBeforeEditing;
|
||||
@property (nonatomic, strong) EditHistoryCoordinatorBridgePresenter *editHistoryPresenter;
|
||||
@property (nonatomic, strong) MXKDocumentPickerPresenter *documentPickerPresenter;
|
||||
@property (nonatomic, strong) EmojiPickerCoordinatorBridgePresenter *emojiPickerCoordinatorBridgePresenter;
|
||||
@@ -212,6 +213,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
@property (nonatomic, strong) ThreadsCoordinatorBridgePresenter *threadsBridgePresenter;
|
||||
@property (nonatomic, strong) ThreadsBetaCoordinatorBridgePresenter *threadsBetaBridgePresenter;
|
||||
@property (nonatomic, strong) SlidingModalPresenter *threadsNoticeModalPresenter;
|
||||
@property (nonatomic, strong) ComposerCreateActionListBridgePresenter *composerCreateActionListBridgePresenter;
|
||||
@property (nonatomic, getter=isActivitiesViewExpanded) BOOL activitiesViewExpanded;
|
||||
@property (nonatomic, getter=isScrollToBottomHidden) BOOL scrollToBottomHidden;
|
||||
@property (nonatomic, getter=isMissedDiscussionsBadgeHidden) BOOL missedDiscussionsBadgeHidden;
|
||||
@@ -605,6 +607,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
isAppeared = NO;
|
||||
|
||||
[VoiceMessageMediaServiceProvider.sharedProvider pauseAllServices];
|
||||
[VoiceBroadcastRecorderProvider.shared pauseRecording];
|
||||
|
||||
if([BWIBuildSettings.shared showMentionsInRoom]) {
|
||||
[Mentions setCountMentionsToZeroWithRoomID:self.roomDataSource.roomId];
|
||||
@@ -685,9 +688,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
{
|
||||
// Retrieve the potential message partially typed during last room display.
|
||||
// Note: We have to wait for viewDidAppear before updating growingTextView (viewWillAppear is too early)
|
||||
RoomInputToolbarView *inputToolbar = (RoomInputToolbarView *)self.inputToolbarView;
|
||||
|
||||
inputToolbar.attributedTextMessage = self.roomDataSource.partialAttributedTextMessage;
|
||||
self.inputToolbarView.attributedTextMessage = self.roomDataSource.partialAttributedTextMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1165,10 +1166,23 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
[self notifyDelegateOnLeaveRoomIfNecessary];
|
||||
}
|
||||
|
||||
|
||||
+ (Class) mainToolbarClass
|
||||
{
|
||||
if (RiotSettings.shared.enableWysiwygComposer)
|
||||
{
|
||||
return WysiwygInputToolbarView.class;
|
||||
}
|
||||
else
|
||||
{
|
||||
return RoomInputToolbarView.class;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the input toolbar according to the current display
|
||||
- (void)updateRoomInputToolbarViewClassIfNeeded
|
||||
{
|
||||
Class roomInputToolbarViewClass = RoomInputToolbarView.class;
|
||||
Class roomInputToolbarViewClass = [RoomViewController mainToolbarClass];
|
||||
|
||||
BOOL shouldDismissContextualMenu = NO;
|
||||
|
||||
@@ -1211,10 +1225,10 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
{
|
||||
[super setRoomInputToolbarViewClass:roomInputToolbarViewClass];
|
||||
|
||||
// The voice message toolbar cannot be set on DisabledInputToolbarView and on new direct chat.
|
||||
if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class] && !self.isNewDirectChat)
|
||||
{
|
||||
[(RoomInputToolbarView *)self.inputToolbarView setVoiceMessageToolbarView:self.voiceMessageController.voiceMessageToolbarView];
|
||||
|
||||
if ([self.inputToolbarView.class conformsToProtocol:@protocol(RoomInputToolbarViewProtocol)]) {
|
||||
id<RoomInputToolbarViewProtocol> inputToolbar = (id<RoomInputToolbarViewProtocol>)self.inputToolbarView;
|
||||
[inputToolbar setVoiceMessageToolbarView:self.voiceMessageController.voiceMessageToolbarView];
|
||||
}
|
||||
|
||||
[self updateInputToolBarViewHeight];
|
||||
@@ -1227,9 +1241,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
{
|
||||
CGFloat height = 0;
|
||||
|
||||
if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class])
|
||||
{
|
||||
height = ((RoomInputToolbarView*)self.inputToolbarView).mainToolbarHeightConstraint.constant;
|
||||
if ([self.inputToolbarView.class conformsToProtocol:@protocol(RoomInputToolbarViewProtocol)]) {
|
||||
id<RoomInputToolbarViewProtocol> inputToolbar = (id<RoomInputToolbarViewProtocol>)self.inputToolbarView;
|
||||
height = inputToolbar.toolbarHeight;
|
||||
}
|
||||
else if ([self.inputToolbarView isKindOfClass:DisabledRoomInputToolbarView.class])
|
||||
{
|
||||
@@ -1775,15 +1789,20 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|| self.customizedRoomDataSource.jitsiWidget;
|
||||
}
|
||||
|
||||
- (BOOL)canSendStateEventWithType:(MXEventTypeString)eventTypeString
|
||||
{
|
||||
MXRoomPowerLevels *powerLevels = [self.roomDataSource.roomState powerLevels];
|
||||
NSInteger requiredPower = [powerLevels minimumPowerLevelForSendingEventAsStateEvent:eventTypeString];
|
||||
NSInteger myPower = [powerLevels powerLevelOfUserWithUserID:self.roomDataSource.mxSession.myUserId];
|
||||
return myPower >= requiredPower;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a flag for the current user whether it's privileged to add/remove Jitsi widgets to this room.
|
||||
*/
|
||||
- (BOOL)canEditJitsiWidget
|
||||
{
|
||||
MXRoomPowerLevels *powerLevels = [self.roomDataSource.roomState powerLevels];
|
||||
NSInteger requiredPower = [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kWidgetModularEventTypeString];
|
||||
NSInteger myPower = [powerLevels powerLevelOfUserWithUserID:self.roomDataSource.mxSession.myUserId];
|
||||
return myPower >= requiredPower;
|
||||
return [self canSendStateEventWithType:kWidgetModularEventTypeString];
|
||||
}
|
||||
|
||||
- (void)registerURLPreviewNotifications
|
||||
@@ -2000,9 +2019,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
[self updateInputToolBarVisibility];
|
||||
|
||||
// Check whether the input toolbar is ready before updating it.
|
||||
if (self.inputToolbarView && [self.inputToolbarView isKindOfClass:RoomInputToolbarView.class])
|
||||
if (self.inputToolbarView && [self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
RoomInputToolbarView *roomInputToolbarView = (RoomInputToolbarView*)self.inputToolbarView;
|
||||
id<RoomInputToolbarViewProtocol> roomInputToolbarView = (id<RoomInputToolbarViewProtocol>) self.inputToolbarView;
|
||||
|
||||
// Update encryption decoration if needed
|
||||
[self updateEncryptionDecorationForRoomInputToolbar:roomInputToolbarView];
|
||||
@@ -2049,9 +2068,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
- (void)setInputToolBarSendMode:(RoomInputToolbarViewSendMode)sendMode forEventWithId:(NSString *)eventId
|
||||
{
|
||||
if (self.inputToolbarView && [self.inputToolbarView isKindOfClass:[RoomInputToolbarView class]])
|
||||
if (self.inputToolbarView && [self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
RoomInputToolbarView *roomInputToolbarView = (RoomInputToolbarView*)self.inputToolbarView;
|
||||
MXKRoomInputToolbarView <RoomInputToolbarViewProtocol> *roomInputToolbarView = (MXKRoomInputToolbarView <RoomInputToolbarViewProtocol> *) self.inputToolbarView;
|
||||
if (eventId)
|
||||
{
|
||||
MXEvent *event = [self.roomDataSource eventWithEventId:eventId];
|
||||
@@ -2122,9 +2141,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
- (void)updateInputToolbarEncryptionDecoration
|
||||
{
|
||||
if (self.inputToolbarView && [self.inputToolbarView isKindOfClass:RoomInputToolbarView.class])
|
||||
if (self.inputToolbarView && [self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
RoomInputToolbarView *roomInputToolbarView = (RoomInputToolbarView*)self.inputToolbarView;
|
||||
id<RoomInputToolbarViewProtocol> roomInputToolbarView = (id<RoomInputToolbarViewProtocol>)self.inputToolbarView;
|
||||
[self updateEncryptionDecorationForRoomInputToolbar:roomInputToolbarView];
|
||||
}
|
||||
}
|
||||
@@ -2140,7 +2159,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
roomTitleView.badgeImageView.image = self.roomEncryptionBadgeImage;
|
||||
}
|
||||
|
||||
- (void)updateEncryptionDecorationForRoomInputToolbar:(RoomInputToolbarView*)roomInputToolbarView
|
||||
- (void)updateEncryptionDecorationForRoomInputToolbar:(id<RoomInputToolbarViewProtocol>)roomInputToolbarView
|
||||
{
|
||||
roomInputToolbarView.isEncryptionEnabled = self.isEncryptionEnabled;
|
||||
}
|
||||
@@ -2185,11 +2204,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
UIView *sourceView;
|
||||
|
||||
RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView];
|
||||
|
||||
if (roomInputToolbarView)
|
||||
if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class])
|
||||
{
|
||||
sourceView = roomInputToolbarView.attachMediaButton;
|
||||
sourceView = ((RoomInputToolbarView*)self.inputToolbarView).attachMediaButton;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2261,6 +2278,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
}
|
||||
|
||||
- (void)setupActions {
|
||||
|
||||
if (![self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) {
|
||||
return;
|
||||
}
|
||||
@@ -2298,6 +2316,16 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
[self roomInputToolbarViewDidTapFileUpload];
|
||||
}]];
|
||||
}
|
||||
if (RiotSettings.shared.enableVoiceBroadcast && !self.isNewDirectChat)
|
||||
{
|
||||
[actionItems addObject:[[RoomActionItem alloc] initWithImage:AssetImages.actionLive.image andAction:^{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) {
|
||||
((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO;
|
||||
}
|
||||
[self roomInputToolbarViewDidTapVoiceBroadcast];
|
||||
}]];
|
||||
}
|
||||
if (BuildSettings.pollsEnabled && self.displayConfiguration.sendingPollsEnabled && !self.isNewDirectChat)
|
||||
{
|
||||
[actionItems addObject:[[RoomActionItem alloc] initWithImage:AssetImages.actionPoll.image andAction:^{
|
||||
@@ -2415,6 +2443,39 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
self.documentPickerPresenter = documentPickerPresenter;
|
||||
}
|
||||
|
||||
- (void)roomInputToolbarViewDidTapVoiceBroadcast
|
||||
{
|
||||
// Check first the room permission
|
||||
if (![self canSendStateEventWithType:VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType])
|
||||
{
|
||||
[self showAlertWithTitle:[VectorL10n voiceBroadcastUnauthorizedTitle] message:[VectorL10n voiceBroadcastPermissionDeniedMessage]];
|
||||
return;
|
||||
}
|
||||
|
||||
MXSession* session = self.roomDataSource.mxSession;
|
||||
// Check whether the user is not already broadcasting here or in another room
|
||||
if (session.voiceBroadcastService)
|
||||
{
|
||||
[self showAlertWithTitle:[VectorL10n voiceBroadcastUnauthorizedTitle] message:[VectorL10n voiceBroadcastAlreadyInProgressMessage]];
|
||||
return;
|
||||
}
|
||||
|
||||
// Request the voice broadcast service to start recording - No service is returned if someone else is already broadcasting in the room
|
||||
[session getOrCreateVoiceBroadcastServiceFor:self.roomDataSource.room completion:^(VoiceBroadcastService *voiceBroadcastService) {
|
||||
if (voiceBroadcastService) {
|
||||
[voiceBroadcastService startVoiceBroadcastWithSuccess:^(NSString * _Nullable success) {
|
||||
|
||||
} failure:^(NSError * _Nonnull error) {
|
||||
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self showAlertWithTitle:[VectorL10n voiceBroadcastUnauthorizedTitle] message:[VectorL10n voiceBroadcastBlockedBySomeoneElseMessage]];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
Send a video asset via the room input toolbar prompting the user for the conversion preset to use
|
||||
if the `showMediaCompressionPrompt` setting has been enabled.
|
||||
@@ -2423,8 +2484,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
*/
|
||||
- (void)sendVideoAsset:(AVAsset *)videoAsset isPhotoLibraryAsset:(BOOL)isPhotoLibraryAsset
|
||||
{
|
||||
RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView];
|
||||
if (!roomInputToolbarView)
|
||||
if (![self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -2445,15 +2505,27 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
// Create before sending the message in case of a discussion (direct chat)
|
||||
[self createDiscussionIfNeeded:^(BOOL readyToSend) {
|
||||
if (readyToSend)
|
||||
if (readyToSend && [self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
[[self inputToolbarViewAsRoomInputToolbarView] sendSelectedVideoAsset:videoAsset isPhotoLibraryAsset:isPhotoLibraryAsset];
|
||||
[self.inputToolbarView sendSelectedVideoAsset:videoAsset isPhotoLibraryAsset:isPhotoLibraryAsset];
|
||||
}
|
||||
// Errors are handled at the request level. This should be improved in case of code rewriting.
|
||||
}];
|
||||
}];
|
||||
compressionPrompt.popoverPresentationController.sourceView = roomInputToolbarView.attachMediaButton;
|
||||
compressionPrompt.popoverPresentationController.sourceRect = roomInputToolbarView.attachMediaButton.bounds;
|
||||
|
||||
UIView *sourceView;
|
||||
|
||||
if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class])
|
||||
{
|
||||
sourceView = ((RoomInputToolbarView*)self.inputToolbarView).attachMediaButton;
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceView = self.inputToolbarView;
|
||||
}
|
||||
|
||||
compressionPrompt.popoverPresentationController.sourceView = sourceView;
|
||||
compressionPrompt.popoverPresentationController.sourceRect = sourceView.bounds;
|
||||
|
||||
[self presentViewController:compressionPrompt animated:YES completion:nil];
|
||||
}
|
||||
@@ -2464,9 +2536,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
// Create before sending the message in case of a discussion (direct chat)
|
||||
[self createDiscussionIfNeeded:^(BOOL readyToSend) {
|
||||
if (readyToSend)
|
||||
if (readyToSend && [self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
[[self inputToolbarViewAsRoomInputToolbarView] sendSelectedVideoAsset:videoAsset isPhotoLibraryAsset:isPhotoLibraryAsset];
|
||||
[self.inputToolbarView sendSelectedVideoAsset:videoAsset isPhotoLibraryAsset:isPhotoLibraryAsset];
|
||||
}
|
||||
// Errors are handled at the request level. This should be improved in case of code rewriting.
|
||||
}];
|
||||
@@ -3189,6 +3261,55 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagVoiceBroadcastPlayback)
|
||||
{
|
||||
if (bubbleData.isIncoming)
|
||||
{
|
||||
if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellIdentifier = RoomTimelineCellIdentifierIncomingVoiceBroadcastWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellIdentifier = RoomTimelineCellIdentifierIncomingVoiceBroadcastWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellIdentifier = RoomTimelineCellIdentifierIncomingVoiceBroadcast;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellIdentifier = RoomTimelineCellIdentifierOutgoingVoiceBroadcastWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellIdentifier = RoomTimelineCellIdentifierOutgoingVoiceBroadcastWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellIdentifier = RoomTimelineCellIdentifierOutgoingVoiceBroadcast;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bubbleData.tag == RoomBubbleCellDataTagVoiceBroadcastRecord)
|
||||
{
|
||||
if (bubbleData.isPaginationFirstBubble)
|
||||
{
|
||||
cellIdentifier = RoomTimelineCellIdentifierOutgoingVoiceBroadcastRecorderWithPaginationTitle;
|
||||
}
|
||||
else if (bubbleData.shouldHideSenderInformation)
|
||||
{
|
||||
cellIdentifier = RoomTimelineCellIdentifierOutgoingVoiceBroadcastRecorderWithoutSenderInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellIdentifier = RoomTimelineCellIdentifierOutgoingVoiceBroadcastRecorder;
|
||||
}
|
||||
}
|
||||
|
||||
else if (roomBubbleCellData.getFirstBubbleComponentWithDisplay.event.isEmote)
|
||||
{
|
||||
if (bubbleData.isIncoming)
|
||||
@@ -4509,6 +4630,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
// Do nothing for dummy links
|
||||
shouldDoAction = NO;
|
||||
break;
|
||||
case RoomMessageURLTypeHttp:
|
||||
shouldDoAction = YES;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
MXEvent *tappedEvent = userInfo[kMXKRoomBubbleCellEventKey];
|
||||
@@ -4534,16 +4658,20 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
break;
|
||||
case UITextItemInteractionPresentActions:
|
||||
{
|
||||
// Retrieve the tapped event
|
||||
MXEvent *tappedEvent = userInfo[kMXKRoomBubbleCellEventKey];
|
||||
|
||||
if (tappedEvent)
|
||||
{
|
||||
// Long press on link, present room contextual menu.
|
||||
[self showContextualMenuForEvent:tappedEvent fromSingleTapGesture:NO cell:cell animated:YES];
|
||||
if (roomMessageURLType == RoomMessageURLTypeHttp) {
|
||||
shouldDoAction = YES;
|
||||
} else {
|
||||
// Retrieve the tapped event
|
||||
MXEvent *tappedEvent = userInfo[kMXKRoomBubbleCellEventKey];
|
||||
|
||||
if (tappedEvent)
|
||||
{
|
||||
// Long press on link, present room contextual menu.
|
||||
[self showContextualMenuForEvent:tappedEvent fromSingleTapGesture:NO cell:cell animated:YES];
|
||||
}
|
||||
|
||||
shouldDoAction = NO;
|
||||
}
|
||||
|
||||
shouldDoAction = NO;
|
||||
}
|
||||
break;
|
||||
case UITextItemInteractionPreview:
|
||||
@@ -4608,12 +4736,16 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
{
|
||||
MXEvent *event = [self.roomDataSource eventWithEventId:eventId];
|
||||
|
||||
RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView];
|
||||
|
||||
if (roomInputToolbarView)
|
||||
if ([self inputToolbarConformsToHtmlToolbarViewProtocol])
|
||||
{
|
||||
self.textMessageBeforeEditing = roomInputToolbarView.attributedTextMessage;
|
||||
roomInputToolbarView.attributedTextMessage = [self.customizedRoomDataSource editableAttributedTextMessageFor:event];
|
||||
MXKRoomInputToolbarView <HtmlRoomInputToolbarViewProtocol> *htmlInputToolBarView = (MXKRoomInputToolbarView <HtmlRoomInputToolbarViewProtocol> *) self.inputToolbarView;
|
||||
self.htmlTextBeforeEditing = htmlInputToolBarView.htmlContent;
|
||||
htmlInputToolBarView.htmlContent = [self.customizedRoomDataSource editableHtmlTextMessageFor:event];
|
||||
}
|
||||
else if ([self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
self.textMessageBeforeEditing = self.inputToolbarView.attributedTextMessage;
|
||||
self.inputToolbarView.attributedTextMessage = [self.customizedRoomDataSource editableAttributedTextMessageFor:event];
|
||||
}
|
||||
|
||||
[self selectEventWithId:eventId inputToolBarSendMode:RoomInputToolbarViewSendModeEdit showTimestamp:YES];
|
||||
@@ -4621,26 +4753,30 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
- (void)restoreTextMessageBeforeEditing
|
||||
{
|
||||
RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView];
|
||||
|
||||
if (self.textMessageBeforeEditing)
|
||||
|
||||
if (self.htmlTextBeforeEditing && [self inputToolbarConformsToHtmlToolbarViewProtocol])
|
||||
{
|
||||
roomInputToolbarView.attributedTextMessage = self.textMessageBeforeEditing;
|
||||
MXKRoomInputToolbarView <HtmlRoomInputToolbarViewProtocol> *htmlInputToolBarView = (MXKRoomInputToolbarView <HtmlRoomInputToolbarViewProtocol> *) self.inputToolbarView;
|
||||
htmlInputToolBarView.htmlContent = self.htmlTextBeforeEditing;
|
||||
}
|
||||
else if (self.textMessageBeforeEditing && [self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
self.inputToolbarView.attributedTextMessage = self.textMessageBeforeEditing;
|
||||
}
|
||||
|
||||
self.textMessageBeforeEditing = nil;
|
||||
self.htmlTextBeforeEditing = nil;
|
||||
}
|
||||
|
||||
- (RoomInputToolbarView*)inputToolbarViewAsRoomInputToolbarView
|
||||
- (BOOL)inputToolbarConformsToHtmlToolbarViewProtocol
|
||||
{
|
||||
RoomInputToolbarView *roomInputToolbarView;
|
||||
|
||||
if (self.inputToolbarView && [self.inputToolbarView isKindOfClass:[RoomInputToolbarView class]])
|
||||
{
|
||||
roomInputToolbarView = (RoomInputToolbarView*)self.inputToolbarView;
|
||||
}
|
||||
|
||||
return roomInputToolbarView;
|
||||
return [self.inputToolbarView conformsToProtocol:@protocol(HtmlRoomInputToolbarViewProtocol)];
|
||||
}
|
||||
|
||||
- (BOOL)inputToolbarConformsToToolbarViewProtocol
|
||||
{
|
||||
return [self.inputToolbarView conformsToProtocol:@protocol(RoomInputToolbarViewProtocol)];
|
||||
}
|
||||
|
||||
- (void)showDifferentURLsAlertFor:(NSURL *)url visibleURLString:(NSString *)visibleURLString
|
||||
@@ -4933,32 +5069,17 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
{
|
||||
if (self.roomInputToolbarContainerHeightConstraint.constant != height)
|
||||
{
|
||||
// Hide temporarily the placeholder to prevent its distorsion during height animation
|
||||
if (!savedInputToolbarPlaceholder)
|
||||
{
|
||||
savedInputToolbarPlaceholder = toolbarView.placeholder.length ? toolbarView.placeholder : @"";
|
||||
}
|
||||
toolbarView.placeholder = nil;
|
||||
|
||||
[super roomInputToolbarView:toolbarView heightDidChanged:height completion:^(BOOL finished) {
|
||||
|
||||
if (completion)
|
||||
{
|
||||
completion (finished);
|
||||
}
|
||||
|
||||
// Consider here the saved placeholder only if no new placeholder has been defined during the height animation.
|
||||
if (!toolbarView.placeholder)
|
||||
{
|
||||
// Restore the placeholder if any
|
||||
toolbarView.placeholder = self->savedInputToolbarPlaceholder.length ? self->savedInputToolbarPlaceholder : nil;
|
||||
}
|
||||
self->savedInputToolbarPlaceholder = nil;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)roomInputToolbarViewDidTapCancel:(RoomInputToolbarView*)toolbarView
|
||||
- (void)roomInputToolbarViewDidTapCancel:(MXKRoomInputToolbarView<RoomInputToolbarViewProtocol>*)toolbarView
|
||||
{
|
||||
[self cancelEventSelection];
|
||||
}
|
||||
@@ -4977,6 +5098,57 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)roomInputToolbarView:(RoomInputToolbarView *)toolbarView sendFormattedTextMessage:(NSString *)formattedTextMessage withRawText:(NSString *)rawText
|
||||
{
|
||||
// Create before sending the message in case of a discussion (direct chat)
|
||||
MXWeakify(self);
|
||||
[self createDiscussionIfNeeded:^(BOOL readyToSend) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
if (readyToSend) {
|
||||
[self sendFormattedTextMessage:rawText htmlMsg:formattedTextMessage];
|
||||
}
|
||||
// Errors are handled at the request level. This should be improved in case of code rewriting.
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)roomInputToolbarViewShowSendMediaActions:(MXKRoomInputToolbarView *)toolbarView
|
||||
{
|
||||
NSMutableArray *actionItems = [NSMutableArray new];
|
||||
if (RiotSettings.shared.roomScreenAllowMediaLibraryAction)
|
||||
{
|
||||
[actionItems addObject:@(ComposerCreateActionPhotoLibrary)];
|
||||
}
|
||||
if (RiotSettings.shared.roomScreenAllowStickerAction && !self.isNewDirectChat)
|
||||
{
|
||||
[actionItems addObject:@(ComposerCreateActionStickers)];
|
||||
}
|
||||
if (RiotSettings.shared.roomScreenAllowFilesAction)
|
||||
{
|
||||
[actionItems addObject:@(ComposerCreateActionAttachments)];
|
||||
}
|
||||
if (RiotSettings.shared.enableVoiceBroadcast && !self.isNewDirectChat)
|
||||
{
|
||||
[actionItems addObject:@(ComposerCreateActionVoiceBroadcast)];
|
||||
}
|
||||
if (BuildSettings.pollsEnabled && self.displayConfiguration.sendingPollsEnabled && !self.isNewDirectChat)
|
||||
{
|
||||
[actionItems addObject:@(ComposerCreateActionPolls)];
|
||||
}
|
||||
if (BuildSettings.locationSharingEnabled && !self.isNewDirectChat)
|
||||
{
|
||||
[actionItems addObject:@(ComposerCreateActionLocation)];
|
||||
}
|
||||
if (RiotSettings.shared.roomScreenAllowCameraAction)
|
||||
{
|
||||
[actionItems addObject:@(ComposerCreateActionCamera)];
|
||||
}
|
||||
|
||||
self.composerCreateActionListBridgePresenter = [[ComposerCreateActionListBridgePresenter alloc] initWithActions:actionItems];
|
||||
self.composerCreateActionListBridgePresenter.delegate = self;
|
||||
[self.composerCreateActionListBridgePresenter presentFrom:self animated:YES];
|
||||
}
|
||||
|
||||
- (void)roomInputToolbarView:(RoomInputToolbarView *)toolbarView sendAttributedTextMessage:(NSAttributedString *)attributedTextMessage
|
||||
{
|
||||
// Create before sending the message in case of a discussion (direct chat)
|
||||
@@ -5323,7 +5495,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
else
|
||||
{
|
||||
// Enable back the text input
|
||||
[self setRoomInputToolbarViewClass:RoomInputToolbarView.class];
|
||||
[self setRoomInputToolbarViewClass:[RoomViewController mainToolbarClass]];
|
||||
[self updateInputToolBarViewHeight];
|
||||
|
||||
// And the extra area
|
||||
@@ -6122,7 +6294,13 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
// Acknowledge the existence of all devices
|
||||
[self startActivityIndicator];
|
||||
[self.mainSession.crypto setDevicesKnown:self->unknownDevices complete:^{
|
||||
|
||||
if (![self.mainSession.crypto isKindOfClass:[MXLegacyCrypto class]])
|
||||
{
|
||||
MXLogFailure(@"[RoomVC] eventDidChangeSentState: Only legacy crypto supports manual setting of known devices");
|
||||
return;
|
||||
}
|
||||
[(MXLegacyCrypto *)self.mainSession.crypto setDevicesKnown:self->unknownDevices complete:^{
|
||||
|
||||
self->unknownDevices = nil;
|
||||
[self stopActivityIndicator];
|
||||
@@ -7590,9 +7768,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
// Create before sending the message in case of a discussion (direct chat)
|
||||
[self createDiscussionIfNeeded:^(BOOL readyToSend) {
|
||||
if (readyToSend)
|
||||
if (readyToSend && [self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
[[self inputToolbarViewAsRoomInputToolbarView] sendSelectedImage:imageData
|
||||
[self.inputToolbarView sendSelectedImage:imageData
|
||||
withMimeType:MXKUTI.jpeg.mimeType
|
||||
andCompressionMode:MediaCompressionHelper.defaultCompressionMode
|
||||
isPhotoLibraryAsset:NO];
|
||||
@@ -7625,9 +7803,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
// Create before sending the message in case of a discussion (direct chat)
|
||||
[self createDiscussionIfNeeded:^(BOOL readyToSend) {
|
||||
if (readyToSend)
|
||||
if (readyToSend && [self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
[[self inputToolbarViewAsRoomInputToolbarView] sendSelectedImage:imageData
|
||||
[self.inputToolbarView sendSelectedImage:imageData
|
||||
withMimeType:uti.mimeType
|
||||
andCompressionMode:MediaCompressionHelper.defaultCompressionMode
|
||||
isPhotoLibraryAsset:YES];
|
||||
@@ -7654,9 +7832,9 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
|
||||
// Create before sending the message in case of a discussion (direct chat)
|
||||
[self createDiscussionIfNeeded:^(BOOL readyToSend) {
|
||||
if (readyToSend)
|
||||
if (readyToSend && [self inputToolbarConformsToToolbarViewProtocol])
|
||||
{
|
||||
[[self inputToolbarViewAsRoomInputToolbarView] sendSelectedAssets:assets withCompressionMode:MediaCompressionHelper.defaultCompressionMode];
|
||||
[self.inputToolbarView sendSelectedAssets:assets withCompressionMode:MediaCompressionHelper.defaultCompressionMode];
|
||||
}
|
||||
// Errors are handled at the request level. This should be improved in case of code rewriting.
|
||||
}];
|
||||
@@ -7920,4 +8098,42 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - ComposerCreateActionListBridgePresenter
|
||||
|
||||
- (void)composerCreateActionListBridgePresenterDelegateDidComplete:(ComposerCreateActionListBridgePresenter *)coordinatorBridgePresenter action:(enum ComposerCreateAction)action
|
||||
{
|
||||
|
||||
[coordinatorBridgePresenter dismissWithAnimated:true completion:^{
|
||||
switch (action) {
|
||||
case ComposerCreateActionPhotoLibrary:
|
||||
[self showMediaPickerAnimated:YES];
|
||||
break;
|
||||
case ComposerCreateActionStickers:
|
||||
[self roomInputToolbarViewPresentStickerPicker];
|
||||
break;
|
||||
case ComposerCreateActionAttachments:
|
||||
[self roomInputToolbarViewDidTapFileUpload];
|
||||
break;
|
||||
case ComposerCreateActionVoiceBroadcast:
|
||||
[self roomInputToolbarViewDidTapVoiceBroadcast];
|
||||
break;
|
||||
case ComposerCreateActionPolls:
|
||||
[self.delegate roomViewControllerDidRequestPollCreationFormPresentation:self];
|
||||
break;
|
||||
case ComposerCreateActionLocation:
|
||||
[self.delegate roomViewControllerDidRequestLocationSharingFormPresentation:self];
|
||||
break;
|
||||
case ComposerCreateActionCamera:
|
||||
[self showCameraControllerAnimated:YES];
|
||||
break;
|
||||
}
|
||||
self.composerCreateActionListBridgePresenter = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)composerCreateActionListBridgePresenterDidDismissInteractively:(ComposerCreateActionListBridgePresenter *)coordinatorBridgePresenter
|
||||
{
|
||||
self.composerCreateActionListBridgePresenter = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user