Chat: bounce icon on unread messages even in call and in chats list

This commit is contained in:
Gautier Pelloux-Prayer 2015-12-11 11:42:26 +01:00
parent 7d4130a7ba
commit f804300beb
15 changed files with 294 additions and 306 deletions

View file

@ -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

View file

@ -11,6 +11,8 @@
<outlet property="bottomBar" destination="mga-O5-mUn" id="ObF-wX-nBD"/>
<outlet property="callPauseButton" destination="7f5-7T-fV3" id="A5d-op-0Iq"/>
<outlet property="callView" destination="9" id="TKY-dp-lKv"/>
<outlet property="chatNotificationLabel" destination="Saa-p5-chV" id="XEA-19-Jur"/>
<outlet property="chatNotificationView" destination="d9Y-2a-CDI" id="Cys-zI-ApZ"/>
<outlet property="conferenceCallsTable" destination="sif-q0-7oE" id="Fjr-dB-s4q"/>
<outlet property="conferencePauseButton" destination="HAk-mv-6sG" id="SJg-ew-UIZ"/>
<outlet property="conferenceView" destination="0Ju-u5-N7A" id="H5K-Nv-IKI"/>
@ -688,6 +690,30 @@
<action selector="onChatClick:" destination="-1" eventType="touchUpInside" id="Jdk-1s-UnN"/>
</connections>
</button>
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="70" contentMode="scaleToFill" id="d9Y-2a-CDI" userLabel="chatNotificationView" customClass="UIBouncingView">
<rect key="frame" x="330" y="8" width="21" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" tag="71" contentMode="scaleAspectFit" image="history_chat_indicator.png" id="nPO-PM-4zJ" userLabel="chatNotificationImage">
<rect key="frame" x="0.0" y="0.0" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="72" contentMode="left" text="99" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="7" id="Saa-p5-chV" userLabel="chatNotificationLabel">
<rect key="frame" x="0.0" y="0.0" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Missed message(s)">
<accessibilityTraits key="traits" none="YES"/>
</accessibility>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
</subviews>
<animations/>
</view>
@ -1320,6 +1346,30 @@
<action selector="onChatClick:" destination="-1" eventType="touchUpInside" id="PMo-F3-WMK"/>
</connections>
</button>
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="70" contentMode="scaleToFill" id="1pd-et-5dy" userLabel="chatNotificationView" customClass="UIBouncingView">
<rect key="frame" x="295" y="8" width="21" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" tag="71" contentMode="scaleAspectFit" image="history_chat_indicator.png" id="7ZF-Ch-AL1" userLabel="chatNotificationImage">
<rect key="frame" x="0.0" y="0.0" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="72" contentMode="left" text="99" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="7" id="P2K-eB-z8Z" userLabel="chatNotificationLabel">
<rect key="frame" x="0.0" y="0.0" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Missed message(s)">
<accessibilityTraits key="traits" none="YES"/>
</accessibility>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
</subviews>
<animations/>
</view>
@ -1357,6 +1407,7 @@
<image name="footer_chat_default.png" width="27" height="27"/>
<image name="footer_dialer_default.png" width="27" height="27"/>
<image name="footer_dialer_disabled.png" width="27" height="27"/>
<image name="history_chat_indicator.png" width="13" height="13"/>
<image name="micro_default.png" width="29" height="37"/>
<image name="micro_disabled.png" width="29" height="37"/>
<image name="micro_selected.png" width="29" height="37"/>

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -89,7 +89,7 @@
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<animations/>
</imageView>
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="7" contentMode="scaleToFill" id="37" userLabel="chatNotificationView">
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="7" contentMode="scaleToFill" id="37" userLabel="chatNotificationView" customClass="UIBouncingView">
<rect key="frame" x="338" y="0.0" width="21" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
@ -113,7 +113,7 @@
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="10" contentMode="scaleToFill" id="32" userLabel="historyNotificationView">
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="10" contentMode="scaleToFill" id="32" userLabel="historyNotificationView" customClass="UIBouncingView">
<rect key="frame" x="68" y="0.0" width="21" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
@ -198,7 +198,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<animations/>
</imageView>
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="7" contentMode="scaleToFill" id="djA-EL-HUt" userLabel="chatNotificationView">
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="7" contentMode="scaleToFill" id="djA-EL-HUt" userLabel="chatNotificationView" customClass="UIBouncingView">
<rect key="frame" x="68" y="233" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
@ -222,7 +222,7 @@
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="10" contentMode="scaleToFill" id="Ldd-jk-0kY" userLabel="historyNotificationView">
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="10" contentMode="scaleToFill" id="Ldd-jk-0kY" userLabel="historyNotificationView" customClass="UIBouncingView">
<rect key="frame" x="68" y="35" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>

View file

@ -11,7 +11,8 @@
<outlet property="avatarImage" destination="19" id="30"/>
<outlet property="chatContentLabel" destination="21" id="24"/>
<outlet property="chatLatestTimeLabel" destination="r7A-Mk-LQX" id="J0r-yr-YLk"/>
<outlet property="unreadCountButton" destination="VDt-hI-meD" id="YO9-Vz-JKy"/>
<outlet property="unreadCountLabel" destination="ZXq-Do-7Ua" id="anx-Na-sYz"/>
<outlet property="unreadCountView" destination="7DE-KJ-9Q3" id="hkt-rA-EKa"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
@ -51,17 +52,30 @@
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" userInteractionEnabled="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="VDt-hI-meD" userLabel="unreadCountButton" customClass="UIIconButton">
<rect key="frame" x="346" y="4" width="28" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<view autoresizesSubviews="NO" userInteractionEnabled="NO" tag="7" contentMode="scaleToFill" id="7DE-KJ-9Q3" userLabel="unreadCountView" customClass="UIBouncingView">
<rect key="frame" x="350" y="7" width="21" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" tag="8" contentMode="scaleAspectFit" image="history_chat_indicator.png" id="NXj-A8-YLh" userLabel="unreadCountImage">
<rect key="frame" x="0.0" y="0.0" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="9" contentMode="left" text="99" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="7" id="ZXq-Do-7Ua" userLabel="unreadCountLabel">
<rect key="frame" x="0.0" y="0.0" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Missed message(s)">
<accessibilityTraits key="traits" none="YES"/>
</accessibility>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<accessibility key="accessibilityConfiguration" label="Unread message count">
<accessibilityTraits key="traits" staticText="YES" notEnabled="YES"/>
</accessibility>
<state key="normal" title="0" backgroundImage="chat_list_indicator.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
</button>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
</subviews>
<animations/>
<nil key="simulatedStatusBarMetrics"/>
@ -71,6 +85,6 @@
</objects>
<resources>
<image name="avatar.png" width="255" height="255"/>
<image name="chat_list_indicator.png" width="20" height="20"/>
<image name="history_chat_indicator.png" width="13" height="13"/>
</resources>
</document>

View file

@ -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

View file

@ -19,6 +19,7 @@
#import <UIKit/UIKit.h>
#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;

View file

@ -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

View file

@ -0,0 +1,16 @@
//
// UIBouncingView.h
// linphone
//
// Created by Gautier Pelloux-Prayer on 11/12/15.
//
//
#import <UIKit/UIKit.h>
@interface UIBouncingView : UIView
- (void)startAnimating:(BOOL)animated;
- (void)stopAnimating:(BOOL)animated;
@end

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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 = "<group>"; };
6377AC7E1BDE4068007F7625 /* UIBackToCallButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIBackToCallButton.h; sourceTree = "<group>"; };
6377AC7F1BDE4069007F7625 /* UIBackToCallButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIBackToCallButton.m; sourceTree = "<group>"; };
6381DA7B1C1AD5EA00DF3BBD /* UIBouncingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIBouncingView.h; sourceTree = "<group>"; };
6381DA7C1C1AD5EA00DF3BBD /* UIBouncingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIBouncingView.m; sourceTree = "<group>"; };
639CEAFE1A1DF4D9004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/StatusBarView.xib; sourceTree = "<group>"; };
639CEB011A1DF4E4004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UIHistoryCell.xib; sourceTree = "<group>"; };
639CEB041A1DF4EB004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UICompositeView.xib; sourceTree = "<group>"; };
@ -1912,6 +1915,8 @@
D3196D3D15A32BD8007FEEBA /* UITransferButton.m */,
340751E5150F38FC00B89C47 /* UIVideoButton.h */,
340751E6150F38FD00B89C47 /* UIVideoButton.m */,
6381DA7B1C1AD5EA00DF3BBD /* UIBouncingView.h */,
6381DA7C1C1AD5EA00DF3BBD /* UIBouncingView.m */,
);
path = LinphoneUI;
sourceTree = "<group>";
@ -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;