diff --git a/Classes/AssistantView.m b/Classes/AssistantView.m
index 41c3f548d..b63ba79d9 100644
--- a/Classes/AssistantView.m
+++ b/Classes/AssistantView.m
@@ -726,29 +726,4 @@ void assistant_validation_tested(LinphoneAccountCreator *creator, LinphoneAccoun
[PhoneMainView.instance changeCurrentView:DialerView.compositeViewDescription];
}
-// TODO: remove that!
-#pragma mark - TPMultiLayoutViewController Functions
-
-- (NSDictionary *)attributesForView:(UIView *)view {
- NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
- [attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
- [attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
- if ([view isKindOfClass:[UIButton class]]) {
- UIButton *button = (UIButton *)view;
- [LinphoneUtils buttonMultiViewAddAttributes:attributes button:button];
- }
- [attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
- return attributes;
-}
-
-- (void)applyAttributes:(NSDictionary *)attributes toView:(UIView *)view {
- view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
- view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
- if ([view isKindOfClass:[UIButton class]]) {
- UIButton *button = (UIButton *)view;
- [LinphoneUtils buttonMultiViewApplyAttributes:attributes button:button];
- }
- view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
-}
-
@end
diff --git a/Classes/Base.lproj/CallView.xib b/Classes/Base.lproj/CallView.xib
index fd1c1707f..268b67b09 100644
--- a/Classes/Base.lproj/CallView.xib
+++ b/Classes/Base.lproj/CallView.xib
@@ -11,6 +11,8 @@
+
+
@@ -688,6 +690,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1320,6 +1346,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1357,6 +1407,7 @@
+
diff --git a/Classes/CallIncomingView.m b/Classes/CallIncomingView.m
index 58b24c2b9..4b2572b71 100644
--- a/Classes/CallIncomingView.m
+++ b/Classes/CallIncomingView.m
@@ -130,30 +130,4 @@ static UICompositeViewDescription *compositeDescription = nil;
[_delegate incomingCallAccepted:_call evenWithVideo:NO];
}
-#pragma mark - TPMultiLayoutViewController Functions
-
-- (NSDictionary *)attributesForView:(UIView *)view {
- NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
-
- [attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
- [attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
- if ([view isKindOfClass:[UIButton class]]) {
- UIButton *button = (UIButton *)view;
- [LinphoneUtils buttonMultiViewAddAttributes:attributes button:button];
- }
- [attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
-
- return attributes;
-}
-
-- (void)applyAttributes:(NSDictionary *)attributes toView:(UIView *)view {
- view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
- view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
- if ([view isKindOfClass:[UIButton class]]) {
- UIButton *button = (UIButton *)view;
- [LinphoneUtils buttonMultiViewApplyAttributes:attributes button:button];
- }
- view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
-}
-
@end
diff --git a/Classes/CallView.h b/Classes/CallView.h
index 864144edd..9647eee25 100644
--- a/Classes/CallView.h
+++ b/Classes/CallView.h
@@ -32,6 +32,7 @@
#import "UIHangUpButton.h"
#import "UIDigitButton.h"
#import "UIRoundedImageView.h"
+#import "UIBouncingView.h"
@class VideoView;
@@ -71,6 +72,8 @@
@property(nonatomic, strong) IBOutlet UIButton *optionsTransferButton;
@property(nonatomic, strong) IBOutlet UIToggleButton *numpadButton;
@property(weak, nonatomic) IBOutlet UIPauseButton *conferencePauseButton;
+@property(weak, nonatomic) IBOutlet UIBouncingView *chatNotificationView;
+@property(weak, nonatomic) IBOutlet UILabel *chatNotificationLabel;
@property(weak, nonatomic) IBOutlet UIView *bottomBar;
@property(nonatomic, strong) IBOutlet UIDigitButton *oneButton;
diff --git a/Classes/CallView.m b/Classes/CallView.m
index 0a3af1846..346050f8a 100644
--- a/Classes/CallView.m
+++ b/Classes/CallView.m
@@ -112,6 +112,12 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(messageReceived:)
+ name:kLinphoneMessageReceived
+ object:nil];
+ [self updateUnreadMessage:FALSE];
+
// Update on show
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL) ? linphone_call_get_state(call) : 0;
@@ -217,6 +223,7 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
+ [self updateUnreadMessage:NO];
[self previewTouchLift];
[self showStatusBar:!videoShown || (_nameLabel.alpha > 0.f)];
}
@@ -876,4 +883,17 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
}];
}
+#pragma mark - Bounce
+- (void)messageReceived:(NSNotification *)notif {
+ [self updateUnreadMessage:TRUE];
+}
+- (void)updateUnreadMessage:(BOOL)appear {
+ int unreadMessage = [LinphoneManager unreadMessageCount];
+ if (unreadMessage > 0) {
+ _chatNotificationLabel.text = [NSString stringWithFormat:@"%i", unreadMessage];
+ [_chatNotificationView startAnimating:appear];
+ } else {
+ [_chatNotificationView stopAnimating:appear];
+ }
+}
@end
diff --git a/Classes/LinphoneUI/Base.lproj/TabBarView.xib b/Classes/LinphoneUI/Base.lproj/TabBarView.xib
index c7a620ad7..c8f03344a 100644
--- a/Classes/LinphoneUI/Base.lproj/TabBarView.xib
+++ b/Classes/LinphoneUI/Base.lproj/TabBarView.xib
@@ -89,7 +89,7 @@
-
+
@@ -113,7 +113,7 @@
-
+
@@ -198,7 +198,7 @@
-
+
@@ -222,7 +222,7 @@
-
+
diff --git a/Classes/LinphoneUI/Base.lproj/UIChatCell.xib b/Classes/LinphoneUI/Base.lproj/UIChatCell.xib
index a751d05ee..a3782140b 100644
--- a/Classes/LinphoneUI/Base.lproj/UIChatCell.xib
+++ b/Classes/LinphoneUI/Base.lproj/UIChatCell.xib
@@ -11,7 +11,8 @@
-
+
+
@@ -51,17 +52,30 @@
-
+
+
@@ -71,6 +85,6 @@
-
+
diff --git a/Classes/LinphoneUI/StatusBarView.m b/Classes/LinphoneUI/StatusBarView.m
index 076ec8207..4d5f759ee 100644
--- a/Classes/LinphoneUI/StatusBarView.m
+++ b/Classes/LinphoneUI/StatusBarView.m
@@ -345,22 +345,4 @@
linphone_core_refresh_registers([LinphoneManager getLc]);
}
-#pragma mark - TPMultiLayoutViewController Functions
-
-- (NSDictionary *)attributesForView:(UIView *)view {
- NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
-
- [attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
- [attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
- [attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
-
- return attributes;
-}
-
-- (void)applyAttributes:(NSDictionary *)attributes toView:(UIView *)view {
- view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
- view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
- view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
-}
-
@end
diff --git a/Classes/LinphoneUI/TabBarView.h b/Classes/LinphoneUI/TabBarView.h
index 193fef6a6..9f249378b 100644
--- a/Classes/LinphoneUI/TabBarView.h
+++ b/Classes/LinphoneUI/TabBarView.h
@@ -19,6 +19,7 @@
#import
#import "TPMultiLayoutViewController.h"
+#import "UIBouncingView.h"
@interface TabBarView : TPMultiLayoutViewController {
}
@@ -27,10 +28,10 @@
@property(nonatomic, strong) IBOutlet UIButton *contactsButton;
@property(nonatomic, strong) IBOutlet UIButton *dialerButton;
@property(nonatomic, strong) IBOutlet UIButton *chatButton;
-@property(nonatomic, strong) IBOutlet UIView *historyNotificationView;
-@property(nonatomic, strong) IBOutlet UILabel *historyNotificationLabel;
-@property(nonatomic, strong) IBOutlet UIView *chatNotificationView;
+@property(nonatomic, strong) IBOutlet UIBouncingView *historyNotificationView;
+@property(nonatomic, strong) IBOutlet UIBouncingView *chatNotificationView;
@property(nonatomic, strong) IBOutlet UILabel *chatNotificationLabel;
+@property(nonatomic, strong) IBOutlet UILabel *historyNotificationLabel;
@property(weak, nonatomic) IBOutlet UIImageView *selectedButtonImage;
- (IBAction)onHistoryClick:(id)event;
diff --git a/Classes/LinphoneUI/TabBarView.m b/Classes/LinphoneUI/TabBarView.m
index 6ffe371a4..f061214d2 100644
--- a/Classes/LinphoneUI/TabBarView.m
+++ b/Classes/LinphoneUI/TabBarView.m
@@ -19,23 +19,9 @@
#import "TabBarView.h"
#import "PhoneMainView.h"
-#import "CAAnimation+Blocks.h"
@implementation TabBarView
-static NSString *const kBounceAnimation = @"bounce";
-static NSString *const kAppearAnimation = @"appear";
-static NSString *const kDisappearAnimation = @"disappear";
-
-@synthesize historyButton;
-@synthesize contactsButton;
-@synthesize dialerButton;
-@synthesize chatButton;
-@synthesize historyNotificationView;
-@synthesize historyNotificationLabel;
-@synthesize chatNotificationView;
-@synthesize chatNotificationLabel;
-
#pragma mark - ViewController Functions
- (void)viewWillAppear:(BOOL)animated {
@@ -53,10 +39,6 @@ static NSString *const kDisappearAnimation = @"disappear";
selector:@selector(messageReceived:)
name:kLinphoneMessageReceived
object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(settingsUpdate:)
- name:kLinphoneSettingsUpdate
- object:nil];
[self update:FALSE];
}
@@ -65,40 +47,12 @@ static NSString *const kDisappearAnimation = @"disappear";
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-- (void)viewDidLoad {
- [super viewDidLoad];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(applicationWillEnterForeground:)
- name:UIApplicationWillEnterForegroundNotification
- object:nil];
-}
-
-- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
- duration:(NSTimeInterval)duration {
- // Force the animations
- [[self.view layer] removeAllAnimations];
- [historyNotificationView.layer setTransform:CATransform3DIdentity];
- [chatNotificationView.layer setTransform:CATransform3DIdentity];
-}
-
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
- [chatNotificationView setHidden:TRUE];
- [historyNotificationView setHidden:TRUE];
[self update:FALSE];
}
#pragma mark - Event Functions
-- (void)applicationWillEnterForeground:(NSNotification *)notif {
- // Force the animations
- [[self.view layer] removeAllAnimations];
- [historyNotificationView.layer setTransform:CATransform3DIdentity];
- [chatNotificationView.layer setTransform:CATransform3DIdentity];
- [chatNotificationView setHidden:TRUE];
- [historyNotificationView setHidden:TRUE];
- [self update:FALSE];
-}
-
- (void)callUpdate:(NSNotification *)notif {
// LinphoneCall *call = [[notif.userInfo objectForKey: @"call"] pointerValue];
// LinphoneCallState state = [[notif.userInfo objectForKey: @"state"] intValue];
@@ -112,23 +66,6 @@ static NSString *const kDisappearAnimation = @"disappear";
}
}
-- (void)settingsUpdate:(NSNotification *)notif {
- if ([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == false) {
- [self stopBounceAnimation:kBounceAnimation target:chatNotificationView];
- chatNotificationView.layer.transform = CATransform3DIdentity;
- [self stopBounceAnimation:kBounceAnimation target:historyNotificationView];
- historyNotificationView.layer.transform = CATransform3DIdentity;
- } else {
- if (![chatNotificationView isHidden] && [chatNotificationView.layer animationForKey:kBounceAnimation] == nil) {
- [self startBounceAnimation:kBounceAnimation target:chatNotificationView];
- }
- if (![historyNotificationView isHidden] &&
- [historyNotificationView.layer animationForKey:kBounceAnimation] == nil) {
- [self startBounceAnimation:kBounceAnimation target:historyNotificationView];
- }
- }
-}
-
- (void)messageReceived:(NSNotification *)notif {
[self updateUnreadMessage:TRUE];
}
@@ -144,112 +81,60 @@ static NSString *const kDisappearAnimation = @"disappear";
- (void)updateUnreadMessage:(BOOL)appear {
int unreadMessage = [LinphoneManager unreadMessageCount];
if (unreadMessage > 0) {
- if ([chatNotificationView isHidden]) {
- [chatNotificationView setHidden:FALSE];
- if ([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == true) {
- if (appear) {
- [self appearAnimation:kAppearAnimation
- target:chatNotificationView
- completion:^(BOOL finished) {
- [self startBounceAnimation:kBounceAnimation target:chatNotificationView];
- [chatNotificationView.layer removeAnimationForKey:kAppearAnimation];
- }];
- } else {
- [self startBounceAnimation:kBounceAnimation target:chatNotificationView];
- }
- }
- }
- [chatNotificationLabel setText:[NSString stringWithFormat:@"%i", unreadMessage]];
+ _chatNotificationLabel.text = [NSString stringWithFormat:@"%i", unreadMessage];
+ [_chatNotificationView startAnimating:appear];
} else {
- if (![chatNotificationView isHidden]) {
- [self stopBounceAnimation:kBounceAnimation target:chatNotificationView];
- if (appear) {
- [self disappearAnimation:kDisappearAnimation
- target:chatNotificationView
- completion:^(BOOL finished) {
- [chatNotificationView setHidden:TRUE];
- [chatNotificationView.layer removeAnimationForKey:kDisappearAnimation];
- }];
- } else {
- [chatNotificationView setHidden:TRUE];
- }
- }
+ [_chatNotificationView stopAnimating:appear];
}
}
- (void)updateMissedCall:(int)missedCall appear:(BOOL)appear {
if (missedCall > 0) {
- if ([historyNotificationView isHidden]) {
- [historyNotificationView setHidden:FALSE];
- if ([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == true) {
- if (appear) {
- [self appearAnimation:kAppearAnimation
- target:historyNotificationView
- completion:^(BOOL finished) {
- [self startBounceAnimation:kBounceAnimation target:historyNotificationView];
- [historyNotificationView.layer removeAnimationForKey:kAppearAnimation];
- }];
- } else {
- [self startBounceAnimation:kBounceAnimation target:historyNotificationView];
- }
- }
- }
- [historyNotificationLabel setText:[NSString stringWithFormat:@"%i", missedCall]];
+ _historyNotificationLabel.text = [NSString stringWithFormat:@"%i", missedCall];
+ [_historyNotificationView startAnimating:appear];
} else {
- if (![historyNotificationView isHidden]) {
- [self stopBounceAnimation:kBounceAnimation target:historyNotificationView];
- if (appear) {
- [self disappearAnimation:kDisappearAnimation
- target:historyNotificationView
- completion:^(BOOL finished) {
- [historyNotificationView setHidden:TRUE];
- [historyNotificationView.layer removeAnimationForKey:kDisappearAnimation];
- }];
- } else {
- [historyNotificationView setHidden:TRUE];
- }
- }
+ [_historyNotificationView stopAnimating:appear];
}
}
- (void)updateSelectedButton:(UICompositeViewDescription *)view {
- historyButton.selected = [view equal:HistoryListView.compositeViewDescription] ||
- [view equal:HistoryDetailsView.compositeViewDescription];
- contactsButton.selected = [view equal:ContactsListView.compositeViewDescription] ||
- [view equal:ContactDetailsView.compositeViewDescription];
- dialerButton.selected = [view equal:DialerView.compositeViewDescription];
- chatButton.selected = [view equal:ChatsListView.compositeViewDescription] ||
- [view equal:ChatConversationCreateView.compositeViewDescription] ||
- [view equal:ChatConversationView.compositeViewDescription];
+ _historyButton.selected = [view equal:HistoryListView.compositeViewDescription] ||
+ [view equal:HistoryDetailsView.compositeViewDescription];
+ _contactsButton.selected = [view equal:ContactsListView.compositeViewDescription] ||
+ [view equal:ContactDetailsView.compositeViewDescription];
+ _dialerButton.selected = [view equal:DialerView.compositeViewDescription];
+ _chatButton.selected = [view equal:ChatsListView.compositeViewDescription] ||
+ [view equal:ChatConversationCreateView.compositeViewDescription] ||
+ [view equal:ChatConversationView.compositeViewDescription];
CGRect selectedNewFrame = _selectedButtonImage.frame;
if ([self viewIsCurrentlyPortrait]) {
selectedNewFrame.origin.x =
- (historyButton.selected
- ? historyButton.frame.origin.x
- : (contactsButton.selected
- ? contactsButton.frame.origin.x
- : (dialerButton.selected
- ? dialerButton.frame.origin.x
- : (chatButton.selected
- ? chatButton.frame.origin.x
+ (_historyButton.selected
+ ? _historyButton.frame.origin.x
+ : (_contactsButton.selected
+ ? _contactsButton.frame.origin.x
+ : (_dialerButton.selected
+ ? _dialerButton.frame.origin.x
+ : (_chatButton.selected
+ ? _chatButton.frame.origin.x
: -selectedNewFrame.size.width /*hide it if none is selected*/))));
} else {
selectedNewFrame.origin.y =
- (historyButton.selected
- ? historyButton.frame.origin.y
- : (contactsButton.selected
- ? contactsButton.frame.origin.y
- : (dialerButton.selected
- ? dialerButton.frame.origin.y
- : (chatButton.selected
- ? chatButton.frame.origin.y
+ (_historyButton.selected
+ ? _historyButton.frame.origin.y
+ : (_contactsButton.selected
+ ? _contactsButton.frame.origin.y
+ : (_dialerButton.selected
+ ? _dialerButton.frame.origin.y
+ : (_chatButton.selected
+ ? _chatButton.frame.origin.y
: -selectedNewFrame.size.height /*hide it if none is selected*/))));
}
-
+
CGFloat delay = [[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] ? 0.3 : 0;
[UIView animateWithDuration:delay animations:^{
_selectedButtonImage.frame = selectedNewFrame;
-
+
}];
}
@@ -279,73 +164,4 @@ static NSString *const kDisappearAnimation = @"disappear";
[PhoneMainView.instance changeCurrentView:ChatsListView.compositeViewDescription];
}
-#pragma mark - Animation
-
-- (void)appearAnimation:(NSString *)animationID target:(UIView *)target completion:(void (^)(BOOL finished))completion {
- CABasicAnimation *appear = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
- appear.duration = 0.4;
- appear.fromValue = [NSNumber numberWithDouble:0.0f];
- appear.toValue = [NSNumber numberWithDouble:1.0f];
- appear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
- appear.fillMode = kCAFillModeForwards;
- appear.removedOnCompletion = NO;
- [appear setCompletion:completion];
- [target.layer addAnimation:appear forKey:animationID];
-}
-
-- (void)disappearAnimation:(NSString *)animationID
- target:(UIView *)target
- completion:(void (^)(BOOL finished))completion {
- CABasicAnimation *disappear = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
- disappear.duration = 0.4;
- disappear.fromValue = [NSNumber numberWithDouble:1.0f];
- disappear.toValue = [NSNumber numberWithDouble:0.0f];
- disappear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
- disappear.fillMode = kCAFillModeForwards;
- disappear.removedOnCompletion = NO;
- [disappear setCompletion:completion];
- [target.layer addAnimation:disappear forKey:animationID];
-}
-
-- (void)startBounceAnimation:(NSString *)animationID target:(UIView *)target {
- CABasicAnimation *bounce = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
- bounce.duration = 0.3;
- bounce.fromValue = [NSNumber numberWithDouble:0.0f];
- bounce.toValue = [NSNumber numberWithDouble:8.0f];
- bounce.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
- bounce.autoreverses = TRUE;
- bounce.repeatCount = HUGE_VALF;
- [target.layer addAnimation:bounce forKey:animationID];
-}
-
-- (void)stopBounceAnimation:(NSString *)animationID target:(UIView *)target {
- [target.layer removeAnimationForKey:animationID];
-}
-
-#pragma mark - TPMultiLayoutViewController Functions
-
-- (NSDictionary *)attributesForView:(UIView *)view {
- NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
-
- [attributes setObject:[NSValue valueWithCGRect:view.frame] forKey:@"frame"];
- [attributes setObject:[NSValue valueWithCGRect:view.bounds] forKey:@"bounds"];
- if ([view isKindOfClass:[UIButton class]]) {
- UIButton *button = (UIButton *)view;
- [LinphoneUtils buttonMultiViewAddAttributes:attributes button:button];
- }
- [attributes setObject:[NSNumber numberWithInteger:view.autoresizingMask] forKey:@"autoresizingMask"];
-
- return attributes;
-}
-
-- (void)applyAttributes:(NSDictionary *)attributes toView:(UIView *)view {
- view.frame = [[attributes objectForKey:@"frame"] CGRectValue];
- view.bounds = [[attributes objectForKey:@"bounds"] CGRectValue];
- if ([view isKindOfClass:[UIButton class]]) {
- UIButton *button = (UIButton *)view;
- [LinphoneUtils buttonMultiViewApplyAttributes:attributes button:button];
- }
- view.autoresizingMask = [[attributes objectForKey:@"autoresizingMask"] integerValue];
-}
-
@end
diff --git a/Classes/LinphoneUI/UIBouncingView.h b/Classes/LinphoneUI/UIBouncingView.h
new file mode 100644
index 000000000..34d77f963
--- /dev/null
+++ b/Classes/LinphoneUI/UIBouncingView.h
@@ -0,0 +1,16 @@
+//
+// UIBouncingView.h
+// linphone
+//
+// Created by Gautier Pelloux-Prayer on 11/12/15.
+//
+//
+
+#import
+
+@interface UIBouncingView : UIView
+
+- (void)startAnimating:(BOOL)animated;
+- (void)stopAnimating:(BOOL)animated;
+
+@end
diff --git a/Classes/LinphoneUI/UIBouncingView.m b/Classes/LinphoneUI/UIBouncingView.m
new file mode 100644
index 000000000..60e4ce007
--- /dev/null
+++ b/Classes/LinphoneUI/UIBouncingView.m
@@ -0,0 +1,123 @@
+//
+// UIBouncingView.m
+// linphone
+//
+// Created by Gautier Pelloux-Prayer on 11/12/15.
+//
+//
+
+#import "UIBouncingView.h"
+
+#import "CAAnimation+Blocks.h"
+#import "Utils.h"
+
+static NSString *const kBounceAnimation = @"bounce";
+static NSString *const kAppearAnimation = @"appear";
+static NSString *const kDisappearAnimation = @"disappear";
+
+@implementation UIBouncingView
+
+INIT_WITH_COMMON {
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(settingsUpdate:)
+ name:kLinphoneSettingsUpdate
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(applicationWillEnterForeground:)
+ name:UIApplicationWillEnterForegroundNotification
+ object:nil];
+ return self;
+}
+
+- (void)settingsUpdate:(NSNotification *)notif {
+ if ([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == false) {
+ [self stopBounceAnimation:kBounceAnimation target:self];
+ } else {
+ if (![self isHidden] && [self.layer animationForKey:kBounceAnimation] == nil) {
+ [self startBounceAnimation:kBounceAnimation target:self];
+ }
+ }
+}
+
+- (void)applicationWillEnterForeground:(NSNotification *)notif {
+ // Force the animations
+ if (!self.isHidden) {
+ [self startAnimating:NO];
+ } else {
+ [self stopAnimating:NO];
+ }
+}
+
+#pragma mark - Animation
+
+- (void)appearAnimation:(NSString *)animationID target:(UIView *)target completion:(void (^)(BOOL finished))completion {
+ CABasicAnimation *appear = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+ appear.duration = 0.4;
+ appear.fromValue = [NSNumber numberWithDouble:0.0f];
+ appear.toValue = [NSNumber numberWithDouble:1.0f];
+ appear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
+ appear.fillMode = kCAFillModeForwards;
+ appear.removedOnCompletion = NO;
+ [appear setCompletion:completion];
+ [target.layer addAnimation:appear forKey:animationID];
+}
+
+- (void)disappearAnimation:(NSString *)animationID
+ target:(UIView *)target
+ completion:(void (^)(BOOL finished))completion {
+ CABasicAnimation *disappear = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+ disappear.duration = 0.4;
+ disappear.fromValue = [NSNumber numberWithDouble:1.0f];
+ disappear.toValue = [NSNumber numberWithDouble:0.0f];
+ disappear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
+ disappear.fillMode = kCAFillModeForwards;
+ disappear.removedOnCompletion = NO;
+ [disappear setCompletion:completion];
+ [target.layer addAnimation:disappear forKey:animationID];
+}
+
+- (void)startBounceAnimation:(NSString *)animationID target:(UIView *)target {
+ CABasicAnimation *bounce = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
+ bounce.duration = 0.3;
+ bounce.fromValue = [NSNumber numberWithDouble:0.0f];
+ bounce.toValue = [NSNumber numberWithDouble:8.0f];
+ bounce.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
+ bounce.autoreverses = TRUE;
+ bounce.repeatCount = HUGE_VALF;
+ [target.layer addAnimation:bounce forKey:animationID];
+}
+
+- (void)stopBounceAnimation:(NSString *)animationID target:(UIView *)target {
+ [target.layer removeAnimationForKey:animationID];
+}
+
+- (void)startAnimating:(BOOL)animated {
+ [self setHidden:FALSE];
+ if ([[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"] == true) {
+ if (animated) {
+ [self appearAnimation:kAppearAnimation
+ target:self
+ completion:^(BOOL finished) {
+ [self startBounceAnimation:kBounceAnimation target:self];
+ [self.layer removeAnimationForKey:kAppearAnimation];
+ }];
+ } else {
+ [self startBounceAnimation:kBounceAnimation target:self];
+ }
+ }
+}
+
+- (void)stopAnimating:(BOOL)animated {
+ [self stopBounceAnimation:kBounceAnimation target:self];
+ if (animated) {
+ [self disappearAnimation:kDisappearAnimation
+ target:self
+ completion:^(BOOL finished) {
+ [self setHidden:TRUE];
+ [self.layer removeAnimationForKey:kDisappearAnimation];
+ }];
+ } else {
+ [self setHidden:TRUE];
+ }
+}
+@end
diff --git a/Classes/LinphoneUI/UIChatCell.h b/Classes/LinphoneUI/UIChatCell.h
index e2d9257a7..6c8415b17 100644
--- a/Classes/LinphoneUI/UIChatCell.h
+++ b/Classes/LinphoneUI/UIChatCell.h
@@ -21,6 +21,7 @@
#import "UIRoundedImageView.h"
#import "UIIconButton.h"
+#import "UIBouncingView.h"
#include "linphone/linphonecore.h"
@@ -33,6 +34,8 @@
@property (nonatomic, strong) IBOutlet UILabel* chatContentLabel;
@property(weak, nonatomic) IBOutlet UILabel *chatLatestTimeLabel;
@property(weak, nonatomic) IBOutlet UIIconButton *unreadCountButton;
+@property(weak, nonatomic) IBOutlet UIBouncingView *unreadCountView;
+@property(weak, nonatomic) IBOutlet UILabel *unreadCountLabel;
- (id)initWithIdentifier:(NSString*)identifier;
diff --git a/Classes/LinphoneUI/UIChatCell.m b/Classes/LinphoneUI/UIChatCell.m
index 4f1c3d6d9..ccfb9b78b 100644
--- a/Classes/LinphoneUI/UIChatCell.m
+++ b/Classes/LinphoneUI/UIChatCell.m
@@ -95,8 +95,12 @@
}
int count = linphone_chat_room_get_unread_messages_count(chatRoom);
- [_unreadCountButton setTitle:[NSString stringWithFormat:@"%i", count] forState:UIControlStateNormal];
- _unreadCountButton.hidden = (count <= 0);
+ _unreadCountLabel.text = [NSString stringWithFormat:@"%i", count];
+ if (count > 0) {
+ [_unreadCountView startAnimating:YES];
+ } else {
+ [_unreadCountView stopAnimating:YES];
+ }
UIFont *addressFont = (count <= 0) ? [UIFont systemFontOfSize:25] : [UIFont boldSystemFontOfSize:25];
_addressLabel.font = addressFont;
diff --git a/linphone.xcodeproj/project.pbxproj b/linphone.xcodeproj/project.pbxproj
index 205b02aaf..7d862e665 100755
--- a/linphone.xcodeproj/project.pbxproj
+++ b/linphone.xcodeproj/project.pbxproj
@@ -469,6 +469,7 @@
63730FB91C07570C00AD7A74 /* waiting_time.png in Resources */ = {isa = PBXBuildFile; fileRef = 63730E511C07570C00AD7A74 /* waiting_time.png */; };
63730FBA1C07570C00AD7A74 /* waiting_time@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 63730E521C07570C00AD7A74 /* waiting_time@2x.png */; };
6377AC801BDE4069007F7625 /* UIBackToCallButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 6377AC7F1BDE4069007F7625 /* UIBackToCallButton.m */; };
+ 6381DA7D1C1AD5EA00DF3BBD /* UIBouncingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6381DA7C1C1AD5EA00DF3BBD /* UIBouncingView.m */; };
639CEAFD1A1DF4D9004DE38F /* StatusBarView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEAFF1A1DF4D9004DE38F /* StatusBarView.xib */; };
639CEB001A1DF4E4004DE38F /* UIHistoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB021A1DF4E4004DE38F /* UIHistoryCell.xib */; };
639CEB031A1DF4EB004DE38F /* UICompositeView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB051A1DF4EB004DE38F /* UICompositeView.xib */; };
@@ -1286,6 +1287,8 @@
63730E521C07570C00AD7A74 /* waiting_time@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "waiting_time@2x.png"; sourceTree = ""; };
6377AC7E1BDE4068007F7625 /* UIBackToCallButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIBackToCallButton.h; sourceTree = ""; };
6377AC7F1BDE4069007F7625 /* UIBackToCallButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIBackToCallButton.m; sourceTree = ""; };
+ 6381DA7B1C1AD5EA00DF3BBD /* UIBouncingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIBouncingView.h; sourceTree = ""; };
+ 6381DA7C1C1AD5EA00DF3BBD /* UIBouncingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIBouncingView.m; sourceTree = ""; };
639CEAFE1A1DF4D9004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/StatusBarView.xib; sourceTree = ""; };
639CEB011A1DF4E4004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UIHistoryCell.xib; sourceTree = ""; };
639CEB041A1DF4EB004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UICompositeView.xib; sourceTree = ""; };
@@ -1912,6 +1915,8 @@
D3196D3D15A32BD8007FEEBA /* UITransferButton.m */,
340751E5150F38FC00B89C47 /* UIVideoButton.h */,
340751E6150F38FD00B89C47 /* UIVideoButton.m */,
+ 6381DA7B1C1AD5EA00DF3BBD /* UIBouncingView.h */,
+ 6381DA7C1C1AD5EA00DF3BBD /* UIBouncingView.m */,
);
path = LinphoneUI;
sourceTree = "";
@@ -3469,6 +3474,7 @@
63BC49E21BA2CDFC004EC273 /* UICallPausedCell.m in Sources */,
D37EE162160377D7003608A6 /* DTActionSheet.m in Sources */,
D306459E1611EC2A00BB571E /* UILoadingImageView.m in Sources */,
+ 6381DA7D1C1AD5EA00DF3BBD /* UIBouncingView.m in Sources */,
D37E3ECD1619C27A0087659A /* CAAnimation+Blocks.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;