mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-05-21 07:02:09 +02:00
Chat screen : support event edition
This commit is contained in:
@@ -34,6 +34,8 @@
|
||||
"save" = "Save";
|
||||
"join" = "Join";
|
||||
"reject" = "Reject";
|
||||
"edit" = "Edit";
|
||||
"redact" = "Redact";
|
||||
|
||||
// Authentication
|
||||
"auth_sign_in" = "Sign in";
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
|
||||
#import <MatrixKit/MatrixKit.h>
|
||||
|
||||
/**
|
||||
Action identifier used when the user pressed edit button displayed in front of a selected event.
|
||||
|
||||
The `userInfo` dictionary contains an `MXEvent` object under the `kMXKRoomBubbleCellEventKey` key, representing the selected event.
|
||||
*/
|
||||
extern NSString *const kMXKRoomBubbleCellVectorEditButtonPressed;
|
||||
|
||||
/**
|
||||
Define a `MXKRoomBubbleTableViewCell` category at Vector level to handle bubble customisation.
|
||||
*/
|
||||
@@ -52,4 +59,19 @@
|
||||
*/
|
||||
@property(nonatomic) BOOL blurred;
|
||||
|
||||
/**
|
||||
The 'edit' button displayed in front of the selected component (if any). Default is nil.
|
||||
*/
|
||||
@property(nonatomic) UIButton *editButton;
|
||||
|
||||
/**
|
||||
The read receipts container associated to the selected component (if any). Default is nil.
|
||||
*/
|
||||
@property(nonatomic) MXKReceiptSendersContainer* selectedReadReceiptsContainer;
|
||||
|
||||
/**
|
||||
The trailing constraint of the read receipts container associated to the selected component (if any). Default is nil.
|
||||
*/
|
||||
@property(nonatomic) NSLayoutConstraint* selectedReadReceiptsContainerTrailingConstraint;
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
NSString *const kMXKRoomBubbleCellVectorEditButtonPressed = @"kMXKRoomBubbleCellVectorEditButtonPressed";
|
||||
|
||||
@implementation MXKRoomBubbleTableViewCell (Vector)
|
||||
|
||||
- (void)addTimestampLabelForComponent:(NSUInteger)componentIndex
|
||||
@@ -71,7 +73,6 @@
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
multiplier:1.0
|
||||
constant:0];
|
||||
// Vertical constraints are required for iOS > 8
|
||||
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:dateTimeLabel
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
@@ -85,7 +86,7 @@
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:15];
|
||||
constant:18];
|
||||
|
||||
// Available on iOS 8 and later
|
||||
[NSLayoutConstraint activateConstraints:@[leftConstraint, rightConstraint, topConstraint, heightConstraint]];
|
||||
@@ -110,8 +111,10 @@
|
||||
MXKRoomBubbleComponent *component;
|
||||
if (componentIndex < self.bubbleData.bubbleComponents.count)
|
||||
{
|
||||
// Add time label
|
||||
[self addTimestampLabelForComponent:componentIndex];
|
||||
|
||||
// Hightlight selection by blurring other components
|
||||
component = self.bubbleData.bubbleComponents[componentIndex];
|
||||
[self highlightTextMessageForEvent:component.event.eventId];
|
||||
|
||||
@@ -125,7 +128,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Blur read receipts which are not related to the selected component (if any)
|
||||
// Retrieve the read receipts container related to the selected component (if any)
|
||||
// Blur the others
|
||||
for (UIView* view in self.bubbleOverlayContainer.subviews)
|
||||
{
|
||||
// Note read receipt container tag is equal to the index of the related component.
|
||||
@@ -133,12 +137,22 @@
|
||||
{
|
||||
view.alpha = 0.2;
|
||||
}
|
||||
else if ([view isKindOfClass:MXKReceiptSendersContainer.class])
|
||||
{
|
||||
self.selectedReadReceiptsContainer = (MXKReceiptSendersContainer*)view;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the edit button (shift left the receipts container if any).
|
||||
[self addEditButtonForComponent:componentIndex completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)unselectComponent
|
||||
{
|
||||
// Remove edit button (Restore receipts container position if any)
|
||||
[self removeEditButton:nil];
|
||||
|
||||
// Remove all timestamps by default
|
||||
[self removeTimestampLabels];
|
||||
|
||||
@@ -211,4 +225,223 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setEditButton:(UIButton *)editButton
|
||||
{
|
||||
objc_setAssociatedObject(self, @selector(editButton), editButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (UIButton*)editButton
|
||||
{
|
||||
return objc_getAssociatedObject(self, @selector(editButton));
|
||||
}
|
||||
|
||||
- (void)setSelectedReadReceiptsContainer:(MXKReceiptSendersContainer *)readReceiptsContainer
|
||||
{
|
||||
objc_setAssociatedObject(self, @selector(selectedReadReceiptsContainer), readReceiptsContainer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (UIButton*)selectedReadReceiptsContainer
|
||||
{
|
||||
return objc_getAssociatedObject(self, @selector(selectedReadReceiptsContainer));
|
||||
}
|
||||
|
||||
- (void)setSelectedReadReceiptsContainerTrailingConstraint:(NSLayoutConstraint *)readReceiptsContainerTrailingConstraint
|
||||
{
|
||||
objc_setAssociatedObject(self, @selector(selectedReadReceiptsContainerTrailingConstraint), readReceiptsContainerTrailingConstraint, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (UIButton*)selectedReadReceiptsContainerTrailingConstraint
|
||||
{
|
||||
return objc_getAssociatedObject(self, @selector(selectedReadReceiptsContainerTrailingConstraint));
|
||||
}
|
||||
|
||||
#pragma mark - User actions
|
||||
|
||||
- (IBAction)onEditButtonPressed:(id)sender
|
||||
{
|
||||
if (self.delegate)
|
||||
{
|
||||
MXEvent *selectedEvent = nil;
|
||||
|
||||
// Note edit button tag is equal to the index of the related component.
|
||||
NSInteger index = ((UIView*)sender).tag;
|
||||
if (index < self.bubbleData.bubbleComponents.count)
|
||||
{
|
||||
MXKRoomBubbleComponent *component = self.bubbleData.bubbleComponents[index];
|
||||
selectedEvent = component.event;
|
||||
}
|
||||
|
||||
if (selectedEvent)
|
||||
{
|
||||
[self.delegate cell:self didRecognizeAction:kMXKRoomBubbleCellVectorEditButtonPressed userInfo:@{kMXKRoomBubbleCellEventKey:selectedEvent}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Internals
|
||||
|
||||
- (void)addEditButtonForComponent:(NSUInteger)componentIndex completion:(void (^ __nullable)(BOOL finished))completion
|
||||
{
|
||||
MXKRoomBubbleComponent *component = self.bubbleData.bubbleComponents[componentIndex];
|
||||
|
||||
// Define 'Edit' button frame by overlapping slightly the time label
|
||||
// (vertical pos = (component.position.y + 9) instead of (component.position.y + 18))
|
||||
UIButton *editButton = [[UIButton alloc] initWithFrame:CGRectMake(0, component.position.y + 9, self.bubbleInfoContainer.frame.size.width , 33)];
|
||||
|
||||
[editButton setTitle:NSLocalizedStringFromTable(@"edit", @"Vector", nil) forState:UIControlStateNormal];
|
||||
[editButton setTitle:NSLocalizedStringFromTable(@"edit", @"Vector", nil) forState:UIControlStateSelected];
|
||||
[editButton setTitleColor:VECTOR_GREEN_COLOR forState:UIControlStateNormal];
|
||||
[editButton setTitleColor:VECTOR_GREEN_COLOR forState:UIControlStateSelected];
|
||||
editButton.titleLabel.textAlignment = NSTextAlignmentRight;
|
||||
|
||||
editButton.backgroundColor = [UIColor clearColor];
|
||||
if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)])
|
||||
{
|
||||
editButton.titleLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightMedium];
|
||||
}
|
||||
else
|
||||
{
|
||||
editButton.titleLabel.font = [UIFont systemFontOfSize:15];
|
||||
}
|
||||
|
||||
editButton.hidden = YES;
|
||||
editButton.tag = componentIndex;
|
||||
[editButton addTarget:self action:@selector(onEditButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
[editButton setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
[self.bubbleInfoContainer addSubview:editButton];
|
||||
self.bubbleInfoContainer.userInteractionEnabled = YES;
|
||||
|
||||
// Force edit button in full width (to handle auto-layout in case of screen rotation)
|
||||
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:editButton
|
||||
attribute:NSLayoutAttributeLeading
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.bubbleInfoContainer
|
||||
attribute:NSLayoutAttributeLeading
|
||||
multiplier:1.0
|
||||
constant:0];
|
||||
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:editButton
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.bubbleInfoContainer
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
multiplier:1.0
|
||||
constant:0];
|
||||
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:editButton
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.bubbleInfoContainer
|
||||
attribute:NSLayoutAttributeTop
|
||||
multiplier:1.0
|
||||
constant:component.position.y + 9];
|
||||
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:editButton
|
||||
attribute:NSLayoutAttributeHeight
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:33];
|
||||
// Available on iOS 8 and later
|
||||
[NSLayoutConstraint activateConstraints:@[leftConstraint, rightConstraint, topConstraint, heightConstraint]];
|
||||
|
||||
// Store the created button
|
||||
self.editButton = editButton;
|
||||
|
||||
// Check whether this edit button overlaps a potential receipts container displayed for this component
|
||||
if (self.selectedReadReceiptsContainer)
|
||||
{
|
||||
// Adjust edit button frame to be able to compare it to bubble overlay container (superview of receipts container).
|
||||
CGRect frame = CGRectOffset (editButton.frame, self.bubbleInfoContainer.frame.origin.x, self.bubbleInfoContainer.frame.origin.y);
|
||||
if (CGRectIntersectsRect(frame, self.selectedReadReceiptsContainer.frame))
|
||||
{
|
||||
// Retrieve the trailing constraint of the receipts container
|
||||
NSArray *constraints = self.bubbleOverlayContainer.constraints;
|
||||
for (NSLayoutConstraint *constraint in constraints)
|
||||
{
|
||||
if (constraint.firstAttribute == NSLayoutAttributeTrailing && constraint.firstItem == self.selectedReadReceiptsContainer)
|
||||
{
|
||||
self.selectedReadReceiptsContainerTrailingConstraint = constraint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.selectedReadReceiptsContainerTrailingConstraint)
|
||||
{
|
||||
// Update layout with animation
|
||||
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn
|
||||
animations:^{
|
||||
|
||||
// Shift the container to left
|
||||
self.selectedReadReceiptsContainerTrailingConstraint.constant -= (self.bubbleInfoContainer.frame.size.width + 6);
|
||||
|
||||
// Force to render the view
|
||||
[self layoutIfNeeded];
|
||||
|
||||
editButton.hidden = NO;
|
||||
|
||||
}
|
||||
completion:^(BOOL finished){
|
||||
|
||||
if (completion)
|
||||
{
|
||||
completion(finished);
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
editButton.hidden = NO;
|
||||
|
||||
if (completion)
|
||||
{
|
||||
completion(YES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeEditButton:(void (^ __nullable)(BOOL finished))completion
|
||||
{
|
||||
if (self.selectedReadReceiptsContainerTrailingConstraint)
|
||||
{
|
||||
// Update layout with animation
|
||||
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn
|
||||
animations:^{
|
||||
|
||||
[self.editButton removeFromSuperview];
|
||||
|
||||
self.selectedReadReceiptsContainerTrailingConstraint.constant = -6;
|
||||
|
||||
// Force to render the view
|
||||
[self layoutIfNeeded];
|
||||
}
|
||||
completion:^(BOOL finished){
|
||||
|
||||
self.editButton = nil;
|
||||
self.selectedReadReceiptsContainer = nil;
|
||||
self.selectedReadReceiptsContainerTrailingConstraint = nil;
|
||||
|
||||
if (completion)
|
||||
{
|
||||
completion(finished);
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self.editButton removeFromSuperview];
|
||||
self.editButton = nil;
|
||||
self.selectedReadReceiptsContainer = nil;
|
||||
self.selectedReadReceiptsContainerTrailingConstraint = nil;
|
||||
|
||||
if (completion)
|
||||
{
|
||||
completion(YES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -158,12 +158,12 @@
|
||||
|
||||
// Force receipts container size
|
||||
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:150];
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:150];
|
||||
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeHeight
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
@@ -173,13 +173,13 @@
|
||||
constant:12];
|
||||
|
||||
// Force receipts container position
|
||||
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:bubbleCell.bubbleOverlayContainer
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
multiplier:1.0
|
||||
constant:-6];
|
||||
NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:bubbleCell.bubbleOverlayContainer
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
multiplier:1.0
|
||||
constant:-6];
|
||||
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
@@ -188,17 +188,8 @@
|
||||
multiplier:1.0
|
||||
constant:bottomPositionY - 12];
|
||||
|
||||
if ([NSLayoutConstraint respondsToSelector:@selector(activateConstraints:)])
|
||||
{
|
||||
[NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint, topConstraint, rightConstraint]];
|
||||
}
|
||||
else
|
||||
{
|
||||
[avatarsContainer addConstraint:heightConstraint];
|
||||
[avatarsContainer addConstraint:widthConstraint];
|
||||
[bubbleCell.bubbleOverlayContainer addConstraint:topConstraint];
|
||||
[bubbleCell.bubbleOverlayContainer addConstraint:rightConstraint];
|
||||
}
|
||||
// Available on iOS 8 and later
|
||||
[NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint, topConstraint, trailingConstraint]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
[[AppDelegate theDelegate] showRoom:room.state.roomId withMatrixSession:self.mainSession];
|
||||
} failure:^(NSError *error)
|
||||
{
|
||||
NSLog(@"[Console RoomVC] Join roomAlias (%@) failed: %@", roomAlias, error);
|
||||
NSLog(@"[Vector RoomVC] Join roomAlias (%@) failed: %@", roomAlias, error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
@@ -380,30 +380,17 @@
|
||||
// Retrieve the tapped event
|
||||
MXEvent *tappedEvent = userInfo[kMXKRoomBubbleCellEventKey];
|
||||
|
||||
// Update display of the visible table cell view
|
||||
NSArray* cellArray = self.bubblesTableView.visibleCells;
|
||||
|
||||
// Check whether a selection already exist or not
|
||||
if (customizedRoomDataSource.selectedEventId)
|
||||
{
|
||||
// Cancel the current selection
|
||||
for (MXKRoomBubbleTableViewCell *tableViewCell in cellArray)
|
||||
{
|
||||
if (tableViewCell.blurred)
|
||||
{
|
||||
tableViewCell.blurred = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
[tableViewCell unselectComponent];
|
||||
}
|
||||
}
|
||||
|
||||
customizedRoomDataSource.selectedEventId = nil;
|
||||
[self cancelEventSelection];
|
||||
}
|
||||
else if (tappedEvent)
|
||||
{
|
||||
// Highlight this event in displayed message
|
||||
|
||||
// Update display of the visible table cell view
|
||||
NSArray* cellArray = self.bubblesTableView.visibleCells;
|
||||
|
||||
// Blur all table cells, except the tapped one
|
||||
for (MXKRoomBubbleTableViewCell *tableViewCell in cellArray)
|
||||
@@ -435,21 +422,272 @@
|
||||
else if ([actionIdentifier isEqualToString:kMXKRoomBubbleCellTapOnOverlayContainer])
|
||||
{
|
||||
// Cancel the current event selection
|
||||
NSArray* cellArray = self.bubblesTableView.visibleCells;
|
||||
[self cancelEventSelection];
|
||||
}
|
||||
else if ([actionIdentifier isEqualToString:kMXKRoomBubbleCellVectorEditButtonPressed])
|
||||
{
|
||||
[self dismissKeyboard];
|
||||
|
||||
for (MXKRoomBubbleTableViewCell *tableViewCell in cellArray)
|
||||
MXEvent *selectedEvent = userInfo[kMXKRoomBubbleCellEventKey];
|
||||
MXKRoomBubbleTableViewCell *roomBubbleTableViewCell = (MXKRoomBubbleTableViewCell *)cell;
|
||||
MXKAttachment *attachment = roomBubbleTableViewCell.bubbleData.attachment;
|
||||
|
||||
if (selectedEvent)
|
||||
{
|
||||
if (tableViewCell.blurred)
|
||||
if (self.currentAlert)
|
||||
{
|
||||
tableViewCell.blurred = NO;
|
||||
[self.currentAlert dismiss:NO];
|
||||
self.currentAlert = nil;
|
||||
}
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
self.currentAlert = [[MXKAlert alloc] initWithTitle:nil message:nil style:MXKAlertStyleActionSheet];
|
||||
|
||||
// Add actions for a failed event
|
||||
if (selectedEvent.mxkState == MXKEventStateSendingFailed)
|
||||
{
|
||||
[self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"resend"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
// Let the datasource resend. It will manage local echo, etc.
|
||||
[strongSelf.roomDataSource resendEventWithEventId:selectedEvent.eventId success:nil failure:nil];
|
||||
|
||||
}];
|
||||
|
||||
[self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"delete"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
[strongSelf.roomDataSource removeEventWithEventId:selectedEvent.eventId];
|
||||
}];
|
||||
}
|
||||
|
||||
// Add actions for text message
|
||||
if (!attachment)
|
||||
{
|
||||
// Retrieved data related to the selected event
|
||||
NSArray *components = roomBubbleTableViewCell.bubbleData.bubbleComponents;
|
||||
MXKRoomBubbleComponent *selectedComponent;
|
||||
for (selectedComponent in components)
|
||||
{
|
||||
if ([selectedComponent.event.eventId isEqualToString:selectedEvent.eventId])
|
||||
{
|
||||
break;
|
||||
}
|
||||
selectedComponent = nil;
|
||||
}
|
||||
|
||||
[self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"copy"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
[[UIPasteboard generalPasteboard] setString:selectedComponent.textMessage];
|
||||
|
||||
}];
|
||||
|
||||
[self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"share"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
NSArray *activityItems = [NSArray arrayWithObjects:selectedComponent.textMessage, nil];
|
||||
|
||||
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
|
||||
activityViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
|
||||
|
||||
if (activityViewController)
|
||||
{
|
||||
[strongSelf presentViewController:activityViewController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
else // Add action for attachment
|
||||
{
|
||||
if (attachment.type == MXKAttachmentTypeImage || attachment.type == MXKAttachmentTypeVideo)
|
||||
{
|
||||
[self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"save"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
[strongSelf startActivityIndicator];
|
||||
|
||||
[attachment save:^{
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf stopActivityIndicator];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf stopActivityIndicator];
|
||||
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
|
||||
// Start animation in case of download during attachment preparing
|
||||
[roomBubbleTableViewCell startProgressUI];
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
[self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"copy"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
[strongSelf startActivityIndicator];
|
||||
|
||||
[attachment copy:^{
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf stopActivityIndicator];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf stopActivityIndicator];
|
||||
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
|
||||
// Start animation in case of download during attachment preparing
|
||||
[roomBubbleTableViewCell startProgressUI];
|
||||
}];
|
||||
|
||||
[self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"share"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
[attachment prepareShare:^(NSURL *fileURL) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
strongSelf->documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
|
||||
[strongSelf->documentInteractionController setDelegate:strongSelf];
|
||||
strongSelf->currentSharedAttachment = attachment;
|
||||
|
||||
if (![strongSelf->documentInteractionController presentOptionsMenuFromRect:strongSelf.view.frame inView:strongSelf.view animated:YES])
|
||||
{
|
||||
strongSelf->documentInteractionController = nil;
|
||||
[attachment onShareEnded];
|
||||
strongSelf->currentSharedAttachment = nil;
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
|
||||
// Start animation in case of download during attachment preparing
|
||||
[roomBubbleTableViewCell startProgressUI];
|
||||
}];
|
||||
}
|
||||
|
||||
// Check status of the selected event
|
||||
if (selectedEvent.mxkState == MXKEventStateUploading)
|
||||
{
|
||||
// Upload id is stored in attachment url (nasty trick)
|
||||
NSString *uploadId = roomBubbleTableViewCell.bubbleData.attachment.actualURL;
|
||||
if ([MXKMediaManager existingUploaderWithId:uploadId])
|
||||
{
|
||||
[self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel_upload"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
// Get again the loader
|
||||
MXKMediaLoader *loader = [MXKMediaManager existingUploaderWithId:uploadId];
|
||||
if (loader)
|
||||
{
|
||||
[loader cancel];
|
||||
}
|
||||
// Hide the progress animation
|
||||
roomBubbleTableViewCell.progressView.hidden = YES;
|
||||
|
||||
}];
|
||||
}
|
||||
}
|
||||
else if (selectedEvent.mxkState != MXKEventStateSending && selectedEvent.mxkState != MXKEventStateSendingFailed)
|
||||
{
|
||||
// Check whether download is in progress
|
||||
if (selectedEvent.isMediaAttachment)
|
||||
{
|
||||
NSString *cacheFilePath = roomBubbleTableViewCell.bubbleData.attachment.cacheFilePath;
|
||||
if ([MXKMediaManager existingDownloaderWithOutputFilePath:cacheFilePath])
|
||||
{
|
||||
[self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel_download"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
// Get again the loader
|
||||
MXKMediaLoader *loader = [MXKMediaManager existingDownloaderWithOutputFilePath:cacheFilePath];
|
||||
if (loader)
|
||||
{
|
||||
[loader cancel];
|
||||
}
|
||||
// Hide the progress animation
|
||||
roomBubbleTableViewCell.progressView.hidden = YES;
|
||||
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
[self.currentAlert addActionWithTitle:NSLocalizedStringFromTable(@"redact", @"Vector", nil) style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
[strongSelf startActivityIndicator];
|
||||
|
||||
[strongSelf.roomDataSource.room redactEvent:selectedEvent.eventId reason:nil success:^{
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf stopActivityIndicator];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf stopActivityIndicator];
|
||||
|
||||
NSLog(@"[Vector RoomVC] Redact event (%@) failed: %@", selectedEvent.eventId, error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
self.currentAlert.cancelButtonIndex = [self.currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
|
||||
|
||||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||
[strongSelf cancelEventSelection];
|
||||
|
||||
}];
|
||||
|
||||
// Do not display empty action sheet
|
||||
if (self.currentAlert.cancelButtonIndex)
|
||||
{
|
||||
self.currentAlert.sourceView = roomBubbleTableViewCell;
|
||||
[self.currentAlert showInViewController:self];
|
||||
}
|
||||
else
|
||||
{
|
||||
[tableViewCell unselectComponent];
|
||||
self.currentAlert = nil;
|
||||
}
|
||||
}
|
||||
|
||||
customizedRoomDataSource.selectedEventId = nil;
|
||||
}
|
||||
else if ([actionIdentifier isEqualToString:kMXKRoomBubbleCellLongPressOnEvent])
|
||||
{
|
||||
@@ -468,6 +706,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancelEventSelection
|
||||
{
|
||||
if (self.currentAlert)
|
||||
{
|
||||
[self.currentAlert dismiss:NO];
|
||||
self.currentAlert = nil;
|
||||
}
|
||||
|
||||
// Cancel the current selection
|
||||
NSArray* cellArray = self.bubblesTableView.visibleCells;
|
||||
for (MXKRoomBubbleTableViewCell *tableViewCell in cellArray)
|
||||
{
|
||||
if (tableViewCell.blurred)
|
||||
{
|
||||
tableViewCell.blurred = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
[tableViewCell unselectComponent];
|
||||
}
|
||||
}
|
||||
|
||||
customizedRoomDataSource.selectedEventId = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Segues
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
|
||||
|
||||
Reference in New Issue
Block a user