Merge branch 'feature/call_recorder' into feature/integration

This commit is contained in:
Danmei Chen 2018-10-10 15:16:38 +02:00
commit be3dac0b07
25 changed files with 1941 additions and 202 deletions

File diff suppressed because it is too large Load diff

View file

@ -42,6 +42,7 @@
NSTimer *hideControlsTimer;
NSTimer *videoDismissTimer;
BOOL videoHidden;
BOOL callRecording;
VideoZoomHandler *videoZoomHandler;
}
@ -74,6 +75,8 @@
@property(weak, nonatomic) IBOutlet UIPauseButton *conferencePauseButton;
@property(weak, nonatomic) IBOutlet UIBouncingView *chatNotificationView;
@property(weak, nonatomic) IBOutlet UILabel *chatNotificationLabel;
@property (weak, nonatomic) IBOutlet UIButton *recordButton;
@property (weak, nonatomic) IBOutlet UIButton *recordButtonOnView;
@property(weak, nonatomic) IBOutlet UIView *bottomBar;
@property(nonatomic, strong) IBOutlet UIDigitButton *oneButton;
@ -107,5 +110,6 @@
- (IBAction)onOptionsConferenceClick:(id)sender;
- (IBAction)onNumpadClick:(id)sender;
- (IBAction)onChatClick:(id)sender;
- (IBAction)onRecordClick:(id)sender;
@end

View file

@ -48,6 +48,7 @@ const NSInteger SECURE_BUTTON_TAG = 5;
singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleControls:)];
videoZoomHandler = [[VideoZoomHandler alloc] init];
videoHidden = TRUE;
callRecording = FALSE;
}
return self;
}
@ -716,6 +717,39 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
[PhoneMainView.instance getOrCreateOneToOneChatRoom:addr waitView:_waitView];
}
- (IBAction)onRecordClick:(id)sender {
if (![_optionsView isHidden])
[self hideOptions:TRUE animated:ANIMATED];
if (callRecording) {
LOGD(@"Recording Stops");
[_recordButton setImage:[UIImage imageNamed:@"rec_on_default.png"] forState:UIControlStateNormal];
[_recordButtonOnView setHidden:TRUE];
LinphoneCall *call = linphone_core_get_current_call(LC);
linphone_call_stop_recording(call);
callRecording = FALSE;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *writablePath = [paths objectAtIndex:0];
writablePath = [writablePath stringByAppendingString:@"/"];
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:writablePath error:NULL];
if (directoryContent) {
return;
}
} else {
LOGD(@"Recording Starts");
[_recordButton setImage:[UIImage imageNamed:@"rec_off_default.png"] forState:UIControlStateNormal];
[_recordButtonOnView setHidden:FALSE];
LinphoneCall *call = linphone_core_get_current_call(LC);
linphone_call_start_recording(call);
callRecording = TRUE;
}
}
- (IBAction)onRoutesBluetoothClick:(id)sender {
[self hideRoutes:TRUE animated:TRUE];
[LinphoneManager.instance setSpeakerEnabled:FALSE];

View file

@ -173,7 +173,8 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
}
[dict setObject:display
forKey:@"display"];
[dict setObject:[NSNumber numberWithBool:!!linphone_chat_room_get_conference_address(cr)]
BOOL isGroupChat = linphone_chat_room_get_capabilities(cr) & LinphoneChatRoomCapabilitiesConference;
[dict setObject:[NSNumber numberWithBool:isGroupChat]
forKey:@"nbParticipants"];
[addresses addObject:dict];
if (addresses.count >= 4) //send no more data than needed

View file

@ -2617,6 +2617,12 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
}
linphone_call_params_enable_video(lcallParams, video);
//We set the record file name here because we can't do it after the call is started.
NSString *writablePath = [LinphoneUtils recordingFilePathFromCall:linphone_call_log_get_from_address(linphone_call_get_call_log(call))];
LOGD(@"record file path: %@\n", writablePath);
linphone_call_params_set_record_file(lcallParams, [writablePath cStringUsingEncoding:NSUTF8StringEncoding]);
linphone_call_accept_with_params(call, lcallParams);
linphone_call_params_unref(lcallParams);
}
@ -2727,6 +2733,10 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
LinphoneManager.instance.nextCallIsTransfer = NO;
ms_free(caddr);
} else {
//We set the record file name here because we can't do it after the call is started.
NSString *writablePath = [LinphoneUtils recordingFilePathFromCall:addr];
LOGD(@"record file path: %@\n", writablePath);
linphone_call_params_set_record_file(lcallParams, [writablePath cStringUsingEncoding:NSUTF8StringEncoding]);
call = linphone_core_invite_address_with_params(theLinphoneCore, addr, lcallParams);
if (call) {
// The LinphoneCallAppData object should be set on call creation with callback

View file

@ -0,0 +1,26 @@
//
// UILinphoneAudioPlayer.h
// linphone
//
// Created by David Idmansour on 13/07/2018.
//
#import <UIKit/UIKit.h>
@interface UILinphoneAudioPlayer : UIViewController
@property (weak, nonatomic) IBOutlet UIButton *playButton;
@property (weak, nonatomic) IBOutlet UIButton *stopButton;
@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
@property (weak, nonatomic) IBOutlet UIProgressView *timeProgress;
@property (weak, nonatomic) NSString *file;
+ (id)audioPlayerWithFilePath:(NSString *)filePath;
- (void)close;
- (BOOL)isOpened;
- (void)open;
- (void)pause;
- (void)setFile:(NSString *)fileName;
- (IBAction)onPlay:(id)sender;
- (IBAction)onStop:(id)sender;
- (IBAction)onTapTimeBar:(UITapGestureRecognizer *)sender;
@end

View file

@ -0,0 +1,207 @@
//
// UILinphoneAudioPlayer.m
// linphone
//
// Created by David Idmansour on 13/07/2018.
//
#import "UILinphoneAudioPlayer.h"
#import "Utils.h"
@implementation UILinphoneAudioPlayer {
@private
LinphonePlayer *player;
LinphonePlayerCbs *cbs;
int duration;
BOOL eofReached;
}
@synthesize file;
#pragma mark - Factory
+ (id)audioPlayerWithFilePath:(NSString *)filePath {
return [[self alloc] initWithFilePath:filePath];
}
#pragma mark - Life cycle
- (instancetype)initWithFilePath:(NSString *)filePath {
if (self = [super initWithNibName:NSStringFromClass(self.class) bundle:[NSBundle mainBundle]]) {
player = linphone_core_create_local_player(LC, NULL, NULL, NULL);
cbs = linphone_player_get_callbacks(player);
linphone_player_set_user_data(player, (__bridge void *)self);
linphone_player_cbs_set_eof_reached(cbs, on_eof_reached);
file = filePath;
eofReached = NO;
}
return self;
}
- (void)dealloc {
[self close];
}
- (void)close {
if (player) {
linphone_player_unref(player);
player = NULL;
}
[self.view removeFromSuperview];
}
- (void)viewDidAppear:(BOOL)animated {
[_playButton setTitle:@"" forState:UIControlStateNormal];
if (player && linphone_player_get_state(player) == LinphonePlayerPlaying)
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPause:[UIColor blackColor]] forState:UIControlStateNormal];
else
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal];
[_stopButton setTitle:@"" forState:UIControlStateNormal];
[_stopButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemRefresh:[UIColor blackColor]] forState:UIControlStateNormal];
}
- (void)open {
linphone_player_open(player, file.UTF8String);
duration = linphone_player_get_duration(player);
[self updateTimeLabel:0];
_timeProgress.progress = 0;
eofReached = NO;
[_playButton setTitle:@"" forState:UIControlStateNormal];
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal];
[_stopButton setTitle:@"" forState:UIControlStateNormal];
[_stopButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemRefresh:[UIColor blackColor]] forState:UIControlStateNormal];
}
- (BOOL)isOpened {
return player && linphone_player_get_state(player) != LinphonePlayerClosed;
}
- (void)setFile:(NSString *)fileName {
linphone_player_close(player);
file = fileName;
}
#pragma mark - Callbacks
void on_eof_reached(LinphonePlayer *pl) {
NSLog(@"EOF reached");
UILinphoneAudioPlayer *player = (__bridge UILinphoneAudioPlayer *)linphone_player_get_user_data(pl);
dispatch_async(dispatch_get_main_queue(), ^{
[player.playButton setTitle:@"" forState:UIControlStateNormal];
[player.playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal];
});
player->eofReached = YES;
}
#pragma mark - ViewController methods
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Utils
+ (NSString *)timeToString:(int)time {
time /= 1000;
int hours = time / 3600;
time %= 3600;
int minutes = time / 60;
int seconds = time % 60;
NSNumberFormatter *formatter = [NSNumberFormatter new];
formatter.maximumIntegerDigits = 2;
formatter.minimumIntegerDigits = 2;
NSString *ret = [NSString stringWithFormat:@"%@:%@",
[formatter stringFromNumber:[NSNumber numberWithInt:minutes]],
[formatter stringFromNumber:[NSNumber numberWithInt:seconds]]];
ret = (hours == 0)?ret:[[NSString stringWithFormat:@"%d:", hours] stringByAppendingString:ret];
return ret;
}
#pragma mark - Updating
- (void)updateTimeLabel:(int)currentTime {
_timeLabel.text = [NSString stringWithFormat:@"%@ / %@", [self.class timeToString:currentTime], [self.class timeToString:duration]];
}
- (void)update {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
while (player && linphone_player_get_state(player) == LinphonePlayerPlaying) {
int start = linphone_player_get_current_position(player);
while (player && start + 100 < duration && start + 100 > linphone_player_get_current_position(player)) {
[NSThread sleepForTimeInterval:0.01];
if (!player || linphone_player_get_state(player) == LinphonePlayerPaused)
break;
}
start = player ? linphone_player_get_current_position(player) : start;
dispatch_async(dispatch_get_main_queue(), ^{
_timeProgress.progress = (float)start / (float)duration;
[self updateTimeLabel:start];
});
}
});
}
- (void)pause {
if ([self isOpened]) {
linphone_player_pause(player);
[_playButton setTitle:@"" forState:UIControlStateNormal];
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal];
}
}
#pragma mark - Event handlers
- (IBAction)onPlay:(id)sender {
if (eofReached) {
linphone_player_seek(player, 0);
eofReached = NO;
}
LinphonePlayerState state = linphone_player_get_state(player);
switch (state) {
case LinphonePlayerClosed:
break;
case LinphonePlayerPaused:
NSLog(@"Play");
[_playButton setTitle:@"" forState:UIControlStateNormal];
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPause:[UIColor blackColor]] forState:UIControlStateNormal];
linphone_player_start(player);
break;
case LinphonePlayerPlaying:
NSLog(@"Pause");
[_playButton setTitle:@"" forState:UIControlStateNormal];
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal];
linphone_player_pause(player);
break;
}
[self update];
}
- (IBAction)onStop:(id)sender {
NSLog(@"Stop");
linphone_player_pause(player);
linphone_player_seek(player, 0);
eofReached = NO;
[_playButton setTitle:@"" forState:UIControlStateNormal];
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal];
_timeProgress.progress = 0;
[self updateTimeLabel:0];
}
- (IBAction)onTapTimeBar:(UITapGestureRecognizer *)sender {
if (sender.state != UIGestureRecognizerStateEnded)
return;
CGPoint loc = [sender locationInView:self.view];
CGPoint timeLoc = _timeProgress.frame.origin;
CGSize timeSize = _timeProgress.frame.size;
if (loc.x >= timeLoc.x && loc.x <= timeLoc.x + timeSize.width && loc.y >= timeLoc.y - 10 && loc.y <= timeLoc.y + timeSize.height + 10) {
float progress = (loc.x - timeLoc.x) / timeSize.width;
_timeProgress.progress = progress;
[self updateTimeLabel:(int)(progress * duration)];
linphone_player_seek(player, (int)(progress * duration));
}
}
@end

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UILinphoneAudioPlayer">
<connections>
<outlet property="playButton" destination="DUO-wG-b7H" id="Yb4-v3-wo2"/>
<outlet property="stopButton" destination="FXh-QI-38P" id="JUI-lL-g0e"/>
<outlet property="timeLabel" destination="YhA-gd-k7i" id="sLG-Mu-eAV"/>
<outlet property="timeProgress" destination="Un6-Ly-zHN" id="jpN-bN-hba"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="375" height="244"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DUO-wG-b7H">
<rect key="frame" x="10" y="112" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="20" id="0Ih-RU-H6C"/>
<constraint firstAttribute="height" constant="20" id="SxX-FF-vrP"/>
</constraints>
<color key="tintColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Play"/>
<connections>
<action selector="onPlay:" destination="-1" eventType="touchUpInside" id="mdn-z8-Vx0"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FXh-QI-38P">
<rect key="frame" x="40" y="112" width="20" height="20"/>
<gestureRecognizers/>
<constraints>
<constraint firstAttribute="height" constant="20" id="L60-0M-7lU"/>
<constraint firstAttribute="width" constant="20" id="XbH-oS-0HR"/>
</constraints>
<color key="tintColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Stop"/>
<connections>
<action selector="onStop:" destination="-1" eventType="touchUpInside" id="DwC-vv-yxp"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00 / 00:00" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YhA-gd-k7i">
<rect key="frame" x="275.5" y="113" width="89.5" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Un6-Ly-zHN">
<rect key="frame" x="70" y="121" width="195.5" height="2"/>
</progressView>
</subviews>
<gestureRecognizers/>
<constraints>
<constraint firstItem="Un6-Ly-zHN" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="BWM-Qg-HeY"/>
<constraint firstItem="YhA-gd-k7i" firstAttribute="leading" secondItem="Un6-Ly-zHN" secondAttribute="trailing" constant="10" id="G9J-X5-6oS"/>
<constraint firstItem="FXh-QI-38P" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="NRb-Ss-DJM"/>
<constraint firstItem="DUO-wG-b7H" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="10" id="Oph-fo-dql"/>
<constraint firstItem="YhA-gd-k7i" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="bPH-p6-5Ld"/>
<constraint firstItem="FXh-QI-38P" firstAttribute="leading" secondItem="DUO-wG-b7H" secondAttribute="trailing" constant="10" id="beC-Uz-QCv"/>
<constraint firstItem="Un6-Ly-zHN" firstAttribute="leading" secondItem="FXh-QI-38P" secondAttribute="trailing" constant="10" id="gcp-l1-wUa"/>
<constraint firstItem="DUO-wG-b7H" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="rwM-cP-iOM"/>
<constraint firstAttribute="trailing" secondItem="YhA-gd-k7i" secondAttribute="trailing" constant="10" id="yxZ-qn-Oyi"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outletCollection property="gestureRecognizers" destination="gGk-Ya-vJQ" appends="YES" id="SS3-4b-5sv"/>
</connections>
<point key="canvasLocation" x="24.5" y="-160"/>
</view>
<tapGestureRecognizer id="gGk-Ya-vJQ" userLabel="onTapRecognizer">
<connections>
<action selector="onTapTimeBar:" destination="-1" id="2St-UF-1QP"/>
</connections>
</tapGestureRecognizer>
</objects>
</document>

View file

@ -0,0 +1,24 @@
//
// UIRecordingCell.h
// linphone
//
// Created by benjamin_verdier on 25/07/2018.
//
#import <UIKit/UIKit.h>
@interface UIRecordingCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIView *playerView;
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (strong, nonatomic) IBOutlet UIToolbar *toolbar;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *shareButton;
@property(nonatomic, assign) __block NSString *recording;
- (id)initWithIdentifier:(NSString*)identifier;
- (void)updateFrame;
@end

View file

@ -0,0 +1,126 @@
//
// UIRecordingCell.m
// linphone
//
// Created by benjamin_verdier on 25/07/2018.
//
#import "UIRecordingCell.h"
#import "PhoneMainView.h"
#import "UILabel+Boldify.h"
#import "Utils.h"
#import "UILinphoneAudioPlayer.h"
@implementation UIRecordingCell
static UILinphoneAudioPlayer *player;
#pragma mark - Lifecycle Functions
/*
* TODO:
* - When we scroll past a selected row, the player loads incorrectly (no buttons). Probably a problem in the player code.
* - mkv recording is probably buggy, wrong eof. wav playing works but does not display the length/timestamp.
* - The share button is greyed out when not clicking it. idk why, it's really weird.
*/
- (id)initWithIdentifier:(NSString *)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier])) {
NSArray *arrayOfViews =
[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil];
// resize cell to match .nib size. It is needed when resized the cell to
// correctly adapt its height too
UIRecordingCell *sub = [arrayOfViews objectAtIndex:0];
[self setFrame:CGRectMake(0, 0, sub.frame.size.width, 40)];
self = sub;
self.recording = NULL;
_shareButton.target = self;
_shareButton.action = @selector(onShareButtonPressed);
}
return self;
}
- (void)dealloc {
self.recording = NULL;
[NSNotificationCenter.defaultCenter removeObserver:self];
}
#pragma mark - Property Functions
- (void)setRecording:(NSString *)arecording {
_recording = arecording;
if(_recording) {
NSArray *parsedRecording = [LinphoneUtils parseRecordingName:_recording];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"HH:mm:ss"];
_nameLabel.text = [[[parsedRecording objectAtIndex:0] stringByAppendingString:@" @ "] stringByAppendingString:[dateFormat stringFromDate:[parsedRecording objectAtIndex:1]]];
}
}
#pragma mark -
- (NSString *)accessibilityLabel {
return _nameLabel.text;
}
- (void)setEditing:(BOOL)editing {
[self setEditing:editing animated:FALSE];
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
if (animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
}
if (animated) {
[UIView commitAnimations];
}
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
self.selectionStyle = UITableViewCellSelectionStyleNone;
}
- (void)updateFrame {
CGRect frame = self.frame;
if (!self.selected) {
frame.size.height = 40;
} else {
frame.size.height = 150;
}
[self setFrame:frame];
}
-(void)setSelected:(BOOL)selected animated:(BOOL)animated{
[super setSelected:selected animated:animated];
_toolbar.hidden = !selected;
if (!selected) {
return;
}
if (!player)
player = [UILinphoneAudioPlayer audioPlayerWithFilePath:[self recording]];
else
[player setFile:[self recording]];
if ([player isOpened])
[player close];
[player.view removeFromSuperview];
[self addSubview:player.view];
[self bringSubviewToFront:player.view];
player.view.frame = _playerView.frame;
player.view.bounds = _playerView.bounds;
[player open];
}
- (void)onShareButtonPressed {
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:@[[NSURL fileURLWithPath:_recording]] applicationActivities:nil];
[activityVC setCompletionWithItemsHandler:^(UIActivityType __nullable activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError) {
//This is used to select the same row when we get back to the recordings view.
NSString *file = player.file;
//This reloads the view, if don't it's empty for some reason. Idealy we'd want to do this before closing the view but it's functionnal.
[PhoneMainView.instance popCurrentView];
[PhoneMainView.instance changeCurrentView:RecordingsListView.compositeViewDescription];
[[(RecordingsListView *)VIEW(RecordingsListView) tableController] setSelected:file];
}];
[PhoneMainView.instance presentViewController:activityVC animated:YES completion:nil];
}
@end

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="Safe area layout guides" minToolsVersion="9.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 autoresizesSubviews="NO" clipsSubviews="YES" contentMode="scaleToFill" id="e3d-Tw-Cmt" customClass="UIRecordingCell">
<rect key="frame" x="0.0" y="0.0" width="360" height="150"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Nk9-eo-eCo">
<rect key="frame" x="0.0" y="42" width="360" height="108"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Bzd-99-LAI">
<rect key="frame" x="16" y="0.0" width="300" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleAspectFill" fixedFrame="YES" translucent="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xjs-iK-dSH">
<rect key="frame" x="300" y="0.0" width="60" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<items>
<barButtonItem style="plain" systemItem="action" id="Drx-8h-kbM"/>
</items>
</toolbar>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<viewLayoutGuide key="safeArea" id="Ak9-b1-W1C"/>
<connections>
<outlet property="nameLabel" destination="Bzd-99-LAI" id="Ubb-kU-T09"/>
<outlet property="playerView" destination="Nk9-eo-eCo" id="64I-70-nHC"/>
<outlet property="shareButton" destination="Drx-8h-kbM" id="Vhv-4D-Ptx"/>
<outlet property="toolbar" destination="xjs-iK-dSH" id="NY4-Wk-dld"/>
</connections>
<point key="canvasLocation" x="26" y="105"/>
</view>
</objects>
</document>

View file

@ -45,6 +45,7 @@
#import "HistoryDetailsView.h"
#import "HistoryListView.h"
#import "ImageView.h"
#import "RecordingsListView.h"
#import "SettingsView.h"
#import "SideMenuView.h"
#import "UIConfirmationDialog.h"

View file

@ -0,0 +1,23 @@
//
// RecordingsListTableView.h
// linphone
//
// Created by benjamin_verdier on 25/07/2018.
//
#import <UIKit/UIKit.h>
#import "UICheckBoxTableView.h"
@interface RecordingsListTableView : UICheckBoxTableView {
@private
NSMutableDictionary *recordings;
//This has sub arrays indexed with the date of the recordings, themselves containings the recordings.
NSString *writablePath;
//This is the path to the folder where we write the recordings to. We should probably define it in LinphoneManager though.
}
- (void)loadData;
- (void)removeAllRecordings;
- (void)setSelected:(NSString *)filepath;
@end

View file

@ -0,0 +1,249 @@
//
// RecordingsListTableView.m
// linphone
//
// Created by benjamin_verdier on 25/07/2018.
//
#import "RecordingsListTableView.h"
#import "UIRecordingCell.h"
#import "LinphoneManager.h"
#import "PhoneMainView.h"
#import "Utils.h"
@implementation RecordingsListTableView
#pragma mark - Lifecycle Functions
- (void)initRecordingsTableViewController {
recordings = [NSMutableDictionary dictionary];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
writablePath = [paths objectAtIndex:0];
writablePath = [writablePath stringByAppendingString:@"/"];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (![self selectFirstRow]) {
//TODO: Make first cell expand to show player
}
[self loadData];
}
- (id)init {
self = [super init];
if (self) {
[self initRecordingsTableViewController];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
[self initRecordingsTableViewController];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self removeAllRecordings];
}
- (void)removeAllRecordings {
for (NSInteger j = 0; j < [self.tableView numberOfSections]; ++j) {
for (NSInteger i = 0; i < [self.tableView numberOfRowsInSection:j]; ++i) {
[[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]] setRecording:nil];
}
}
}
- (void)loadData {
LOGI(@"====>>>> Load recording list - Start");
recordings = [NSMutableDictionary dictionary];
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:writablePath error:NULL];
for (NSString *file in directoryContent) {
if (![file hasPrefix:@"recording_"]) {
continue;
}
NSArray *parsedName = [LinphoneUtils parseRecordingName:file];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"EEEE, MMM d, yyyy"];
NSString *dayPretty = [dateFormat stringFromDate:[parsedName objectAtIndex:1]];
NSMutableArray *recOfDay = [recordings objectForKey:dayPretty];
if (recOfDay) {
// Loop through the object until a later object, then insert it right before
int i;
for (i = 0; i < [recOfDay count]; ++i) {
NSString *fileAtIndex = [recOfDay objectAtIndex:i];
NSArray *parsedNameAtIndex = [LinphoneUtils parseRecordingName:fileAtIndex];
if ([[parsedName objectAtIndex:1] compare:[parsedNameAtIndex objectAtIndex:1]] == NSOrderedDescending) {
break;
}
}
[recOfDay insertObject:[writablePath stringByAppendingString:file] atIndex:i];
} else {
recOfDay = [NSMutableArray arrayWithObjects:[writablePath stringByAppendingString:file], nil];
[recordings setObject:recOfDay forKey:dayPretty];
}
}
LOGI(@"====>>>> Load recording list - End");
[super loadData];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *selectedRow = [self.tableView indexPathForSelectedRow];
if (selectedRow && [selectedRow compare:indexPath] == NSOrderedSame) {
return 150;
} else {
return 40;
}
}
#pragma mark - UITableViewDataSource Functions
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [recordings count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *sortedKey = [self getSortedKeys];
return [(NSArray *)[recordings objectForKey:[sortedKey objectAtIndex:section]] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *kCellId = NSStringFromClass(UIRecordingCell.class);
UIRecordingCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
if (cell == nil) {
cell = [[UIRecordingCell alloc] initWithIdentifier:kCellId];
}
NSString *date = [[self getSortedKeys] objectAtIndex:[indexPath section]];
NSMutableArray *subAr = [recordings objectForKey:date];
NSString *recordingPath = subAr[indexPath.row];
[cell setRecording:recordingPath];
[super accessoryForCell:cell atPath:indexPath];
//accessoryForCell set it to gray but we don't want it
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[cell updateFrame];
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
CGRect frame = CGRectMake(0, 0, tableView.frame.size.width, tableView.sectionHeaderHeight);
UIView *tempView = [[UIView alloc] initWithFrame:frame];
tempView.backgroundColor = [UIColor whiteColor];
UILabel *tempLabel = [[UILabel alloc] initWithFrame:frame];
tempLabel.backgroundColor = [UIColor clearColor];
tempLabel.textColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"color_A.png"]];
tempLabel.text = [[self getSortedKeys] objectAtIndex:section];
tempLabel.textAlignment = NSTextAlignmentCenter;
tempLabel.font = [UIFont boldSystemFontOfSize:17];
tempLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[tempView addSubview:tempLabel];
return tempView;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
if (![self isEditing]) {
[tableView beginUpdates];
[(UIRecordingCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath] updateFrame];
[tableView endUpdates];
}
}
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[NSNotificationCenter.defaultCenter removeObserver:self];
[tableView beginUpdates];
NSString *date = [[self getSortedKeys] objectAtIndex:[indexPath section]];
NSMutableArray *subAr = [recordings objectForKey:date];
NSString *recordingPath = subAr[indexPath.row];
[subAr removeObjectAtIndex:indexPath.row];
if (subAr.count == 0) {
[recordings removeObjectForKey:date];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section]
withRowAnimation:UITableViewRowAnimationFade];
}
UIRecordingCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
[cell setRecording:NULL];
remove([recordingPath cStringUsingEncoding:NSUTF8StringEncoding]);
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
[self loadData];
}
}
- (void)removeSelectionUsing:(void (^)(NSIndexPath *))remover {
[super removeSelectionUsing:^(NSIndexPath *indexPath) {
[NSNotificationCenter.defaultCenter removeObserver:self];
NSString *date = [[self getSortedKeys] objectAtIndex:[indexPath section]];
NSMutableArray *subAr = [recordings objectForKey:date];
NSString *recordingPath = subAr[indexPath.row];
[subAr removeObjectAtIndex:indexPath.row];
if (subAr.count == 0) {
[recordings removeObjectForKey:date];
}
UIRecordingCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
[cell setRecording:NULL];
remove([recordingPath cStringUsingEncoding:NSUTF8StringEncoding]);
}];
}
- (void)setSelected:(NSString *)filepath {
NSArray *parsedName = [LinphoneUtils parseRecordingName:filepath];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"EEEE, MMM d, yyyy"];
NSString *dayPretty = [dateFormat stringFromDate:[parsedName objectAtIndex:1]];
NSUInteger section;
NSArray *keys = [recordings allKeys];
for (section = 0; section < [keys count]; ++section) {
if ([dayPretty isEqualToString:(NSString *)[keys objectAtIndex:section]]) {
break;
}
}
NSUInteger row;
NSArray *recs = [recordings objectForKey:dayPretty];
for (row = 0; row < [recs count]; ++row) {
if ([filepath isEqualToString:(NSString *)[recs objectAtIndex:row]]) {
break;
}
}
NSUInteger indexes[] = {section, row};
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathWithIndexes:indexes length:2] animated:TRUE scrollPosition:UITableViewScrollPositionNone];
}
#pragma mark - Utilities
- (NSArray *)getSortedKeys {
return [[recordings allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString *day2, NSString *day1){
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"EEEE, MMM d, yyyy"];
NSDate *date1 = [dateFormat dateFromString:day1];
NSDate *date2 = [dateFormat dateFromString:day2];
return [date1 compare:date2];
}];
}
@end

View file

@ -0,0 +1,35 @@
//
// RecordingsListView.h
// linphone
//
// Created by benjamin_verdier on 25/07/2018.
//
#import <UIKit/UIKit.h>
#import "UICompositeView.h"
#import "RecordingsListTableView.h"
#import "UIIconButton.h"
typedef enum _RecordingSelectionMode { RecordingSelectionModeNone, RecordingSelectionModeEdit } RecordingSelectionMode;
@interface RecordingSelection : NSObject <UISearchBarDelegate> {
}
+ (void)setSelectionMode:(RecordingSelectionMode)selectionMode;
+ (RecordingSelectionMode)getSelectionMode;
@end
@interface RecordingsListView : UIViewController <UICompositeViewDelegate>
@property(strong, nonatomic) IBOutlet RecordingsListTableView *tableController;
@property(strong, nonatomic) IBOutlet UIView *topBar;
@property(weak, nonatomic) IBOutlet UIIconButton *deleteButton;
@property (strong, nonatomic) IBOutlet UIIconButton *backButton;
- (IBAction)onDeleteClick:(id)sender;
- (IBAction)onEditionChangeClick:(id)sender;
- (IBAction)onBackPressed:(id)sender;
@end

View file

@ -0,0 +1,101 @@
//
// RecordingsListView.m
// linphone
//
// Created by benjamin_verdier on 25/07/2018.
//
#import "RecordingsListView.h"
#import "PhoneMainView.h"
@implementation RecordingSelection
static RecordingSelectionMode sSelectionMode = RecordingSelectionModeNone;
+ (void)setSelectionMode:(RecordingSelectionMode)selectionMode {
sSelectionMode = selectionMode;
}
+ (RecordingSelectionMode)getSelectionMode {
return sSelectionMode;
}
@end
@implementation RecordingsListView
@synthesize tableController;
@synthesize topBar;
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:self.class
statusBar:StatusBarView.class
tabBar:TabBarView.class
sideMenu:SideMenuView.class
fullscreen:false
isLeftFragment:YES
fragmentWith:ContactDetailsView.class];
}
return compositeDescription;
}
- (UICompositeViewDescription *)compositeViewDescription {
return self.class.compositeViewDescription;
}
#pragma mark - ViewController Functions
- (void)viewDidLoad {
[super viewDidLoad];
tableController.tableView.accessibilityIdentifier = @"Recordings table";
tableController.tableView.tableFooterView = [[UIView alloc] init];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (tableController.isEditing) {
tableController.editing = NO;
}
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated {
self.view = NULL;
[self.tableController removeAllRecordings];
}
#pragma mark - Action Functions
- (IBAction)onDeleteClick:(id)sender {
NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"Do you want to delete selected recordings?", nil)];
[LinphoneManager.instance setContactsUpdated:TRUE];
[UIConfirmationDialog ShowWithMessage:msg
cancelMessage:nil
confirmMessage:nil
onCancelClick:^() {
[self onEditionChangeClick:nil];
}
onConfirmationClick:^() {
[tableController removeSelectionUsing:nil];
[tableController loadData];
[self onEditionChangeClick:nil];
}];
}
- (IBAction)onEditionChangeClick:(id)sender {
_backButton.hidden = self.tableController.isEditing;
}
- (IBAction)onBackPressed:(id)sender {
[PhoneMainView.instance popCurrentView];
}
@end

View file

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="RecordingsListView">
<connections>
<outlet property="backButton" destination="rAc-tI-AVp" id="CVb-Cy-yWP"/>
<outlet property="deleteButton" destination="zDs-pW-vyA" id="mye-fK-RaT"/>
<outlet property="tableController" destination="1pR-qo-CIP" id="FD0-NI-8ox"/>
<outlet property="topBar" destination="See-Aw-LPP" id="daF-pK-NHy"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="See-Aw-LPP" userLabel="topBar">
<rect key="frame" x="0.0" y="0.0" width="375" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_F.png" translatesAutoresizingMaskIntoConstraints="NO" id="7wu-Ow-YYU" userLabel="backgroundColor">
<rect key="frame" x="0.0" y="0.0" width="375" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
</imageView>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CqG-tB-maQ" userLabel="cancelButton" customClass="UIIconButton">
<rect key="frame" x="0.0" y="0.0" width="75" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Delete all"/>
<state key="normal" image="cancel_edit_default.png">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" image="cancel_edit_disabled.png"/>
<state key="highlighted" backgroundImage="color_E.png"/>
<connections>
<action selector="onCancelClick:" destination="1pR-qo-CIP" eventType="touchUpInside" id="qcZ-s6-jgK"/>
<action selector="onEditionChangeClick:" destination="-1" eventType="touchUpInside" id="vly-0H-4W2"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zDs-pW-vyA" userLabel="deleteButton" customClass="UIIconButton">
<rect key="frame" x="300" y="0.0" width="75" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Delete all"/>
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
<state key="normal" image="delete_default.png">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" image="delete_disabled.png"/>
<state key="highlighted" backgroundImage="color_E.png"/>
<connections>
<action selector="onDeleteClick:" destination="-1" eventType="touchUpInside" id="8LI-ry-dTU"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CWx-9g-0JG" userLabel="editButton" customClass="UIIconButton">
<rect key="frame" x="300" y="0.0" width="75" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Edit"/>
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
<state key="normal" image="edit_list_default.png">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" image="edit_list_disabled.png"/>
<state key="highlighted" backgroundImage="color_E.png"/>
<connections>
<action selector="onEditClick:" destination="1pR-qo-CIP" eventType="touchUpInside" id="0LH-n9-p0c"/>
<action selector="onEditionChangeClick:" destination="-1" eventType="touchUpInside" id="IeY-Yd-XP2"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="16S-9G-2cb" userLabel="toggleSelectionButton" customClass="UIIconButton">
<rect key="frame" x="225" y="0.0" width="75" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Select all"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
<state key="normal" image="deselect_all.png">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" image="select_all_disabled.png"/>
<state key="selected" image="select_all_default.png"/>
<state key="highlighted" backgroundImage="color_E.png"/>
<connections>
<action selector="onSelectionToggle:" destination="1pR-qo-CIP" eventType="touchUpInside" id="Hfi-f6-qfI"/>
</connections>
</button>
<button opaque="NO" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rAc-tI-AVp" userLabel="backButton" customClass="UIIconButton">
<rect key="frame" x="0.0" y="0.0" width="75" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Back"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
<state key="normal" image="back_default.png">
<color key="titleColor" red="0.28619974850000002" green="0.3214434981" blue="0.3598001301" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" image="back_disabled.png"/>
<state key="highlighted" backgroundImage="color_E.png"/>
<connections>
<action selector="onBackPressed:" destination="-1" eventType="touchUpInside" id="Quz-zf-q3K"/>
</connections>
</button>
</subviews>
</view>
<tableView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" allowsSelectionDuringEditing="YES" allowsMultipleSelectionDuringEditing="YES" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="3b0-Nd-4r0">
<rect key="frame" x="0.0" y="74" width="375" height="593"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<connections>
<outlet property="dataSource" destination="1pR-qo-CIP" id="z2V-Yd-AwQ"/>
<outlet property="delegate" destination="1pR-qo-CIP" id="eJQ-AV-7ts"/>
</connections>
</tableView>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No recording found" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zXd-Ic-rwm" userLabel="emptyTableLabel">
<rect key="frame" x="0.0" y="74" width="375" height="593"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="Q5M-cg-NOt"/>
<point key="canvasLocation" x="25.5" y="51.5"/>
</view>
<tableViewController id="1pR-qo-CIP" customClass="RecordingsListTableView">
<connections>
<outlet property="cancelButton" destination="CqG-tB-maQ" id="C90-0S-5WL"/>
<outlet property="deleteButton" destination="zDs-pW-vyA" id="mgV-PB-law"/>
<outlet property="editButton" destination="CWx-9g-0JG" id="hAA-6f-kX8"/>
<outlet property="emptyView" destination="zXd-Ic-rwm" id="D4k-nO-LKW"/>
<outlet property="toggleSelectionButton" destination="16S-9G-2cb" id="6pj-Yn-hy1"/>
<outlet property="view" destination="3b0-Nd-4r0" id="ng8-q5-bwm"/>
</connections>
<point key="canvasLocation" x="478" y="52"/>
</tableViewController>
</objects>
<resources>
<image name="back_default.png" width="24" height="22"/>
<image name="back_disabled.png" width="24" height="22"/>
<image name="cancel_edit_default.png" width="29" height="29"/>
<image name="cancel_edit_disabled.png" width="29" height="29"/>
<image name="color_E.png" width="2" height="2"/>
<image name="color_F.png" width="2" height="2"/>
<image name="delete_default.png" width="21" height="28"/>
<image name="delete_disabled.png" width="21" height="28"/>
<image name="deselect_all.png" width="27" height="27"/>
<image name="edit_list_default.png" width="30" height="28"/>
<image name="edit_list_disabled.png" width="30" height="28"/>
<image name="select_all_default.png" width="27" height="27"/>
<image name="select_all_disabled.png" width="27" height="27"/>
</resources>
</document>

View file

@ -15,6 +15,7 @@
#import "StatusBarView.h"
#import "ShopView.h"
#import "LinphoneManager.h"
#import "RecordingsListView.h"
@implementation SideMenuEntry
@ -60,6 +61,12 @@
}]];
}
[_sideMenuEntries
addObject:[[SideMenuEntry alloc] initWithTitle:NSLocalizedString(@"Recordings", nil)
tapBlock:^() {
[PhoneMainView.instance
changeCurrentView:RecordingsListView.compositeViewDescription];
}]];
[_sideMenuEntries
addObject:[[SideMenuEntry alloc] initWithTitle:NSLocalizedString(@"Settings", nil)
tapBlock:^() {

View file

@ -51,6 +51,9 @@ typedef enum {
+ (NSMutableDictionary <NSString *, PHAsset *> *)photoAssetsDictionary;
+ (NSString *)recordingFilePathFromCall:(const LinphoneAddress *)iaddr;
+ (NSArray *)parseRecordingName:(NSString *)filename;
@end
@interface NSNumber (HumanReadableSize)
@ -59,6 +62,12 @@ typedef enum {
@end
@interface UIImage (systemIcons)
+ (UIImage *)imageFromSystemBarButton:(UIBarButtonSystemItem)systemItem :(UIColor *) color;
@end
@interface NSString (linphoneExt)
- (NSString *)md5;

View file

@ -510,6 +510,44 @@
return addr;
}
+ (NSString *)recordingFilePathFromCall:(const LinphoneAddress *)iaddr {
NSString *filepath = @"recording_";
const char *address = linphone_address_get_username(iaddr);
filepath = [filepath stringByAppendingString:[NSString stringWithCString:address encoding:NSUTF8StringEncoding]];
NSDate * now = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"E-d-MMM-yyyy-HH-mm-ss"];
NSString *date = [dateFormat stringFromDate:now];
filepath = [filepath stringByAppendingString:@"_"];
filepath = [filepath stringByAppendingString:date];
filepath = [filepath stringByAppendingString:@".mkv"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *writablePath = [paths objectAtIndex:0];
writablePath = [writablePath stringByAppendingString:@"/"];
writablePath = [writablePath stringByAppendingString:filepath];
LOGD(@"file path is: %@\n", writablePath);
return writablePath;
//file name is recording_contact-name_dayName-day-monthName-year-hour-minutes-seconds
//The recording prefix is used to identify recordings in the cache directory.
//We will use name_dayName-day-monthName-year to separate recordings by days, then hour-minutes-seconds to order them in each day.
}
+ (NSArray *)parseRecordingName:(NSString *)filename {
NSString *rec = @"recording_"; //key that helps find recordings
NSString *subName = [filename substringFromIndex:[filename rangeOfString:rec].location]; //We remove the parent folders if they exist in the filename
NSArray *splitString = [subName componentsSeparatedByString:@"_"];
//splitString: first element is the 'recording' prefix, last element is the date with the "E-d-MMM-yyyy-HH-mm-ss" format.
NSString *name = [[splitString subarrayWithRange:NSMakeRange(1, [splitString count] -2)] componentsJoinedByString:@""];
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:@"E-d-MMM-yyyy-HH-mm-ss"];
NSString *dateWithMkv = [splitString objectAtIndex:[splitString count]-1]; //this will be in the form "E-d-MMM-yyyy-HH-mm-ss.mkv", we have to delete the extension
NSDate *date = [format dateFromString:[dateWithMkv substringToIndex:[dateWithMkv length] - 4]];
NSArray *res = [NSArray arrayWithObjects:name, date, nil];
return res;
}
@end
@implementation NSNumber (HumanReadableSize)
@ -531,6 +569,29 @@
@end
@implementation UIImage (systemIcons)
+ (UIImage *)imageFromSystemBarButton:(UIBarButtonSystemItem)systemItem :(UIColor *) color {
// thanks to Renetik https://stackoverflow.com/a/49822488
UIToolbar *bar = UIToolbar.new;
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:systemItem target:nil action:nil];
[bar setItems:@[buttonItem] animated:NO];
[bar snapshotViewAfterScreenUpdates:YES];
for (UIView *view in [(id) buttonItem view].subviews)
if ([view isKindOfClass:UIButton.class]) {
UIImage *image = [((UIButton *) view).imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
//[color set];
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
return nil;
}
@end
@implementation NSString (md5)
- (NSString *)md5 {

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -743,6 +743,17 @@
C90FAA7915AF54E6002091CB /* HistoryDetailsView.m in Sources */ = {isa = PBXBuildFile; fileRef = C90FAA7715AF54E6002091CB /* HistoryDetailsView.m */; };
CF15F21E20E4F9A3008B1DE6 /* UIImageViewDeletable.m in Sources */ = {isa = PBXBuildFile; fileRef = CF15F21C20E4F9A3008B1DE6 /* UIImageViewDeletable.m */; };
CF15F21F20E4F9A3008B1DE6 /* UIImageViewDeletable.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF15F21D20E4F9A3008B1DE6 /* UIImageViewDeletable.xib */; };
CF1DE92D210A0F5D00A0A97E /* UILinphoneAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = CF1DE924210A0F5A00A0A97E /* UILinphoneAudioPlayer.m */; };
CF1DE92E210A0F5D00A0A97E /* UILinphoneAudioPlayer.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF1DE92B210A0F5B00A0A97E /* UILinphoneAudioPlayer.xib */; };
CF7602D7210867E800749F76 /* RecordingsListView.m in Sources */ = {isa = PBXBuildFile; fileRef = CF7602D5210867E800749F76 /* RecordingsListView.m */; };
CF7602D8210867E800749F76 /* RecordingsListView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF7602D6210867E800749F76 /* RecordingsListView.xib */; };
CF7602E221086EB200749F76 /* RecordingsListTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = CF7602E021086EB200749F76 /* RecordingsListTableView.m */; };
CF7602E72108759A00749F76 /* UIRecordingCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CF7602E52108759A00749F76 /* UIRecordingCell.m */; };
CF7602E82108759A00749F76 /* UIRecordingCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF7602E62108759A00749F76 /* UIRecordingCell.xib */; };
CF7602F5210898CC00749F76 /* rec_off_default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CF7602EB210898C100749F76 /* rec_off_default@2x.png */; };
CF7602F6210898CC00749F76 /* rec_on_default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CF7602F2210898C400749F76 /* rec_on_default@2x.png */; };
CF7602F7210898CC00749F76 /* rec_off_default.png in Resources */ = {isa = PBXBuildFile; fileRef = CF7602F3210898C600749F76 /* rec_off_default.png */; };
CF7602F8210898CC00749F76 /* rec_on_default.png in Resources */ = {isa = PBXBuildFile; fileRef = CF7602F4210898C800749F76 /* rec_on_default.png */; };
CFBD7A2A20E504AE007C5286 /* delete_img.png in Resources */ = {isa = PBXBuildFile; fileRef = CFBD7A2320E504AD007C5286 /* delete_img.png */; };
D306459E1611EC2A00BB571E /* UILoadingImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D306459D1611EC2900BB571E /* UILoadingImageView.m */; };
D3128FE115AABC7E00A2147A /* ContactDetailsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3128FDF15AABC7E00A2147A /* ContactDetailsView.m */; };
@ -1763,7 +1774,6 @@
8C5BCECC1EB3859200A9AAEF /* mswebrtc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mswebrtc.framework; path = "liblinphone-sdk/apple-darwin/Frameworks/mswebrtc.framework"; sourceTree = "<group>"; };
8C5BCECD1EB3859200A9AAEF /* ortp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ortp.framework; path = "liblinphone-sdk/apple-darwin/Frameworks/ortp.framework"; sourceTree = "<group>"; };
8C5D1B991D9BC48100DC6539 /* UIShopTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIShopTableCell.h; sourceTree = "<group>"; };
8C5D1B9A1D9BC48100DC6539 /* UIShopTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIShopTableCell.m; sourceTree = "<group>"; };
8C5D1B9B1D9BC48100DC6539 /* UIShopTableCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = UIShopTableCell.xib; sourceTree = "<group>"; };
8C601FD220B462B0004FF95C /* mediastreamer2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mediastreamer2.framework; path = "liblinphone-sdk/apple-darwin/Frameworks/mediastreamer2.framework"; sourceTree = "<group>"; };
8C73477B1D9BA3A00022EE8C /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
@ -1862,6 +1872,21 @@
CF15F21B20E4F9A3008B1DE6 /* UIImageViewDeletable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIImageViewDeletable.h; sourceTree = "<group>"; };
CF15F21C20E4F9A3008B1DE6 /* UIImageViewDeletable.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIImageViewDeletable.m; sourceTree = "<group>"; };
CF15F21D20E4F9A3008B1DE6 /* UIImageViewDeletable.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UIImageViewDeletable.xib; sourceTree = "<group>"; };
CF1DE924210A0F5A00A0A97E /* UILinphoneAudioPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UILinphoneAudioPlayer.m; sourceTree = "<group>"; };
CF1DE92B210A0F5B00A0A97E /* UILinphoneAudioPlayer.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = UILinphoneAudioPlayer.xib; sourceTree = "<group>"; };
CF1DE92C210A0F5C00A0A97E /* UILinphoneAudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UILinphoneAudioPlayer.h; sourceTree = "<group>"; };
CF7602D4210867E800749F76 /* RecordingsListView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordingsListView.h; sourceTree = "<group>"; };
CF7602D5210867E800749F76 /* RecordingsListView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordingsListView.m; sourceTree = "<group>"; };
CF7602D6210867E800749F76 /* RecordingsListView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RecordingsListView.xib; sourceTree = "<group>"; };
CF7602DF21086EB100749F76 /* RecordingsListTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordingsListTableView.h; sourceTree = "<group>"; };
CF7602E021086EB200749F76 /* RecordingsListTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordingsListTableView.m; sourceTree = "<group>"; };
CF7602E42108759A00749F76 /* UIRecordingCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIRecordingCell.h; sourceTree = "<group>"; };
CF7602E52108759A00749F76 /* UIRecordingCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIRecordingCell.m; sourceTree = "<group>"; };
CF7602E62108759A00749F76 /* UIRecordingCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UIRecordingCell.xib; sourceTree = "<group>"; };
CF7602EB210898C100749F76 /* rec_off_default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "rec_off_default@2x.png"; sourceTree = "<group>"; };
CF7602F2210898C400749F76 /* rec_on_default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "rec_on_default@2x.png"; sourceTree = "<group>"; };
CF7602F3210898C600749F76 /* rec_off_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rec_off_default.png; sourceTree = "<group>"; };
CF7602F4210898C800749F76 /* rec_on_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rec_on_default.png; sourceTree = "<group>"; };
CFBD7A2320E504AD007C5286 /* delete_img.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = delete_img.png; sourceTree = "<group>"; };
D306459C1611EC2900BB571E /* UILoadingImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UILoadingImageView.h; sourceTree = "<group>"; };
D306459D1611EC2900BB571E /* UILoadingImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UILoadingImageView.m; sourceTree = "<group>"; };
@ -2214,12 +2239,6 @@
D3F83EEA1582021700336684 /* CallView.m */,
D381881C15FE3FCA00C3EDCA /* CallView.xib */,
638F1A861C2167C2004B8E02 /* CallView~ipad.xib */,
8CA70ACF1F9E0ABA00A3D2EB /* ChatConversationInfoView.h */,
8CA70AD01F9E0AE100A3D2EB /* ChatConversationInfoView.m */,
8CBD7BA220B6B7FD00E5DCC0 /* ChatConversationInfoView.xib */,
8CD99A3D2090BA24008A7CDA /* ChatConversationImdnView.h */,
8CD99A3B2090B9FA008A7CDA /* ChatConversationImdnView.m */,
8CBD7BA520B6B80D00E5DCC0 /* ChatConversationImdnView.xib */,
8C9C5E0B1F83B2EF006987FA /* ChatConversationCreateCollectionViewController.h */,
8C9C5E0C1F83B2EF006987FA /* ChatConversationCreateCollectionViewController.m */,
6341807A1BBC103100F71761 /* ChatConversationCreateTableView.h */,
@ -2227,6 +2246,12 @@
6336715E1BCBAAD200BFCBDE /* ChatConversationCreateView.h */,
6336715F1BCBAAD200BFCBDE /* ChatConversationCreateView.m */,
63B8D68E1BCBE65600C12B09 /* ChatConversationCreateView.xib */,
8CD99A3D2090BA24008A7CDA /* ChatConversationImdnView.h */,
8CD99A3B2090B9FA008A7CDA /* ChatConversationImdnView.m */,
8CBD7BA520B6B80D00E5DCC0 /* ChatConversationImdnView.xib */,
8CA70ACF1F9E0ABA00A3D2EB /* ChatConversationInfoView.h */,
8CA70AD01F9E0AE100A3D2EB /* ChatConversationInfoView.m */,
8CBD7BA220B6B7FD00E5DCC0 /* ChatConversationInfoView.xib */,
D32B6E2715A5BC430033019F /* ChatConversationTableView.h */,
D32B6E2815A5BC430033019F /* ChatConversationTableView.m */,
D3F795D315A582800077328B /* ChatConversationView.h */,
@ -2247,9 +2272,9 @@
D35497FB15875372000081D8 /* ContactsListView.h */,
D35497FC15875372000081D8 /* ContactsListView.m */,
D38187C015FE342800C3EDCA /* ContactsListView.xib */,
631098501D4660630041F2B3 /* CountryListView.xib */,
631098471D4660580041F2B3 /* CountryListView.h */,
631098481D4660580041F2B3 /* CountryListView.m */,
631098501D4660630041F2B3 /* CountryListView.xib */,
22F2508B107141E100AC9B3F /* DialerView.h */,
22F2508C107141E100AC9B3F /* DialerView.m */,
D38187C415FE345B00C3EDCA /* DialerView.xib */,
@ -2277,8 +2302,6 @@
63E27A311C4FECD000D332AE /* LaunchScreen.xib */,
1D3623240D0F684500981E51 /* LinphoneAppDelegate.h */,
1D3623250D0F684500981E51 /* LinphoneAppDelegate.m */,
8C2595D51DEDC8E1007A6424 /* ProviderDelegate.h */,
8C2595DC1DEDC92D007A6424 /* ProviderDelegate.m */,
D37DC6BF1594AE1800B2A5EB /* LinphoneCoreSettingsStore.h */,
D37DC6C01594AE1800B2A5EB /* LinphoneCoreSettingsStore.m */,
D3EA53FB159850E80037DC6B /* LinphoneManager.h */,
@ -2288,6 +2311,13 @@
D3F83F8C158229C500336684 /* PhoneMainView.h */,
D3F83F8D15822ABD00336684 /* PhoneMainView.m */,
639E9CB31C0DB88200019A75 /* PhoneMainView.xib */,
8C2595D51DEDC8E1007A6424 /* ProviderDelegate.h */,
8C2595DC1DEDC92D007A6424 /* ProviderDelegate.m */,
CF7602DF21086EB100749F76 /* RecordingsListTableView.h */,
CF7602E021086EB200749F76 /* RecordingsListTableView.m */,
CF7602D4210867E800749F76 /* RecordingsListView.h */,
CF7602D5210867E800749F76 /* RecordingsListView.m */,
CF7602D6210867E800749F76 /* RecordingsListView.xib */,
D35E759C159460B50066B1C1 /* SettingsView.h */,
D35E759D159460B50066B1C1 /* SettingsView.m */,
636316D61A1DEC650009B839 /* SettingsView.xib */,
@ -2333,9 +2363,6 @@
2214EB7012F84668002A5394 /* LinphoneUI */ = {
isa = PBXGroup;
children = (
CF15F21B20E4F9A3008B1DE6 /* UIImageViewDeletable.h */,
CF15F21C20E4F9A3008B1DE6 /* UIImageViewDeletable.m */,
CF15F21D20E4F9A3008B1DE6 /* UIImageViewDeletable.xib */,
63F1DF421BCE618E00EDED90 /* UIAddressTextField.h */,
63F1DF431BCE618E00EDED90 /* UIAddressTextField.m */,
63C441C11BBC23ED0053DC5E /* UIAssistantTextField.h */,
@ -2364,27 +2391,24 @@
D3A8BB6E15A6C7D500F96BE5 /* UIChatBubbleTextCell.h */,
D3A8BB6F15A6C7D500F96BE5 /* UIChatBubbleTextCell.m */,
639E9CA51C0DB7EA00019A75 /* UIChatBubbleTextCell.xib */,
8C92ABF11FA773C20006FB5D /* UIChatNotifiedEventCell.h */,
8C92ABF21FA773E50006FB5D /* UIChatNotifiedEventCell.m */,
8C92ABE71FA773190006FB5D /* UIChatNotifiedEventCell.xib */,
D3EA540F159853750037DC6B /* UIChatCell.h */,
D3EA5410159853750037DC6B /* UIChatCell.m */,
639CEB0B1A1DF4FA004DE38F /* UIChatCell.xib */,
8CA70AE11F9E39E400A3D2EB /* UIChatConversationInfoTableViewCell.h */,
8CA70AE21F9E39E400A3D2EB /* UIChatConversationInfoTableViewCell.m */,
8CBD7BA820B6B82400E5DCC0 /* UIChatConversationInfoTableViewCell.xib */,
8CD99A402090CE25008A7CDA /* UIChatConversationImdnTableViewCell.h */,
8CD99A412090CE6F008A7CDA /* UIChatConversationImdnTableViewCell.m */,
8CBD7BAB20B6B82A00E5DCC0 /* UIChatConversationImdnTableViewCell.xib */,
8C9C5E0E1F83BD97006987FA /* UIChatCreateCollectionViewCell.h */,
8C9C5E0F1F83BD97006987FA /* UIChatCreateCollectionViewCell.m */,
8CBD7BAE20B6B82F00E5DCC0 /* UIChatCreateCollectionViewCell.xib */,
8CA70AE11F9E39E400A3D2EB /* UIChatConversationInfoTableViewCell.h */,
8CA70AE21F9E39E400A3D2EB /* UIChatConversationInfoTableViewCell.m */,
8CBD7BA820B6B82400E5DCC0 /* UIChatConversationInfoTableViewCell.xib */,
63B8D69F1BCBF43100C12B09 /* UIChatCreateCell.h */,
63B8D6A01BCBF43100C12B09 /* UIChatCreateCell.m */,
639E9CA81C0DB7F200019A75 /* UIChatCreateCell.xib */,
8C5D1B991D9BC48100DC6539 /* UIShopTableCell.h */,
8C5D1B9A1D9BC48100DC6539 /* UIShopTableCell.m */,
8C5D1B9B1D9BC48100DC6539 /* UIShopTableCell.xib */,
8C9C5E0E1F83BD97006987FA /* UIChatCreateCollectionViewCell.h */,
8C9C5E0F1F83BD97006987FA /* UIChatCreateCollectionViewCell.m */,
8CBD7BAE20B6B82F00E5DCC0 /* UIChatCreateCollectionViewCell.xib */,
8C92ABF11FA773C20006FB5D /* UIChatNotifiedEventCell.h */,
8C92ABF21FA773E50006FB5D /* UIChatNotifiedEventCell.m */,
8C92ABE71FA773190006FB5D /* UIChatNotifiedEventCell.xib */,
639E9C7E1C0DB13D00019A75 /* UICheckBoxTableView.h */,
639E9C7F1C0DB13D00019A75 /* UICheckBoxTableView.m */,
D31B4B1E159876C0002E6C72 /* UICompositeView.h */,
@ -2397,9 +2421,6 @@
D3A55FBA15877E5E003FD403 /* UIContactCell.h */,
D3A55FBB15877E5E003FD403 /* UIContactCell.m */,
F088488D19FF8C41007FFCF3 /* UIContactCell.xib */,
24A345A71D95799900881A5C /* UIShopTableCell.h */,
24A345A51D95798A00881A5C /* UIShopTableCell.m */,
24A3459D1D95797700881A5C /* UIShopTableCell.xib */,
D3C6526515AC1A8F0092A874 /* UIContactDetailsCell.h */,
D3C6526615AC1A8F0092A874 /* UIContactDetailsCell.m */,
639E9CAE1C0DB80300019A75 /* UIContactDetailsCell.xib */,
@ -2412,18 +2433,31 @@
639CEB021A1DF4E4004DE38F /* UIHistoryCell.xib */,
636BC9951B5F921B00C754CE /* UIIconButton.h */,
636BC9961B5F921B00C754CE /* UIIconButton.m */,
CF15F21B20E4F9A3008B1DE6 /* UIImageViewDeletable.h */,
CF15F21C20E4F9A3008B1DE6 /* UIImageViewDeletable.m */,
CF15F21D20E4F9A3008B1DE6 /* UIImageViewDeletable.xib */,
634610041B61330300548952 /* UILabel+Boldify.h */,
634610051B61330300548952 /* UILabel+Boldify.m */,
CF1DE92C210A0F5C00A0A97E /* UILinphoneAudioPlayer.h */,
CF1DE924210A0F5A00A0A97E /* UILinphoneAudioPlayer.m */,
CF1DE92B210A0F5B00A0A97E /* UILinphoneAudioPlayer.xib */,
D306459C1611EC2900BB571E /* UILoadingImageView.h */,
D306459D1611EC2900BB571E /* UILoadingImageView.m */,
2214EBF112F86360002A5394 /* UIMutedMicroButton.h */,
2214EBF212F86360002A5394 /* UIMutedMicroButton.m */,
D36FB2D31589EF7C0036F6F2 /* UIPauseButton.h */,
D36FB2D41589EF7C0036F6F2 /* UIPauseButton.m */,
CF7602E42108759A00749F76 /* UIRecordingCell.h */,
CF7602E52108759A00749F76 /* UIRecordingCell.m */,
CF7602E62108759A00749F76 /* UIRecordingCell.xib */,
6313482E1B6F7B6600C6BDCB /* UIRoundBorderedButton.h */,
6313482F1B6F7B6600C6BDCB /* UIRoundBorderedButton.m */,
63FB30331A680E73008CA393 /* UIRoundedImageView.h */,
63FB30341A680E73008CA393 /* UIRoundedImageView.m */,
8C5D1B991D9BC48100DC6539 /* UIShopTableCell.h */,
24A345A51D95798A00881A5C /* UIShopTableCell.m */,
8C5D1B9B1D9BC48100DC6539 /* UIShopTableCell.xib */,
24A345A71D95799900881A5C /* UIShopTableCell.h */,
22968A5D12F875C600588287 /* UISpeakerButton.h */,
22968A5E12F875C600588287 /* UISpeakerButton.m */,
630CF5551AF7CE1500539F7A /* UITextField+DoneButton.h */,
@ -2434,6 +2468,8 @@
D32648431588F6FB00930C67 /* UIToggleButton.m */,
340751E5150F38FC00B89C47 /* UIVideoButton.h */,
340751E6150F38FD00B89C47 /* UIVideoButton.m */,
24A345A51D95798A00881A5C /* UIShopTableCell.m */,
24A3459D1D95797700881A5C /* UIShopTableCell.xib */,
);
path = LinphoneUI;
sourceTree = "<group>";
@ -2694,41 +2730,7 @@
633FEBE11D3CD5570014B822 /* images */ = {
isa = PBXGroup;
children = (
CFBD7A2320E504AD007C5286 /* delete_img.png */,
24BFAA9B209B062F004F47A7 /* callkit_logo.png */,
24BFAA99209B062E004F47A7 /* contacts_sip_default.png */,
24BFAA94209B062C004F47A7 /* contacts_sip_default@2x.png */,
24BFAA97209B062E004F47A7 /* contacts_sip_selected.png */,
24BFAA9C209B062F004F47A7 /* contacts_sip_selected@2x.png */,
24BFAA8C209B062B004F47A7 /* dialer_background.png */,
24BFAA98209B062E004F47A7 /* linphone_logo.png */,
24BFAA9D209B0630004F47A7 /* linphone_logo@2x.png */,
24BFAA93209B062C004F47A7 /* linphone_user.png */,
24BFAA95209B062D004F47A7 /* linphone_user@2x.png */,
24BFAA9A209B062F004F47A7 /* linphone_user~ipad.png */,
24BFAA96209B062D004F47A7 /* linphone_user~ipad@2x.png */,
8CF25D9B1F9F76BC00BEA0C1 /* chat_group_informations.png */,
8CF25D9C1F9F76BD00BEA0C1 /* chat_group_informations@2x.png */,
8CF25D941F9F336100BEA0C1 /* check_unselected.png */,
8CF25D8B1F9F336000BEA0C1 /* check_unselected@2x.png */,
8CA70AD31F9E285B00A3D2EB /* chat_group_add.png */,
8CA70AD21F9E285B00A3D2EB /* chat_group_add@2x.png */,
8C2A81941F87B8000012A66B /* chat_group_avatar.png */,
8C2A81931F87B7FF0012A66B /* chat_group_avatar@2x.png */,
8CB2B8F61F86229B0015CEE2 /* chat_secure.png */,
8CB2B8F71F86229C0015CEE2 /* next_disabled.png */,
8CB2B8F81F86229D0015CEE2 /* next_disabled@2x.png */,
8CDC61961F84D9270087CF7F /* check_selected@2x.png */,
8CDC618C1F84D89B0087CF7F /* check_selected.png */,
8CE24F551F8268840077AC0A /* conference_delete.png */,
8CE24F561F8268840077AC0A /* conference_delete@2x.png */,
8CE24F491F8234A20077AC0A /* next_default.png */,
8CE24F4A1F8234A30077AC0A /* next_default@2x.png */,
8C300D981E40E0CC00728EF3 /* lime_ko.png */,
8C300D991E40E0CC00728EF3 /* lime_ko@2x.png */,
8CD99A1B20908C27008A7CDA /* callkit_logo@2x.png */,
633FEBE21D3CD5570014B822 /* add_field_default.png */,
244523BC1E8D3A6C0037A187 /* chat_unsecure.png */,
633FEBE31D3CD5570014B822 /* add_field_default@2x.png */,
633FEBE41D3CD5570014B822 /* add_field_over.png */,
633FEBE51D3CD5570014B822 /* add_field_over@2x.png */,
@ -2781,9 +2783,6 @@
633FEC141D3CD5570014B822 /* call_quality_indicator_1.png */,
633FEC151D3CD5570014B822 /* call_quality_indicator_1@2x.png */,
633FEC161D3CD5570014B822 /* call_quality_indicator_2.png */,
244523AC1E8266CC0037A187 /* chat_delivered.png */,
244523AD1E8266CC0037A187 /* chat_error.png */,
244523AE1E8266CC0037A187 /* chat_read.png */,
633FEC171D3CD5570014B822 /* call_quality_indicator_2@2x.png */,
633FEC181D3CD5570014B822 /* call_quality_indicator_3.png */,
633FEC191D3CD5570014B822 /* call_quality_indicator_3@2x.png */,
@ -2821,6 +2820,8 @@
633FEC391D3CD5570014B822 /* call_video_start_default@2x.png */,
633FEC3A1D3CD5570014B822 /* call_video_start_disabled.png */,
633FEC3B1D3CD5570014B822 /* call_video_start_disabled@2x.png */,
24BFAA9B209B062F004F47A7 /* callkit_logo.png */,
8CD99A1B20908C27008A7CDA /* callkit_logo@2x.png */,
633FEC3C1D3CD5570014B822 /* camera_default.png */,
633FEC3D1D3CD5570014B822 /* camera_default@2x.png */,
633FEC3E1D3CD5570014B822 /* camera_disabled.png */,
@ -2847,10 +2848,20 @@
633FEC531D3CD5570014B822 /* chat_attachment_disabled@2x.png */,
633FEC541D3CD5570014B822 /* chat_attachment_over.png */,
633FEC551D3CD5570014B822 /* chat_attachment_over@2x.png */,
244523AC1E8266CC0037A187 /* chat_delivered.png */,
244523AD1E8266CC0037A187 /* chat_error.png */,
8CA70AD31F9E285B00A3D2EB /* chat_group_add.png */,
8CA70AD21F9E285B00A3D2EB /* chat_group_add@2x.png */,
8C2A81941F87B8000012A66B /* chat_group_avatar.png */,
8C2A81931F87B7FF0012A66B /* chat_group_avatar@2x.png */,
8CF25D9B1F9F76BC00BEA0C1 /* chat_group_informations.png */,
8CF25D9C1F9F76BD00BEA0C1 /* chat_group_informations@2x.png */,
633FEC561D3CD5570014B822 /* chat_list_indicator~ipad.png */,
633FEC571D3CD5570014B822 /* chat_list_indicator~ipad@2x.png */,
633FEC581D3CD5570014B822 /* chat_message_not_delivered.png */,
633FEC591D3CD5570014B822 /* chat_message_not_delivered@2x.png */,
244523AE1E8266CC0037A187 /* chat_read.png */,
8CB2B8F61F86229B0015CEE2 /* chat_secure.png */,
633FEC5A1D3CD5570014B822 /* chat_send_default.png */,
633FEC5B1D3CD5570014B822 /* chat_send_default@2x.png */,
633FEC5C1D3CD5570014B822 /* chat_send_disabled.png */,
@ -2869,6 +2880,11 @@
633FEC691D3CD5570014B822 /* chat_start_body_over@2x.png */,
633FEC6A1D3CD5570014B822 /* chat_start_body_over~ipad.png */,
633FEC6B1D3CD5570014B822 /* chat_start_body_over~ipad@2x.png */,
244523BC1E8D3A6C0037A187 /* chat_unsecure.png */,
8CDC618C1F84D89B0087CF7F /* check_selected.png */,
8CDC61961F84D9270087CF7F /* check_selected@2x.png */,
8CF25D941F9F336100BEA0C1 /* check_unselected.png */,
8CF25D8B1F9F336000BEA0C1 /* check_unselected@2x.png */,
633FEC6C1D3CD5570014B822 /* checkbox_checked.png */,
633FEC6D1D3CD5570014B822 /* checkbox_checked@2x.png */,
633FEC6E1D3CD5570014B822 /* checkbox_unchecked.png */,
@ -2883,6 +2899,8 @@
633FEC771D3CD5570014B822 /* color_I.png */,
633FEC781D3CD5570014B822 /* color_L.png */,
633FEC791D3CD5570014B822 /* color_M.png */,
8CE24F551F8268840077AC0A /* conference_delete.png */,
8CE24F561F8268840077AC0A /* conference_delete@2x.png */,
633FEC7A1D3CD5570014B822 /* conference_exit_default.png */,
633FEC7B1D3CD5570014B822 /* conference_exit_default@2x.png */,
633FEC7C1D3CD5570014B822 /* conference_exit_over.png */,
@ -2897,6 +2915,10 @@
633FEC851D3CD5570014B822 /* contacts_all_disabled@2x.png */,
633FEC861D3CD5570014B822 /* contacts_all_selected.png */,
633FEC871D3CD5570014B822 /* contacts_all_selected@2x.png */,
24BFAA99209B062E004F47A7 /* contacts_sip_default.png */,
24BFAA94209B062C004F47A7 /* contacts_sip_default@2x.png */,
24BFAA97209B062E004F47A7 /* contacts_sip_selected.png */,
24BFAA9C209B062F004F47A7 /* contacts_sip_selected@2x.png */,
633FEC8E1D3CD5570014B822 /* delete_default.png */,
633FEC8F1D3CD5570014B822 /* delete_default@2x.png */,
633FEC901D3CD5570014B822 /* delete_disabled.png */,
@ -2905,6 +2927,7 @@
633FEC931D3CD5570014B822 /* delete_field_default@2x.png */,
633FEC941D3CD5570014B822 /* delete_field_over.png */,
633FEC951D3CD5570014B822 /* delete_field_over@2x.png */,
CFBD7A2320E504AD007C5286 /* delete_img.png */,
633FEC961D3CD5570014B822 /* deselect_all.png */,
633FEC971D3CD5570014B822 /* deselect_all@2x.png */,
633FEC981D3CD5570014B822 /* dialer_alt_back.png */,
@ -2913,6 +2936,7 @@
633FEC9B1D3CD5570014B822 /* dialer_back_default@2x.png */,
633FEC9C1D3CD5570014B822 /* dialer_back_disabled.png */,
633FEC9D1D3CD5570014B822 /* dialer_back_disabled@2x.png */,
24BFAA8C209B062B004F47A7 /* dialer_background.png */,
633FECA01D3CD5570014B822 /* edit_default.png */,
633FECA11D3CD5570014B822 /* edit_default@2x.png */,
633FECA21D3CD5570014B822 /* edit_disabled.png */,
@ -2922,8 +2946,8 @@
633FECA61D3CD5570014B822 /* edit_list_disabled.png */,
633FECA71D3CD5570014B822 /* edit_list_disabled@2x.png */,
633FECA81D3CD5570014B822 /* footer_chat_default.png */,
633FECAA1D3CD5570014B822 /* footer_chat_disabled.png */,
633FECA91D3CD5570014B822 /* footer_chat_default@2x.png */,
633FECAA1D3CD5570014B822 /* footer_chat_disabled.png */,
633FECAB1D3CD5570014B822 /* footer_chat_disabled@2x.png */,
633FECAC1D3CD5570014B822 /* footer_contacts_default.png */,
633FECAD1D3CD5570014B822 /* footer_contacts_default@2x.png */,
@ -2959,6 +2983,14 @@
633FECCB1D3CD5570014B822 /* led_error@2x.png */,
633FECCC1D3CD5570014B822 /* led_inprogress.png */,
633FECCD1D3CD5570014B822 /* led_inprogress@2x.png */,
8C300D981E40E0CC00728EF3 /* lime_ko.png */,
8C300D991E40E0CC00728EF3 /* lime_ko@2x.png */,
24BFAA98209B062E004F47A7 /* linphone_logo.png */,
24BFAA9D209B0630004F47A7 /* linphone_logo@2x.png */,
24BFAA93209B062C004F47A7 /* linphone_user.png */,
24BFAA95209B062D004F47A7 /* linphone_user@2x.png */,
24BFAA9A209B062F004F47A7 /* linphone_user~ipad.png */,
24BFAA96209B062D004F47A7 /* linphone_user~ipad@2x.png */,
633FECD41D3CD5580014B822 /* list_details_default.png */,
633FECD51D3CD5580014B822 /* list_details_default@2x.png */,
633FECD61D3CD5580014B822 /* list_details_over.png */,
@ -2971,6 +3003,10 @@
633FECDD1D3CD5580014B822 /* micro_disabled@2x.png */,
633FECDE1D3CD5580014B822 /* micro_selected.png */,
633FECDF1D3CD5580014B822 /* micro_selected@2x.png */,
8CE24F491F8234A20077AC0A /* next_default.png */,
8CE24F4A1F8234A30077AC0A /* next_default@2x.png */,
8CB2B8F71F86229C0015CEE2 /* next_disabled.png */,
8CB2B8F81F86229D0015CEE2 /* next_disabled@2x.png */,
633FECE01D3CD5580014B822 /* nowebcamCIF.jpg */,
633FECE11D3CD5580014B822 /* numpad_0_default.png */,
633FECE21D3CD5580014B822 /* numpad_0_default@2x.png */,
@ -3107,6 +3143,10 @@
633FED651D3CD5590014B822 /* presence_online@2x.png */,
633FED661D3CD5590014B822 /* presence_unregistered.png */,
633FED671D3CD5590014B822 /* presence_unregistered@2x.png */,
CF7602F3210898C600749F76 /* rec_off_default.png */,
CF7602EB210898C100749F76 /* rec_off_default@2x.png */,
CF7602F4210898C800749F76 /* rec_on_default.png */,
CF7602F2210898C400749F76 /* rec_on_default@2x.png */,
633FED681D3CD5590014B822 /* route_bluetooth_default.png */,
633FED691D3CD5590014B822 /* route_bluetooth_default@2x.png */,
633FED6A1D3CD5590014B822 /* route_bluetooth_disabled.png */,
@ -3141,14 +3181,14 @@
633FED871D3CD5590014B822 /* select_all_default@2x.png */,
633FED881D3CD5590014B822 /* select_all_disabled.png */,
633FED891D3CD5590014B822 /* select_all_disabled@2x.png */,
8CD99A362090A824008A7CDA /* splashscreen.png */,
8CD99A352090A823008A7CDA /* splashscreen@2x.png */,
633FED8A1D3CD5590014B822 /* speaker_default.png */,
633FED8B1D3CD5590014B822 /* speaker_default@2x.png */,
633FED8C1D3CD5590014B822 /* speaker_disabled.png */,
633FED8D1D3CD5590014B822 /* speaker_disabled@2x.png */,
633FED8E1D3CD5590014B822 /* speaker_selected.png */,
633FED8F1D3CD5590014B822 /* speaker_selected@2x.png */,
8CD99A362090A824008A7CDA /* splashscreen.png */,
8CD99A352090A823008A7CDA /* splashscreen@2x.png */,
633FED941D3CD5590014B822 /* valid_default.png */,
633FED951D3CD5590014B822 /* valid_default@2x.png */,
633FED961D3CD5590014B822 /* valid_disabled.png */,
@ -3713,6 +3753,7 @@
636316D11A1DEBCB0009B839 /* AboutView.xib in Resources */,
8CBD7BA620B6B82400E5DCC0 /* UIChatConversationInfoTableViewCell.xib in Resources */,
244523AF1E8266CC0037A187 /* chat_delivered.png in Resources */,
CF7602F8210898CC00749F76 /* rec_on_default.png in Resources */,
633FEF481D3CD55A0014B822 /* speaker_selected.png in Resources */,
633FEED91D3CD55A0014B822 /* numpad_7~ipad.png in Resources */,
633FEE2B1D3CD5590014B822 /* color_C.png in Resources */,
@ -3843,6 +3884,7 @@
633FEDE91D3CD5590014B822 /* call_status_missed~ipad@2x.png in Resources */,
8CE24F4C1F8234A30077AC0A /* next_default@2x.png in Resources */,
244523B11E8266CC0037A187 /* chat_read.png in Resources */,
CF7602D8210867E800749F76 /* RecordingsListView.xib in Resources */,
639E9CAC1C0DB80300019A75 /* UIContactDetailsCell.xib in Resources */,
633FEE511D3CD5590014B822 /* deselect_all@2x.png in Resources */,
8CF25D951F9F336100BEA0C1 /* check_unselected@2x.png in Resources */,
@ -3939,6 +3981,7 @@
633FEEA41D3CD55A0014B822 /* numpad_1_default@2x.png in Resources */,
63E27A321C4FECD000D332AE /* LaunchScreen.xib in Resources */,
633FEED11D3CD55A0014B822 /* numpad_6~ipad.png in Resources */,
CF7602E82108759A00749F76 /* UIRecordingCell.xib in Resources */,
633FEED21D3CD55A0014B822 /* numpad_6~ipad@2x.png in Resources */,
633FEDCD1D3CD5590014B822 /* call_quality_indicator_0@2x.png in Resources */,
636316D41A1DEC650009B839 /* SettingsView.xib in Resources */,
@ -4007,6 +4050,7 @@
633FEE8F1D3CD55A0014B822 /* list_details_default@2x.png in Resources */,
633FEE5E1D3CD5590014B822 /* edit_list_default.png in Resources */,
633FEDB11D3CD5590014B822 /* call_add_disabled@2x.png in Resources */,
CF7602F7210898CC00749F76 /* rec_off_default.png in Resources */,
633FEDB21D3CD5590014B822 /* call_alt_back_default.png in Resources */,
633FEE3D1D3CD5590014B822 /* contacts_all_default@2x.png in Resources */,
633FEF251D3CD55A0014B822 /* route_bluetooth_disabled@2x.png in Resources */,
@ -4057,6 +4101,7 @@
633FEEA81D3CD55A0014B822 /* numpad_1_over~ipad@2x.png in Resources */,
D38187AD15FE340100C3EDCA /* ChatConversationView.xib in Resources */,
633FEE7C1D3CD5590014B822 /* history_missed_disabled.png in Resources */,
CF1DE92E210A0F5D00A0A97E /* UILinphoneAudioPlayer.xib in Resources */,
633FEDF11D3CD5590014B822 /* call_transfer_disabled@2x.png in Resources */,
633FEDFF1D3CD5590014B822 /* camera_switch_disabled@2x.png in Resources */,
633FEDDF1D3CD5590014B822 /* call_start_body_over@2x.png in Resources */,
@ -4123,6 +4168,7 @@
633FEE851D3CD5590014B822 /* led_error@2x.png in Resources */,
633FEDBE1D3CD5590014B822 /* call_back_default.png in Resources */,
633FEF0F1D3CD55A0014B822 /* pause_big_default@2x.png in Resources */,
CF7602F6210898CC00749F76 /* rec_on_default@2x.png in Resources */,
633FEF081D3CD55A0014B822 /* options_start_conference_disabled.png in Resources */,
63F1DF511BCE986A00EDED90 /* UICallConferenceCell.xib in Resources */,
633FEE301D3CD5590014B822 /* color_H.png in Resources */,
@ -4194,6 +4240,7 @@
639E9CA91C0DB7FB00019A75 /* UIConfirmationDialog.xib in Resources */,
633FEF111D3CD55A0014B822 /* pause_big_disabled@2x.png in Resources */,
633FEE321D3CD5590014B822 /* color_L.png in Resources */,
CF7602F5210898CC00749F76 /* rec_off_default@2x.png in Resources */,
633FEDB41D3CD5590014B822 /* call_alt_back_disabled.png in Resources */,
633FEE631D3CD5590014B822 /* footer_chat_default@2x.png in Resources */,
633FEE661D3CD5590014B822 /* footer_contacts_default.png in Resources */,
@ -4380,6 +4427,7 @@
buildActionMask = 2147483647;
files = (
63B81A0F1B57DA33009604A6 /* TPKeyboardAvoidingTableView.m in Sources */,
CF1DE92D210A0F5D00A0A97E /* UILinphoneAudioPlayer.m in Sources */,
1D60589B0D05DD56006BFB54 /* main.m in Sources */,
8CD99A3C2090B9FA008A7CDA /* ChatConversationImdnView.m in Sources */,
1D3623260D0F684500981E51 /* LinphoneAppDelegate.m in Sources */,
@ -4409,6 +4457,7 @@
34216F401547EBCD00EA9777 /* VideoZoomHandler.m in Sources */,
D3F83EEC1582021700336684 /* CallView.m in Sources */,
8C2595DD1DEDC92D007A6424 /* ProviderDelegate.m in Sources */,
CF7602D7210867E800749F76 /* RecordingsListView.m in Sources */,
63F1DF4B1BCE983200EDED90 /* CallConferenceTableView.m in Sources */,
D3F83F8E15822ABE00336684 /* PhoneMainView.m in Sources */,
6377AC801BDE4069007F7625 /* UIBackToCallButton.m in Sources */,
@ -4472,6 +4521,7 @@
D3807FC115C28940005BE9BC /* DCRoundSwitchKnobLayer.m in Sources */,
6306440E1BECB08500134C72 /* FirstLoginView.m in Sources */,
D3807FC315C28940005BE9BC /* DCRoundSwitchOutlineLayer.m in Sources */,
CF7602E221086EB200749F76 /* RecordingsListTableView.m in Sources */,
D3807FC515C28940005BE9BC /* DCRoundSwitchToggleLayer.m in Sources */,
633E41821D74259000320475 /* AssistantLinkView.m in Sources */,
D3807FE815C2894A005BE9BC /* IASKAppSettingsViewController.m in Sources */,
@ -4484,6 +4534,7 @@
D3807FF215C2894A005BE9BC /* IASKSettingsStoreFile.m in Sources */,
D3807FF415C2894A005BE9BC /* IASKSettingsStoreUserDefaults.m in Sources */,
639E9C801C0DB13D00019A75 /* UICheckBoxTableView.m in Sources */,
CF7602E72108759A00749F76 /* UIRecordingCell.m in Sources */,
D3807FF615C2894A005BE9BC /* IASKSpecifier.m in Sources */,
D3807FF815C2894A005BE9BC /* IASKPSSliderSpecifierViewCell.m in Sources */,
D3807FFA15C2894A005BE9BC /* IASKPSTextFieldSpecifierViewCell.m in Sources */,