Merge pull request #4265 from vector-im/voip_jitsi_remover

Voip Jitsi Widget Remover
This commit is contained in:
ismailgulek 2021-05-05 10:39:40 +03:00 committed by GitHub
commit c1e99196b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 818 additions and 145 deletions

View file

@ -11,6 +11,8 @@ Changes to be released in next version
* SettingsVC: Show / hide NSFW and decrypted content options from build settings (#4290).
* RoomVC: Tweaked Scroll to Bottom FAB button (#4272).
* DesignKit: Introduce a new framework to manage design components.
* Add Jitsi widget remove banner for privileged users.
* Update "Jump to unread" banner to a pill style button.
🐛 Bugfix
* RoomVC: Avoid navigation to integration management using integration popup with settings set to integration disabled (#4261).

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 B

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "Close.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Close@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Close@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "Up.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Up@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Up@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "original"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,015 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,23 +1,26 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "cancel.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "cancel@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "cancel@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
}

View file

@ -313,7 +313,8 @@ Tap the + to start adding people.";
"room_member_power_level_short_custom" = "Custom";
// Chat
"room_jump_to_first_unread" = "Jump to first unread message";
"room_slide_to_end_group_call" = "Slide to end the call for everyone";
"room_jump_to_first_unread" = "Jump to unread";
"room_accessiblity_scroll_to_bottom" = "Scroll to bottom";
"room_new_message_notification" = "%d new message";
"room_new_messages_notification" = "%d new messages";

View file

@ -64,4 +64,16 @@ extension UIView {
self.accessibilityTraits.insert(.notEnabled)
}
}
@objc func vc_addShadow(withColor color: UIColor, offset: CGSize, radius: CGFloat, opacity: CGFloat) {
layer.shadowColor = color.cgColor
layer.shadowOpacity = Float(opacity)
layer.shadowRadius = radius
layer.shadowOffset = offset
}
@objc func vc_removeShadow() {
layer.shadowColor = UIColor.clear.cgColor
}
}

View file

@ -105,7 +105,9 @@ internal enum Asset {
internal static let actionSticker = ImageAsset(name: "action_sticker")
internal static let error = ImageAsset(name: "error")
internal static let errorMessageTick = ImageAsset(name: "error_message_tick")
internal static let newClose = ImageAsset(name: "new_close")
internal static let roomActivitiesRetry = ImageAsset(name: "room_activities_retry")
internal static let roomScrollUp = ImageAsset(name: "room_scroll_up")
internal static let scrolldown = ImageAsset(name: "scrolldown")
internal static let scrolldownDark = ImageAsset(name: "scrolldown_dark")
internal static let sendingMessageTick = ImageAsset(name: "sending_message_tick")

View file

@ -2930,7 +2930,7 @@ internal enum VectorL10n {
internal static var roomJoinGroupCall: String {
return VectorL10n.tr("Vector", "room_join_group_call")
}
/// Jump to first unread message
/// Jump to unread
internal static var roomJumpToFirstUnread: String {
return VectorL10n.tr("Vector", "room_jump_to_first_unread")
}
@ -3390,6 +3390,10 @@ internal enum VectorL10n {
internal static var roomResourceUsageLimitReachedMessageContact3: String {
return VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_contact_3")
}
/// Slide to end the call for everyone
internal static var roomSlideToEndGroupCall: String {
return VectorL10n.tr("Vector", "room_slide_to_end_group_call")
}
/// Invite members
internal static var roomTitleInviteMembers: String {
return VectorL10n.tr("Vector", "room_title_invite_members")

View file

@ -165,7 +165,7 @@ class CallPresenter: NSObject {
})
}
if let jitsiVC = jitsiVC, jitsiVC.widget.widgetId == widget.widgetId {
if let jitsiVC = jitsiVC {
if jitsiVC.widget.widgetId == widget.widgetId {
self.presentCallVC(jitsiVC)
} else {
@ -610,7 +610,11 @@ class CallPresenter: NSObject {
return
}
presentCallVC(callVC)
if callVC == pipCallVC {
exitPipCallVC(callVC)
} else {
presentCallVC(callVC)
}
}
@objc
@ -644,7 +648,11 @@ class CallPresenter: NSObject {
return
}
presentCallVC(jitsiVC)
if jitsiVC == pipCallVC {
exitPipCallVC(jitsiVC)
} else {
presentCallVC(jitsiVC)
}
}
// MARK: - Call Screens

View file

@ -94,6 +94,9 @@ import DesignKit
/// Color to tint the search background image
var matrixSearchBackgroundImageTintColor: UIColor { get }
/// Color to use in shadows. Should be contrast to `backgroundColor`.
var shadowColor: UIColor { get }
// MARK: - Customisation methods

View file

@ -155,6 +155,9 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChan
// Define the UISearchBar cancel button color
[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitleTextAttributes:@{ NSForegroundColorAttributeName : self.theme.tintColor } forState: UIControlStateNormal];
[[UIStackView appearanceWhenContainedInInstancesOfClasses:@[[UINavigationBar class]]] setSpacing:-7];
[[UIStackView appearanceWhenContainedInInstancesOfClasses:@[[UINavigationBar class]]] setDistribution:UIStackViewDistributionEqualCentering];
}
@end

View file

@ -88,6 +88,8 @@ class DarkTheme: NSObject, Theme {
var matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E)
var secondaryCircleButtonBackgroundColor: UIColor = UIColor(rgb: 0xE3E8F0)
var shadowColor: UIColor = UIColor(rgb: 0xFFFFFF)
var messageTickColor: UIColor = .white
func applyStyle(onTabBar tabBar: UITabBar) {

View file

@ -98,6 +98,8 @@ class DefaultTheme: NSObject, Theme {
var secondaryCircleButtonBackgroundColor: UIColor = UIColor(rgb: 0xE3E8F0)
var shadowColor: UIColor = UIColor(rgb: 0x000000)
func applyStyle(onTabBar tabBar: UITabBar) {
tabBar.unselectedItemTintColor = self.tabBarUnselectedItemTintColor
tabBar.tintColor = self.tintColor

View file

@ -233,10 +233,15 @@ class DialpadViewController: UIViewController {
theme.applyStyle(onNavigationBar: navigationBar)
}
titleLabel.textColor = theme.noticeSecondaryColor
if theme.identifier == ThemeIdentifier.light.rawValue {
titleLabel.textColor = theme.noticeSecondaryColor
closeButton.setBackgroundImage(Asset.Images.closeButton.image.vc_tintedImage(usingColor: theme.tabBarUnselectedItemTintColor), for: .normal)
} else {
titleLabel.textColor = theme.baseTextSecondaryColor
closeButton.setBackgroundImage(Asset.Images.closeButton.image.vc_tintedImage(usingColor: theme.baseTextSecondaryColor), for: .normal)
}
phoneNumberTextField.textColor = theme.textPrimaryColor
lineView.backgroundColor = theme.lineBreakColor
closeButton.setBackgroundImage(Asset.Images.closeButton.image.vc_tintedImage(usingColor: theme.tabBarUnselectedItemTintColor), for: .normal)
updateThemesOfAllButtons(in: digitsStackView, with: theme)
}

View file

@ -31,9 +31,9 @@ class DialpadActionButton: DialpadButton {
switch type {
case .backspace:
backgroundColor = .clear
tintColor = theme.noticeSecondaryColor
tintColor = theme.colors.tertiaryContent
case .call:
backgroundColor = theme.tintColor
backgroundColor = theme.colors.accent
tintColor = .white
}
}

View file

@ -47,16 +47,18 @@ extern NSNotificationName const RoomGroupCallTileTappedNotification;
// The jump to last unread banner
@property (weak, nonatomic) IBOutlet UIView *jumpToLastUnreadBannerContainer;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *jumpToLastUnreadBannerContainerTopConstraint;
@property (weak, nonatomic) IBOutlet UIView *jumpToLastUnreadBanner;
@property (weak, nonatomic) IBOutlet UIImageView *jumpToLastUnreadImageView;
@property (weak, nonatomic) IBOutlet UIButton *jumpToLastUnreadButton;
@property (weak, nonatomic) IBOutlet UILabel *jumpToLastUnreadLabel;
@property (weak, nonatomic) IBOutlet UIButton *resetReadMarkerButton;
@property (weak, nonatomic) IBOutlet UIView *jumpToLastUnreadBannerSeparatorView;
@property (weak, nonatomic) IBOutlet UIView *inputBackgroundView;
@property (weak, nonatomic) IBOutlet UIButton *scrollToBottomButton;
@property (weak, nonatomic) IBOutlet BadgeLabel *scrollToBottomBadgeLabel;
// Remove Jitsi widget container
@property (weak, nonatomic) IBOutlet UIView *removeJitsiWidgetContainer;
/**
Preview data for a room invitation received by email, or a link to a room.
*/

View file

@ -135,7 +135,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
@interface RoomViewController () <UISearchBarDelegate, UIGestureRecognizerDelegate, UIScrollViewAccessibilityDelegate, RoomTitleViewTapGestureDelegate, RoomParticipantsViewControllerDelegate, MXKRoomMemberDetailsViewControllerDelegate, ContactsTableViewControllerDelegate, MXServerNoticesDelegate, RoomContextualMenuViewControllerDelegate,
ReactionsMenuViewModelCoordinatorDelegate, EditHistoryCoordinatorBridgePresenterDelegate, MXKDocumentPickerPresenterDelegate, EmojiPickerCoordinatorBridgePresenterDelegate,
ReactionHistoryCoordinatorBridgePresenterDelegate, CameraPresenterDelegate, MediaPickerCoordinatorBridgePresenterDelegate,
RoomDataSourceDelegate, RoomCreationModalCoordinatorBridgePresenterDelegate, RoomInfoCoordinatorBridgePresenterDelegate, DialpadViewControllerDelegate>
RoomDataSourceDelegate, RoomCreationModalCoordinatorBridgePresenterDelegate, RoomInfoCoordinatorBridgePresenterDelegate, DialpadViewControllerDelegate, RemoveJitsiWidgetViewDelegate>
{
// The preview header
@ -220,6 +220,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
@property (nonatomic, weak) IBOutlet UIView *overlayContainerView;
@property (nonatomic, strong) RemoveJitsiWidgetView *removeJitsiWidgetView;
@property (nonatomic, strong) RoomContextualMenuViewController *roomContextualMenuViewController;
@ -387,6 +388,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self vc_removeBackTitle];
[self setupRemoveJitsiWidgetRemoveView];
// Replace the default input toolbar view.
// Note: this operation will force the layout of subviews. That is why cell view classes must be registered before.
[self updateRoomInputToolbarViewClassIfNeeded];
@ -455,11 +458,11 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor;
[self.removeJitsiWidgetView updateWithTheme:ThemeService.shared.theme];
// Prepare jump to last unread banner
self.jumpToLastUnreadBannerContainer.backgroundColor = ThemeService.shared.theme.backgroundColor;
self.jumpToLastUnreadImageView.tintColor = ThemeService.shared.theme.textPrimaryColor;
self.jumpToLastUnreadImageView.tintColor = ThemeService.shared.theme.tintColor;
self.jumpToLastUnreadLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
self.jumpToLastUnreadBannerSeparatorView.backgroundColor = ThemeService.shared.theme.lineBreakColor;
self.previewHeaderContainer.backgroundColor = ThemeService.shared.theme.headerBackgroundColor;
@ -473,23 +476,31 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self.bubblesTableView reloadData];
}
self.scrollToBottomButton.layer.shadowColor = [UIColor blackColor].CGColor;
self.scrollToBottomButton.layer.shadowOpacity = 0.2;
self.scrollToBottomButton.layer.shadowRadius = 6;
self.scrollToBottomButton.layer.shadowOffset = CGSizeMake(0, 4);
[self.scrollToBottomButton vc_addShadowWithColor:ThemeService.shared.theme.shadowColor
offset:CGSizeMake(0, 4)
radius:6
opacity:0.2];
self.inputBackgroundView.backgroundColor = [ThemeService.shared.theme.backgroundColor colorWithAlphaComponent:0.98];
if ([ThemeService.shared.themeId isEqualToString:@"light"])
if (ThemeService.shared.isCurrentThemeDark)
{
[self.scrollToBottomButton setImage:[UIImage imageNamed:@"scrolldown_dark"] forState:UIControlStateNormal];
self.jumpToLastUnreadBanner.backgroundColor = ThemeService.shared.theme.colors.navigation;
[self.jumpToLastUnreadBanner vc_removeShadow];
self.resetReadMarkerButton.tintColor = ThemeService.shared.theme.colors.quarterlyContent;
}
else
{
[self.scrollToBottomButton setImage:[UIImage imageNamed:@"scrolldown"] forState:UIControlStateNormal];
}
else if ([ThemeService.shared.themeId isEqualToString:@"dark"] || [ThemeService.shared.themeId isEqualToString:@"black"])
{
[self.scrollToBottomButton setImage:[UIImage imageNamed:@"scrolldown_dark"] forState:UIControlStateNormal];
}
else if (@available(iOS 12.0, *) && ThemeService.shared.theme.userInterfaceStyle == UIUserInterfaceStyleDark) {
[self.scrollToBottomButton setImage:[UIImage imageNamed:@"scrolldown_dark"] forState:UIControlStateNormal];
self.jumpToLastUnreadBanner.backgroundColor = ThemeService.shared.theme.colors.background;
[self.jumpToLastUnreadBanner vc_addShadowWithColor:ThemeService.shared.theme.shadowColor
offset:CGSizeMake(0, 4)
radius:8
opacity:0.1];
self.resetReadMarkerButton.tintColor = ThemeService.shared.theme.colors.tertiaryContent;
}
self.scrollToBottomBadgeLabel.badgeColor = ThemeService.shared.theme.tintColor;
@ -518,6 +529,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Refresh the room title view
[self refreshRoomTitle];
// refresh remove Jitsi widget view
[self refreshRemoveJitsiWidgetView];
// Refresh tool bar if the room data source is set.
if (self.roomDataSource)
{
@ -732,15 +746,12 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
self.previewHeaderContainerHeightConstraint.constant = frame.origin.y + frame.size.height;
self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.mxk_adjustedContentInset.top;
self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant;
}
else
{
// In non expanded header mode, the navigation bar is opaque
// The table view must not display behind it
self.edgesForExtendedLayout = UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight;
self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.bubblesTableView.mxk_adjustedContentInset.top; // no expanded
}
// stay at the bottom if already was
@ -1396,6 +1407,29 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
#pragma mark - Internals
- (UIBarButtonItem *)videoCallBarButtonItem
{
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"video_call"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(onVideoCallPressed:)];
item.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_video_call", @"Vector", nil);
return item;
}
- (void)setupRemoveJitsiWidgetRemoveView
{
self.removeJitsiWidgetView = [RemoveJitsiWidgetView instantiate];
self.removeJitsiWidgetView.delegate = self;
[self.removeJitsiWidgetContainer vc_addSubViewMatchingParent:self.removeJitsiWidgetView];
self.removeJitsiWidgetContainer.hidden = YES;
[self refreshRemoveJitsiWidgetView];
}
- (void)forceLayoutRefresh
{
// Sanity check: check whether the table view data source is set.
@ -1467,70 +1501,84 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
if (self.roomDataSource.isLive)
{
rightBarButtonItems = [NSMutableArray new];
BOOL hasCustomJoinButton = NO;
UIEdgeInsets itemInsets = UIEdgeInsetsMake(0, -5, 0, 5);
if (self.supportCallOption)
{
if (self.roomDataSource.room.summary.membersCount.joined == 2 && self.roomDataSource.room.isDirect)
{
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"voice_call_hangon_icon"] style:UIBarButtonItemStylePlain target:self action:@selector(onVoiceCallPressed:)];
item.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_call", @"Vector", nil);
item.imageInsets = UIEdgeInsetsMake(0, -5, 0, 5);
item.enabled = !self.isCallActive;
[rightBarButtonItems addObject:item];
}
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"video_call"] style:UIBarButtonItemStylePlain target:self action:@selector(onVideoCallPressed:)];
item.imageInsets = rightBarButtonItems.count ? UIEdgeInsetsMake(0, 10, 0, -10) : itemInsets;
item.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_video_call", @"Vector", nil);
if (self.roomDataSource.room.summary.membersCount.joined == 2 && self.roomDataSource.room.isDirect)
{
// Matrix call
item.enabled = !self.isCallActive;
// voice call button for Matrix call
UIBarButtonItem *itemVoice = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"voice_call_hangon_icon"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(onVoiceCallPressed:)];
itemVoice.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_call", @"Vector", nil);
itemVoice.enabled = !self.isCallActive;
[rightBarButtonItems addObject:itemVoice];
// video call button for Matrix call
UIBarButtonItem *itemVideo = [self videoCallBarButtonItem];
itemVideo.enabled = !self.isCallActive;
[rightBarButtonItems addObject:itemVideo];
}
else
{
// Jitsi call
// video call button for Jitsi call
if (self.isCallActive)
{
JitsiViewController *jitsiVC = [AppDelegate theDelegate].callPresenter.jitsiVC;
if ([jitsiVC.widget.roomId isEqualToString:self.roomDataSource.roomId])
{
// show a disabled call button
UIBarButtonItem *item = [self videoCallBarButtonItem];
item.enabled = NO;
[rightBarButtonItems addObject:item];
}
else
{
// show Join button
CallTileActionButton *button = [CallTileActionButton new];
[button setImage:[UIImage imageNamed:@"call_video_icon"] forState:UIControlStateNormal];
[button setTitle:NSLocalizedStringFromTable(@"room_join_group_call", @"Vector", nil) forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"call_video_icon"]
forState:UIControlStateNormal];
[button setTitle:NSLocalizedStringFromTable(@"room_join_group_call", @"Vector", nil)
forState:UIControlStateNormal];
[button addTarget:self
action:@selector(onVideoCallPressed:)
forControlEvents:UIControlEventTouchUpInside];
button.contentEdgeInsets = UIEdgeInsetsMake(4, 12, 4, 12);
item.customView = button;
item.enabled = YES;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:button];
item.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_video_call", @"Vector", nil);
[rightBarButtonItems addObject:item];
hasCustomJoinButton = YES;
}
}
else
{
// show a video call button
// item will still be enabled, and when tapped an alert will be displayed to the user
UIBarButtonItem *item = [self videoCallBarButtonItem];
if (!self.canEditJitsiWidget)
{
item.image = [[UIImage imageNamed:@"video_call"] vc_withAlpha:0.3];
}
// item will still be enabled, and when tapped an alert will be displayed to the user
item.enabled = YES;
[rightBarButtonItems addObject:item];
}
}
[rightBarButtonItems addObject:item];
itemInsets = UIEdgeInsetsMake(0, 20, 0, -20);
}
if ([self widgetsCount:NO])
{
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"integrations_icon"] style:UIBarButtonItemStylePlain target:self action:@selector(onIntegrationsPressed:)];
item.imageInsets = itemInsets;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"integrations_icon"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(onIntegrationsPressed:)];
item.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_integrations", @"Vector", nil);
if (hasCustomJoinButton)
{
item.imageInsets = UIEdgeInsetsMake(0, -5, 0, -5);
item.landscapeImagePhoneInsets = UIEdgeInsetsMake(0, -5, 0, -5);
}
[rightBarButtonItems addObject:item];
}
@ -2075,7 +2123,6 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
animations:^{
self.bubblesTableViewTopConstraint.constant = 0;
self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.bubblesTableView.mxk_adjustedContentInset.top;
// Force to render the view
[self forceLayoutRefresh];
@ -2194,7 +2241,6 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
animations:^{
self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.mxk_adjustedContentInset.top;
self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant;
previewHeader.roomAvatar.alpha = 1;
@ -4431,17 +4477,20 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
- (void)listenWidgetNotifications
{
MXWeakify(self);
kMXKWidgetManagerDidUpdateWidgetObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kWidgetManagerDidUpdateWidgetNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
Widget *widget = notif.object;
if (widget.mxSession == self.roomDataSource.mxSession
&& [widget.roomId isEqualToString:customizedRoomDataSource.roomId])
&& [widget.roomId isEqualToString:self->customizedRoomDataSource.roomId])
{
// Jitsi conference widget existence is shown in the bottom bar
// Update the bar
[self refreshActivitiesViewDisplay];
[self refreshRoomInputToolbar];
// Call button update
[self refreshRoomTitle];
// Remove Jitsi widget view update
[self refreshRemoveJitsiWidgetView];
}
}];
}
@ -4489,8 +4538,6 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[roomActivitiesView removeGestureRecognizer:roomActivitiesView.gestureRecognizers[0]];
}
Widget *jitsiWidget = [customizedRoomDataSource jitsiWidget];
if ([self.roomDataSource.mxSession.syncError.errcode isEqualToString:kMXErrCodeStringResourceLimitExceeded])
{
self.activitiesViewExpanded = YES;
@ -5092,6 +5139,32 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
}
- (void)refreshRemoveJitsiWidgetView
{
if (self.roomDataSource.isLive && !self.roomDataSource.isPeeking)
{
Widget *jitsiWidget = [customizedRoomDataSource jitsiWidget];
if (jitsiWidget && self.canEditJitsiWidget)
{
[self.removeJitsiWidgetView reset];
self.removeJitsiWidgetContainer.hidden = NO;
self.removeJitsiWidgetView.delegate = self;
}
else
{
self.removeJitsiWidgetContainer.hidden = YES;
self.removeJitsiWidgetView.delegate = nil;
}
}
else
{
[self.removeJitsiWidgetView reset];
self.removeJitsiWidgetContainer.hidden = YES;
self.removeJitsiWidgetView.delegate = self;
}
}
- (void)refreshJumpToLastUnreadBannerDisplay
{
// This banner is only displayed when the room timeline is in live (and no peeking).
@ -6050,4 +6123,37 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
self.roomInfoCoordinatorBridgePresenter = nil;
}
#pragma mark - RemoveJitsiWidgetViewDelegate
- (void)removeJitsiWidgetViewDidCompleteSliding:(RemoveJitsiWidgetView *)view
{
view.delegate = nil;
Widget *jitsiWidget = [customizedRoomDataSource jitsiWidget];
[self startActivityIndicator];
// close the widget
MXWeakify(self);
[[WidgetManager sharedManager] closeWidget:jitsiWidget.widgetId
inRoom:self.roomDataSource.room
success:^{
MXStrongifyAndReturnIfNil(self);
[self stopActivityIndicator];
// we can wait for kWidgetManagerDidUpdateWidgetNotification, but we want to be faster
self.removeJitsiWidgetContainer.hidden = YES;
self.removeJitsiWidgetView.delegate = nil;
// end active call if exists
if ([[AppDelegate theDelegate].callPresenter.jitsiVC.widget.widgetId isEqualToString:jitsiWidget.widgetId])
{
[[AppDelegate theDelegate].callPresenter endActiveJitsiCall];
}
} failure:^(NSError *error) {
MXStrongifyAndReturnIfNil(self);
[self showJitsiErrorAsAlert:error];
[self stopActivityIndicator];
}];
}
@end

View file

@ -15,15 +15,15 @@
<outlet property="bubblesTableViewBottomConstraint" destination="1SD-y2-oTg" id="n8D-hT-eqt"/>
<outlet property="bubblesTableViewTopConstraint" destination="bFw-dg-qEr" id="KxM-H0-h2y"/>
<outlet property="inputBackgroundView" destination="Xt7-83-dQh" id="xoG-eb-zFB"/>
<outlet property="jumpToLastUnreadBannerContainer" destination="S6r-bo-jxw" id="Ady-Eh-4E0"/>
<outlet property="jumpToLastUnreadBannerContainerTopConstraint" destination="5eM-eJ-khq" id="b1J-aM-ZcT"/>
<outlet property="jumpToLastUnreadBannerSeparatorView" destination="knN-q1-QkJ" id="hHJ-c8-QfN"/>
<outlet property="jumpToLastUnreadButton" destination="ISb-UT-u0O" id="fs0-sQ-lRe"/>
<outlet property="jumpToLastUnreadImageView" destination="Vlz-UJ-Jz8" id="8iM-Go-SqC"/>
<outlet property="jumpToLastUnreadBanner" destination="S6r-bo-jxw" id="FSS-Be-E15"/>
<outlet property="jumpToLastUnreadBannerContainer" destination="S6H-Az-RCM" id="YlI-fu-OpT"/>
<outlet property="jumpToLastUnreadButton" destination="1bj-1n-LgM" id="vB7-oE-h7O"/>
<outlet property="jumpToLastUnreadImageView" destination="Vlz-UJ-Jz8" id="r53-4l-Ld7"/>
<outlet property="jumpToLastUnreadLabel" destination="S1q-B4-Df3" id="McV-gv-bUa"/>
<outlet property="overlayContainerView" destination="gt1-EO-UVY" id="5q6-pW-UyZ"/>
<outlet property="previewHeaderContainer" destination="54r-18-K1g" id="Klt-RV-V1E"/>
<outlet property="previewHeaderContainerHeightConstraint" destination="goj-GZ-IkD" id="GbA-T9-kiL"/>
<outlet property="removeJitsiWidgetContainer" destination="hB3-nR-MVR" id="Fbu-c2-Qys"/>
<outlet property="resetReadMarkerButton" destination="c4g-BY-xOo" id="KuR-hH-rz1"/>
<outlet property="roomActivitiesContainer" destination="XX4-n6-hCm" id="uD0-ab-8s8"/>
<outlet property="roomActivitiesContainerHeightConstraint" destination="E8v-l2-8eV" id="ebD-oV-ttx"/>
@ -55,76 +55,86 @@
<constraint firstAttribute="height" constant="368" id="goj-GZ-IkD"/>
</constraints>
</view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="S6r-bo-jxw">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="fmF-ad-erE">
<rect key="frame" x="0.0" y="0.0" width="375" height="0.0"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ISb-UT-u0O">
<rect key="frame" x="5" y="0.0" width="51" height="44"/>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hB3-nR-MVR">
<rect key="frame" x="0.0" y="0.0" width="375" height="54"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="XgY-bC-cpU"/>
<constraint firstAttribute="height" constant="54" id="QJx-Yo-mCC"/>
</constraints>
<connections>
<action selector="onButtonPressed:" destination="-1" eventType="touchUpInside" id="7pe-19-Zxc"/>
</connections>
</button>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="scrollup" translatesAutoresizingMaskIntoConstraints="NO" id="Vlz-UJ-Jz8">
<rect key="frame" x="13" y="7" width="30" height="30"/>
</view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="S6H-Az-RCM">
<rect key="frame" x="0.0" y="0.0" width="375" height="76"/>
<subviews>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="S6r-bo-jxw">
<rect key="frame" x="93" y="16" width="189.5" height="44"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="room_scroll_up" translatesAutoresizingMaskIntoConstraints="NO" id="Vlz-UJ-Jz8">
<rect key="frame" x="14" y="10" width="24" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="24" id="JCI-mP-w3F"/>
<constraint firstAttribute="width" secondItem="Vlz-UJ-Jz8" secondAttribute="height" multiplier="1:1" id="gEk-9p-KUO"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Jump to unread" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="S1q-B4-Df3">
<rect key="frame" x="42" y="13" width="107.5" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1bj-1n-LgM">
<rect key="frame" x="0.0" y="0.0" width="143.5" height="44"/>
<connections>
<action selector="onButtonPressed:" destination="-1" eventType="touchUpInside" id="bNQ-wp-3le"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="c4g-BY-xOo">
<rect key="frame" x="143.5" y="0.0" width="44" height="44"/>
<constraints>
<constraint firstAttribute="width" constant="44" id="2YD-H9-DyP"/>
<constraint firstAttribute="width" secondItem="c4g-BY-xOo" secondAttribute="height" multiplier="1:1" id="DG6-tf-YUj"/>
</constraints>
<inset key="imageEdgeInsets" minX="14" minY="14" maxX="14" maxY="14"/>
<state key="normal" image="new_close"/>
<connections>
<action selector="onButtonPressed:" destination="-1" eventType="touchUpInside" id="8by-6v-ZGR"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" systemColor="systemGray6Color"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="1bj-1n-LgM" secondAttribute="bottom" id="06E-yF-opV"/>
<constraint firstAttribute="height" constant="44" id="7TA-9m-DJm"/>
<constraint firstItem="S1q-B4-Df3" firstAttribute="leading" secondItem="Vlz-UJ-Jz8" secondAttribute="trailing" constant="4" id="Aer-yt-Ipv"/>
<constraint firstItem="c4g-BY-xOo" firstAttribute="leading" secondItem="S1q-B4-Df3" secondAttribute="trailing" constant="-6" id="Iqm-Q5-jWz"/>
<constraint firstItem="Vlz-UJ-Jz8" firstAttribute="centerY" secondItem="S6r-bo-jxw" secondAttribute="centerY" id="Oyl-YW-LyY"/>
<constraint firstAttribute="trailing" secondItem="1bj-1n-LgM" secondAttribute="trailing" constant="46" id="SbE-4d-jky"/>
<constraint firstItem="S1q-B4-Df3" firstAttribute="centerY" secondItem="S6r-bo-jxw" secondAttribute="centerY" id="YEJ-zl-raJ"/>
<constraint firstItem="1bj-1n-LgM" firstAttribute="leading" secondItem="S6r-bo-jxw" secondAttribute="leading" id="ZEh-qn-hpl"/>
<constraint firstAttribute="trailing" secondItem="c4g-BY-xOo" secondAttribute="trailing" constant="2" id="f9h-zF-Kj7"/>
<constraint firstItem="1bj-1n-LgM" firstAttribute="top" secondItem="S6r-bo-jxw" secondAttribute="top" id="g2R-SU-q9s"/>
<constraint firstItem="c4g-BY-xOo" firstAttribute="centerY" secondItem="S6r-bo-jxw" secondAttribute="centerY" id="q7f-Lx-2kO"/>
<constraint firstItem="Vlz-UJ-Jz8" firstAttribute="leading" secondItem="S6r-bo-jxw" secondAttribute="leading" constant="14" id="rya-xy-hDd"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="22"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="JCI-mP-w3F"/>
<constraint firstAttribute="width" secondItem="Vlz-UJ-Jz8" secondAttribute="height" multiplier="1:1" id="gEk-9p-KUO"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="S1q-B4-Df3">
<rect key="frame" x="56" y="22" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="c4g-BY-xOo">
<rect key="frame" x="335" y="0.0" width="44" height="44"/>
<constraints>
<constraint firstAttribute="width" constant="44" id="2YD-H9-DyP"/>
<constraint firstAttribute="width" secondItem="c4g-BY-xOo" secondAttribute="height" multiplier="1:1" id="DG6-tf-YUj"/>
</constraints>
<connections>
<action selector="onButtonPressed:" destination="-1" eventType="touchUpInside" id="8by-6v-ZGR"/>
</connections>
</button>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="cancel" translatesAutoresizingMaskIntoConstraints="NO" id="TYG-1i-OrY">
<rect key="frame" x="347" y="12" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="20" id="2Nx-YU-skd"/>
<constraint firstAttribute="width" secondItem="TYG-1i-OrY" secondAttribute="height" multiplier="1:1" id="jBy-Ex-gBc"/>
</constraints>
</imageView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="knN-q1-QkJ" userLabel="Separator View">
<rect key="frame" x="0.0" y="43" width="375" height="1"/>
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="1" id="8k7-fr-b8R"/>
<constraint firstAttribute="height" constant="1" id="G1Q-g6-4kp"/>
<constraint firstItem="S6r-bo-jxw" firstAttribute="centerX" secondItem="S6H-Az-RCM" secondAttribute="centerX" id="2eL-aC-qst"/>
<constraint firstItem="S6r-bo-jxw" firstAttribute="centerY" secondItem="S6H-Az-RCM" secondAttribute="centerY" id="Bdj-uB-YN7"/>
<constraint firstAttribute="height" constant="76" id="YE8-fe-fJ9"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="7TA-9m-DJm"/>
<constraint firstItem="ISb-UT-u0O" firstAttribute="trailing" secondItem="S1q-B4-Df3" secondAttribute="trailing" id="ABS-rW-2Up"/>
<constraint firstItem="knN-q1-QkJ" firstAttribute="leading" secondItem="S6r-bo-jxw" secondAttribute="leading" id="DL5-gC-Y2y"/>
<constraint firstAttribute="bottom" secondItem="knN-q1-QkJ" secondAttribute="bottom" id="HrB-BI-pbX"/>
<constraint firstItem="Vlz-UJ-Jz8" firstAttribute="centerY" secondItem="S6r-bo-jxw" secondAttribute="centerY" id="Oyl-YW-LyY"/>
<constraint firstItem="c4g-BY-xOo" firstAttribute="centerY" secondItem="TYG-1i-OrY" secondAttribute="centerY" id="PY6-yg-tuv"/>
<constraint firstAttribute="trailing" secondItem="knN-q1-QkJ" secondAttribute="trailing" id="RFO-8F-wd7"/>
<constraint firstItem="S1q-B4-Df3" firstAttribute="centerY" secondItem="S6r-bo-jxw" secondAttribute="centerY" id="YEJ-zl-raJ"/>
<constraint firstItem="ISb-UT-u0O" firstAttribute="leading" secondItem="S6r-bo-jxw" secondAttribute="leading" constant="5" id="Znj-wf-lOm"/>
<constraint firstAttribute="trailing" secondItem="TYG-1i-OrY" secondAttribute="trailing" constant="8" id="bcg-1X-Ujo"/>
<constraint firstItem="TYG-1i-OrY" firstAttribute="centerY" secondItem="S6r-bo-jxw" secondAttribute="centerY" id="dr9-xy-Nhj"/>
<constraint firstItem="Vlz-UJ-Jz8" firstAttribute="leading" secondItem="S6r-bo-jxw" secondAttribute="leading" constant="13" id="rya-xy-hDd"/>
<constraint firstItem="S1q-B4-Df3" firstAttribute="leading" secondItem="S6r-bo-jxw" secondAttribute="leading" constant="56" id="t7w-84-xaw"/>
<constraint firstItem="c4g-BY-xOo" firstAttribute="centerX" secondItem="TYG-1i-OrY" secondAttribute="centerX" id="tXP-dn-3bC"/>
<constraint firstItem="ISb-UT-u0O" firstAttribute="centerY" secondItem="Vlz-UJ-Jz8" secondAttribute="centerY" id="w7t-WC-VjP"/>
</constraints>
</view>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
<button opaque="NO" alpha="0.0" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ih9-EU-BOU" userLabel="scroll Button">
<rect key="frame" x="327" y="570" width="32" height="32"/>
<state key="normal" image="scrolldown"/>
@ -168,16 +178,16 @@
<accessibility key="accessibilityConfiguration" identifier="RoomVCView"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="BGD-sd-SQR" secondAttribute="bottom" constant="41" id="1SD-y2-oTg"/>
<constraint firstItem="S6r-bo-jxw" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="5eM-eJ-khq"/>
<constraint firstItem="Xt7-83-dQh" firstAttribute="leading" secondItem="QpJ-1u-4ii" secondAttribute="leading" id="6lr-Tx-pEb"/>
<constraint firstItem="QpJ-1u-4ii" firstAttribute="trailing" secondItem="Ih9-EU-BOU" secondAttribute="trailing" constant="16" id="6rq-lR-0sB"/>
<constraint firstItem="54r-18-K1g" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="7Ft-EV-Br0"/>
<constraint firstItem="gt1-EO-UVY" firstAttribute="leading" secondItem="QpJ-1u-4ii" secondAttribute="leading" id="8Ff-Ot-h3F"/>
<constraint firstItem="Xt7-83-dQh" firstAttribute="bottom" secondItem="iN0-l3-epB" secondAttribute="bottom" id="9g2-wm-4M9"/>
<constraint firstItem="S6r-bo-jxw" firstAttribute="leading" secondItem="QpJ-1u-4ii" secondAttribute="leading" id="Bcq-e4-B0D"/>
<constraint firstItem="fmF-ad-erE" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="DtG-PR-F24"/>
<constraint firstItem="BGD-sd-SQR" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="ECb-mP-EOG"/>
<constraint firstAttribute="trailing" secondItem="BGD-sd-SQR" secondAttribute="trailing" id="EGD-cX-OGq"/>
<constraint firstItem="XX4-n6-hCm" firstAttribute="top" secondItem="Ih9-EU-BOU" secondAttribute="bottom" constant="24" id="GUp-ZU-6h3"/>
<constraint firstAttribute="trailing" secondItem="fmF-ad-erE" secondAttribute="trailing" id="JnG-B8-qQf"/>
<constraint firstItem="QHs-rM-UU8" firstAttribute="centerX" secondItem="Ih9-EU-BOU" secondAttribute="centerX" id="K8X-wJ-hkh"/>
<constraint firstItem="QHs-rM-UU8" firstAttribute="centerY" secondItem="Ih9-EU-BOU" secondAttribute="top" id="KL4-OU-cP6"/>
<constraint firstItem="gt1-EO-UVY" firstAttribute="trailing" secondItem="QpJ-1u-4ii" secondAttribute="trailing" id="L9A-P5-xeT"/>
@ -185,13 +195,13 @@
<constraint firstItem="XX4-n6-hCm" firstAttribute="bottom" secondItem="nLd-BP-JAE" secondAttribute="top" id="QO8-nF-xys"/>
<constraint firstItem="nLd-BP-JAE" firstAttribute="leading" secondItem="QpJ-1u-4ii" secondAttribute="leading" id="T1Y-r9-bYV"/>
<constraint firstItem="XX4-n6-hCm" firstAttribute="trailing" secondItem="QpJ-1u-4ii" secondAttribute="trailing" id="Tij-mR-KZp"/>
<constraint firstItem="S6r-bo-jxw" firstAttribute="trailing" secondItem="QpJ-1u-4ii" secondAttribute="trailing" id="VVn-vW-lbm"/>
<constraint firstItem="gt1-EO-UVY" firstAttribute="top" secondItem="QpJ-1u-4ii" secondAttribute="top" id="YfN-0Z-0bc"/>
<constraint firstItem="54r-18-K1g" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="aR5-rp-1Cp"/>
<constraint firstItem="gt1-EO-UVY" firstAttribute="bottom" secondItem="nLd-BP-JAE" secondAttribute="bottom" id="acJ-g8-R7x"/>
<constraint firstItem="BGD-sd-SQR" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="bFw-dg-qEr"/>
<constraint firstAttribute="bottom" secondItem="nLd-BP-JAE" secondAttribute="bottom" id="omU-sm-3bK"/>
<constraint firstItem="nLd-BP-JAE" firstAttribute="trailing" secondItem="QpJ-1u-4ii" secondAttribute="trailing" id="pRw-S0-6WL"/>
<constraint firstItem="fmF-ad-erE" firstAttribute="top" secondItem="QpJ-1u-4ii" secondAttribute="top" id="qYq-nb-cu5"/>
<constraint firstItem="Xt7-83-dQh" firstAttribute="trailing" secondItem="QpJ-1u-4ii" secondAttribute="trailing" id="tAK-09-gTA"/>
<constraint firstAttribute="trailing" secondItem="54r-18-K1g" secondAttribute="trailing" id="wOi-Ih-yfq"/>
<constraint firstItem="Xt7-83-dQh" firstAttribute="top" secondItem="XX4-n6-hCm" secondAttribute="top" id="xHx-En-Ppf"/>
@ -206,11 +216,14 @@
</designable>
</designables>
<resources>
<image name="cancel" width="20" height="20"/>
<image name="new_close" width="16" height="16"/>
<image name="room_scroll_up" width="24" height="24"/>
<image name="scrolldown" width="32" height="32"/>
<image name="scrollup" width="30" height="30"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemGray6Color">
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>

View file

@ -2156,6 +2156,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
UITableViewHeaderFooterView *tableViewHeaderFooterView = (UITableViewHeaderFooterView*)view;
tableViewHeaderFooterView.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
tableViewHeaderFooterView.textLabel.font = [UIFont systemFontOfSize:15];
tableViewHeaderFooterView.contentView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor;
}
}

View file

@ -103,7 +103,7 @@ extension CallBubbleCellBaseContentView: Themable {
paginationLabel.textColor = theme.tintColor
paginationSeparatorView.backgroundColor = theme.tintColor
bgView.backgroundColor = theme.headerBackgroundColor
bgView.backgroundColor = theme.colors.tile
callerNameLabel.textColor = theme.textPrimaryColor
callIconView.tintColor = theme.textTertiaryColor
callTypeLabel.textColor = theme.textSecondaryColor

View file

@ -0,0 +1,114 @@
//
// Copyright 2021 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 ArrowsAnimationView: UIView {
private enum Constants {
static let numberOfArrows: Int = 3
static let arrowSize: CGSize = CGSize(width: 14, height: 14)
static let gradientAnimationKey: String = "gradient"
static let gradientRatios: [CGFloat] = [1.0, 0.3, 0.2]
}
private var gradientLayer: CAGradientLayer!
private lazy var gradientAnimation: CABasicAnimation = {
let animation = CABasicAnimation(keyPath: "locations")
animation.fromValue = [0.0, 0.0, 0.25]
animation.toValue = [0.75, 1.0, 1.0]
animation.repeatCount = .infinity
animation.duration = 1
return animation
}()
private var theme: Theme = ThemeService.shared().theme
private var arrowImageViews: [UIImageView] = []
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
private func setup() {
let arrowImage = Asset.Images.disclosureIcon.image
for i in 0..<Constants.numberOfArrows {
let totalSpace = frame.width - CGFloat(Constants.numberOfArrows) * Constants.arrowSize.width
let oneSpace = totalSpace / CGFloat(Constants.numberOfArrows - 1)
let x = CGFloat(i) * (oneSpace + Constants.arrowSize.width)
let y = (frame.height - Constants.arrowSize.height) / 2
let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: x, y: y),
size: Constants.arrowSize))
imageView.contentMode = .scaleAspectFit
imageView.tintColor = theme.tabBarUnselectedItemTintColor
imageView.image = arrowImage
addSubview(imageView)
arrowImageViews.append(imageView)
}
gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.locations = [0.25, 0.5, 0.75]
gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
// this color doesn't have to come from the theme, it's only used as a mask
let color = UIColor.black
let colors = Constants.gradientRatios.map({ color.withAlphaComponent($0) })
gradientLayer.colors = colors.map({ $0.cgColor })
layer.mask = gradientLayer
}
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer.frame = bounds
}
// MARK: - API
var isAnimating: Bool = false {
didSet {
if isAnimating {
if gradientLayer.animation(forKey: Constants.gradientAnimationKey) == nil {
gradientLayer.add(gradientAnimation,
forKey: Constants.gradientAnimationKey)
}
} else {
if gradientLayer.animation(forKey: Constants.gradientAnimationKey) != nil {
gradientLayer.removeAnimation(forKey: Constants.gradientAnimationKey)
}
}
}
}
}
// MARK: - Themable
extension ArrowsAnimationView: Themable {
func update(theme: Theme) {
self.theme = theme
arrowImageViews.forEach({ $0.tintColor = theme.tabBarUnselectedItemTintColor })
}
}

View file

@ -0,0 +1,194 @@
//
// Copyright 2021 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
import Reusable
@objcMembers
class RemoveJitsiWidgetView: UIView {
private enum Constants {
static let activationThreshold: CGFloat = 0.5
}
private enum State: Equatable {
case notStarted
case sliding(percentage: CGFloat)
case completed
static func == (lhs: State, rhs: State) -> Bool {
switch (lhs, rhs) {
case (.notStarted, .notStarted):
return true
case (let .sliding(percentage1), let .sliding(percentage2)):
return percentage1 == percentage2
case (.completed, .completed):
return true
default:
return false
}
}
}
@IBOutlet private weak var slidingViewLeadingConstraint: NSLayoutConstraint!
@IBOutlet private weak var slidingView: UIView!
@IBOutlet private weak var slidingViewLabel: UILabel! {
didSet {
slidingViewLabel.text = VectorL10n.roomSlideToEndGroupCall
}
}
@IBOutlet private weak var arrowsView: ArrowsAnimationView!
@IBOutlet private weak var hangupView: UIView!
@IBOutlet private weak var hangupImage: UIImageView!
@IBOutlet private weak var topSeparatorView: UIView!
@IBOutlet private weak var bottomSeparatorView: UIView!
private var state: State = .notStarted
private var theme: Theme = ThemeService.shared().theme
// MARK - Private
private func configure(withState state: State) {
switch state {
case .notStarted:
arrowsView.isAnimating = false
hangupView.backgroundColor = .clear
hangupImage.tintColor = theme.noticeColor
slidingViewLeadingConstraint.constant = 0
case .sliding(let percentage):
arrowsView.isAnimating = true
if percentage < Constants.activationThreshold {
hangupView.backgroundColor = .clear
hangupImage.tintColor = theme.noticeColor
} else {
hangupView.backgroundColor = theme.noticeColor
hangupImage.tintColor = theme.callScreenButtonTintColor
}
slidingViewLeadingConstraint.constant = percentage * slidingView.frame.width
case .completed:
arrowsView.isAnimating = false
hangupView.backgroundColor = theme.noticeColor
hangupImage.tintColor = theme.callScreenButtonTintColor
}
}
private func updateState(to newState: State) {
guard newState != state else {
return
}
configure(withState: newState)
state = newState
if state == .completed {
delegate?.removeJitsiWidgetViewDidCompleteSliding(self)
}
}
// MARK: - Touch Handling
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
if state == .notStarted {
updateState(to: .sliding(percentage: 0))
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
switch state {
case .sliding:
if let touch = touches.first {
let touchLocation = touch.location(in: self)
if frame.contains(touchLocation) {
let percentage = touchLocation.x / frame.width
updateState(to: .sliding(percentage: percentage))
}
}
default:
break
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
switch state {
case .sliding(let percentage):
if percentage < Constants.activationThreshold {
updateState(to: .notStarted)
} else {
updateState(to: .completed)
}
default:
break
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event)
switch state {
case .sliding(let percentage):
if percentage < Constants.activationThreshold {
updateState(to: .notStarted)
} else {
updateState(to: .completed)
}
default:
break
}
}
// MARK: - API
weak var delegate: RemoveJitsiWidgetViewDelegate?
static func instantiate() -> RemoveJitsiWidgetView {
let view = RemoveJitsiWidgetView.loadFromNib()
view.update(theme: ThemeService.shared().theme)
return view
}
func reset() {
updateState(to: .notStarted)
}
}
// MARK: - NibLoadable
extension RemoveJitsiWidgetView: NibLoadable { }
// MARK: - Themable
extension RemoveJitsiWidgetView: Themable {
func update(theme: Theme) {
self.theme = theme
self.backgroundColor = theme.headerBackgroundColor
slidingViewLabel.textColor = theme.textPrimaryColor
arrowsView.update(theme: theme)
topSeparatorView.backgroundColor = theme.lineBreakColor
bottomSeparatorView.backgroundColor = theme.lineBreakColor
configure(withState: state)
}
}

View file

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="RemoveJitsiWidgetView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="55"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kKF-lQ-ZyI">
<rect key="frame" x="0.0" y="0.0" width="236.5" height="55"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Slide to end the call for everyone " textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dT6-Xr-WEJ">
<rect key="frame" x="24" y="0.0" width="202.5" height="55"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="dT6-Xr-WEJ" secondAttribute="trailing" constant="10" id="EbF-GZ-NzF"/>
<constraint firstItem="dT6-Xr-WEJ" firstAttribute="top" secondItem="kKF-lQ-ZyI" secondAttribute="top" id="Qu0-Ik-PYy"/>
<constraint firstItem="dT6-Xr-WEJ" firstAttribute="leading" secondItem="kKF-lQ-ZyI" secondAttribute="leading" constant="24" id="aJj-xS-5HE"/>
<constraint firstAttribute="bottom" secondItem="dT6-Xr-WEJ" secondAttribute="bottom" id="n5n-Ky-ncI"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bi1-rF-LRz" customClass="ArrowsAnimationView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="236.5" y="0.0" width="50.5" height="55"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="50" id="sKo-iu-uGJ"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PIa-uP-1J7">
<rect key="frame" x="295" y="0.0" width="80" height="55"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="voice_call_hangup_icon" translatesAutoresizingMaskIntoConstraints="NO" id="bWv-EC-L99">
<rect key="frame" x="28" y="15.5" width="24" height="24"/>
<color key="tintColor" systemColor="systemRedColor"/>
</imageView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="bWv-EC-L99" firstAttribute="centerY" secondItem="PIa-uP-1J7" secondAttribute="centerY" id="2Vl-CE-QUT"/>
<constraint firstItem="bWv-EC-L99" firstAttribute="centerX" secondItem="PIa-uP-1J7" secondAttribute="centerX" id="9vE-r4-Nje"/>
<constraint firstAttribute="width" constant="80" id="NW6-rp-ycN"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ntn-XH-RxI">
<rect key="frame" x="0.0" y="0.0" width="375" height="1"/>
<color key="backgroundColor" systemColor="systemGrayColor"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="yX4-ag-LWD"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bLk-fK-yz0">
<rect key="frame" x="0.0" y="54" width="375" height="1"/>
<color key="backgroundColor" systemColor="systemGrayColor"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="LsE-CW-ztj"/>
</constraints>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="PIa-uP-1J7" firstAttribute="bottom" secondItem="vUN-kp-3ea" secondAttribute="bottom" id="41n-Yu-G3I"/>
<constraint firstItem="kKF-lQ-ZyI" firstAttribute="bottom" secondItem="vUN-kp-3ea" secondAttribute="bottom" id="Ciw-a7-Pct"/>
<constraint firstAttribute="trailing" secondItem="Ntn-XH-RxI" secondAttribute="trailing" id="E9k-gw-h02"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="bLk-fK-yz0" secondAttribute="trailing" id="ERx-So-ce7"/>
<constraint firstAttribute="bottom" secondItem="bLk-fK-yz0" secondAttribute="bottom" id="I42-n7-cBJ"/>
<constraint firstItem="bi1-rF-LRz" firstAttribute="bottom" secondItem="vUN-kp-3ea" secondAttribute="bottom" id="Iyl-NN-rCe"/>
<constraint firstItem="bLk-fK-yz0" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="Oj8-Jf-cWi"/>
<constraint firstItem="PIa-uP-1J7" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="XJo-0J-fte"/>
<constraint firstItem="kKF-lQ-ZyI" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="aUb-po-3Dw"/>
<constraint firstItem="PIa-uP-1J7" firstAttribute="trailing" secondItem="vUN-kp-3ea" secondAttribute="trailing" id="fn9-gi-1Fo"/>
<constraint firstItem="bi1-rF-LRz" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="gbK-bh-J3T"/>
<constraint firstItem="bi1-rF-LRz" firstAttribute="leading" secondItem="kKF-lQ-ZyI" secondAttribute="trailing" priority="750" id="hWc-xf-WTt"/>
<constraint firstItem="kKF-lQ-ZyI" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="k9f-Tc-VQw"/>
<constraint firstItem="Ntn-XH-RxI" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="lzw-UG-Zeh"/>
<constraint firstItem="PIa-uP-1J7" firstAttribute="leading" secondItem="bi1-rF-LRz" secondAttribute="trailing" constant="8" id="sSR-kg-guw"/>
<constraint firstItem="Ntn-XH-RxI" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="vJc-3a-yWr"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="arrowsView" destination="bi1-rF-LRz" id="9NK-yt-cXa"/>
<outlet property="bottomSeparatorView" destination="bLk-fK-yz0" id="6Fn-W3-VTa"/>
<outlet property="hangupImage" destination="bWv-EC-L99" id="UAz-cI-2ai"/>
<outlet property="hangupView" destination="PIa-uP-1J7" id="Qd0-It-bFg"/>
<outlet property="slidingView" destination="kKF-lQ-ZyI" id="bLF-Aa-1Oy"/>
<outlet property="slidingViewLabel" destination="dT6-Xr-WEJ" id="OSR-IL-92L"/>
<outlet property="slidingViewLeadingConstraint" destination="aUb-po-3Dw" id="R7j-74-W4J"/>
<outlet property="topSeparatorView" destination="Ntn-XH-RxI" id="nRw-nh-427"/>
</connections>
<point key="canvasLocation" x="110.86956521739131" y="-142.96875"/>
</view>
</objects>
<resources>
<image name="voice_call_hangup_icon" width="24" height="24"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemGrayColor">
<color red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemRedColor">
<color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>

View file

@ -0,0 +1,25 @@
//
// Copyright 2021 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
@objc
protocol RemoveJitsiWidgetViewDelegate: class {
/// Tells the delegate that the user complete sliding on the view
/// - Parameter view: The view instance
func removeJitsiWidgetViewDidCompleteSliding(_ view: RemoveJitsiWidgetView)
}