forked from mirrors/linphone-iphone
Merge branch 'master' into travis_cmake
This commit is contained in:
commit
86d0b3f489
65 changed files with 2837 additions and 2501 deletions
64
.clang-format
Normal file
64
.clang-format
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: true
|
||||
AlignEscapedNewlinesLeft: false
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
IndentCaseLabels: false
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: Always
|
||||
...
|
||||
51
.git-pre-commit
Executable file
51
.git-pre-commit
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This hook purpose is to keep coding style consistent between all developers
|
||||
# It is automatically installed in .git/hooks folder by cmake on first run.
|
||||
|
||||
# From https://github.com/tatsuhiro-t/nghttp2/blob/master/pre-commit
|
||||
|
||||
function invalid-format-detected {
|
||||
cat git-clang-format.diff
|
||||
echo "*****************"
|
||||
echo "$0: Invalid coding style detected (see git-clang-format.diff for issues). Please correct it using one of the following:"
|
||||
echo "1) Apply patch located at git-clang-format.diff using:"
|
||||
echo " cd $(git rev-parse --show-toplevel) && $1"
|
||||
echo "2) Use clang-format to correctly format source code using:"
|
||||
echo " $2"
|
||||
echo "3) Reformat these lines manually."
|
||||
echo "*** Aborting commit.***"
|
||||
exit 1
|
||||
}
|
||||
function git-clang-format-diffing {
|
||||
format_diff=$(which git-clang-format)
|
||||
format_diff_options="--style=file"
|
||||
|
||||
#only diffing commited files, ignored staged one
|
||||
$format_diff $format_diff_options --diff $(git --no-pager diff --cached --name-status | grep -v '^D' | cut -f2) > git-clang-format.diff
|
||||
|
||||
if ! grep -q -E '(no modified files to format|clang-format did not modify any files)' git-clang-format.diff; then
|
||||
invalid-format-detected "git apply git-clang-format.diff" "clang-format $format_diff_options -i <some_file.c>"
|
||||
fi
|
||||
}
|
||||
|
||||
function clang-format-diff-diffing {
|
||||
format_diff=$(find /usr/bin/ -name 'clang-format-diff*' -type f | tail -n1)
|
||||
format_diff_options="-style file"
|
||||
|
||||
git diff-index --cached --diff-filter=ACMR -p HEAD -- | $format_diff $format_diff_options -p1 > git-clang-format.diff
|
||||
if [ -s git-clang-format.diff ]; then
|
||||
invalid-format-detected "patch -p0 < git-clang-format.diff" "${format_diff/-diff/} $format_diff_options -i <some_file.cpp>"
|
||||
fi
|
||||
}
|
||||
|
||||
set -e
|
||||
if which git-clang-format &>/dev/null; then
|
||||
git-clang-format-diffing $@
|
||||
elif [ ! -z "$(find /usr/bin/ /usr/local/bin/ /opt/bin/ -name 'clang-format-diff*' -type f 2>/dev/null)" ]; then
|
||||
# Warning! We need at least version 1.6...
|
||||
clang-format-diff-diffing $@
|
||||
else
|
||||
echo "$0: Please install clang-format (coding style checker) - could not find git-clang-format nor clang-format-diff in PATH. Skipping code verification..."
|
||||
exit 0
|
||||
fi
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -10,3 +10,5 @@ build
|
|||
test-reports
|
||||
WORK
|
||||
Makefile
|
||||
OUTPUT
|
||||
git-clang-format.diff
|
||||
|
|
|
|||
2
.gitmodules
vendored
2
.gitmodules
vendored
|
|
@ -32,7 +32,7 @@
|
|||
url = git://git.linphone.org/msx264.git
|
||||
[submodule "submodules/externals/libvpx"]
|
||||
path = submodules/externals/libvpx
|
||||
url = http://git.chromium.org/webm/libvpx.git
|
||||
url = https://github.com/webmproject/libvpx
|
||||
ignore = dirty
|
||||
[submodule "submodules/bzrtp"]
|
||||
path = submodules/bzrtp
|
||||
|
|
|
|||
|
|
@ -6,13 +6,11 @@ xcode_sdk: iphonesimulator8.1
|
|||
branches:
|
||||
only:
|
||||
- master
|
||||
- travis_cmake
|
||||
|
||||
env:
|
||||
global:
|
||||
- VERSION="8.1"
|
||||
- BYPASS_TOOLCHECK=1
|
||||
- KIF_SCREENSHOTS=Screens
|
||||
- secure: "JPPcWdmNIJiR3YcIwe0LRYce6qDdsiagO+eKKAp7eVk/wD9UHbz96Ms2FFkXxPhRJB1PA6Pf8FpAzIL2YRiJL9jRtKHSvtdF1cSto+57XyBkCsw7PkMVUIxp7fg6Wiwn3H3tucF8jisIkv/Pn7R+9EqePkZSqqu3+ig5AX9ApQ4="
|
||||
|
||||
before_install:
|
||||
|
|
@ -29,11 +27,11 @@ before_install:
|
|||
- sudo ln -s /usr/bin/strings /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/strings
|
||||
- git submodule update --init --recursive
|
||||
|
||||
install:
|
||||
install:
|
||||
- ./prepare.py all
|
||||
- make
|
||||
- make -s 1>/dev/null
|
||||
- mkdir -p Screens
|
||||
- export KIF_SCREENSHOTS=`pwd`/Screens
|
||||
|
||||
after_script:
|
||||
- ./Tools/imgur_upload.sh
|
||||
- ./Tools/imgur_upload.sh
|
||||
|
|
|
|||
|
|
@ -1,31 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ChatRoomViewController">
|
||||
<connections>
|
||||
<outlet property="addressLabel" destination="40" id="43"/>
|
||||
<outlet property="avatarImage" destination="41" id="44"/>
|
||||
<outlet property="cancelTransferButton" destination="75" id="85"/>
|
||||
<outlet property="chatView" destination="49" id="54"/>
|
||||
<outlet property="composeIndicatorView" destination="fx4-ao-53M" id="xk5-nK-lur"/>
|
||||
<outlet property="composeLabel" destination="fpY-Fv-ht2" id="4L6-ik-ZAe"/>
|
||||
<outlet property="editButton" destination="10" id="35"/>
|
||||
<outlet property="headerView" destination="39" id="45"/>
|
||||
<outlet property="imageTransferProgressBar" destination="74" id="79"/>
|
||||
<outlet property="messageBackgroundImage" destination="66" id="90"/>
|
||||
<outlet property="messageField" destination="63" id="64"/>
|
||||
<outlet property="messageView" destination="14" id="89"/>
|
||||
<outlet property="pictureButton" destination="73" id="84"/>
|
||||
<outlet property="sendButton" destination="15" id="27"/>
|
||||
<outlet property="tableController" destination="29" id="32"/>
|
||||
<outlet property="transferBackgroundImage" destination="83" id="88"/>
|
||||
<outlet property="transferView" destination="72" id="86"/>
|
||||
<outlet property="view" destination="6" id="11"/>
|
||||
<outlet property="waitView" destination="91" id="93"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
|
|
@ -90,46 +85,11 @@
|
|||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" id="72" userLabel="transferView">
|
||||
<rect key="frame" x="0.0" y="359" width="320" height="57"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="chat_progressbar_background.png" id="83" userLabel="transfertBackgroundImage">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="57"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</imageView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" id="75" userLabel="cancelTransferButton">
|
||||
<rect key="frame" x="262" y="0.0" width="58" height="57"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Cancel"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" backgroundImage="chat_cancel_default.png">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<state key="highlighted" backgroundImage="chat_cancel_over.png">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onTransferCancelClick:" destination="-1" eventType="touchUpInside" id="78"/>
|
||||
</connections>
|
||||
</button>
|
||||
<progressView opaque="NO" contentMode="scaleToFill" progress="0.5" id="74" userLabel="transferProgressBar">
|
||||
<rect key="frame" x="20" y="27" width="222" height="2"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Upload or download progression">
|
||||
<accessibilityTraits key="traits" none="YES" notEnabled="YES" updatesFrequently="YES"/>
|
||||
</accessibility>
|
||||
</progressView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" id="14" userLabel="messageView">
|
||||
<rect key="frame" x="0.0" y="359" width="320" height="57"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="chat_message_background.png" id="66" userLabel="messageBackgroundImage">
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" id="66" userLabel="messageBackgroundImage">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="57"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
|
|
@ -235,17 +195,6 @@
|
|||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view hidden="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="91" userLabel="waitView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<activityIndicatorView opaque="NO" clearsContextBeforeDrawing="NO" userInteractionEnabled="NO" contentMode="scaleToFill" animating="YES" style="whiteLarge" id="92" userLabel="activityIndicator">
|
||||
<rect key="frame" x="142" y="211" width="37" height="37"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
</activityIndicatorView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="0.66000000000000003" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<gestureRecognizers/>
|
||||
|
|
@ -264,16 +213,12 @@
|
|||
<image name="avatar_unknown_small.png" width="131" height="131"/>
|
||||
<image name="chat_back_default.png" width="320" height="88"/>
|
||||
<image name="chat_back_over.png" width="320" height="88"/>
|
||||
<image name="chat_cancel_default.png" width="116" height="115"/>
|
||||
<image name="chat_cancel_over.png" width="116" height="115"/>
|
||||
<image name="chat_edit_default.png" width="320" height="88"/>
|
||||
<image name="chat_edit_over.png" width="320" height="88"/>
|
||||
<image name="chat_message_background.png" width="640" height="117"/>
|
||||
<image name="chat_ok_default.png" width="320" height="88"/>
|
||||
<image name="chat_photo_default.png" width="71" height="115"/>
|
||||
<image name="chat_photo_disabled.png" width="71" height="115"/>
|
||||
<image name="chat_photo_over.png" width="71" height="115"/>
|
||||
<image name="chat_progressbar_background.png" width="524" height="115"/>
|
||||
<image name="chat_send_default.png" width="117" height="115"/>
|
||||
<image name="chat_send_disabled.png" width="117" height="115"/>
|
||||
<image name="chat_send_over.png" width="117" height="115"/>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
@protocol ChatRoomDelegate <NSObject>
|
||||
|
||||
- (BOOL)chatRoomStartImageDownload:(NSURL*)url userInfo:(id)userInfo;
|
||||
- (BOOL)chatRoomStartImageUpload:(UIImage*)image url:(NSURL*)url;
|
||||
- (void)resendChat:(NSString*)message withExternalUrl:(NSString*)url;
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,16 @@
|
|||
if( !chatRoom ) return;
|
||||
[self clearMessageList];
|
||||
self->messageList = linphone_chat_room_get_history(chatRoom, 0);
|
||||
|
||||
// also append transient upload messages because they are not in history yet!
|
||||
for (FileTransferDelegate *ftd in [[LinphoneManager instance] fileTransferDelegates]) {
|
||||
if (linphone_chat_room_get_peer_address(linphone_chat_message_get_chat_room(ftd.message)) ==
|
||||
linphone_chat_room_get_peer_address(chatRoom) &&
|
||||
linphone_chat_message_is_outgoing(ftd.message)) {
|
||||
LOGI(@"Appending transient upload message %p", ftd.message);
|
||||
self->messageList = ms_list_append(self->messageList, ftd.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reloadData {
|
||||
|
|
@ -76,9 +86,10 @@
|
|||
messageList = ms_list_append(messageList, linphone_chat_message_ref(chat));
|
||||
int pos = ms_list_size(messageList) - 1;
|
||||
|
||||
[self.tableView beginUpdates];
|
||||
[self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:pos inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
|
||||
[self.tableView endUpdates];
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:pos inSection:0];
|
||||
[self.tableView beginUpdates];
|
||||
[self.tableView insertRowsAtIndexPaths:@[ indexPath ] withRowAnimation:UITableViewRowAnimationFade];
|
||||
[self.tableView endUpdates];
|
||||
}
|
||||
|
||||
- (void)updateChatEntry:(LinphoneChatMessage*)chat {
|
||||
|
|
@ -183,7 +194,6 @@
|
|||
[tableView beginUpdates];
|
||||
LinphoneChatMessage *chat = ms_list_nth_data(self->messageList, (int)[indexPath row]);
|
||||
if( chat ){
|
||||
|
||||
linphone_chat_room_delete_message(chatRoom, chat);
|
||||
messageList = ms_list_remove(messageList, chat);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,14 +24,12 @@
|
|||
#import "ChatRoomTableViewController.h"
|
||||
#import "HPGrowingTextView.h"
|
||||
#import "ImagePickerViewController.h"
|
||||
#import "ImageSharing.h"
|
||||
#import "OrderedDictionary.h"
|
||||
|
||||
#include "linphone/linphonecore.h"
|
||||
|
||||
@interface ChatRoomViewController : UIViewController<HPGrowingTextViewDelegate, UICompositeViewDelegate, ImagePickerDelegate, ImageSharingDelegate, ChatRoomDelegate> {
|
||||
@interface ChatRoomViewController : UIViewController<HPGrowingTextViewDelegate, UICompositeViewDelegate, ImagePickerDelegate, ChatRoomDelegate> {
|
||||
LinphoneChatRoom *chatRoom;
|
||||
ImageSharing *imageSharing;
|
||||
OrderedDictionary *imageQualities;
|
||||
BOOL scrollOnGrowingEnabled;
|
||||
BOOL composingVisible;
|
||||
|
|
@ -54,17 +52,12 @@
|
|||
@property (strong, nonatomic) IBOutlet UIView *composeIndicatorView;
|
||||
|
||||
@property (nonatomic, strong) IBOutlet UIButton* pictureButton;
|
||||
@property (nonatomic, strong) IBOutlet UIButton* cancelTransferButton;
|
||||
@property (nonatomic, strong) IBOutlet UIProgressView* imageTransferProgressBar;
|
||||
@property (nonatomic, strong) IBOutlet UIView* transferView;
|
||||
@property (nonatomic, strong) IBOutlet UIView* waitView;
|
||||
|
||||
- (IBAction)onBackClick:(id)event;
|
||||
- (IBAction)onEditClick:(id)event;
|
||||
- (IBAction)onMessageChange:(id)sender;
|
||||
- (IBAction)onSendClick:(id)event;
|
||||
- (IBAction)onPictureClick:(id)event;
|
||||
- (IBAction)onTransferCancelClick:(id)event;
|
||||
- (IBAction)onListTap:(id)sender;
|
||||
|
||||
- (void)setChatRoom:(LinphoneChatRoom*)room;
|
||||
|
|
|
|||
|
|
@ -21,10 +21,12 @@
|
|||
#import "PhoneMainView.h"
|
||||
#import "DTActionSheet.h"
|
||||
#import "UILinphone.h"
|
||||
|
||||
#import "DTAlertView.h"
|
||||
#import "Utils/FileTransferDelegate.h"
|
||||
#import <NinePatch.h>
|
||||
#import <MobileCoreServices/UTCoreTypes.h>
|
||||
#import "Utils.h"
|
||||
#import "UIChatRoomCell.h"
|
||||
|
||||
@implementation ChatRoomViewController
|
||||
|
||||
|
|
@ -44,28 +46,23 @@
|
|||
@synthesize listTapGestureRecognizer;
|
||||
@synthesize listSwipeGestureRecognizer;
|
||||
@synthesize pictureButton;
|
||||
@synthesize imageTransferProgressBar;
|
||||
@synthesize cancelTransferButton;
|
||||
@synthesize transferView;
|
||||
@synthesize waitView;
|
||||
|
||||
#pragma mark - Lifecycle Functions
|
||||
|
||||
- (id)init {
|
||||
self = [super initWithNibName:@"ChatRoomViewController" bundle:[NSBundle mainBundle]];
|
||||
if (self != nil) {
|
||||
self->scrollOnGrowingEnabled = TRUE;
|
||||
self->chatRoom = NULL;
|
||||
self->imageSharing = NULL;
|
||||
self->listTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onListTap:)];
|
||||
self.listSwipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(onListSwipe:)];
|
||||
self->imageQualities = [[OrderedDictionary alloc] initWithObjectsAndKeys:
|
||||
[NSNumber numberWithFloat:0.9], NSLocalizedString(@"Maximum", nil),
|
||||
[NSNumber numberWithFloat:0.5], NSLocalizedString(@"Average", nil),
|
||||
[NSNumber numberWithFloat:0.0], NSLocalizedString(@"Minimum", nil), nil];
|
||||
self->composingVisible = TRUE;
|
||||
}
|
||||
return self;
|
||||
self = [super initWithNibName:@"ChatRoomViewController" bundle:[NSBundle mainBundle]];
|
||||
if (self != nil) {
|
||||
self->scrollOnGrowingEnabled = TRUE;
|
||||
self->chatRoom = NULL;
|
||||
self->listTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onListTap:)];
|
||||
self.listSwipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(onListSwipe:)];
|
||||
self->imageQualities = [[OrderedDictionary alloc] initWithObjectsAndKeys:
|
||||
[NSNumber numberWithFloat:0.9], NSLocalizedString(@"Maximum", nil),
|
||||
[NSNumber numberWithFloat:0.5], NSLocalizedString(@"Average", nil),
|
||||
[NSNumber numberWithFloat:0.0], NSLocalizedString(@"Minimum", nil), nil];
|
||||
self->composingVisible = TRUE;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
|
@ -156,6 +153,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
selector:@selector(textComposeEvent:)
|
||||
name:kLinphoneTextComposeEvent
|
||||
object:nil];
|
||||
|
||||
if([tableController isEditing])
|
||||
[tableController setEditing:FALSE animated:FALSE];
|
||||
[editButton setOff];
|
||||
|
|
@ -167,39 +165,16 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
BOOL fileSharingEnabled = [[LinphoneManager instance] lpConfigStringForKey:@"sharing_server_preference"] != NULL
|
||||
&& [[[LinphoneManager instance] lpConfigStringForKey:@"sharing_server_preference"] length]>0;
|
||||
[pictureButton setEnabled:fileSharingEnabled];
|
||||
[waitView setHidden:TRUE];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
if(imageSharing) {
|
||||
[imageSharing cancel];
|
||||
}
|
||||
|
||||
[messageField resignFirstResponder];
|
||||
|
||||
[self setComposingVisible:FALSE withDelay:0]; // will hide the "user is composing.." message
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIKeyboardWillShowNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIKeyboardWillHideNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:kLinphoneTextReceived
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UITextViewTextDidChangeNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:kLinphoneTextComposeEvent
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
|
||||
|
|
@ -211,7 +186,6 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
|
||||
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
|
||||
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
|
||||
|
||||
}
|
||||
|
||||
-(void)didReceiveMemoryWarning {
|
||||
|
|
@ -287,9 +261,9 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
|
||||
static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud) {
|
||||
ChatRoomViewController* thiz = (__bridge ChatRoomViewController*)ud;
|
||||
const char*text = linphone_chat_message_get_text(msg);
|
||||
const char *text = (linphone_chat_message_get_file_transfer_information(msg) != NULL) ? "photo transfer" : linphone_chat_message_get_text(msg);
|
||||
LOGI(@"Delivery status for [%s] is [%s]",text,linphone_chat_message_state_to_string(state));
|
||||
ChatRoomViewController* thiz = (__bridge ChatRoomViewController*)ud;
|
||||
[thiz.tableController updateChatEntry:msg];
|
||||
}
|
||||
|
||||
|
|
@ -317,39 +291,34 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
|
|||
}
|
||||
|
||||
- (void)saveAndSend:(UIImage*)image url:(NSURL*)url {
|
||||
if(url == nil) {
|
||||
[waitView setHidden:FALSE];
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[[LinphoneManager instance].photoLibrary
|
||||
writeImageToSavedPhotosAlbum:image.CGImage
|
||||
orientation:(ALAssetOrientation)[image imageOrientation]
|
||||
completionBlock:^(NSURL *assetURL, NSError *error){
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[waitView setHidden:TRUE];
|
||||
if (error) {
|
||||
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
|
||||
// photo from Camera, must be saved first
|
||||
if (url == nil) {
|
||||
[[LinphoneManager instance]
|
||||
.photoLibrary
|
||||
writeImageToSavedPhotosAlbum:image.CGImage
|
||||
orientation:(ALAssetOrientation)[image imageOrientation]
|
||||
completionBlock:^(NSURL *assetURL, NSError *error) {
|
||||
if (error) {
|
||||
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
|
||||
|
||||
UIAlertView* errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write image to photo library", nil)
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"Ok",nil)
|
||||
otherButtonTitles:nil ,nil];
|
||||
[errorAlert show];
|
||||
return;
|
||||
}
|
||||
LOGI(@"Image saved to [%@]", [assetURL absoluteString]);
|
||||
[self chatRoomStartImageUpload:image url:assetURL];
|
||||
});
|
||||
}];
|
||||
});
|
||||
} else {
|
||||
[self chatRoomStartImageUpload:image url:url];
|
||||
}
|
||||
UIAlertView *errorAlert = [[UIAlertView alloc]
|
||||
initWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write image to photo library", nil)
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"Ok", nil)
|
||||
otherButtonTitles:nil, nil];
|
||||
[errorAlert show];
|
||||
} else {
|
||||
LOGI(@"Image saved to [%@]", [assetURL absoluteString]);
|
||||
[self chatRoomStartImageUpload:image url:assetURL];
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
[self chatRoomStartImageUpload:image url:url];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)chooseImageQuality:(UIImage*)image url:(NSURL*)url {
|
||||
[waitView setHidden:FALSE];
|
||||
|
||||
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:NSLocalizedString(@"Choose the image size", nil)];
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
//UIImage *image = [original_image normalizedImage];
|
||||
|
|
@ -365,7 +334,6 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
|
|||
}
|
||||
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Cancel", nil) block:nil];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[waitView setHidden:TRUE];
|
||||
[sheet showInView:[PhoneMainView instance].view];
|
||||
});
|
||||
});
|
||||
|
|
@ -498,8 +466,8 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
|
|||
#pragma mark - Action Functions
|
||||
|
||||
- (IBAction)onBackClick:(id)event {
|
||||
[self.tableController setChatRoom:NULL];
|
||||
[[PhoneMainView instance] popCurrentView];
|
||||
[self.tableController setChatRoom:NULL];
|
||||
[[PhoneMainView instance] popCurrentView];
|
||||
}
|
||||
|
||||
- (IBAction)onEditClick:(id)event {
|
||||
|
|
@ -577,111 +545,21 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
|
|||
[sheet showInView:[PhoneMainView instance].view];
|
||||
}
|
||||
|
||||
- (IBAction)onTransferCancelClick:(id)event {
|
||||
if(imageSharing) {
|
||||
[imageSharing cancel];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark ChatRoomDelegate
|
||||
|
||||
- (BOOL)chatRoomStartImageDownload:(NSURL*)url userInfo:(id)userInfo {
|
||||
if(imageSharing == nil) {
|
||||
imageSharing = [ImageSharing newImageSharingDownload:url delegate:self userInfo:userInfo];
|
||||
[messageView setHidden:TRUE];
|
||||
[transferView setHidden:FALSE];
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
- (BOOL)chatRoomStartImageUpload:(UIImage*)image url:(NSURL*)url{
|
||||
if(imageSharing == nil) {
|
||||
NSString *urlString = [[LinphoneManager instance] lpConfigStringForKey:@"sharing_server_preference"];
|
||||
imageSharing = [ImageSharing newImageSharingUpload:[NSURL URLWithString:urlString] image:image delegate:self userInfo:url];
|
||||
[messageView setHidden:TRUE];
|
||||
[transferView setHidden:FALSE];
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
FileTransferDelegate * fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
[[[LinphoneManager instance] fileTransferDelegates] addObject:fileTransfer];
|
||||
[fileTransfer upload:image withURL:url forChatRoom:chatRoom];
|
||||
[tableController addChatEntry:linphone_chat_message_ref(fileTransfer.message)];
|
||||
[tableController scrollToBottom:true];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url {
|
||||
[self sendMessage:message withExterlBodyUrl:[NSURL URLWithString:url] withInternalURL:nil];
|
||||
}
|
||||
|
||||
#pragma mark ImageSharingDelegate
|
||||
|
||||
- (void)imageSharingProgress:(ImageSharing*)aimageSharing progress:(float)progress {
|
||||
[imageTransferProgressBar setProgress:progress];
|
||||
}
|
||||
|
||||
- (void)imageSharingAborted:(ImageSharing*)aimageSharing {
|
||||
[messageView setHidden:FALSE];
|
||||
[transferView setHidden:TRUE];
|
||||
imageSharing = nil;
|
||||
}
|
||||
|
||||
- (void)imageSharingError:(ImageSharing*)aimageSharing error:(NSError *)error {
|
||||
[messageView setHidden:FALSE];
|
||||
[transferView setHidden:TRUE];
|
||||
NSString *url = [aimageSharing.connection.currentRequest.URL absoluteString];
|
||||
if (aimageSharing.upload) {
|
||||
LOGE(@"Cannot upload file to server [%@] because [%@]", url, [error localizedDescription]);
|
||||
UIAlertView* errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot transfer file to remote contact", nil)
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"Ok",nil)
|
||||
otherButtonTitles:nil ,nil];
|
||||
[errorAlert show];
|
||||
} else {
|
||||
LOGE(@"Cannot download file from [%@] because [%@]", url, [error localizedDescription]);
|
||||
UIAlertView* errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot transfer file from remote contact", nil)
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"Continue", nil)
|
||||
otherButtonTitles:nil, nil];
|
||||
[errorAlert show];
|
||||
}
|
||||
imageSharing = nil;
|
||||
}
|
||||
|
||||
- (void)imageSharingUploadDone:(ImageSharing*)aimageSharing url:(NSURL*)url{
|
||||
[self sendMessage:nil withExterlBodyUrl:url withInternalURL:[aimageSharing userInfo] ];
|
||||
|
||||
[messageView setHidden:FALSE];
|
||||
[transferView setHidden:TRUE];
|
||||
imageSharing = nil;
|
||||
}
|
||||
|
||||
- (void)imageSharingDownloadDone:(ImageSharing*)aimageSharing image:(UIImage *)image {
|
||||
[messageView setHidden:FALSE];
|
||||
[transferView setHidden:TRUE];
|
||||
|
||||
__block LinphoneChatMessage *chat = (LinphoneChatMessage *)[(NSValue*)[imageSharing userInfo] pointerValue];
|
||||
[[LinphoneManager instance].photoLibrary writeImageToSavedPhotosAlbum:image.CGImage
|
||||
orientation:(ALAssetOrientation)[image imageOrientation]
|
||||
completionBlock:^(NSURL *assetURL, NSError *error){
|
||||
if (error) {
|
||||
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
|
||||
|
||||
UIAlertView* errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write image to photo library", nil)
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"Ok",nil)
|
||||
otherButtonTitles:nil ,nil];
|
||||
[errorAlert show];
|
||||
return;
|
||||
}
|
||||
LOGI(@"Image saved to [%@]", [assetURL absoluteString]);
|
||||
[LinphoneManager setValueInMessageAppData:[assetURL absoluteString] forKey:@"localimage" inMessage:chat];
|
||||
[tableController updateChatEntry:chat];
|
||||
}];
|
||||
imageSharing = nil;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark ImagePickerDelegate
|
||||
|
||||
- (void)imagePickerDelegateImage:(UIImage*)image info:(NSDictionary *)info {
|
||||
|
|
@ -698,7 +576,6 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
|
|||
[self chooseImageQuality:image url:url];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Keyboard Event Functions
|
||||
|
||||
- (void)keyboardWillHide:(NSNotification *)notif {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#import "ChatTableViewController.h"
|
||||
#import "UIChatCell.h"
|
||||
|
||||
#import "FileTransferDelegate.h"
|
||||
|
||||
#import "linphone/linphonecore.h"
|
||||
#import "PhoneMainView.h"
|
||||
#import "UACellBackgroundView.h"
|
||||
|
|
@ -64,43 +66,44 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
|
|||
LinphoneChatMessage* last_elem_message = linphone_chat_room_get_user_data(elem);
|
||||
|
||||
if( last_new_message && last_elem_message ){
|
||||
time_t new = linphone_chat_message_get_time(last_new_message);
|
||||
time_t old = linphone_chat_message_get_time(last_elem_message);
|
||||
if ( new < old ) return 1;
|
||||
else if ( new > old) return -1;
|
||||
}
|
||||
return 0;
|
||||
time_t new = linphone_chat_message_get_time(last_new_message);
|
||||
time_t old = linphone_chat_message_get_time(last_elem_message);
|
||||
if (new < old)
|
||||
return 1;
|
||||
else if (new > old)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (MSList*)sortChatRooms {
|
||||
MSList* sorted = nil;
|
||||
MSList* unsorted = linphone_core_get_chat_rooms([LinphoneManager getLc]);
|
||||
MSList* iter = unsorted;
|
||||
MSList *sorted = nil;
|
||||
MSList *unsorted = linphone_core_get_chat_rooms([LinphoneManager getLc]);
|
||||
MSList *iter = unsorted;
|
||||
|
||||
while (iter) {
|
||||
// store last message in user data
|
||||
MSList* history = linphone_chat_room_get_history(iter->data, 1);
|
||||
LinphoneChatMessage* last_msg = history? history->data : NULL;
|
||||
if( last_msg ){
|
||||
linphone_chat_room_set_user_data(iter->data, linphone_chat_message_ref(last_msg));
|
||||
}
|
||||
ms_list_free_with_data(history, (void (*)(void *))linphone_chat_message_unref);
|
||||
while (iter) {
|
||||
// store last message in user data
|
||||
LinphoneChatRoom *chat_room = iter->data;
|
||||
MSList *history = linphone_chat_room_get_history(iter->data, 1);
|
||||
assert(ms_list_size(history) <= 1);
|
||||
LinphoneChatMessage *last_msg = history ? history->data : NULL;
|
||||
if (last_msg) {
|
||||
linphone_chat_message_ref(last_msg);
|
||||
linphone_chat_room_set_user_data(chat_room, last_msg);
|
||||
}
|
||||
sorted = ms_list_insert_sorted(sorted, chat_room, (MSCompareFunc)sorted_history_comparison);
|
||||
|
||||
sorted = ms_list_insert_sorted(sorted,
|
||||
iter->data,
|
||||
(MSCompareFunc)sorted_history_comparison);
|
||||
|
||||
iter = iter->next;
|
||||
}
|
||||
return sorted;
|
||||
iter = iter->next;
|
||||
}
|
||||
return sorted;
|
||||
}
|
||||
|
||||
static void chatTable_free_chatrooms(void *data){
|
||||
LinphoneChatMessage* lastMsg = linphone_chat_room_get_user_data(data);
|
||||
if( lastMsg ){
|
||||
linphone_chat_message_unref(lastMsg);
|
||||
linphone_chat_room_set_user_data(data, NULL);
|
||||
}
|
||||
LinphoneChatMessage *lastMsg = linphone_chat_room_get_user_data(data);
|
||||
if (lastMsg) {
|
||||
linphone_chat_message_unref(lastMsg);
|
||||
linphone_chat_room_set_user_data(data, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadData {
|
||||
|
|
@ -170,8 +173,14 @@ static void chatTable_free_chatrooms(void *data){
|
|||
linphone_chat_message_unref(last_msg);
|
||||
linphone_chat_room_set_user_data(chatRoom, NULL);
|
||||
}
|
||||
linphone_chat_room_delete_history(chatRoom);
|
||||
linphone_chat_room_unref(chatRoom);
|
||||
|
||||
for (FileTransferDelegate *ftd in [[LinphoneManager instance] fileTransferDelegates]) {
|
||||
if (linphone_chat_message_get_chat_room(ftd.message) == chatRoom) {
|
||||
[ftd cancel];
|
||||
}
|
||||
}
|
||||
linphone_chat_room_delete_history(chatRoom);
|
||||
linphone_chat_room_unref(chatRoom);
|
||||
data = ms_list_remove(data, chatRoom);
|
||||
|
||||
// will force a call to [self loadData]
|
||||
|
|
|
|||
|
|
@ -369,7 +369,6 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
char* lAddress = linphone_address_as_string_uri_only(addr);
|
||||
if(lAddress == NULL)
|
||||
return;
|
||||
|
||||
// Go to ChatRoom view
|
||||
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
|
||||
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
/* ImageSharing.h
|
||||
*
|
||||
* Copyright (C) 2012 Belledonne Comunications, Grenoble, France
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class ImageSharing;
|
||||
|
||||
@protocol ImageSharingDelegate <NSObject>
|
||||
|
||||
- (void)imageSharingProgress:(ImageSharing*)imageSharing progress:(float)progress;
|
||||
- (void)imageSharingAborted:(ImageSharing*)imageSharing;
|
||||
- (void)imageSharingError:(ImageSharing*)imageSharing error:(NSError *)error;
|
||||
- (void)imageSharingUploadDone:(ImageSharing*)imageSharing url:(NSURL*)url;
|
||||
- (void)imageSharingDownloadDone:(ImageSharing*)imageSharing image:(UIImage *)image;
|
||||
|
||||
@end
|
||||
|
||||
@interface ImageSharing : NSObject<NSURLConnectionDataDelegate> {
|
||||
@private
|
||||
NSInteger totalBytesExpectedToRead;
|
||||
id<ImageSharingDelegate> delegate;
|
||||
NSInteger statusCode;
|
||||
}
|
||||
|
||||
+ (id)newImageSharingUpload:(NSURL*)url image:(UIImage*)image delegate:(id<ImageSharingDelegate>)delegate userInfo:(id)userInfo;
|
||||
+ (id)newImageSharingDownload:(NSURL*)url delegate:(id<ImageSharingDelegate>)delegate userInfo:(id)userInfo;
|
||||
|
||||
- (void)cancel;
|
||||
|
||||
@property (nonatomic, strong) id userInfo;
|
||||
|
||||
@property (nonatomic, readonly) BOOL upload;
|
||||
@property (nonatomic, readonly) NSMutableData* data;
|
||||
@property (nonatomic, readonly) NSURLConnection* connection;
|
||||
|
||||
@end
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
/* ImageSharing.m
|
||||
*
|
||||
* Copyright (C) 2012 Belledonne Comunications, Grenoble, France
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import "ImageSharing.h"
|
||||
#import "Utils.h"
|
||||
#import "LinphoneManager.h"
|
||||
|
||||
@implementation ImageSharing
|
||||
|
||||
@synthesize connection;
|
||||
@synthesize data;
|
||||
@synthesize upload;
|
||||
@synthesize userInfo;
|
||||
|
||||
#pragma mark - Lifecycle Functions
|
||||
|
||||
+ (id)newImageSharingUpload:(NSURL*)url image:(UIImage*)image delegate:(id<ImageSharingDelegate>)delegate userInfo:(id)auserInfo{
|
||||
ImageSharing *imgs = [[ImageSharing alloc] init];
|
||||
if(imgs != nil) {
|
||||
imgs.userInfo = auserInfo;
|
||||
imgs->upload = TRUE;
|
||||
imgs->delegate = delegate;
|
||||
imgs->data = [[NSMutableData alloc] init];
|
||||
if(delegate) {
|
||||
[delegate imageSharingProgress:imgs progress:0];
|
||||
}
|
||||
[imgs uploadImageTo:url image:image];
|
||||
}
|
||||
return imgs;
|
||||
}
|
||||
|
||||
+ (id)newImageSharingDownload:(NSURL*)url delegate:(id<ImageSharingDelegate>)delegate userInfo:(id)auserInfo{
|
||||
ImageSharing *imgs = [[ImageSharing alloc] init];
|
||||
if(imgs != nil) {
|
||||
imgs.userInfo = auserInfo;
|
||||
imgs->upload = FALSE;
|
||||
imgs->delegate = delegate;
|
||||
imgs->data = [[NSMutableData alloc] init];
|
||||
if(delegate) {
|
||||
[delegate imageSharingProgress:imgs progress:0];
|
||||
}
|
||||
[imgs downloadImageFrom:url];
|
||||
}
|
||||
return imgs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)cancel {
|
||||
[connection cancel];
|
||||
LOGI(@"File transfer interrupted by user");
|
||||
if(delegate) {
|
||||
[delegate imageSharingAborted:self];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)downloadImageFrom:(NSURL*)url {
|
||||
LOGI(@"downloading [%@]", [url absoluteString]);
|
||||
|
||||
NSURLRequest* request = [NSURLRequest requestWithURL:url
|
||||
cachePolicy:NSURLRequestUseProtocolCachePolicy
|
||||
timeoutInterval:60.0];
|
||||
|
||||
connection = [[NSURLConnection alloc] initWithRequest:request delegate: self];
|
||||
}
|
||||
|
||||
|
||||
- (void)uploadImageTo:(NSURL*)url image:(UIImage*)image {
|
||||
LOGI(@"downloading [%@]", [url absoluteString]);
|
||||
|
||||
// setting up the request object now
|
||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
|
||||
[request setURL:url];
|
||||
[request setHTTPMethod:@"POST"];
|
||||
|
||||
/*
|
||||
add some header info now
|
||||
we always need a boundary when we post a file
|
||||
also we need to set the content type
|
||||
|
||||
You might want to generate a random boundary.. this is just the same
|
||||
as my output from wireshark on a valid html post
|
||||
*/
|
||||
NSString *boundary = @"---------------------------14737809831466499882746641449";
|
||||
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
|
||||
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
|
||||
|
||||
/*
|
||||
now lets create the body of the post
|
||||
*/
|
||||
NSMutableData *body = [NSMutableData data];
|
||||
NSString *imageName = [NSString stringWithFormat:@"%lu-%f.jpg", (unsigned long)[image hash],[NSDate timeIntervalSinceReferenceDate]];
|
||||
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@\"\r\n",imageName] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[body appendData:[NSData dataWithData:UIImageJPEGRepresentation(image, 1.0)]];
|
||||
[body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[request setHTTPBody:body];
|
||||
|
||||
connection = [[NSURLConnection alloc] initWithRequest:(NSURLRequest *)request delegate:self];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - NSURLConnectionDelegate
|
||||
|
||||
- (void)connection:(NSURLConnection *)aconnection didFailWithError:(NSError *)error {
|
||||
if(delegate) {
|
||||
[delegate imageSharingError:self error:error];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
|
||||
if(upload && delegate) {
|
||||
[delegate imageSharingProgress:self progress:(float)totalBytesWritten/(float)totalBytesExpectedToWrite];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)adata {
|
||||
[data appendData:adata];
|
||||
if(!upload && delegate) {
|
||||
[delegate imageSharingProgress:self progress:(float)data.length/(float)totalBytesExpectedToRead];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
|
||||
NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *) response;
|
||||
statusCode = httpResponse.statusCode;
|
||||
LOGI(@"File transfer status code [%i]", statusCode);
|
||||
|
||||
if (statusCode == 200 && !upload) {
|
||||
totalBytesExpectedToRead = (int)[response expectedContentLength];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
|
||||
if(statusCode >= 400) {
|
||||
NSError *error = [NSError errorWithDomain:@"ImageSharing" code:statusCode userInfo:nil];
|
||||
if(delegate) {
|
||||
[delegate imageSharingError:self error:error];
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (upload) {
|
||||
NSString* imageRemoteUrl = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
LOGI(@"File can be downloaded from [%@]", imageRemoteUrl);
|
||||
if(delegate) {
|
||||
[delegate imageSharingUploadDone:self url:[NSURL URLWithString:imageRemoteUrl]];
|
||||
}
|
||||
} else {
|
||||
UIImage* image = [UIImage imageWithData:data];
|
||||
LOGI(@"File downloaded");
|
||||
if(delegate) {
|
||||
[delegate imageSharingDownloadDone:self image:image];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
//
|
||||
// InAppProductsCell.h
|
||||
// linphone
|
||||
//
|
||||
// Created by Gautier Pelloux-Prayer on 15/04/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <StoreKit/StoreKit.h>
|
||||
|
||||
@interface InAppProductsCell : UITableViewCell {
|
||||
}
|
||||
@property (strong, nonatomic) IBOutlet UILabel *ptitle;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *pdescription;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *pprice;
|
||||
@property (strong, nonatomic) IBOutlet UISwitch *ppurchased;
|
||||
@property (nonatomic) BOOL isMaximized;
|
||||
@property (strong, nonatomic) NSString *productID;
|
||||
|
||||
- (id)initWithIdentifier:(NSString*)identifier maximized:(bool)maximized;
|
||||
|
||||
+ (CGFloat)getHeight:(BOOL)maximized;
|
||||
|
||||
- (void)fillFromProduct:(SKProduct*)prod;
|
||||
|
||||
@end
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
//
|
||||
// InAppProductsCell.m
|
||||
// linphone
|
||||
//
|
||||
// Created by Gautier Pelloux-Prayer on 15/04/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import "InAppProductsCell.h"
|
||||
#import "LinphoneManager.h"
|
||||
|
||||
@implementation InAppProductsCell
|
||||
|
||||
- (void)setIsMaximized:(BOOL)isMaximized {
|
||||
_isMaximized = isMaximized;
|
||||
|
||||
//show the BUY button only when not maximized
|
||||
// _buyButton.hidden = !isMaximized;
|
||||
|
||||
self.frame = CGRectMake(self.frame.origin.x,
|
||||
self.frame.origin.y,
|
||||
self.frame.size.width,
|
||||
[InAppProductsCell getHeight:isMaximized]);
|
||||
}
|
||||
|
||||
- (void)fillFromProduct:(SKProduct *)prod {
|
||||
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
|
||||
[formatter setLocale:prod.priceLocale];
|
||||
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
|
||||
NSString * formattedPrice = [formatter stringFromNumber:prod.price];
|
||||
|
||||
[_ptitle setText: [prod localizedTitle]];
|
||||
[_pdescription setText: [prod localizedDescription]];
|
||||
[_pprice setText: formattedPrice];
|
||||
[_ppurchased setOn: [[[LinphoneManager instance] iapManager] isPurchasedWithID:prod.productIdentifier]];
|
||||
_productID = prod.productIdentifier;
|
||||
}
|
||||
- (id)initWithIdentifier:(NSString*)identifier maximized:(bool)maximized {
|
||||
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
|
||||
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"InAppProductsCell"
|
||||
owner:self
|
||||
options:nil];
|
||||
if ([arrayOfViews count] >= 1) {
|
||||
[self.contentView addSubview:[arrayOfViews objectAtIndex:0]];
|
||||
}
|
||||
_isMaximized = maximized;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"%@ (%@): %@ (%@)", _ptitle.text, _pprice.text, _pdescription.text, _isMaximized ? @"maximized":@"minimized"];
|
||||
}
|
||||
|
||||
+ (CGFloat)getHeight:(BOOL)maximized {
|
||||
return maximized ? 40 : 40;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" variant="6xAndEarlier" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<development version="5100" identifier="xcode"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="InAppProductsCell">
|
||||
<connections>
|
||||
<outlet property="pdescription" destination="4s8-UV-skT" id="gYv-YR-7Kx"/>
|
||||
<outlet property="pprice" destination="jzs-nJ-jrK" id="UBe-qg-Gmj"/>
|
||||
<outlet property="ppurchased" destination="Bcv-Vz-Tq1" id="EB5-Ic-nCq"/>
|
||||
<outlet property="ptitle" destination="Np2-5N-fTR" id="X3D-TQ-R8R"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="Jvg-Ga-qnD" userLabel="view">
|
||||
<rect key="frame" x="0.0" y="0.0" width="340" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="title" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="6" id="Np2-5N-fTR" userLabel="ptitle">
|
||||
<rect key="frame" x="0.0" y="6" width="55" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="description..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" id="4s8-UV-skT" userLabel="pdescription">
|
||||
<rect key="frame" x="119" y="6" width="136" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="$0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" id="jzs-nJ-jrK" userLabel="pprice">
|
||||
<rect key="frame" x="63" y="6" width="48" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" id="Bcv-Vz-Tq1" userLabel="ppurchased">
|
||||
<rect key="frame" x="263" y="6" width="79" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||
</switch>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="14" y="539"/>
|
||||
</view>
|
||||
</objects>
|
||||
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
||||
<simulatedStatusBarMetrics key="statusBar"/>
|
||||
<simulatedOrientationMetrics key="orientation"/>
|
||||
<simulatedScreenMetrics key="destination" type="retina4"/>
|
||||
</simulatedMetricsContainer>
|
||||
</document>
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
#import "LinphoneManager.h"
|
||||
|
||||
#import "PhoneMainView.h"
|
||||
#import "InAppProductsViewController.h"
|
||||
|
||||
@interface InAppProductsManager()
|
||||
@property (strong, nonatomic) NSDate *expirationDate;
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
//
|
||||
// InAppProductsTableViewController.h
|
||||
// linphone
|
||||
//
|
||||
// Created by Gautier Pelloux-Prayer on 16/04/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface InAppProductsTableViewController : UITableViewController
|
||||
|
||||
@end
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
//
|
||||
// InAppProductsTableViewController.m
|
||||
// linphone
|
||||
//
|
||||
// Created by Gautier Pelloux-Prayer on 16/04/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import "InAppProductsTableViewController.h"
|
||||
#import "InAppProductsCell.h"
|
||||
#import "InAppProductsManager.h"
|
||||
#import "LinphoneManager.h"
|
||||
#import "DTAlertView.h"
|
||||
|
||||
@implementation InAppProductsTableViewController {
|
||||
NSInteger currentExpanded;
|
||||
InAppProductsManager *iapm;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
currentExpanded = -1;
|
||||
iapm = [[LinphoneManager instance] iapManager];
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return [iapm productsAvailable].count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
static NSString *kCellId = @"InAppProductsCell";
|
||||
InAppProductsCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
|
||||
if (cell == nil) {
|
||||
cell = [[InAppProductsCell alloc] initWithIdentifier:kCellId maximized:(currentExpanded == indexPath.row)];
|
||||
}
|
||||
SKProduct *prod = [[[[LinphoneManager instance] iapManager] productsAvailable] objectAtIndex:indexPath.row];
|
||||
[cell fillFromProduct:prod];
|
||||
cell.isMaximized = (currentExpanded == indexPath.row);
|
||||
return cell;
|
||||
}
|
||||
|
||||
//- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
// if(currentExpanded == indexPath.row) {
|
||||
// currentExpanded = -1;
|
||||
// [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
|
||||
// return;
|
||||
// } else if(currentExpanded >= 0) {
|
||||
// NSIndexPath *previousPath = [NSIndexPath indexPathForRow:currentExpanded inSection:0];
|
||||
// currentExpanded = indexPath.row;
|
||||
// [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:previousPath] withRowAnimation:UITableViewRowAnimationFade];
|
||||
// }
|
||||
// currentExpanded = indexPath.row;
|
||||
// [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
|
||||
//}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
InAppProductsCell *cell = (InAppProductsCell*)[tableView cellForRowAtIndexPath:indexPath];
|
||||
if (cell.ppurchased.isOn) {
|
||||
DTAlertView* alert = [[DTAlertView alloc] initWithTitle:NSLocalizedString(@"Already purchased", nil) message: [NSString stringWithFormat:NSLocalizedString(@"You already bought %@.",nil), cell.ptitle.text]];
|
||||
|
||||
[alert addCancelButtonWithTitle:NSLocalizedString(@"OK", nil) block:nil];
|
||||
[alert show];
|
||||
} else {
|
||||
//try to purchase item, and if successfull change the switch
|
||||
[[[LinphoneManager instance] iapManager] purchaseWitID: cell.productID];
|
||||
}
|
||||
}
|
||||
|
||||
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return [InAppProductsCell getHeight:(currentExpanded == indexPath.row)];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
//
|
||||
// InAppProductsViewController.h
|
||||
// linphone
|
||||
//
|
||||
// Created by Gautier Pelloux-Prayer on 15/04/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UICompositeViewController.h"
|
||||
#import "InAppProductsTableViewController.h"
|
||||
|
||||
@interface InAppProductsViewController : UIViewController<UICompositeViewDelegate> {
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) IBOutlet InAppProductsTableViewController* tableController;
|
||||
@property (strong, nonatomic) IBOutlet UIView *waitView;
|
||||
- (IBAction)onRestoreClicked:(UIButton *)sender;
|
||||
|
||||
@end
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
//
|
||||
// InAppProductsViewController.m
|
||||
// linphone
|
||||
//
|
||||
// Created by Gautier Pelloux-Prayer on 15/04/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import "InAppProductsViewController.h"
|
||||
#import "InAppProductsCell.h"
|
||||
|
||||
@implementation InAppProductsViewController
|
||||
|
||||
#pragma mark - Lifecycle Functions
|
||||
|
||||
- (id)init {
|
||||
return [super initWithNibName:@"InAppProductsViewController" bundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - ViewController Functions
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
for (NSString* notification in [NSArray arrayWithObjects:kIAPReady, kIAPRestoreSucceeded, kIAPPurchaseSucceeded, kIAPReceiptSucceeded, kIAPPurchaseTrying, nil]) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(onIAPPurchaseNotification:)
|
||||
name:notification
|
||||
object:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
for (NSString* notification in [NSArray arrayWithObjects:kIAPReady, kIAPRestoreSucceeded, kIAPPurchaseSucceeded, kIAPReceiptSucceeded, kIAPPurchaseTrying, nil]) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:notification
|
||||
object:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onIAPPurchaseNotification:(NSNotification*)notif {
|
||||
InAppProductsManager *iapm = [[LinphoneManager instance] iapManager];
|
||||
[[_tableController tableView] reloadData];
|
||||
[_waitView setHidden:([[iapm productsAvailable] count] != 0 && ![notif.name isEqualToString:kIAPPurchaseTrying])];
|
||||
}
|
||||
|
||||
#pragma mark - UICompositeViewDelegate Functions
|
||||
|
||||
static UICompositeViewDescription *compositeDescription = nil;
|
||||
|
||||
+ (UICompositeViewDescription *)compositeViewDescription {
|
||||
if(compositeDescription == nil) {
|
||||
compositeDescription = [[UICompositeViewDescription alloc] init:@"InAppProducts"
|
||||
content:@"InAppProductsViewController"
|
||||
stateBar:nil
|
||||
stateBarEnabled:false
|
||||
tabBar: @"UIMainBar"
|
||||
tabBarEnabled:true
|
||||
fullscreen:false
|
||||
landscapeMode:[LinphoneManager runningOnIpad]
|
||||
portraitMode:true];
|
||||
}
|
||||
return compositeDescription;
|
||||
}
|
||||
|
||||
- (IBAction)onRestoreClicked:(UIButton *)sender {
|
||||
[[[LinphoneManager instance] iapManager] restore];
|
||||
}
|
||||
@end
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="InAppProductsViewController">
|
||||
<connections>
|
||||
<outlet property="tableController" destination="FRQ-Fw-iZ8" id="HVZ-37-Tau"/>
|
||||
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
|
||||
<outlet property="waitView" destination="4pA-a2-gQ7" id="4f0-jJ-Wv4"/>
|
||||
</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="320" height="460"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="1" sectionFooterHeight="10" id="fwu-cz-Gse" userLabel="productsTable">
|
||||
<rect key="frame" x="0.0" y="38" width="320" height="422"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="FRQ-Fw-iZ8" id="uQQ-fT-hHp"/>
|
||||
<outlet property="delegate" destination="FRQ-Fw-iZ8" id="2Dx-aQ-XVB"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="XrD-Mn-6EM" userLabel="restoreButton">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Restore">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onRestoreClicked:" destination="-1" eventType="touchUpInside" id="ZYY-WP-1of"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" alpha="0.49999999999999961" contentMode="scaleToFill" id="4pA-a2-gQ7" userLabel="waitView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="whiteLarge" id="K5m-Dx-cXk" userLabel="spinner">
|
||||
<rect key="frame" x="142" y="211" width="37" height="37"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
</activityIndicatorView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="517" y="-365"/>
|
||||
</view>
|
||||
<tableViewController extendedLayoutIncludesOpaqueBars="YES" id="FRQ-Fw-iZ8" userLabel="tableController" customClass="InAppProductsTableViewController">
|
||||
<extendedEdge key="edgesForExtendedLayout" top="YES"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<size key="freeformSize" width="320" height="460"/>
|
||||
<connections>
|
||||
<outlet property="view" destination="fwu-cz-Gse" id="qar-Rf-89v"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="139" y="-365"/>
|
||||
</tableViewController>
|
||||
</objects>
|
||||
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
||||
<simulatedStatusBarMetrics key="statusBar"/>
|
||||
<simulatedOrientationMetrics key="orientation"/>
|
||||
<simulatedScreenMetrics key="destination" type="retina4"/>
|
||||
</simulatedMetricsContainer>
|
||||
</document>
|
||||
|
|
@ -4,18 +4,18 @@
|
|||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "IASKSettingsStore.h"
|
||||
|
|
@ -28,7 +28,6 @@
|
|||
NSDictionary *changedDict;
|
||||
}
|
||||
|
||||
- (void)synchronizeAccount;
|
||||
- (void)transformLinphoneCoreToKeys;
|
||||
|
||||
@end
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -36,7 +36,7 @@
|
|||
#include "linphone/linphonecore.h"
|
||||
#include "linphone/linphone_tunnel.h"
|
||||
|
||||
extern const char *const LINPHONERC_APPLICATION_KEY;
|
||||
extern NSString *const LINPHONERC_APPLICATION_KEY;
|
||||
|
||||
extern NSString *const kLinphoneCoreUpdate;
|
||||
extern NSString *const kLinphoneDisplayStatusUpdate;
|
||||
|
|
@ -52,6 +52,8 @@ extern NSString *const kLinphoneBluetoothAvailabilityUpdate;
|
|||
extern NSString *const kLinphoneConfiguringStateUpdate;
|
||||
extern NSString *const kLinphoneGlobalStateUpdate;
|
||||
extern NSString *const kLinphoneNotifyReceived;
|
||||
extern NSString *const kLinphoneFileTransferSendUpdate;
|
||||
extern NSString *const kLinphoneFileTransferRecvUpdate;
|
||||
|
||||
typedef enum _NetworkType {
|
||||
network_none = 0,
|
||||
|
|
@ -167,18 +169,26 @@ typedef struct _LinphoneManagerSounds {
|
|||
+(void)setValueInMessageAppData:(id)value forKey:(NSString*)key inMessage:(LinphoneChatMessage*)msg;
|
||||
|
||||
- (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key;
|
||||
- (NSString*)lpConfigStringForKey:(NSString*)key;
|
||||
- (NSString*)lpConfigStringForKey:(NSString*)key withDefault:(NSString*)value;
|
||||
- (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key forSection:(NSString*)section;
|
||||
- (NSString *)lpConfigStringForKey:(NSString *)key;
|
||||
- (NSString*)lpConfigStringForKey:(NSString*)key forSection:(NSString*)section;
|
||||
- (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key;
|
||||
- (NSInteger)lpConfigIntForKey:(NSString*)key;
|
||||
- (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key forSection:(NSString*)section;
|
||||
- (NSInteger)lpConfigIntForKey:(NSString*)key forSection:(NSString*)section;
|
||||
- (NSString *)lpConfigStringForKey:(NSString *)key withDefault:(NSString *)value;
|
||||
- (NSString *)lpConfigStringForKey:(NSString *)key forSection:(NSString *)section withDefault:(NSString *)value;
|
||||
|
||||
- (void)lpConfigSetInt:(int)value forKey:(NSString *)key;
|
||||
- (void)lpConfigSetInt:(int)value forKey:(NSString *)key forSection:(NSString *)section;
|
||||
- (int)lpConfigIntForKey:(NSString *)key;
|
||||
- (int)lpConfigIntForKey:(NSString *)key forSection:(NSString *)section;
|
||||
- (int)lpConfigIntForKey:(NSString *)key withDefault:(int)value;
|
||||
- (int)lpConfigIntForKey:(NSString *)key forSection:(NSString *)section withDefault:(int)value;
|
||||
|
||||
- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key;
|
||||
- (BOOL)lpConfigBoolForKey:(NSString*)key;
|
||||
- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key forSection:(NSString*)section;
|
||||
- (BOOL)lpConfigBoolForKey:(NSString *)key;
|
||||
- (BOOL)lpConfigBoolForKey:(NSString*)key forSection:(NSString*)section;
|
||||
- (BOOL)lpConfigBoolForKey:(NSString *)key withDefault:(BOOL)value;
|
||||
- (BOOL)lpConfigBoolForKey:(NSString *)key forSection:(NSString *)section withDefault:(BOOL)value;
|
||||
|
||||
- (void)silentPushFailed:(NSTimer*)timer;
|
||||
|
||||
@property (readonly) BOOL isTesting;
|
||||
|
|
@ -203,5 +213,6 @@ typedef struct _LinphoneManagerSounds {
|
|||
@property (readonly) BOOL wasRemoteProvisioned;
|
||||
@property (readonly) LpConfig *configDb;
|
||||
@property (readonly) InAppProductsManager *iapManager;
|
||||
@end
|
||||
@property(strong, nonatomic) NSMutableArray *fileTransferDelegates;
|
||||
|
||||
@end
|
||||
|
|
@ -52,7 +52,7 @@ static void audioRouteChangeListenerCallback (
|
|||
static LinphoneCore* theLinphoneCore = nil;
|
||||
static LinphoneManager* theLinphoneManager = nil;
|
||||
|
||||
const char *const LINPHONERC_APPLICATION_KEY = "app";
|
||||
NSString *const LINPHONERC_APPLICATION_KEY = @"app";
|
||||
|
||||
NSString *const kLinphoneCoreUpdate = @"LinphoneCoreUpdate";
|
||||
NSString *const kLinphoneDisplayStatusUpdate = @"LinphoneDisplayStatusUpdate";
|
||||
|
|
@ -68,7 +68,8 @@ NSString *const kLinphoneBluetoothAvailabilityUpdate = @"LinphoneBluetoothAvaila
|
|||
NSString *const kLinphoneConfiguringStateUpdate = @"LinphoneConfiguringStateUpdate";
|
||||
NSString *const kLinphoneGlobalStateUpdate = @"LinphoneGlobalStateUpdate";
|
||||
NSString *const kLinphoneNotifyReceived = @"LinphoneNotifyReceived";
|
||||
|
||||
NSString *const kLinphoneFileTransferSendUpdate = @"LinphoneFileTransferSendUpdate";
|
||||
NSString *const kLinphoneFileTransferRecvUpdate = @"LinphoneFileTransferRecvUpdate";
|
||||
|
||||
const int kLinphoneAudioVbrCodecDefaultBitrate=36; /*you can override this from linphonerc or linphonerc-factory*/
|
||||
|
||||
|
|
@ -145,10 +146,10 @@ struct codec_name_pref_table codec_pref_table[]={
|
|||
{ "mp4v-es", 90000, "mp4v-es_preference"},
|
||||
{ "h264", 90000, "h264_preference"},
|
||||
{ "vp8", 90000, "vp8_preference"},
|
||||
{ "mpeg4-generic", 16000, "aaceld_16k_preference"},
|
||||
{ "mpeg4-generic", 22050, "aaceld_22k_preference"},
|
||||
{ "mpeg4-generic", 32000, "aaceld_32k_preference"},
|
||||
{ "mpeg4-generic", 44100, "aaceld_44k_preference"},
|
||||
{ "mpeg4-generic", 16000, "aaceld_16k_preference"},
|
||||
{ "mpeg4-generic", 22050, "aaceld_22k_preference"},
|
||||
{ "mpeg4-generic", 32000, "aaceld_32k_preference"},
|
||||
{ "mpeg4-generic", 44100, "aaceld_44k_preference"},
|
||||
{ "mpeg4-generic", 48000, "aaceld_48k_preference"},
|
||||
{ "opus", 48000, "opus_preference"},
|
||||
{ NULL,0,Nil }
|
||||
|
|
@ -194,9 +195,9 @@ struct codec_name_pref_table codec_pref_table[]={
|
|||
}
|
||||
|
||||
+ (BOOL)isRunningTests {
|
||||
NSDictionary *environment = [[NSProcessInfo processInfo] environment];
|
||||
NSString *injectBundle = environment[@"XCInjectBundle"];
|
||||
return [[injectBundle pathExtension] isEqualToString:@"xctest"];
|
||||
NSDictionary *environment = [[NSProcessInfo processInfo] environment];
|
||||
NSString *injectBundle = environment[@"XCInjectBundle"];
|
||||
return [[injectBundle pathExtension] isEqualToString:@"xctest"];
|
||||
}
|
||||
|
||||
+ (BOOL)isNotIphone3G
|
||||
|
|
@ -244,12 +245,12 @@ struct codec_name_pref_table codec_pref_table[]={
|
|||
#endif
|
||||
|
||||
+ (BOOL)langageDirectionIsRTL {
|
||||
static NSLocaleLanguageDirection dir = NSLocaleLanguageDirectionLeftToRight;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
dir = [NSLocale characterDirectionForLanguage:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
|
||||
});
|
||||
return dir == NSLocaleLanguageDirectionRightToLeft;
|
||||
static NSLocaleLanguageDirection dir = NSLocaleLanguageDirectionLeftToRight;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
dir = [NSLocale characterDirectionForLanguage:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
|
||||
});
|
||||
return dir == NSLocaleLanguageDirectionRightToLeft;
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle Functions
|
||||
|
|
@ -262,17 +263,18 @@ struct codec_name_pref_table codec_pref_table[]={
|
|||
LOGE(@"cannot register route change handler [%ld]",lStatus);
|
||||
}
|
||||
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"];
|
||||
self.messagePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:nil];
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"];
|
||||
self.messagePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:nil];
|
||||
|
||||
sounds.vibrate = kSystemSoundID_Vibrate;
|
||||
sounds.vibrate = kSystemSoundID_Vibrate;
|
||||
|
||||
logs = [[NSMutableArray alloc] init];
|
||||
logs = [[NSMutableArray alloc] init];
|
||||
database = NULL;
|
||||
speakerEnabled = FALSE;
|
||||
bluetoothEnabled = FALSE;
|
||||
tunnelMode = FALSE;
|
||||
|
||||
_fileTransferDelegates = [[NSMutableArray alloc] init];
|
||||
|
||||
pushCallIDs = [[NSMutableArray alloc] init ];
|
||||
photoLibrary = [[ALAssetsLibrary alloc] init];
|
||||
|
|
@ -283,7 +285,7 @@ struct codec_name_pref_table codec_pref_table[]={
|
|||
[self overrideDefaultSettings];
|
||||
|
||||
//set default values for first boot
|
||||
if (lp_config_get_string(configDb,LINPHONERC_APPLICATION_KEY,"debugenable_preference",NULL)==NULL){
|
||||
if ([self lpConfigStringForKey:@"debugenable_preference"] == nil) {
|
||||
#ifdef DEBUG
|
||||
[self lpConfigSetBool:TRUE forKey:@"debugenable_preference"];
|
||||
#else
|
||||
|
|
@ -447,11 +449,11 @@ exit_dbmigration:
|
|||
}
|
||||
|
||||
- (void)migrateFromUserPrefs {
|
||||
static const char* migration_flag = "userpref_migration_done";
|
||||
static NSString *migration_flag = @"userpref_migration_done";
|
||||
|
||||
if( configDb == nil ) return;
|
||||
|
||||
if( lp_config_get_int(configDb, LINPHONERC_APPLICATION_KEY, migration_flag, 0) ){
|
||||
if ([self lpConfigIntForKey:migration_flag withDefault:0]) {
|
||||
LOGI(@"UserPrefs migration already performed, skip");
|
||||
return;
|
||||
}
|
||||
|
|
@ -468,12 +470,12 @@ exit_dbmigration:
|
|||
for( NSString* userpref in values ){
|
||||
if( [defaults_keys containsObject:userpref] ){
|
||||
LOGI(@"Migrating %@ from user preferences: %d", userpref, [[defaults objectForKey:userpref] boolValue]);
|
||||
lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], [[defaults objectForKey:userpref] boolValue]);
|
||||
[self lpConfigSetBool:[[defaults objectForKey:userpref] boolValue] forKey:userpref];
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:userpref];
|
||||
shouldSync = TRUE;
|
||||
} else if ( lp_config_get_string(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], NULL) == NULL ){
|
||||
} else if ([self lpConfigStringForKey:userpref] == nil) {
|
||||
// no default value found in our linphonerc, we need to add them
|
||||
lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], [[values objectForKey:userpref] boolValue]);
|
||||
[self lpConfigSetBool:[[values objectForKey:userpref] boolValue] forKey:userpref];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -482,7 +484,7 @@ exit_dbmigration:
|
|||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
// don't get back here in the future
|
||||
lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, migration_flag, 1);
|
||||
[self lpConfigSetBool:YES forKey:migration_flag];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -543,9 +545,9 @@ static void linphone_iphone_log(struct _LinphoneCore * lc, const char * message)
|
|||
|
||||
- (void)displayStatus:(NSString*) message {
|
||||
// Post event
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneDisplayStatusUpdate
|
||||
object:self
|
||||
userInfo:@{@"message":message}];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneDisplayStatusUpdate
|
||||
object:self
|
||||
userInfo:@{@"message":message}];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -639,14 +641,15 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char
|
|||
data->notification = [[UILocalNotification alloc] init];
|
||||
if (data->notification) {
|
||||
|
||||
// iOS8 doesn't need the timer trick for the local notification.
|
||||
if( [[UIDevice currentDevice].systemVersion floatValue] >= 8){
|
||||
data->notification.soundName = @"ring.caf";
|
||||
data->notification.category = @"incoming_call";
|
||||
} else {
|
||||
data->notification.soundName = @"shortring.caf";
|
||||
data->timer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(localNotifContinue:) userInfo:data->notification repeats:TRUE];
|
||||
}
|
||||
// iOS8 doesn't need the timer trick for the local notification.
|
||||
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8 &&
|
||||
[self lpConfigBoolForKey:@"repeat_call_notification"] == NO) {
|
||||
data->notification.soundName = @"ring.caf";
|
||||
data->notification.category = @"incoming_call";
|
||||
} else {
|
||||
data->notification.soundName = @"shortring.caf";
|
||||
data->timer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(localNotifContinue:) userInfo:data->notification repeats:TRUE];
|
||||
}
|
||||
|
||||
data->notification.repeatInterval = 0;
|
||||
|
||||
|
|
@ -664,9 +667,9 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char
|
|||
incallBgTask=0;
|
||||
}];
|
||||
|
||||
if( data->timer ){
|
||||
[[NSRunLoop currentRunLoop] addTimer:data->timer forMode:NSRunLoopCommonModes];
|
||||
}
|
||||
if( data->timer ){
|
||||
[[NSRunLoop currentRunLoop] addTimer:data->timer forMode:NSRunLoopCommonModes];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -740,9 +743,9 @@ static void linphone_iphone_display_status(struct _LinphoneCore * lc, const char
|
|||
[self setupGSMInteraction];
|
||||
}
|
||||
// Post event
|
||||
NSDictionary* dict = @{@"call": [NSValue valueWithPointer:call],
|
||||
@"state": [NSNumber numberWithInt:state],
|
||||
@"message":[NSString stringWithUTF8String:message]};
|
||||
NSDictionary* dict = @{@"call": [NSValue valueWithPointer:call],
|
||||
@"state": [NSNumber numberWithInt:state],
|
||||
@"message":[NSString stringWithUTF8String:message]};
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneCallUpdate object:self userInfo:dict];
|
||||
}
|
||||
|
||||
|
|
@ -845,12 +848,12 @@ static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyCo
|
|||
silentPushCompletion(UIBackgroundFetchResultNewData);
|
||||
silentPushCompletion = nil;
|
||||
}
|
||||
const LinphoneAddress* remoteAddress = linphone_chat_message_get_from_address(msg);
|
||||
char* c_address = linphone_address_as_string_uri_only(remoteAddress);
|
||||
NSString* address = [NSString stringWithUTF8String:c_address];
|
||||
NSString* remote_uri = [NSString stringWithUTF8String:c_address];
|
||||
const char* call_id = linphone_chat_message_get_custom_header(msg, "Call-ID");
|
||||
NSString* callID = [NSString stringWithUTF8String:call_id];
|
||||
const LinphoneAddress* remoteAddress = linphone_chat_message_get_from_address(msg);
|
||||
char* c_address = linphone_address_as_string_uri_only(remoteAddress);
|
||||
NSString* address = [NSString stringWithUTF8String:c_address];
|
||||
NSString* remote_uri = [NSString stringWithUTF8String:c_address];
|
||||
const char* call_id = linphone_chat_message_get_custom_header(msg, "Call-ID");
|
||||
NSString* callID = [NSString stringWithUTF8String:call_id];
|
||||
|
||||
ms_free(c_address);
|
||||
|
||||
|
|
@ -874,9 +877,9 @@ static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyCo
|
|||
UILocalNotification* notif = [[UILocalNotification alloc] init];
|
||||
if (notif) {
|
||||
notif.repeatInterval = 0;
|
||||
if( [[UIDevice currentDevice].systemVersion floatValue] >= 8){
|
||||
notif.category = @"incoming_msg";
|
||||
}
|
||||
if( [[UIDevice currentDevice].systemVersion floatValue] >= 8){
|
||||
notif.category = @"incoming_msg";
|
||||
}
|
||||
notif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"IM_MSG",nil), address];
|
||||
notif.alertAction = NSLocalizedString(@"Show", nil);
|
||||
notif.soundName = @"msg.caf";
|
||||
|
|
@ -936,58 +939,58 @@ static void linphone_iphone_is_composing_received(LinphoneCore *lc, LinphoneChat
|
|||
}
|
||||
|
||||
+ (void)kickOffNetworkConnection {
|
||||
static BOOL in_progress = FALSE;
|
||||
if( in_progress ){
|
||||
LOGW(@"Connection kickoff already in progress");
|
||||
return;
|
||||
}
|
||||
in_progress = TRUE;
|
||||
static BOOL in_progress = FALSE;
|
||||
if( in_progress ){
|
||||
LOGW(@"Connection kickoff already in progress");
|
||||
return;
|
||||
}
|
||||
in_progress = TRUE;
|
||||
/* start a new thread to avoid blocking the main ui in case of peer host failure */
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
static int sleep_us = 10000;
|
||||
static int timeout_s = 5;
|
||||
BOOL timeout_reached = FALSE;
|
||||
int loop = 0;
|
||||
static int sleep_us = 10000;
|
||||
static int timeout_s = 5;
|
||||
BOOL timeout_reached = FALSE;
|
||||
int loop = 0;
|
||||
CFWriteStreamRef writeStream;
|
||||
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.200"/*"linphone.org"*/, 15000, nil, &writeStream);
|
||||
BOOL res = CFWriteStreamOpen (writeStream);
|
||||
const char* buff="hello";
|
||||
time_t start = time(NULL);
|
||||
time_t loop_time;
|
||||
time_t start = time(NULL);
|
||||
time_t loop_time;
|
||||
|
||||
if( res == FALSE ){
|
||||
LOGI(@"Could not open write stream, backing off");
|
||||
CFRelease(writeStream);
|
||||
in_progress = FALSE;
|
||||
return;
|
||||
}
|
||||
if( res == FALSE ){
|
||||
LOGI(@"Could not open write stream, backing off");
|
||||
CFRelease(writeStream);
|
||||
in_progress = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
// check stream status and handle timeout
|
||||
CFStreamStatus status = CFWriteStreamGetStatus(writeStream);
|
||||
while (status != kCFStreamStatusOpen && status != kCFStreamStatusError ) {
|
||||
usleep(sleep_us);
|
||||
status = CFWriteStreamGetStatus(writeStream);
|
||||
loop_time = time(NULL);
|
||||
if( loop_time - start >= timeout_s){
|
||||
timeout_reached = TRUE;
|
||||
break;
|
||||
}
|
||||
loop++;
|
||||
}
|
||||
// check stream status and handle timeout
|
||||
CFStreamStatus status = CFWriteStreamGetStatus(writeStream);
|
||||
while (status != kCFStreamStatusOpen && status != kCFStreamStatusError ) {
|
||||
usleep(sleep_us);
|
||||
status = CFWriteStreamGetStatus(writeStream);
|
||||
loop_time = time(NULL);
|
||||
if( loop_time - start >= timeout_s){
|
||||
timeout_reached = TRUE;
|
||||
break;
|
||||
}
|
||||
loop++;
|
||||
}
|
||||
|
||||
|
||||
if (status == kCFStreamStatusOpen ) {
|
||||
CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff));
|
||||
} else if( !timeout_reached ){
|
||||
CFErrorRef error = CFWriteStreamCopyError(writeStream);
|
||||
LOGD(@"CFStreamError: %@", error);
|
||||
CFRelease(error);
|
||||
} else if( timeout_reached ){
|
||||
LOGI(@"CFStream timeout reached");
|
||||
}
|
||||
if (status == kCFStreamStatusOpen ) {
|
||||
CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff));
|
||||
} else if( !timeout_reached ){
|
||||
CFErrorRef error = CFWriteStreamCopyError(writeStream);
|
||||
LOGD(@"CFStreamError: %@", error);
|
||||
CFRelease(error);
|
||||
} else if( timeout_reached ){
|
||||
LOGI(@"CFStream timeout reached");
|
||||
}
|
||||
CFWriteStreamClose (writeStream);
|
||||
CFRelease(writeStream);
|
||||
in_progress = FALSE;
|
||||
in_progress = FALSE;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1046,7 +1049,7 @@ static void networkReachabilityNotification(CFNotificationCenterRef center, void
|
|||
|
||||
void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* nilCtx){
|
||||
showNetworkFlags(flags);
|
||||
LinphoneManager* lLinphoneMgr = [LinphoneManager instance];
|
||||
LinphoneManager *lm = [LinphoneManager instance];
|
||||
SCNetworkReachabilityFlags networkDownFlags=kSCNetworkReachabilityFlagsConnectionRequired |kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand;
|
||||
|
||||
if (theLinphoneCore != nil) {
|
||||
|
|
@ -1056,30 +1059,28 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach
|
|||
struct NetworkReachabilityContext* ctx = nilCtx ? ((struct NetworkReachabilityContext*)nilCtx) : 0;
|
||||
if ((flags == 0) || (flags & networkDownFlags)) {
|
||||
linphone_core_set_network_reachable(theLinphoneCore, false);
|
||||
lLinphoneMgr.connectivity = none;
|
||||
lm.connectivity = none;
|
||||
[LinphoneManager kickOffNetworkConnection];
|
||||
} else {
|
||||
LinphoneTunnel *tunnel = linphone_core_get_tunnel([LinphoneManager getLc]);
|
||||
Connectivity newConnectivity;
|
||||
BOOL isWifiOnly = lp_config_get_int(lLinphoneMgr.configDb, LINPHONERC_APPLICATION_KEY, "wifi_only_preference",FALSE);
|
||||
BOOL isWifiOnly = [lm lpConfigBoolForKey:@"wifi_only_preference" withDefault:FALSE];
|
||||
if (!ctx || ctx->testWWan)
|
||||
newConnectivity = flags & kSCNetworkReachabilityFlagsIsWWAN ? wwan:wifi;
|
||||
else
|
||||
newConnectivity = wifi;
|
||||
|
||||
if (newConnectivity == wwan
|
||||
&& proxy
|
||||
&& isWifiOnly
|
||||
&& (lLinphoneMgr.connectivity == newConnectivity || lLinphoneMgr.connectivity == none)) {
|
||||
if (newConnectivity == wwan && proxy && isWifiOnly &&
|
||||
(lm.connectivity == newConnectivity || lm.connectivity == none)) {
|
||||
linphone_proxy_config_expires(proxy, 0);
|
||||
} else if (proxy){
|
||||
NSInteger defaultExpire = [[LinphoneManager instance] lpConfigIntForKey:@"default_expires"];
|
||||
NSInteger defaultExpire = [lm lpConfigIntForKey:@"default_expires"];
|
||||
if (defaultExpire>=0)
|
||||
linphone_proxy_config_expires(proxy, (int)defaultExpire);
|
||||
//else keep default value from linphonecore
|
||||
}
|
||||
|
||||
if (lLinphoneMgr.connectivity != newConnectivity) {
|
||||
if (lm.connectivity != newConnectivity) {
|
||||
if (tunnel) linphone_tunnel_reconnect(tunnel);
|
||||
// connectivity has changed
|
||||
linphone_core_set_network_reachable(theLinphoneCore,false);
|
||||
|
|
@ -1090,10 +1091,10 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach
|
|||
linphone_core_iterate(theLinphoneCore);
|
||||
LOGI(@"Network connectivity changed to type [%s]",(newConnectivity==wifi?"wifi":"wwan"));
|
||||
}
|
||||
lLinphoneMgr.connectivity=newConnectivity;
|
||||
switch (lLinphoneMgr.tunnelMode) {
|
||||
lm.connectivity = newConnectivity;
|
||||
switch (lm.tunnelMode) {
|
||||
case tunnel_wwan:
|
||||
linphone_tunnel_enable(tunnel,lLinphoneMgr.connectivity == wwan);
|
||||
linphone_tunnel_enable(tunnel, lm.connectivity == wwan);
|
||||
break;
|
||||
case tunnel_auto:
|
||||
linphone_tunnel_auto_detect(tunnel);
|
||||
|
|
@ -1104,7 +1105,7 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach
|
|||
}
|
||||
}
|
||||
if (ctx && ctx->networkStateChanged) {
|
||||
(*ctx->networkStateChanged)(lLinphoneMgr.connectivity);
|
||||
(*ctx->networkStateChanged)(lm.connectivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1185,7 +1186,7 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark - VTable
|
||||
|
||||
static LinphoneCoreVTable linphonec_vtable = {
|
||||
.show =NULL,
|
||||
|
|
@ -1208,6 +1209,8 @@ static LinphoneCoreVTable linphonec_vtable = {
|
|||
.notify_received = linphone_iphone_notify_received
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
|
||||
//scheduling loop
|
||||
- (void)iterate {
|
||||
linphone_core_iterate(theLinphoneCore);
|
||||
|
|
@ -1300,6 +1303,11 @@ static LinphoneCoreVTable linphonec_vtable = {
|
|||
linphone_core_set_static_picture(theLinphoneCore, imagePath);
|
||||
}
|
||||
|
||||
NSString *urlString = [self lpConfigStringForKey:@"sharing_server_preference"];
|
||||
if( urlString ){
|
||||
linphone_core_set_file_transfer_server(theLinphoneCore, [urlString UTF8String]);
|
||||
}
|
||||
|
||||
/*DETECT cameras*/
|
||||
frontCamId= backCamId=nil;
|
||||
char** camlist = (char**)linphone_core_get_video_devices(theLinphoneCore);
|
||||
|
|
@ -1394,24 +1402,24 @@ static BOOL libStarted = FALSE;
|
|||
|
||||
connectivity=none;
|
||||
|
||||
ms_init(); // Need to initialize mediastreamer2 before loading the plugins
|
||||
ms_init(); // Need to initialize mediastreamer2 before loading the plugins
|
||||
|
||||
libmsilbc_init();
|
||||
libmsilbc_init();
|
||||
#if defined (HAVE_SILK)
|
||||
libmssilk_init();
|
||||
libmssilk_init();
|
||||
#endif
|
||||
#ifdef HAVE_AMR
|
||||
libmsamr_init(); //load amr plugin if present from the liblinphone sdk
|
||||
libmsamr_init(); //load amr plugin if present from the liblinphone sdk
|
||||
#endif
|
||||
#ifdef HAVE_X264
|
||||
libmsx264_init(); //load x264 plugin if present from the liblinphone sdk
|
||||
libmsx264_init(); //load x264 plugin if present from the liblinphone sdk
|
||||
#endif
|
||||
#ifdef HAVE_OPENH264
|
||||
libmsopenh264_init(); //load openh264 plugin if present from the liblinphone sdk
|
||||
libmsopenh264_init(); //load openh264 plugin if present from the liblinphone sdk
|
||||
#endif
|
||||
|
||||
#if HAVE_G729
|
||||
libmsbcg729_init(); // load g729 plugin
|
||||
libmsbcg729_init(); // load g729 plugin
|
||||
#endif
|
||||
|
||||
linphone_core_set_log_collection_path([[LinphoneManager cacheDirectory] UTF8String]);
|
||||
|
|
@ -1490,39 +1498,39 @@ static int comp_call_id(const LinphoneCall* call , const char *callid) {
|
|||
}
|
||||
|
||||
- (void)cancelLocalNotifTimerForCallId:(NSString*)callid {
|
||||
//first, make sure this callid is not already involved in a call
|
||||
MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
|
||||
MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]);
|
||||
if (call != NULL) {
|
||||
LinphoneCallAppData* data = (__bridge LinphoneCallAppData *)(linphone_call_get_user_data((LinphoneCall*)call->data));
|
||||
if ( data->timer )
|
||||
[data->timer invalidate];
|
||||
data->timer = nil;
|
||||
return;
|
||||
}
|
||||
//first, make sure this callid is not already involved in a call
|
||||
MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
|
||||
MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]);
|
||||
if (call != NULL) {
|
||||
LinphoneCallAppData* data = (__bridge LinphoneCallAppData *)(linphone_call_get_user_data((LinphoneCall*)call->data));
|
||||
if ( data->timer )
|
||||
[data->timer invalidate];
|
||||
data->timer = nil;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)acceptCallForCallId:(NSString*)callid {
|
||||
//first, make sure this callid is not already involved in a call
|
||||
MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
|
||||
MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]);
|
||||
if (call != NULL) {
|
||||
[self acceptCall:(LinphoneCall*)call->data];
|
||||
return;
|
||||
};
|
||||
//first, make sure this callid is not already involved in a call
|
||||
MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
|
||||
MSList* call = ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String]);
|
||||
if (call != NULL) {
|
||||
[self acceptCall:(LinphoneCall*)call->data];
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
- (void)addPushCallId:(NSString*) callid {
|
||||
//first, make sure this callid is not already involved in a call
|
||||
MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
|
||||
if (ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String])) {
|
||||
LOGW(@"Call id [%@] already handled",callid);
|
||||
return;
|
||||
};
|
||||
if ([pushCallIDs count] > 10 /*max number of pending notif*/)
|
||||
[pushCallIDs removeObjectAtIndex:0];
|
||||
MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore);
|
||||
if (ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String])) {
|
||||
LOGW(@"Call id [%@] already handled",callid);
|
||||
return;
|
||||
};
|
||||
if ([pushCallIDs count] > 10 /*max number of pending notif*/)
|
||||
[pushCallIDs removeObjectAtIndex:0];
|
||||
|
||||
[pushCallIDs addObject:callid];
|
||||
[pushCallIDs addObject:callid];
|
||||
}
|
||||
|
||||
- (BOOL)popPushCallID:(NSString*) callId {
|
||||
|
|
@ -1542,11 +1550,11 @@ static int comp_call_id(const LinphoneCall* call , const char *callid) {
|
|||
}
|
||||
|
||||
- (void)playMessageSound {
|
||||
BOOL success = [self.messagePlayer play];
|
||||
if( !success ){
|
||||
LOGE(@"Could not play the message sound");
|
||||
}
|
||||
AudioServicesPlaySystemSound([LinphoneManager instance].sounds.vibrate);
|
||||
BOOL success = [self.messagePlayer play];
|
||||
if( !success ){
|
||||
LOGE(@"Could not play the message sound");
|
||||
}
|
||||
AudioServicesPlaySystemSound([LinphoneManager instance].sounds.vibrate);
|
||||
}
|
||||
|
||||
static int comp_call_state_paused (const LinphoneCall* call, const void* param) {
|
||||
|
|
@ -1559,7 +1567,7 @@ static int comp_call_state_paused (const LinphoneCall* call, const void* param)
|
|||
[[UIApplication sharedApplication] endBackgroundTask:pausedCallBgTask];
|
||||
}];
|
||||
LOGI(@"Long running task started, remaining [%g s] because at least one call is paused"
|
||||
,[[UIApplication sharedApplication] backgroundTimeRemaining]);
|
||||
,[[UIApplication sharedApplication] backgroundTimeRemaining]);
|
||||
}
|
||||
- (BOOL)enterBackgroundMode {
|
||||
LinphoneProxyConfig* proxyCfg;
|
||||
|
|
@ -1864,18 +1872,18 @@ static void audioRouteChangeListenerCallback (
|
|||
}
|
||||
LinphoneCall* call=NULL;
|
||||
|
||||
BOOL addressIsASCII = [address canBeConvertedToEncoding:[NSString defaultCStringEncoding]];
|
||||
BOOL addressIsASCII = [address canBeConvertedToEncoding:[NSString defaultCStringEncoding]];
|
||||
|
||||
if ([address length] == 0) return; //just return
|
||||
if( !addressIsASCII ){
|
||||
UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Invalid SIP address",nil)
|
||||
message:NSLocalizedString(@"The address should only contain ASCII data",nil)
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"Continue",nil)
|
||||
otherButtonTitles:nil];
|
||||
[error show];
|
||||
if( !addressIsASCII ){
|
||||
UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Invalid SIP address",nil)
|
||||
message:NSLocalizedString(@"The address should only contain ASCII data",nil)
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"Continue",nil)
|
||||
otherButtonTitles:nil];
|
||||
[error show];
|
||||
|
||||
}
|
||||
}
|
||||
LinphoneAddress* linphoneAddress = linphone_core_interpret_url(theLinphoneCore, [address cStringUsingEncoding:[NSString defaultCStringEncoding]]);
|
||||
|
||||
if (linphoneAddress) {
|
||||
|
|
@ -1901,7 +1909,7 @@ static void audioRouteChangeListenerCallback (
|
|||
otherButtonTitles:nil];
|
||||
[error show];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (call) {
|
||||
|
|
@ -1929,16 +1937,16 @@ static void audioRouteChangeListenerCallback (
|
|||
pushNotificationToken = nil;
|
||||
}
|
||||
|
||||
if(apushNotificationToken != nil) {
|
||||
pushNotificationToken = apushNotificationToken;
|
||||
}
|
||||
LinphoneProxyConfig *cfg=nil;
|
||||
linphone_core_get_default_proxy(theLinphoneCore, &cfg);
|
||||
if (cfg ) {
|
||||
linphone_proxy_config_edit(cfg);
|
||||
[self configurePushTokenForProxyConfig: cfg];
|
||||
linphone_proxy_config_done(cfg);
|
||||
}
|
||||
if(apushNotificationToken != nil) {
|
||||
pushNotificationToken = apushNotificationToken;
|
||||
}
|
||||
LinphoneProxyConfig *cfg=nil;
|
||||
linphone_core_get_default_proxy(theLinphoneCore, &cfg);
|
||||
if (cfg ) {
|
||||
linphone_proxy_config_edit(cfg);
|
||||
[self configurePushTokenForProxyConfig: cfg];
|
||||
linphone_proxy_config_done(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)configurePushTokenForProxyConfig:(LinphoneProxyConfig*)proxyCfg{
|
||||
|
|
@ -1956,10 +1964,10 @@ static void audioRouteChangeListenerCallback (
|
|||
#else
|
||||
#define APPMODE_SUFFIX @"prod"
|
||||
#endif
|
||||
NSString *params = [NSString stringWithFormat:@"app-id=%@.%@;pn-type=apple;pn-tok=%@;pn-msg-str=IM_MSG;pn-call-str=IC_MSG;pn-call-snd=ring.caf;pn-msg-snd=msg.caf", [[NSBundle mainBundle] bundleIdentifier],APPMODE_SUFFIX,tokenString];
|
||||
NSString *params = [NSString stringWithFormat:@"app-id=%@.%@;pn-type=apple;pn-tok=%@;pn-msg-str=IM_MSG;pn-call-str=IC_MSG;pn-call-snd=ring.caf;pn-msg-snd=msg.caf", [[NSBundle mainBundle] bundleIdentifier],APPMODE_SUFFIX,tokenString];
|
||||
|
||||
linphone_proxy_config_set_contact_uri_parameters(proxyCfg, [params UTF8String]);
|
||||
linphone_proxy_config_set_contact_parameters(proxyCfg, NULL);
|
||||
linphone_proxy_config_set_contact_uri_parameters(proxyCfg, [params UTF8String]);
|
||||
linphone_proxy_config_set_contact_parameters(proxyCfg, NULL);
|
||||
} else {
|
||||
// no push token:
|
||||
linphone_proxy_config_set_contact_uri_parameters(proxyCfg, NULL);
|
||||
|
|
@ -1990,22 +1998,22 @@ static void audioRouteChangeListenerCallback (
|
|||
if (! [[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDir] && isDir == NO) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:nil error:&error];
|
||||
}
|
||||
return cachePath;
|
||||
return cachePath;
|
||||
}
|
||||
|
||||
+ (int)unreadMessageCount {
|
||||
int count = 0;
|
||||
MSList* rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]);
|
||||
MSList* item = rooms;
|
||||
while (item) {
|
||||
LinphoneChatRoom* room = (LinphoneChatRoom*)item->data;
|
||||
if( room ){
|
||||
count += linphone_chat_room_get_unread_messages_count(room);
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
int count = 0;
|
||||
MSList* rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]);
|
||||
MSList* item = rooms;
|
||||
while (item) {
|
||||
LinphoneChatRoom* room = (LinphoneChatRoom*)item->data;
|
||||
if( room ){
|
||||
count += linphone_chat_room_get_unread_messages_count(room);
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return count;
|
||||
return count;
|
||||
}
|
||||
|
||||
+ (BOOL)copyFile:(NSString*)src destination:(NSString*)dst override:(BOOL)override {
|
||||
|
|
@ -2038,16 +2046,16 @@ static void audioRouteChangeListenerCallback (
|
|||
- (void)configureVbrCodecs{
|
||||
PayloadType *pt;
|
||||
int bitrate=lp_config_get_int(configDb,"audio","codec_bitrate_limit",kLinphoneAudioVbrCodecDefaultBitrate);/*default value is in linphonerc or linphonerc-factory*/
|
||||
const MSList *audio_codecs = linphone_core_get_audio_codecs(theLinphoneCore);
|
||||
const MSList* codec = audio_codecs;
|
||||
while (codec) {
|
||||
pt = codec->data;
|
||||
if( linphone_core_payload_type_is_vbr(theLinphoneCore, pt) ) {
|
||||
linphone_core_set_payload_type_bitrate(theLinphoneCore, pt, bitrate);
|
||||
}
|
||||
const MSList *audio_codecs = linphone_core_get_audio_codecs(theLinphoneCore);
|
||||
const MSList* codec = audio_codecs;
|
||||
while (codec) {
|
||||
pt = codec->data;
|
||||
if( linphone_core_payload_type_is_vbr(theLinphoneCore, pt) ) {
|
||||
linphone_core_set_payload_type_bitrate(theLinphoneCore, pt, bitrate);
|
||||
}
|
||||
|
||||
codec = codec->next;
|
||||
}
|
||||
codec = codec->next;
|
||||
}
|
||||
}
|
||||
|
||||
-(void)setLogsEnabled:(BOOL)enabled {
|
||||
|
|
@ -2094,63 +2102,70 @@ static void audioRouteChangeListenerCallback (
|
|||
#pragma mark - LPConfig Functions
|
||||
|
||||
- (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key {
|
||||
[self lpConfigSetString:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
|
||||
[self lpConfigSetString:value forKey:key forSection:LINPHONERC_APPLICATION_KEY];
|
||||
}
|
||||
|
||||
- (void)lpConfigSetString:(NSString*)value forKey:(NSString*)key forSection:(NSString *)section {
|
||||
if (!key) return;
|
||||
lp_config_set_string(configDb, [section UTF8String], [key UTF8String], value?[value UTF8String]:NULL);
|
||||
}
|
||||
|
||||
- (NSString*)lpConfigStringForKey:(NSString*)key {
|
||||
return [self lpConfigStringForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
|
||||
return [self lpConfigStringForKey:key withDefault:nil];
|
||||
}
|
||||
- (NSString*)lpConfigStringForKey:(NSString*)key withDefault:(NSString*)defaultValue {
|
||||
NSString* value = [self lpConfigStringForKey:key];
|
||||
return value?value:defaultValue;
|
||||
return [self lpConfigStringForKey:key forSection:LINPHONERC_APPLICATION_KEY withDefault:defaultValue];
|
||||
}
|
||||
|
||||
- (NSString*)lpConfigStringForKey:(NSString*)key forSection:(NSString *)section {
|
||||
if (!key) return nil;
|
||||
return [self lpConfigStringForKey:key forSection:section withDefault:nil];
|
||||
}
|
||||
- (NSString *)lpConfigStringForKey:(NSString *)key forSection:(NSString *)section withDefault:(NSString *)defaultValue {
|
||||
if (!key)
|
||||
return defaultValue;
|
||||
const char* value = lp_config_get_string(configDb, [section UTF8String], [key UTF8String], NULL);
|
||||
if (value)
|
||||
return [NSString stringWithUTF8String:value];
|
||||
else
|
||||
return nil;
|
||||
return value ? [NSString stringWithUTF8String:value] : defaultValue;
|
||||
}
|
||||
|
||||
- (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key {
|
||||
[self lpConfigSetInt:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
|
||||
- (void)lpConfigSetInt:(int)value forKey:(NSString *)key {
|
||||
[self lpConfigSetInt:value forKey:key forSection:LINPHONERC_APPLICATION_KEY];
|
||||
}
|
||||
|
||||
- (void)lpConfigSetInt:(NSInteger)value forKey:(NSString*)key forSection:(NSString *)section {
|
||||
- (void)lpConfigSetInt:(int)value forKey:(NSString *)key forSection:(NSString *)section {
|
||||
if (!key) return;
|
||||
lp_config_set_int(configDb, [section UTF8String], [key UTF8String], (int)value );
|
||||
lp_config_set_int(configDb, [section UTF8String], [key UTF8String], (int)value);
|
||||
}
|
||||
|
||||
- (NSInteger)lpConfigIntForKey:(NSString*)key {
|
||||
return [self lpConfigIntForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
|
||||
- (int)lpConfigIntForKey:(NSString *)key {
|
||||
return [self lpConfigIntForKey:key withDefault:-1];
|
||||
}
|
||||
|
||||
- (NSInteger)lpConfigIntForKey:(NSString*)key forSection:(NSString *)section {
|
||||
if (!key) return -1;
|
||||
return lp_config_get_int(configDb, [section UTF8String], [key UTF8String], -1);
|
||||
- (int)lpConfigIntForKey:(NSString *)key withDefault:(int)defaultValue {
|
||||
return [self lpConfigIntForKey:key forSection:LINPHONERC_APPLICATION_KEY withDefault:defaultValue];
|
||||
}
|
||||
- (int)lpConfigIntForKey:(NSString *)key forSection:(NSString *)section {
|
||||
return [self lpConfigIntForKey:key forSection:section withDefault:-1];
|
||||
}
|
||||
- (int)lpConfigIntForKey:(NSString *)key forSection:(NSString *)section withDefault:(int)defaultValue {
|
||||
if (!key)
|
||||
return defaultValue;
|
||||
return lp_config_get_int(configDb, [section UTF8String], [key UTF8String], (int)defaultValue);
|
||||
}
|
||||
|
||||
- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key {
|
||||
[self lpConfigSetBool:value forKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
|
||||
[self lpConfigSetBool:value forKey:key forSection:LINPHONERC_APPLICATION_KEY];
|
||||
}
|
||||
|
||||
- (void)lpConfigSetBool:(BOOL)value forKey:(NSString*)key forSection:(NSString *)section {
|
||||
return [self lpConfigSetInt:(NSInteger)(value == TRUE) forKey:key forSection:section];
|
||||
[self lpConfigSetInt:(int)(value == TRUE)forKey:key forSection:section];
|
||||
}
|
||||
|
||||
- (BOOL)lpConfigBoolForKey:(NSString*)key {
|
||||
return [self lpConfigBoolForKey:key forSection:[NSString stringWithUTF8String:LINPHONERC_APPLICATION_KEY]];
|
||||
return [self lpConfigBoolForKey:key withDefault:FALSE];
|
||||
}
|
||||
- (BOOL)lpConfigBoolForKey:(NSString *)key withDefault:(BOOL)defaultValue {
|
||||
return [self lpConfigBoolForKey:key forSection:LINPHONERC_APPLICATION_KEY withDefault:defaultValue];
|
||||
}
|
||||
|
||||
- (BOOL)lpConfigBoolForKey:(NSString*)key forSection:(NSString *)section {
|
||||
return [self lpConfigIntForKey:key forSection:section] == 1;
|
||||
return [self lpConfigBoolForKey:key forSection:section withDefault:FALSE];
|
||||
}
|
||||
- (BOOL)lpConfigBoolForKey:(NSString *)key forSection:(NSString *)section withDefault:(BOOL)defaultValue {
|
||||
if (!key)
|
||||
return defaultValue;
|
||||
int val = [self lpConfigIntForKey:key forSection:section withDefault:-1];
|
||||
return (val != -1) ? (val == 1) : defaultValue;
|
||||
}
|
||||
|
||||
#pragma mark - GSM management
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UICallCell">
|
||||
|
|
@ -33,10 +32,10 @@
|
|||
<outlet property="videoDownloadBandwidthLabel" destination="109" id="125"/>
|
||||
<outlet property="videoIceConnectivityHeaderLabel" destination="111" id="126"/>
|
||||
<outlet property="videoIceConnectivityLabel" destination="112" id="127"/>
|
||||
<outlet property="videoRecvSizeHeaderLabel" destination="nNJ-4U-pl2" id="r20-yj-TG9"/>
|
||||
<outlet property="videoRecvSizeLabel" destination="RxS-YG-dqM" id="fPi-Uk-MHy"/>
|
||||
<outlet property="videoSentSizeHeaderLabel" destination="6PM-O1-cYd" id="G8P-SK-lgu"/>
|
||||
<outlet property="videoSentSizeLabel" destination="CCZ-g0-5g1" id="kgM-NY-RUy"/>
|
||||
<outlet property="videoRecvSizeFPSHeaderLabel" destination="nNJ-4U-pl2" id="mMd-r3-eEC"/>
|
||||
<outlet property="videoRecvSizeFPSLabel" destination="RxS-YG-dqM" id="paX-s0-Cjs"/>
|
||||
<outlet property="videoSentSizeFPSHeaderLabel" destination="6PM-O1-cYd" id="I9e-1I-e8q"/>
|
||||
<outlet property="videoSentSizeFPSLabel" destination="CCZ-g0-5g1" id="uzZ-aa-lnu"/>
|
||||
<outlet property="videoStatsView" destination="99" id="128"/>
|
||||
<outlet property="videoUploadBandwidthHeaderLabel" destination="107" id="129"/>
|
||||
<outlet property="videoUploadBandwidthLabel" destination="108" id="130"/>
|
||||
|
|
@ -218,11 +217,11 @@
|
|||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" id="j5j-bZ-C2L" userLabel="videoSentSizeView">
|
||||
<view contentMode="scaleToFill" id="j5j-bZ-C2L" userLabel="videoSentSizeFPSView">
|
||||
<rect key="frame" x="10" y="80" width="310" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Size sent:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="6PM-O1-cYd" userLabel="videoSentSizeHeaderLabel">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Size sent (FPS):" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="6PM-O1-cYd" userLabel="videoSentSizeFPSHeaderLabel">
|
||||
<rect key="frame" x="0.0" y="0.0" width="160" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration">
|
||||
|
|
@ -231,7 +230,7 @@
|
|||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="320x240" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="CCZ-g0-5g1" userLabel="videoSentSizeLabel">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="320x240 (15FPS)" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="CCZ-g0-5g1" userLabel="videoSentSizeFPSLabel">
|
||||
<rect key="frame" x="168" y="0.0" width="142" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Video upload bandwidth">
|
||||
|
|
@ -243,11 +242,11 @@
|
|||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" id="6oX-23-Ivn" userLabel="videoRecvSizeView">
|
||||
<view contentMode="scaleToFill" id="6oX-23-Ivn" userLabel="videoRecvSizeFPSView">
|
||||
<rect key="frame" x="10" y="110" width="310" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Size received:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="nNJ-4U-pl2" userLabel="videoRecvSizeHeaderLabel">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Size received (FPS):" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="nNJ-4U-pl2" userLabel="videoRecvSizeFPSHeaderLabel">
|
||||
<rect key="frame" x="0.0" y="0.0" width="160" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration">
|
||||
|
|
@ -256,7 +255,7 @@
|
|||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="320x240" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="RxS-YG-dqM" userLabel="videoRecvSizeLabel">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="320x240 (15FPS)" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="RxS-YG-dqM" userLabel="videoRecvSizeFPSLabel">
|
||||
<rect key="frame" x="168" y="0.0" width="142" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Video upload bandwidth">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UIChatRoomCell">
|
||||
|
|
@ -9,9 +10,11 @@
|
|||
<outlet property="backgroundImage" destination="3" id="11"/>
|
||||
<outlet property="backgroundView" destination="7" id="10"/>
|
||||
<outlet property="bubbleView" destination="16" id="30"/>
|
||||
<outlet property="cancelButton" destination="fGh-KI-efm" id="R65-2g-q7P"/>
|
||||
<outlet property="dateLabel" destination="22" id="24"/>
|
||||
<outlet property="deleteButton" destination="18" id="19"/>
|
||||
<outlet property="downloadButton" destination="33" id="34"/>
|
||||
<outlet property="fileTransferProgress" destination="Pd7-2N-Jg3" id="sct-Jr-HnV"/>
|
||||
<outlet property="innerView" destination="2" id="25"/>
|
||||
<outlet property="messageImageView" destination="28" id="31"/>
|
||||
<outlet property="messageText" destination="43" id="44"/>
|
||||
|
|
@ -54,6 +57,7 @@
|
|||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="33" userLabel="downloadButton">
|
||||
<rect key="frame" x="81" y="33" width="132" height="37"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Download"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" title="Download image">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
|
@ -66,11 +70,31 @@
|
|||
<action selector="onDownloadClick:" destination="-1" eventType="touchUpInside" id="39"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="fGh-KI-efm" userLabel="cancelButton">
|
||||
<rect key="frame" x="81" y="34" width="132" height="37"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Cancel transfer"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
||||
<state key="normal" title="Cancel transfer">
|
||||
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<state key="highlighted">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onCancelDownloadClick:" destination="-1" eventType="touchUpInside" id="Ag3-jA-20G"/>
|
||||
</connections>
|
||||
</button>
|
||||
<progressView hidden="YES" opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" id="Pd7-2N-Jg3" userLabel="fileTransferProgress">
|
||||
<rect key="frame" x="15" y="94" width="264" height="2"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
</progressView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<label opaque="NO" clipsSubviews="YES" contentMode="left" text="09/09/2009 at 09:09" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="8" adjustsFontSizeToFit="NO" id="22" userLabel="timestampLabel">
|
||||
<rect key="frame" x="0.0" y="104" width="280" height="10"/>
|
||||
<rect key="frame" x="4" y="104" width="274" height="10"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="9"/>
|
||||
|
|
@ -103,16 +127,23 @@
|
|||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<rect key="contentStretch" x="0.0" y="0.0" width="0.59999999999999964" height="1"/>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" id="7" userLabel="backgroundView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" id="9" userLabel="selectedBackgroundView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
|
|
@ -121,4 +152,9 @@
|
|||
<image name="list_delete_default.png" width="45" height="45"/>
|
||||
<image name="list_delete_over.png" width="45" height="45"/>
|
||||
</resources>
|
||||
</document>
|
||||
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
||||
<simulatedStatusBarMetrics key="statusBar"/>
|
||||
<simulatedOrientationMetrics key="orientation"/>
|
||||
<simulatedScreenMetrics key="destination" type="retina4"/>
|
||||
</simulatedMetricsContainer>
|
||||
</document>
|
||||
|
|
|
|||
|
|
@ -78,10 +78,10 @@ typedef enum _UICallCellOtherView {
|
|||
@property (nonatomic, strong) IBOutlet UILabel* videoCodecLabel;
|
||||
@property (nonatomic, strong) IBOutlet UILabel* videoCodecHeaderLabel;
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UILabel *videoSentSizeHeaderLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *videoSentSizeLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *videoRecvSizeHeaderLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *videoRecvSizeLabel;
|
||||
@property(strong, nonatomic) IBOutlet UILabel *videoSentSizeFPSHeaderLabel;
|
||||
@property(strong, nonatomic) IBOutlet UILabel *videoSentSizeFPSLabel;
|
||||
@property(strong, nonatomic) IBOutlet UILabel *videoRecvSizeFPSHeaderLabel;
|
||||
@property(strong, nonatomic) IBOutlet UILabel *videoRecvSizeFPSLabel;
|
||||
|
||||
@property (nonatomic, strong) IBOutlet UILabel* videoUploadBandwidthLabel;
|
||||
@property (nonatomic, strong) IBOutlet UILabel* videoUploadBandwidthHeaderLabel;
|
||||
|
|
|
|||
|
|
@ -120,8 +120,8 @@
|
|||
@synthesize videoDownloadBandwidthLabel, videoDownloadBandwidthHeaderLabel;
|
||||
@synthesize videoIceConnectivityLabel, videoIceConnectivityHeaderLabel;
|
||||
|
||||
@synthesize videoRecvSizeHeaderLabel, videoRecvSizeLabel;
|
||||
@synthesize videoSentSizeHeaderLabel, videoSentSizeLabel;
|
||||
@synthesize videoRecvSizeFPSHeaderLabel, videoRecvSizeFPSLabel;
|
||||
@synthesize videoSentSizeFPSHeaderLabel, videoSentSizeFPSLabel;
|
||||
|
||||
@synthesize otherView;
|
||||
|
||||
|
|
@ -433,24 +433,28 @@
|
|||
|
||||
const LinphoneCallStats *stats = linphone_call_get_video_stats(call);
|
||||
|
||||
MSVideoSize sentSize = linphone_call_params_get_sent_video_size(params);
|
||||
MSVideoSize recvSize = linphone_call_params_get_received_video_size(params);
|
||||
if (stats != NULL && linphone_call_params_video_enabled(params)) {
|
||||
MSVideoSize sentSize = linphone_call_params_get_sent_video_size(params);
|
||||
MSVideoSize recvSize = linphone_call_params_get_received_video_size(params);
|
||||
float sentFPS = linphone_call_params_get_sent_framerate(params);
|
||||
float recvFPS = linphone_call_params_get_received_framerate(params);
|
||||
|
||||
if(stats != NULL) {
|
||||
[videoUploadBandwidthLabel setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->upload_bandwidth]];
|
||||
[videoDownloadBandwidthLabel setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->download_bandwidth]];
|
||||
[videoIceConnectivityLabel setText:[UICallCell iceToString:stats->ice_state]];
|
||||
[videoSentSizeLabel setText:[NSString stringWithFormat:@"%dx%d",sentSize.width, sentSize.height]];
|
||||
[videoRecvSizeLabel setText:[NSString stringWithFormat:@"%dx%d",recvSize.width, recvSize.height]];
|
||||
} else {
|
||||
[videoUploadBandwidthLabel setText:@""];
|
||||
[videoDownloadBandwidthLabel setText:@""];
|
||||
[videoIceConnectivityLabel setText:@""];
|
||||
[videoSentSizeLabel setText:@"0x0"];
|
||||
[videoRecvSizeLabel setText:@"0x0"];
|
||||
|
||||
}
|
||||
}
|
||||
[videoUploadBandwidthLabel setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->upload_bandwidth]];
|
||||
[videoDownloadBandwidthLabel
|
||||
setText:[NSString stringWithFormat:@"%1.1f kbits/s", stats->download_bandwidth]];
|
||||
[videoIceConnectivityLabel setText:[UICallCell iceToString:stats->ice_state]];
|
||||
[videoSentSizeFPSLabel
|
||||
setText:[NSString stringWithFormat:@"%dx%d (%.1fFPS)", sentSize.width, sentSize.height, sentFPS]];
|
||||
[videoRecvSizeFPSLabel
|
||||
setText:[NSString stringWithFormat:@"%dx%d (%.1fFPS)", recvSize.width, recvSize.height, recvFPS]];
|
||||
} else {
|
||||
[videoUploadBandwidthLabel setText:@""];
|
||||
[videoDownloadBandwidthLabel setText:@""];
|
||||
[videoIceConnectivityLabel setText:@""];
|
||||
[videoSentSizeFPSLabel setText:@"0x0"];
|
||||
[videoRecvSizeFPSLabel setText:@"0x0"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -106,11 +106,12 @@
|
|||
|
||||
if( last_message ){
|
||||
|
||||
const char* text = linphone_chat_message_get_text(last_message);
|
||||
const char* url = linphone_chat_message_get_external_body_url(last_message);
|
||||
// Message
|
||||
if(url) {
|
||||
[chatContentLabel setText:@""];
|
||||
const char* text = linphone_chat_message_get_text(last_message);
|
||||
const char* url = linphone_chat_message_get_external_body_url(last_message);
|
||||
const LinphoneContent *last_content = linphone_chat_message_get_file_transfer_information(last_message);
|
||||
// Message
|
||||
if(url||last_content) {
|
||||
[chatContentLabel setText:@"🗻"];
|
||||
} else if (text) {
|
||||
NSString *message = [NSString stringWithUTF8String:text];
|
||||
// shorten long messages
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#import "UITransparentTVCell.h"
|
||||
#import "UITextViewNoDefine.h"
|
||||
#include "linphone/linphonecore.h"
|
||||
|
||||
#import "FileTransferDelegate.h"
|
||||
|
||||
@interface UIChatRoomCell : UITransparentTVCell {
|
||||
LinphoneChatMessage* chat;
|
||||
|
|
@ -41,6 +41,8 @@
|
|||
@property (nonatomic, strong) IBOutlet UIButton* downloadButton;
|
||||
@property (nonatomic, strong) IBOutlet UITapGestureRecognizer* imageTapGestureRecognizer;
|
||||
@property (nonatomic, strong) IBOutlet UITapGestureRecognizer* resendTapGestureRecognizer;
|
||||
@property (weak, nonatomic) IBOutlet UIProgressView *fileTransferProgress;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *cancelButton;
|
||||
|
||||
- (id)initWithIdentifier:(NSString*)identifier;
|
||||
+ (CGFloat)height:(LinphoneChatMessage*)chatMessage width:(int)width;
|
||||
|
|
@ -50,7 +52,10 @@
|
|||
- (IBAction)onDeleteClick:(id)event;
|
||||
- (IBAction)onDownloadClick:(id)event;
|
||||
- (IBAction)onImageClick:(id)event;
|
||||
- (IBAction)onCancelDownloadClick:(id)sender;
|
||||
|
||||
- (void)setChatMessage:(LinphoneChatMessage*)message;
|
||||
|
||||
- (void)connectToFileDelegate:(FileTransferDelegate*)ftd;
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@
|
|||
#import <NinePatch.h>
|
||||
#include "linphone/linphonecore.h"
|
||||
|
||||
@implementation UIChatRoomCell
|
||||
@implementation UIChatRoomCell {
|
||||
FileTransferDelegate* ftd;
|
||||
}
|
||||
|
||||
@synthesize innerView;
|
||||
@synthesize bubbleView;
|
||||
|
|
@ -56,306 +58,418 @@ static UIFont *CELL_FONT = nil;
|
|||
#pragma mark - Lifecycle Functions
|
||||
|
||||
- (id)initWithIdentifier:(NSString*)identifier {
|
||||
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
|
||||
[[NSBundle mainBundle] loadNibNamed:@"UIChatRoomCell"
|
||||
owner:self
|
||||
options:nil];
|
||||
imageTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onImageClick:)];
|
||||
[messageImageView addGestureRecognizer:imageTapGestureRecognizer];
|
||||
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
|
||||
[[NSBundle mainBundle] loadNibNamed:@"UIChatRoomCell"
|
||||
owner:self
|
||||
options:nil];
|
||||
imageTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onImageClick:)];
|
||||
[messageImageView addGestureRecognizer:imageTapGestureRecognizer];
|
||||
|
||||
resendTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onResendClick:)];
|
||||
[dateLabel addGestureRecognizer:resendTapGestureRecognizer];
|
||||
resendTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onResendClick:)];
|
||||
[dateLabel addGestureRecognizer:resendTapGestureRecognizer];
|
||||
[statusImage addGestureRecognizer:resendTapGestureRecognizer];
|
||||
|
||||
[self addSubview:innerView];
|
||||
[deleteButton setAlpha:0.0f];
|
||||
[self addSubview:innerView];
|
||||
[deleteButton setAlpha:0.0f];
|
||||
|
||||
// shift message box, otherwise it will collide with the bubble
|
||||
CGRect messageCoords = [messageText frame];
|
||||
messageCoords.origin.x += 2;
|
||||
messageCoords.origin.y += 2;
|
||||
messageCoords.size.width -= 5;
|
||||
[messageText setFrame:messageCoords];
|
||||
messageText.allowSelectAll = TRUE;
|
||||
}
|
||||
return self;
|
||||
// shift message box, otherwise it will collide with the bubble
|
||||
CGRect messageCoords = [messageText frame];
|
||||
messageCoords.origin.x += 2;
|
||||
messageCoords.origin.y += 2;
|
||||
messageCoords.size.width -= 5;
|
||||
[messageText setFrame:messageCoords];
|
||||
messageText.allowSelectAll = TRUE;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self disconnectFromFileDelegate];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)message {
|
||||
self->chat = message;
|
||||
[self update];
|
||||
if (message != self->chat) {
|
||||
self->chat = message;
|
||||
messageImageView.image = nil;
|
||||
[self disconnectFromFileDelegate];
|
||||
for (FileTransferDelegate *aftd in [[LinphoneManager instance] fileTransferDelegates]) {
|
||||
if (message &&
|
||||
linphone_chat_message_get_storage_id(aftd.message) == linphone_chat_message_get_storage_id(message)) {
|
||||
LOGI(@"Chat message [%p] with file transfer delegate [%p], connecting to it!", message,
|
||||
linphone_chat_message_get_user_data(message));
|
||||
[self connectToFileDelegate:aftd];
|
||||
break;
|
||||
}
|
||||
}
|
||||
[self update];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+ (NSString*)decodeTextMessage:(const char*)text {
|
||||
NSString* decoded = [NSString stringWithUTF8String:text];
|
||||
if( decoded == nil ){
|
||||
// couldn't decode the string as UTF8, do a lossy conversion
|
||||
decoded = [NSString stringWithCString:text encoding:NSASCIIStringEncoding];
|
||||
if( decoded == nil ){
|
||||
decoded = @"(invalid string)";
|
||||
}
|
||||
}
|
||||
return decoded;
|
||||
NSString* decoded = [NSString stringWithUTF8String:text];
|
||||
if( decoded == nil ){
|
||||
// couldn't decode the string as UTF8, do a lossy conversion
|
||||
decoded = [NSString stringWithCString:text encoding:NSASCIIStringEncoding];
|
||||
if( decoded == nil ){
|
||||
decoded = @"(invalid string)";
|
||||
}
|
||||
}
|
||||
return decoded;
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
if(chat == nil) {
|
||||
LOGW(@"Cannot update chat room cell: null chat");
|
||||
return;
|
||||
}
|
||||
const char* url = linphone_chat_message_get_external_body_url(chat);
|
||||
const char* text = linphone_chat_message_get_text(chat);
|
||||
BOOL is_external = url && (strstr(url, "http") == url);
|
||||
NSString* localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:chat];
|
||||
if(chat == nil) {
|
||||
LOGW(@"Cannot update chat room cell: null chat");
|
||||
return;
|
||||
}
|
||||
const char* url = linphone_chat_message_get_external_body_url(chat);
|
||||
const char* text = linphone_chat_message_get_text(chat);
|
||||
BOOL is_external =
|
||||
(url && (strstr(url, "http") == url)) || linphone_chat_message_get_file_transfer_information(chat);
|
||||
NSString* localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:chat];
|
||||
|
||||
// this is an image (either to download or already downloaded)
|
||||
if (is_external || localImage) {
|
||||
if(localImage) {
|
||||
if (messageImageView.image == nil) {
|
||||
NSURL *imageUrl = [NSURL URLWithString:localImage];
|
||||
messageText.hidden = YES;
|
||||
[messageImageView startLoading];
|
||||
__block LinphoneChatMessage *achat = chat;
|
||||
[[LinphoneManager instance]
|
||||
.photoLibrary assetForURL:imageUrl
|
||||
resultBlock:^(ALAsset *asset) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
|
||||
^(void) {
|
||||
if (achat == self->chat) { // Avoid glitch and scrolling
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:[asset thumbnail]];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[messageImageView setImage:image];
|
||||
[messageImageView setFullImageUrl:asset];
|
||||
[messageImageView stopLoading];
|
||||
messageImageView.hidden = NO;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
failureBlock:^(NSError *error) {
|
||||
LOGE(@"Can't read image");
|
||||
}];
|
||||
}
|
||||
if (ftd.message != nil) {
|
||||
_cancelButton.hidden = NO;
|
||||
_fileTransferProgress.hidden = NO;
|
||||
downloadButton.hidden = YES;
|
||||
} else {
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = downloadButton.hidden = YES;
|
||||
}
|
||||
} else {
|
||||
messageText.hidden = YES;
|
||||
messageImageView.hidden = _cancelButton.hidden = _fileTransferProgress.hidden = (ftd.message == nil);
|
||||
downloadButton.hidden = !_cancelButton.hidden;
|
||||
}
|
||||
// simple text message
|
||||
} else {
|
||||
[messageText setHidden:FALSE];
|
||||
if ( text ){
|
||||
NSString* nstext = [UIChatRoomCell decodeTextMessage:text];
|
||||
|
||||
if(is_external && !localImage ) {
|
||||
[messageText setHidden:TRUE];
|
||||
[messageImageView setImage:nil];
|
||||
[messageImageView setHidden:TRUE];
|
||||
[downloadButton setHidden:FALSE];
|
||||
/* We need to use an attributed string here so that data detector don't mess
|
||||
* with the text style. See http://stackoverflow.com/a/20669356 */
|
||||
|
||||
} else if(localImage) {
|
||||
NSAttributedString* attr_text = [[NSAttributedString alloc]
|
||||
initWithString:nstext
|
||||
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0],
|
||||
NSForegroundColorAttributeName:[UIColor darkGrayColor]}];
|
||||
messageText.attributedText = attr_text;
|
||||
|
||||
NSURL* imageUrl = [NSURL URLWithString:localImage];
|
||||
} else {
|
||||
messageText.text = @"";
|
||||
}
|
||||
messageImageView.hidden = YES;
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = downloadButton.hidden = YES;
|
||||
}
|
||||
|
||||
[messageText setHidden:TRUE];
|
||||
[messageImageView setImage:nil];
|
||||
[messageImageView startLoading];
|
||||
__block LinphoneChatMessage *achat = chat;
|
||||
[[LinphoneManager instance].photoLibrary assetForURL:imageUrl resultBlock:^(ALAsset *asset) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) {
|
||||
if(achat == self->chat) { //Avoid glitch and scrolling
|
||||
UIImage* image = [[UIImage alloc] initWithCGImage:[asset thumbnail]];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[messageImageView setImage:image];
|
||||
[messageImageView setFullImageUrl:asset];
|
||||
[messageImageView stopLoading];
|
||||
});
|
||||
}
|
||||
});
|
||||
} failureBlock:^(NSError *error) {
|
||||
LOGE(@"Can't read image");
|
||||
}];
|
||||
// Date
|
||||
time_t chattime = linphone_chat_message_get_time(chat);
|
||||
NSDate *message_date = (chattime == 0) ? [[NSDate alloc] init] : [NSDate dateWithTimeIntervalSince1970:chattime];
|
||||
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
|
||||
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
|
||||
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
|
||||
NSLocale *locale = [NSLocale currentLocale];
|
||||
[dateFormatter setLocale:locale];
|
||||
[dateLabel setText:[dateFormatter stringFromDate:message_date]];
|
||||
|
||||
[messageImageView setHidden:FALSE];
|
||||
[downloadButton setHidden:TRUE];
|
||||
} else {
|
||||
// simple text message
|
||||
[messageText setHidden:FALSE];
|
||||
if ( text ){
|
||||
NSString* nstext = [UIChatRoomCell decodeTextMessage:text];
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(chat);
|
||||
BOOL outgoing = linphone_chat_message_is_outgoing(chat);
|
||||
|
||||
/* We need to use an attributed string here so that data detector don't mess
|
||||
* with the text style. See http://stackoverflow.com/a/20669356 */
|
||||
|
||||
NSAttributedString* attr_text = [[NSAttributedString alloc]
|
||||
initWithString:nstext
|
||||
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0],
|
||||
NSForegroundColorAttributeName:[UIColor darkGrayColor]}];
|
||||
messageText.attributedText = attr_text;
|
||||
|
||||
} else {
|
||||
messageText.text = @"";
|
||||
}
|
||||
|
||||
[messageImageView setImage:nil];
|
||||
[messageImageView setHidden:TRUE];
|
||||
|
||||
[downloadButton setHidden:TRUE];
|
||||
}
|
||||
|
||||
// Date
|
||||
NSDate* message_date = [NSDate dateWithTimeIntervalSince1970:linphone_chat_message_get_time(chat)];
|
||||
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
|
||||
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
|
||||
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
|
||||
NSLocale *locale = [NSLocale currentLocale];
|
||||
[dateFormatter setLocale:locale];
|
||||
[dateLabel setText:[dateFormatter stringFromDate:message_date]];
|
||||
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(chat);
|
||||
BOOL outgoing = linphone_chat_message_is_outgoing(chat);
|
||||
|
||||
if( !outgoing ){
|
||||
statusImage.hidden = TRUE; // not useful for incoming chats..
|
||||
} else if (state== LinphoneChatMessageStateInProgress) {
|
||||
if( !outgoing ){
|
||||
statusImage.hidden = TRUE; // not useful for incoming chats..
|
||||
} else if (state== LinphoneChatMessageStateInProgress) {
|
||||
[statusImage setImage:[UIImage imageNamed:@"chat_message_inprogress.png"]];
|
||||
[statusImage setAccessibilityValue:@"in progress"];
|
||||
[statusImage setAccessibilityValue:@"in progress"];
|
||||
statusImage.hidden = FALSE;
|
||||
} else if (state == LinphoneChatMessageStateDelivered) {
|
||||
} else if (state == LinphoneChatMessageStateDelivered || state == LinphoneChatMessageStateFileTransferDone) {
|
||||
[statusImage setImage:[UIImage imageNamed:@"chat_message_delivered.png"]];
|
||||
[statusImage setAccessibilityValue:@"delivered"];
|
||||
[statusImage setAccessibilityValue:@"delivered"];
|
||||
statusImage.hidden = FALSE;
|
||||
} else {
|
||||
[statusImage setImage:[UIImage imageNamed:@"chat_message_not_delivered.png"]];
|
||||
[statusImage setAccessibilityValue:@"not delivered"];
|
||||
[statusImage setAccessibilityValue:@"not delivered"];
|
||||
statusImage.hidden = FALSE;
|
||||
|
||||
NSAttributedString* resend_text = [[NSAttributedString alloc]
|
||||
initWithString:NSLocalizedString(@"Resend", @"Resend")
|
||||
attributes:@{NSForegroundColorAttributeName: [UIColor redColor]}];
|
||||
[dateLabel setAttributedText:resend_text];
|
||||
NSAttributedString* resend_text = [[NSAttributedString alloc]
|
||||
initWithString:NSLocalizedString(@"Resend", @"Resend")
|
||||
attributes:@{NSForegroundColorAttributeName: [UIColor redColor]}];
|
||||
[dateLabel setAttributedText:resend_text];
|
||||
}
|
||||
|
||||
if( outgoing){
|
||||
[messageText setAccessibilityLabel:@"Outgoing message"];
|
||||
} else {
|
||||
[messageText setAccessibilityLabel:@"Incoming message"];
|
||||
}
|
||||
|
||||
if( outgoing){
|
||||
[messageText setAccessibilityLabel:@"Outgoing message"];
|
||||
} else {
|
||||
[messageText setAccessibilityLabel:@"Incoming message"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setEditing:(BOOL)editing {
|
||||
[self setEditing:editing animated:FALSE];
|
||||
[self setEditing:editing animated:FALSE];
|
||||
}
|
||||
|
||||
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
|
||||
if(animated) {
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
[UIView setAnimationDuration:0.3];
|
||||
}
|
||||
if(editing) {
|
||||
[deleteButton setAlpha:1.0f];
|
||||
} else {
|
||||
[deleteButton setAlpha:0.0f];
|
||||
}
|
||||
if(animated) {
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
if(animated) {
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
[UIView setAnimationDuration:0.3];
|
||||
}
|
||||
if(editing) {
|
||||
[deleteButton setAlpha:1.0f];
|
||||
} else {
|
||||
[deleteButton setAlpha:0.0f];
|
||||
}
|
||||
if(animated) {
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
}
|
||||
|
||||
+ (CGSize)viewSize:(LinphoneChatMessage*)chat width:(int)width {
|
||||
CGSize messageSize;
|
||||
const char* url = linphone_chat_message_get_external_body_url(chat);
|
||||
const char* text = linphone_chat_message_get_text(chat);
|
||||
NSString* messageText = text ? [UIChatRoomCell decodeTextMessage:text] : @"";
|
||||
if(url == nil) {
|
||||
if(CELL_FONT == nil) {
|
||||
CELL_FONT = [UIFont systemFontOfSize:CELL_FONT_SIZE];
|
||||
}
|
||||
CGSize messageSize;
|
||||
const char* url = linphone_chat_message_get_external_body_url(chat);
|
||||
const char* text = linphone_chat_message_get_text(chat);
|
||||
NSString* messageText = text ? [UIChatRoomCell decodeTextMessage:text] : @"";
|
||||
if (url == nil && linphone_chat_message_get_file_transfer_information(chat) == NULL) {
|
||||
if(CELL_FONT == nil) {
|
||||
CELL_FONT = [UIFont systemFontOfSize:CELL_FONT_SIZE];
|
||||
}
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
|
||||
|
||||
if( [[[UIDevice currentDevice] systemVersion] doubleValue] >= 7){
|
||||
messageSize = [messageText
|
||||
boundingRectWithSize:CGSizeMake(width - CELL_MESSAGE_X_MARGIN, CGFLOAT_MAX)
|
||||
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesFontLeading)
|
||||
attributes:@{NSFontAttributeName: CELL_FONT}
|
||||
context:nil].size;
|
||||
} else
|
||||
if( [[[UIDevice currentDevice] systemVersion] doubleValue] >= 7){
|
||||
messageSize = [messageText
|
||||
boundingRectWithSize:CGSizeMake(width - CELL_MESSAGE_X_MARGIN, CGFLOAT_MAX)
|
||||
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesFontLeading)
|
||||
attributes:@{NSFontAttributeName: CELL_FONT}
|
||||
context:nil].size;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
messageSize = [messageText sizeWithFont: CELL_FONT
|
||||
constrainedToSize: CGSizeMake(width - CELL_MESSAGE_X_MARGIN, 10000.0f)
|
||||
lineBreakMode: NSLineBreakByTruncatingTail];
|
||||
}
|
||||
} else {
|
||||
messageSize = CGSizeMake(CELL_IMAGE_WIDTH, CELL_IMAGE_HEIGHT);
|
||||
}
|
||||
messageSize.height += CELL_MESSAGE_Y_MARGIN;
|
||||
if(messageSize.height < CELL_MIN_HEIGHT)
|
||||
messageSize.height = CELL_MIN_HEIGHT;
|
||||
messageSize.width += CELL_MESSAGE_X_MARGIN;
|
||||
if(messageSize.width < CELL_MIN_WIDTH)
|
||||
messageSize.width = CELL_MIN_WIDTH;
|
||||
return messageSize;
|
||||
{
|
||||
messageSize = [messageText sizeWithFont: CELL_FONT
|
||||
constrainedToSize: CGSizeMake(width - CELL_MESSAGE_X_MARGIN, 10000.0f)
|
||||
lineBreakMode: NSLineBreakByTruncatingTail];
|
||||
}
|
||||
} else {
|
||||
messageSize = CGSizeMake(CELL_IMAGE_WIDTH, CELL_IMAGE_HEIGHT);
|
||||
}
|
||||
messageSize.height += CELL_MESSAGE_Y_MARGIN;
|
||||
if(messageSize.height < CELL_MIN_HEIGHT)
|
||||
messageSize.height = CELL_MIN_HEIGHT;
|
||||
messageSize.width += CELL_MESSAGE_X_MARGIN;
|
||||
if(messageSize.width < CELL_MIN_WIDTH)
|
||||
messageSize.width = CELL_MIN_WIDTH;
|
||||
return messageSize;
|
||||
}
|
||||
|
||||
+ (CGFloat)height:(LinphoneChatMessage*)chatMessage width:(int)width {
|
||||
return [UIChatRoomCell viewSize:chatMessage width:width].height;
|
||||
return [UIChatRoomCell viewSize:chatMessage width:width].height;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - View Functions
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
if(chat != nil) {
|
||||
// Resize inner
|
||||
CGRect innerFrame;
|
||||
BOOL is_outgoing = linphone_chat_message_is_outgoing(chat);
|
||||
innerFrame.size = [UIChatRoomCell viewSize:chat width:[self frame].size.width];
|
||||
if(!is_outgoing) { // Inverted
|
||||
innerFrame.origin.x = 0.0f;
|
||||
innerFrame.origin.y = 0.0f;
|
||||
} else {
|
||||
innerFrame.origin.x = [self frame].size.width - innerFrame.size.width;
|
||||
innerFrame.origin.y = 0.0f;
|
||||
}
|
||||
[innerView setFrame:innerFrame];
|
||||
[super layoutSubviews];
|
||||
if(chat != nil) {
|
||||
// Resize inner
|
||||
CGRect innerFrame;
|
||||
BOOL is_outgoing = linphone_chat_message_is_outgoing(chat);
|
||||
innerFrame.size = [UIChatRoomCell viewSize:chat width:[self frame].size.width];
|
||||
if(!is_outgoing) { // Inverted
|
||||
innerFrame.origin.x = 0.0f;
|
||||
innerFrame.origin.y = 0.0f;
|
||||
} else {
|
||||
innerFrame.origin.x = [self frame].size.width - innerFrame.size.width;
|
||||
innerFrame.origin.y = 0.0f;
|
||||
}
|
||||
[innerView setFrame:innerFrame];
|
||||
|
||||
CGRect messageFrame = [bubbleView frame];
|
||||
messageFrame.origin.y = ([innerView frame].size.height - messageFrame.size.height)/2;
|
||||
if(!is_outgoing) { // Inverted
|
||||
UIImage* image = [UIImage imageNamed:@"chat_bubble_incoming"];
|
||||
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(26, 32, 34, 56)];
|
||||
[backgroundImage setImage:image];
|
||||
messageFrame.origin.y += 5;
|
||||
} else {
|
||||
UIImage* image = [UIImage imageNamed:@"chat_bubble_outgoing"];
|
||||
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(14, 15, 25, 40)];
|
||||
[backgroundImage setImage:image];
|
||||
messageFrame.origin.y -= 5;
|
||||
}
|
||||
[bubbleView setFrame:messageFrame];
|
||||
}
|
||||
CGRect messageFrame = [bubbleView frame];
|
||||
messageFrame.origin.y = ([innerView frame].size.height - messageFrame.size.height)/2;
|
||||
if(!is_outgoing) { // Inverted
|
||||
UIImage* image = [UIImage imageNamed:@"chat_bubble_incoming"];
|
||||
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(26, 32, 34, 56)];
|
||||
[backgroundImage setImage:image];
|
||||
messageFrame.origin.y += 5;
|
||||
} else {
|
||||
UIImage* image = [UIImage imageNamed:@"chat_bubble_outgoing"];
|
||||
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(14, 15, 25, 40)];
|
||||
[backgroundImage setImage:image];
|
||||
messageFrame.origin.y -= 5;
|
||||
}
|
||||
[bubbleView setFrame:messageFrame];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Action Functions
|
||||
|
||||
- (IBAction)onDeleteClick:(id)event {
|
||||
if(chat != NULL) {
|
||||
UIView *view = [self superview];
|
||||
// Find TableViewCell
|
||||
while(view != nil && ![view isKindOfClass:[UITableView class]]) view = [view superview];
|
||||
if(view != nil) {
|
||||
UITableView *tableView = (UITableView*) view;
|
||||
NSIndexPath *indexPath = [tableView indexPathForCell:self];
|
||||
[[tableView dataSource] tableView:tableView commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:indexPath];
|
||||
}
|
||||
}
|
||||
if(chat != NULL) {
|
||||
if (ftd.message != nil) {
|
||||
[ftd cancel];
|
||||
}
|
||||
UIView *view = [self superview];
|
||||
// Find TableViewCell
|
||||
while(view != nil && ![view isKindOfClass:[UITableView class]]) view = [view superview];
|
||||
if(view != nil) {
|
||||
UITableView *tableView = (UITableView*) view;
|
||||
NSIndexPath *indexPath = [tableView indexPathForCell:self];
|
||||
[[tableView dataSource] tableView:tableView commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:indexPath];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)onDownloadClick:(id)event {
|
||||
NSURL* url = [NSURL URLWithString:[NSString stringWithUTF8String:linphone_chat_message_get_external_body_url(chat)]];
|
||||
[chatRoomDelegate chatRoomStartImageDownload:url userInfo:[NSValue valueWithPointer:chat]];
|
||||
|
||||
if (ftd.message == nil) {
|
||||
ftd = [[FileTransferDelegate alloc] init];
|
||||
[[[LinphoneManager instance] fileTransferDelegates] addObject:ftd];
|
||||
[self connectToFileDelegate:ftd];
|
||||
[ftd download:chat];
|
||||
_cancelButton.hidden = NO;
|
||||
downloadButton.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)onCancelDownloadClick:(id)sender {
|
||||
[ftd cancel];
|
||||
[self disconnectFromFileDelegate];
|
||||
[self update];
|
||||
}
|
||||
|
||||
|
||||
- (IBAction)onImageClick:(id)event {
|
||||
if(![messageImageView isLoading]) {
|
||||
ImageViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ImageViewController compositeViewDescription] push:TRUE], ImageViewController);
|
||||
if(controller != nil) {
|
||||
CGImageRef fullScreenRef = [[messageImageView.fullImageUrl defaultRepresentation] fullScreenImage];
|
||||
UIImage* fullScreen = [UIImage imageWithCGImage:fullScreenRef];
|
||||
[controller setImage:fullScreen];
|
||||
}
|
||||
}
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(self->chat);
|
||||
if (state == LinphoneChatMessageStateNotDelivered) {
|
||||
[self onResendClick:nil];
|
||||
} else {
|
||||
if (![messageImageView isLoading]) {
|
||||
ImageViewController *controller = DYNAMIC_CAST(
|
||||
[[PhoneMainView instance] changeCurrentView:[ImageViewController compositeViewDescription] push:TRUE],
|
||||
ImageViewController);
|
||||
if (controller != nil) {
|
||||
CGImageRef fullScreenRef = [[messageImageView.fullImageUrl defaultRepresentation] fullScreenImage];
|
||||
UIImage *fullScreen = [UIImage imageWithCGImage:fullScreenRef];
|
||||
[controller setImage:fullScreen];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)onResendClick:(id)event {
|
||||
if( chat == nil ) return;
|
||||
if( chat == nil ) return;
|
||||
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(self->chat);
|
||||
if (state == LinphoneChatMessageStateNotDelivered) {
|
||||
const char* text = linphone_chat_message_get_text(self->chat);
|
||||
const char* url = linphone_chat_message_get_external_body_url(self->chat);
|
||||
NSString* message = text ? [NSString stringWithUTF8String:text] : nil;
|
||||
NSString* exturl = url ? [NSString stringWithUTF8String:url] : nil;
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(self->chat);
|
||||
if (state == LinphoneChatMessageStateNotDelivered) {
|
||||
if (linphone_chat_message_get_file_transfer_information(chat) != NULL) {
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:chat];
|
||||
NSURL *imageUrl = [NSURL URLWithString:localImage];
|
||||
|
||||
[self onDeleteClick:nil];
|
||||
[self onDeleteClick:nil];
|
||||
|
||||
double delayInSeconds = 0.4;
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
|
||||
[chatRoomDelegate resendChat:message withExternalUrl:exturl];
|
||||
});
|
||||
}
|
||||
[[LinphoneManager instance]
|
||||
.photoLibrary assetForURL:imageUrl
|
||||
resultBlock:^(ALAsset *asset) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
|
||||
^(void) {
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:[asset thumbnail]];
|
||||
[chatRoomDelegate chatRoomStartImageUpload:image url:imageUrl];
|
||||
});
|
||||
}
|
||||
failureBlock:^(NSError *error) {
|
||||
LOGE(@"Can't read image");
|
||||
}];
|
||||
} else {
|
||||
const char *text = linphone_chat_message_get_text(self->chat);
|
||||
NSString *message = text ? [NSString stringWithUTF8String:text] : nil;
|
||||
|
||||
[self onDeleteClick:nil];
|
||||
|
||||
double delayInSeconds = 0.4;
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
|
||||
[chatRoomDelegate resendChat:message withExternalUrl:nil];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - LinphoneFileTransfer Notifications Handling
|
||||
|
||||
- (void)connectToFileDelegate:(FileTransferDelegate*)aftd {
|
||||
ftd = aftd;
|
||||
_fileTransferProgress.progress = 0;
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(onFileTransferSendUpdate:)
|
||||
name:kLinphoneFileTransferSendUpdate
|
||||
object:ftd];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(onFileTransferRecvUpdate:)
|
||||
name:kLinphoneFileTransferRecvUpdate
|
||||
object:ftd];
|
||||
}
|
||||
|
||||
- (void)disconnectFromFileDelegate {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
ftd = nil;
|
||||
}
|
||||
|
||||
- (void)onFileTransferSendUpdate:(NSNotification*)notif {
|
||||
LinphoneChatMessageState state = [[[notif userInfo] objectForKey:@"state"] intValue];
|
||||
|
||||
if (state == LinphoneChatMessageStateInProgress) {
|
||||
float progress = [[[notif userInfo] objectForKey:@"progress"] floatValue];
|
||||
// When uploading a file, the message file is first uploaded to the server,
|
||||
// so we are in progress state. Then state goes to filetransfertdone. Then,
|
||||
// the exact same message is sent to the other chat participant and we come
|
||||
// back to in progress again. This second time is NOT an upload, so we must
|
||||
// not update progress!
|
||||
_fileTransferProgress.progress = MAX(_fileTransferProgress.progress, progress);
|
||||
_fileTransferProgress.hidden = _cancelButton.hidden = (_fileTransferProgress.progress == 1.f);
|
||||
} else {
|
||||
[self update];
|
||||
}
|
||||
}
|
||||
- (void)onFileTransferRecvUpdate:(NSNotification*)notif {
|
||||
LinphoneChatMessageState state = [[[notif userInfo] objectForKey:@"state"] intValue];
|
||||
if (state == LinphoneChatMessageStateInProgress) {
|
||||
float progress = [[[notif userInfo] objectForKey:@"progress"] floatValue];
|
||||
_fileTransferProgress.progress = MAX(_fileTransferProgress.progress, progress);
|
||||
_fileTransferProgress.hidden = _cancelButton.hidden = (_fileTransferProgress.progress == 1.f);
|
||||
} else {
|
||||
[self update];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <AudioToolbox/AudioServices.h>
|
||||
|
||||
#import "InAppProductsViewController.h"
|
||||
#import "LinphoneAppDelegate.h"
|
||||
#import "PhoneMainView.h"
|
||||
#import "Utils.h"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
20
Classes/Utils/FileTransferDelegate.h
Normal file
20
Classes/Utils/FileTransferDelegate.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// FileTransferDelegate.h
|
||||
// linphone
|
||||
//
|
||||
// Created by Gautier Pelloux-Prayer on 10/06/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "LinphoneManager.h"
|
||||
|
||||
@interface FileTransferDelegate : NSObject
|
||||
|
||||
- (void)upload:(UIImage *)image withURL:(NSURL *)url forChatRoom:(LinphoneChatRoom *)chatRoom;
|
||||
- (void)cancel;
|
||||
- (BOOL)download:(LinphoneChatMessage *)message;
|
||||
|
||||
@property() LinphoneChatMessage *message;
|
||||
@end
|
||||
207
Classes/Utils/FileTransferDelegate.m
Normal file
207
Classes/Utils/FileTransferDelegate.m
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
//
|
||||
// FileTransferDelegate.m
|
||||
// linphone
|
||||
//
|
||||
// Created by Gautier Pelloux-Prayer on 10/06/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import "FileTransferDelegate.h"
|
||||
@interface FileTransferDelegate ()
|
||||
@property(strong) NSMutableData *data;
|
||||
@end
|
||||
|
||||
@implementation FileTransferDelegate
|
||||
|
||||
- (void)dealloc {
|
||||
if (_message != nil) {
|
||||
[self cancel];
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, const LinphoneContent *content,
|
||||
const LinphoneBuffer *buffer) {
|
||||
FileTransferDelegate *thiz = (__bridge FileTransferDelegate *)linphone_chat_message_get_user_data(message);
|
||||
size_t size = linphone_buffer_get_size(buffer);
|
||||
|
||||
if (!thiz.data) {
|
||||
thiz.data = [[NSMutableData alloc] initWithCapacity:linphone_content_get_size(content)];
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
LOGI(@"Transfer of %s (%d bytes): download finished", linphone_content_get_name(content), size);
|
||||
assert([thiz.data length] == linphone_content_get_size(content));
|
||||
|
||||
// we're finished, save the image and update the message
|
||||
UIImage *image = [UIImage imageWithData:thiz.data];
|
||||
|
||||
|
||||
[[[LinphoneManager instance] fileTransferDelegates] removeObject:thiz];
|
||||
|
||||
[[LinphoneManager instance]
|
||||
.photoLibrary
|
||||
writeImageToSavedPhotosAlbum:image.CGImage
|
||||
orientation:(ALAssetOrientation)[image imageOrientation]
|
||||
completionBlock:^(NSURL *assetURL, NSError *error) {
|
||||
if (error) {
|
||||
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
|
||||
|
||||
UIAlertView *errorAlert = [[UIAlertView alloc]
|
||||
initWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write image to photo library", nil)
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"Ok", nil)
|
||||
otherButtonTitles:nil, nil];
|
||||
[errorAlert show];
|
||||
} else {
|
||||
LOGI(@"Image saved to [%@]", [assetURL absoluteString]);
|
||||
[LinphoneManager setValueInMessageAppData:[assetURL absoluteString]
|
||||
forKey:@"localimage"
|
||||
inMessage:message];
|
||||
}
|
||||
thiz.message = NULL;
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:kLinphoneFileTransferRecvUpdate
|
||||
object:thiz
|
||||
userInfo:@{
|
||||
@"state" : @(linphone_chat_message_get_state(message)),
|
||||
@"image" : image,
|
||||
@"progress" :
|
||||
@([thiz.data length] * 1.f / linphone_content_get_size(content)),
|
||||
}];
|
||||
|
||||
CFRelease((__bridge CFTypeRef)thiz);
|
||||
}];
|
||||
} else {
|
||||
LOGD(@"Transfer of %s (%d bytes): already %ld sent, adding %ld", linphone_content_get_name(content),
|
||||
linphone_content_get_size(content), [thiz.data length], size);
|
||||
[thiz.data appendBytes:linphone_buffer_get_string_content(buffer) length:size];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:kLinphoneFileTransferRecvUpdate
|
||||
object:thiz
|
||||
userInfo:@{
|
||||
@"state" : @(linphone_chat_message_get_state(message)),
|
||||
@"progress" : @([thiz.data length] * 1.f / linphone_content_get_size(content)),
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *message, const LinphoneContent *content,
|
||||
size_t offset, size_t size) {
|
||||
FileTransferDelegate *thiz = (__bridge FileTransferDelegate *)linphone_chat_message_get_user_data(message);
|
||||
size_t total = thiz.data.length;
|
||||
if (thiz.data) {
|
||||
size_t remaining = total - offset;
|
||||
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"state" : @(linphone_chat_message_get_state(message)),
|
||||
@"progress" : @(offset * 1.f / total),
|
||||
}];
|
||||
LOGD(@"Transfer of %s (%d bytes): already sent %ld, remaining %ld", linphone_content_get_name(content), total,
|
||||
offset, remaining);
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneFileTransferSendUpdate
|
||||
object:thiz
|
||||
userInfo:dict];
|
||||
@try {
|
||||
return linphone_buffer_new_from_data([thiz.data subdataWithRange:NSMakeRange(offset, size)].bytes, size);
|
||||
} @catch (NSException *exception) {
|
||||
LOGE(@"Exception: %@", exception);
|
||||
}
|
||||
} else {
|
||||
LOGE(@"Transfer of %s (%d bytes): %d Error - no upload data in progress!", linphone_content_get_name(content),
|
||||
total, offset);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
|
||||
FileTransferDelegate *thiz = (__bridge FileTransferDelegate *)linphone_chat_message_get_user_data(msg);
|
||||
|
||||
NSString *notification =
|
||||
linphone_chat_message_is_outgoing(msg) ? kLinphoneFileTransferSendUpdate : kLinphoneFileTransferRecvUpdate;
|
||||
|
||||
const char *text = (linphone_chat_message_get_file_transfer_information(msg) != NULL)
|
||||
? "photo transfer"
|
||||
: linphone_chat_message_get_text(msg);
|
||||
LOGI(@"Delivery status for [%s] is [%s]", text, linphone_chat_message_state_to_string(state));
|
||||
|
||||
NSDictionary *dict = @{ @"state" : @(state), @"progress" : @0.f };
|
||||
if (state == LinphoneChatMessageStateFileTransferDone || state == LinphoneChatMessageStateFileTransferError) {
|
||||
thiz.message = NULL;
|
||||
}
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:notification object:thiz userInfo:dict];
|
||||
if (linphone_chat_message_is_outgoing(msg)) {
|
||||
[thiz stopAndDestroy];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)upload:(UIImage *)image withURL:(NSURL *)url forChatRoom:(LinphoneChatRoom *)chatRoom {
|
||||
LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_lc(chatRoom));
|
||||
_data = [NSMutableData dataWithData:UIImageJPEGRepresentation(image, 1.0)];
|
||||
linphone_content_set_type(content, "image");
|
||||
linphone_content_set_subtype(content, "jpeg");
|
||||
linphone_content_set_name(content,
|
||||
[[NSString stringWithFormat:@"%li-%f.jpg", (long)[image hash],
|
||||
[NSDate timeIntervalSinceReferenceDate]] UTF8String]);
|
||||
linphone_content_set_size(content, [_data length]);
|
||||
|
||||
CFTypeRef myself = (__bridge CFTypeRef)self;
|
||||
_message = linphone_chat_room_create_file_transfer_message(chatRoom, content);
|
||||
linphone_chat_message_ref(_message);
|
||||
linphone_chat_message_set_user_data(_message, (void *)CFRetain(myself));
|
||||
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(_message),
|
||||
linphone_iphone_file_transfer_send);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), message_status);
|
||||
|
||||
if (url) {
|
||||
// internal url is saved in the appdata for display and later save
|
||||
[LinphoneManager setValueInMessageAppData:[url absoluteString] forKey:@"localimage" inMessage:_message];
|
||||
}
|
||||
|
||||
linphone_chat_room_send_chat_message(chatRoom, _message);
|
||||
}
|
||||
|
||||
- (BOOL)download:(LinphoneChatMessage *)message {
|
||||
_message = message;
|
||||
// we need to keep a ref on the message to continue downloading even if user quit a chatroom which destroy all chat
|
||||
// messages
|
||||
linphone_chat_message_ref(_message);
|
||||
const char *url = linphone_chat_message_get_external_body_url(_message);
|
||||
LOGI(@"Content to download: %s", url);
|
||||
|
||||
if (url == nil)
|
||||
return FALSE;
|
||||
|
||||
linphone_chat_message_set_user_data(_message, (void *)CFBridgingRetain(self));
|
||||
|
||||
linphone_chat_message_cbs_set_file_transfer_recv(linphone_chat_message_get_callbacks(_message),
|
||||
linphone_iphone_file_transfer_recv);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), message_status);
|
||||
|
||||
linphone_chat_message_download_file(_message);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (void)stopAndDestroy {
|
||||
[[[LinphoneManager instance] fileTransferDelegates] removeObject:self];
|
||||
if (_message != NULL) {
|
||||
linphone_chat_message_set_user_data(_message, NULL);
|
||||
|
||||
linphone_chat_message_cbs_set_file_transfer_progress_indication(linphone_chat_message_get_callbacks(_message),
|
||||
NULL);
|
||||
linphone_chat_message_cbs_set_file_transfer_recv(linphone_chat_message_get_callbacks(_message), NULL);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), NULL);
|
||||
linphone_chat_message_cancel_file_transfer(_message);
|
||||
linphone_chat_message_unref(_message);
|
||||
}
|
||||
_message = nil;
|
||||
_data = nil;
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
[self stopAndDestroy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -105,6 +105,7 @@
|
|||
}
|
||||
|
||||
- (void)viewDidUnload {
|
||||
[super viewDidUnload];
|
||||
// Release any retained subviews of the main view.
|
||||
// e.g. self.myOutlet = nil;
|
||||
self.tableView = nil;
|
||||
|
|
|
|||
59
Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.h
Normal file
59
Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// UIAlertView+Blocks.h
|
||||
// UIAlertViewBlocks
|
||||
//
|
||||
// Created by Ryan Maxwell on 29/08/13.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2013 Ryan Maxwell
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef void (^UIAlertViewBlock) (UIAlertView *alertView);
|
||||
typedef void (^UIAlertViewCompletionBlock) (UIAlertView *alertView, NSInteger buttonIndex);
|
||||
|
||||
@interface UIAlertView (Blocks)
|
||||
|
||||
+ (instancetype)showWithTitle:(NSString *)title
|
||||
message:(NSString *)message
|
||||
style:(UIAlertViewStyle)style
|
||||
cancelButtonTitle:(NSString *)cancelButtonTitle
|
||||
otherButtonTitles:(NSArray *)otherButtonTitles
|
||||
tapBlock:(UIAlertViewCompletionBlock)tapBlock;
|
||||
|
||||
+ (instancetype)showWithTitle:(NSString *)title
|
||||
message:(NSString *)message
|
||||
cancelButtonTitle:(NSString *)cancelButtonTitle
|
||||
otherButtonTitles:(NSArray *)otherButtonTitles
|
||||
tapBlock:(UIAlertViewCompletionBlock)tapBlock;
|
||||
|
||||
@property (copy, nonatomic) UIAlertViewCompletionBlock tapBlock;
|
||||
@property (copy, nonatomic) UIAlertViewCompletionBlock willDismissBlock;
|
||||
@property (copy, nonatomic) UIAlertViewCompletionBlock didDismissBlock;
|
||||
|
||||
@property (copy, nonatomic) UIAlertViewBlock willPresentBlock;
|
||||
@property (copy, nonatomic) UIAlertViewBlock didPresentBlock;
|
||||
@property (copy, nonatomic) UIAlertViewBlock cancelBlock;
|
||||
|
||||
@property (copy, nonatomic) BOOL(^shouldEnableFirstOtherButtonBlock)(UIAlertView *alertView);
|
||||
|
||||
@end
|
||||
264
Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.m
Normal file
264
Classes/Utils/UIAlertView+Blocks/UIAlertView+Blocks.m
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
//
|
||||
// UIAlertView+Blocks.m
|
||||
// UIAlertViewBlocks
|
||||
//
|
||||
// Created by Ryan Maxwell on 29/08/13.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2013 Ryan Maxwell
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import "UIAlertView+Blocks.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
static const void *UIAlertViewOriginalDelegateKey = &UIAlertViewOriginalDelegateKey;
|
||||
|
||||
static const void *UIAlertViewTapBlockKey = &UIAlertViewTapBlockKey;
|
||||
static const void *UIAlertViewWillPresentBlockKey = &UIAlertViewWillPresentBlockKey;
|
||||
static const void *UIAlertViewDidPresentBlockKey = &UIAlertViewDidPresentBlockKey;
|
||||
static const void *UIAlertViewWillDismissBlockKey = &UIAlertViewWillDismissBlockKey;
|
||||
static const void *UIAlertViewDidDismissBlockKey = &UIAlertViewDidDismissBlockKey;
|
||||
static const void *UIAlertViewCancelBlockKey = &UIAlertViewCancelBlockKey;
|
||||
static const void *UIAlertViewShouldEnableFirstOtherButtonBlockKey = &UIAlertViewShouldEnableFirstOtherButtonBlockKey;
|
||||
|
||||
@implementation UIAlertView (Blocks)
|
||||
|
||||
+ (instancetype)showWithTitle:(NSString *)title
|
||||
message:(NSString *)message
|
||||
style:(UIAlertViewStyle)style
|
||||
cancelButtonTitle:(NSString *)cancelButtonTitle
|
||||
otherButtonTitles:(NSArray *)otherButtonTitles
|
||||
tapBlock:(UIAlertViewCompletionBlock)tapBlock {
|
||||
|
||||
NSString *firstObject = otherButtonTitles.count ? otherButtonTitles[0] : nil;
|
||||
|
||||
UIAlertView *alertView = [[self alloc] initWithTitle:title
|
||||
message:message
|
||||
delegate:nil
|
||||
cancelButtonTitle:cancelButtonTitle
|
||||
otherButtonTitles:firstObject, nil];
|
||||
|
||||
alertView.alertViewStyle = style;
|
||||
|
||||
if (otherButtonTitles.count > 1) {
|
||||
for (NSString *buttonTitle in [otherButtonTitles subarrayWithRange:NSMakeRange(1, otherButtonTitles.count - 1)]) {
|
||||
[alertView addButtonWithTitle:buttonTitle];
|
||||
}
|
||||
}
|
||||
|
||||
if (tapBlock) {
|
||||
alertView.tapBlock = tapBlock;
|
||||
}
|
||||
|
||||
[alertView show];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
return [alertView autorelease];
|
||||
#else
|
||||
return alertView;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+ (instancetype)showWithTitle:(NSString *)title
|
||||
message:(NSString *)message
|
||||
cancelButtonTitle:(NSString *)cancelButtonTitle
|
||||
otherButtonTitles:(NSArray *)otherButtonTitles
|
||||
tapBlock:(UIAlertViewCompletionBlock)tapBlock {
|
||||
|
||||
return [self showWithTitle:title
|
||||
message:message
|
||||
style:UIAlertViewStyleDefault
|
||||
cancelButtonTitle:cancelButtonTitle
|
||||
otherButtonTitles:otherButtonTitles
|
||||
tapBlock:tapBlock];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)_checkAlertViewDelegate {
|
||||
if (self.delegate != (id<UIAlertViewDelegate>)self) {
|
||||
objc_setAssociatedObject(self, UIAlertViewOriginalDelegateKey, self.delegate, OBJC_ASSOCIATION_ASSIGN);
|
||||
self.delegate = (id<UIAlertViewDelegate>)self;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIAlertViewCompletionBlock)tapBlock {
|
||||
return objc_getAssociatedObject(self, UIAlertViewTapBlockKey);
|
||||
}
|
||||
|
||||
- (void)setTapBlock:(UIAlertViewCompletionBlock)tapBlock {
|
||||
[self _checkAlertViewDelegate];
|
||||
objc_setAssociatedObject(self, UIAlertViewTapBlockKey, tapBlock, OBJC_ASSOCIATION_COPY);
|
||||
}
|
||||
|
||||
- (UIAlertViewCompletionBlock)willDismissBlock {
|
||||
return objc_getAssociatedObject(self, UIAlertViewWillDismissBlockKey);
|
||||
}
|
||||
|
||||
- (void)setWillDismissBlock:(UIAlertViewCompletionBlock)willDismissBlock {
|
||||
[self _checkAlertViewDelegate];
|
||||
objc_setAssociatedObject(self, UIAlertViewWillDismissBlockKey, willDismissBlock, OBJC_ASSOCIATION_COPY);
|
||||
}
|
||||
|
||||
- (UIAlertViewCompletionBlock)didDismissBlock {
|
||||
return objc_getAssociatedObject(self, UIAlertViewDidDismissBlockKey);
|
||||
}
|
||||
|
||||
- (void)setDidDismissBlock:(UIAlertViewCompletionBlock)didDismissBlock {
|
||||
[self _checkAlertViewDelegate];
|
||||
objc_setAssociatedObject(self, UIAlertViewDidDismissBlockKey, didDismissBlock, OBJC_ASSOCIATION_COPY);
|
||||
}
|
||||
|
||||
- (UIAlertViewBlock)willPresentBlock {
|
||||
return objc_getAssociatedObject(self, UIAlertViewWillPresentBlockKey);
|
||||
}
|
||||
|
||||
- (void)setWillPresentBlock:(UIAlertViewBlock)willPresentBlock {
|
||||
[self _checkAlertViewDelegate];
|
||||
objc_setAssociatedObject(self, UIAlertViewWillPresentBlockKey, willPresentBlock, OBJC_ASSOCIATION_COPY);
|
||||
}
|
||||
|
||||
- (UIAlertViewBlock)didPresentBlock {
|
||||
return objc_getAssociatedObject(self, UIAlertViewDidPresentBlockKey);
|
||||
}
|
||||
|
||||
- (void)setDidPresentBlock:(UIAlertViewBlock)didPresentBlock {
|
||||
[self _checkAlertViewDelegate];
|
||||
objc_setAssociatedObject(self, UIAlertViewDidPresentBlockKey, didPresentBlock, OBJC_ASSOCIATION_COPY);
|
||||
}
|
||||
|
||||
- (UIAlertViewBlock)cancelBlock {
|
||||
return objc_getAssociatedObject(self, UIAlertViewCancelBlockKey);
|
||||
}
|
||||
|
||||
- (void)setCancelBlock:(UIAlertViewBlock)cancelBlock {
|
||||
[self _checkAlertViewDelegate];
|
||||
objc_setAssociatedObject(self, UIAlertViewCancelBlockKey, cancelBlock, OBJC_ASSOCIATION_COPY);
|
||||
}
|
||||
|
||||
- (void)setShouldEnableFirstOtherButtonBlock:(BOOL(^)(UIAlertView *alertView))shouldEnableFirstOtherButtonBlock {
|
||||
[self _checkAlertViewDelegate];
|
||||
objc_setAssociatedObject(self, UIAlertViewShouldEnableFirstOtherButtonBlockKey, shouldEnableFirstOtherButtonBlock, OBJC_ASSOCIATION_COPY);
|
||||
}
|
||||
|
||||
- (BOOL(^)(UIAlertView *alertView))shouldEnableFirstOtherButtonBlock {
|
||||
return objc_getAssociatedObject(self, UIAlertViewShouldEnableFirstOtherButtonBlockKey);
|
||||
}
|
||||
|
||||
#pragma mark - UIAlertViewDelegate
|
||||
|
||||
- (void)willPresentAlertView:(UIAlertView *)alertView {
|
||||
UIAlertViewBlock block = alertView.willPresentBlock;
|
||||
|
||||
if (block) {
|
||||
block(alertView);
|
||||
}
|
||||
|
||||
id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
|
||||
if (originalDelegate && [originalDelegate respondsToSelector:@selector(willPresentAlertView:)]) {
|
||||
[originalDelegate willPresentAlertView:alertView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didPresentAlertView:(UIAlertView *)alertView {
|
||||
UIAlertViewBlock block = alertView.didPresentBlock;
|
||||
|
||||
if (block) {
|
||||
block(alertView);
|
||||
}
|
||||
|
||||
id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
|
||||
if (originalDelegate && [originalDelegate respondsToSelector:@selector(didPresentAlertView:)]) {
|
||||
[originalDelegate didPresentAlertView:alertView];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)alertViewCancel:(UIAlertView *)alertView {
|
||||
UIAlertViewBlock block = alertView.cancelBlock;
|
||||
|
||||
if (block) {
|
||||
block(alertView);
|
||||
}
|
||||
|
||||
id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
|
||||
if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertViewCancel:)]) {
|
||||
[originalDelegate alertViewCancel:alertView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
|
||||
UIAlertViewCompletionBlock completion = alertView.tapBlock;
|
||||
|
||||
if (completion) {
|
||||
completion(alertView, buttonIndex);
|
||||
}
|
||||
|
||||
id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
|
||||
if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertView:clickedButtonAtIndex:)]) {
|
||||
[originalDelegate alertView:alertView clickedButtonAtIndex:buttonIndex];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
|
||||
UIAlertViewCompletionBlock completion = alertView.willDismissBlock;
|
||||
|
||||
if (completion) {
|
||||
completion(alertView, buttonIndex);
|
||||
}
|
||||
|
||||
id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
|
||||
if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertView:willDismissWithButtonIndex:)]) {
|
||||
[originalDelegate alertView:alertView willDismissWithButtonIndex:buttonIndex];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
|
||||
UIAlertViewCompletionBlock completion = alertView.didDismissBlock;
|
||||
|
||||
if (completion) {
|
||||
completion(alertView, buttonIndex);
|
||||
}
|
||||
|
||||
id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
|
||||
if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertView:didDismissWithButtonIndex:)]) {
|
||||
[originalDelegate alertView:alertView didDismissWithButtonIndex:buttonIndex];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView {
|
||||
BOOL(^shouldEnableFirstOtherButtonBlock)(UIAlertView *alertView) = alertView.shouldEnableFirstOtherButtonBlock;
|
||||
|
||||
if (shouldEnableFirstOtherButtonBlock) {
|
||||
return shouldEnableFirstOtherButtonBlock(alertView);
|
||||
}
|
||||
|
||||
id originalDelegate = objc_getAssociatedObject(self, UIAlertViewOriginalDelegateKey);
|
||||
if (originalDelegate && [originalDelegate respondsToSelector:@selector(alertViewShouldEnableFirstOtherButton:)]) {
|
||||
return [originalDelegate alertViewShouldEnableFirstOtherButton:alertView];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -29,7 +29,10 @@
|
|||
OrtpLogLevel ortp_severity;
|
||||
int filesize = 20;
|
||||
if (severity <= LinphoneLoggerDebug) {
|
||||
ortp_severity = ORTP_DEBUG;
|
||||
// lol: ortp_debug(XXX) can be disabled at compile time, but ortp_log(ORTP_DEBUG, xxx) will always be valid even
|
||||
// not in debug build...
|
||||
ortp_debug("%*s:%3d - %s", filesize, file+MAX((int)strlen(file)-filesize,0), line, [str UTF8String]);
|
||||
return;
|
||||
} else if(severity <= LinphoneLoggerLog) {
|
||||
ortp_severity = ORTP_MESSAGE;
|
||||
} else if(severity <= LinphoneLoggerWarning) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#import "ChatTester.h"
|
||||
#include "LinphoneManager.h"
|
||||
#import "UIChatRoomCell.h"
|
||||
|
||||
@implementation ChatTester
|
||||
|
||||
|
|
@ -17,12 +18,36 @@
|
|||
- (void)beforeAll {
|
||||
[super beforeAll];
|
||||
[self switchToValidAccountIfNeeded];
|
||||
|
||||
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Chat")];
|
||||
}
|
||||
|
||||
- (void)beforeEach {
|
||||
[super beforeEach];
|
||||
if ([tester tryFindingTappableViewWithAccessibilityLabel:LOCALIZED(@"Back") error:nil]) {
|
||||
[self goBackFromChat];
|
||||
}
|
||||
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Chat")];
|
||||
[self removeAllRooms];
|
||||
}
|
||||
|
||||
- (void)afterAll {
|
||||
// at the end of tests, go back to chat rooms to display main bar
|
||||
if ([tester tryFindingTappableViewWithAccessibilityLabel:LOCALIZED(@"Back") error:nil]) {
|
||||
[self goBackFromChat];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - tools
|
||||
|
||||
- (void)removeAllRooms {
|
||||
[tester tapViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton];
|
||||
while (
|
||||
[tester tryFindingTappableViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton error:nil]) {
|
||||
[tester tapViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton];
|
||||
}
|
||||
[tester tapViewWithAccessibilityLabel:@"Edit"
|
||||
traits:UIAccessibilityTraitButton]; // same as the first but it is "OK" on screen
|
||||
}
|
||||
|
||||
- (void)goBackFromChat {
|
||||
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Back")];
|
||||
}
|
||||
|
|
@ -114,29 +139,100 @@
|
|||
for( int i =0; i< uuids.count; i++){
|
||||
[tester tapViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton];
|
||||
}
|
||||
|
||||
// then we try to delete all the rest of chatrooms
|
||||
while ( [tester tryFindingTappableViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton error:nil] )
|
||||
{
|
||||
[tester tapViewWithAccessibilityLabel:@"Delete" traits:UIAccessibilityTraitButton];
|
||||
NSLog(@"Deleting an extra chat");
|
||||
}
|
||||
|
||||
[tester tapViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton]; // same as the first but it is "OK" on screen
|
||||
|
||||
// check that the tableview is empty
|
||||
UITableView* tv = nil;
|
||||
NSError* err = nil;
|
||||
if( [tester tryFindingAccessibilityElement:nil view:&tv withIdentifier:@"ChatRoom list" tappable:false error:&err] ){
|
||||
XCTAssert(tv != nil);
|
||||
XCTAssert([tv numberOfRowsInSection:0] == 0); // no more chat rooms
|
||||
} else {
|
||||
NSLog(@"Error: %@",err);
|
||||
}
|
||||
|
||||
// test that there's no more chatrooms in the core
|
||||
XCTAssert(linphone_core_get_chat_rooms([LinphoneManager getLc]) == nil);
|
||||
|
||||
[tester tapViewWithAccessibilityLabel:@"Edit"
|
||||
traits:UIAccessibilityTraitButton]; // same as the first but it is "OK" on screen
|
||||
|
||||
// check that the tableview is empty
|
||||
UITableView *tv = [self findTableView:@"ChatRoom list"];
|
||||
XCTAssert([tv numberOfRowsInSection:0] == 0);
|
||||
|
||||
// test that there's no more chatrooms in the core
|
||||
XCTAssert(linphone_core_get_chat_rooms([LinphoneManager getLc]) == nil);
|
||||
}
|
||||
|
||||
- (UITableView *)findTableView:(NSString *)table {
|
||||
UITableView *tv = nil;
|
||||
NSError *err = nil;
|
||||
if ([tester tryFindingAccessibilityElement:nil view:&tv withIdentifier:table tappable:false error:&err]) {
|
||||
XCTAssertNotNil(tv);
|
||||
} else {
|
||||
XCTFail(@"Error: %@", err);
|
||||
}
|
||||
return tv;
|
||||
}
|
||||
|
||||
- (void)uploadImage {
|
||||
NSString *user = @"testios";
|
||||
|
||||
[self startChatWith:user];
|
||||
|
||||
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Send picture")];
|
||||
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Photo library")];
|
||||
// if popup "Linphone would access your photo" pops up, click OK.
|
||||
if ([ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusNotDetermined) {
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
[tester acknowledgeSystemAlert];
|
||||
#endif
|
||||
}
|
||||
|
||||
[tester choosePhotoInAlbum:@"Camera Roll" atRow:1 column:1];
|
||||
|
||||
// TODO: do not harcode size!
|
||||
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Minimum (108.9 KB)")];
|
||||
|
||||
UITableView *tv = [self findTableView:@"Chat list"];
|
||||
XCTAssertEqual([tv numberOfRowsInSection:0], 1);
|
||||
XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 1);
|
||||
}
|
||||
|
||||
- (void)testUploadImage {
|
||||
NSString *user = @"testios";
|
||||
|
||||
[self uploadImage];
|
||||
[self goBackFromChat];
|
||||
|
||||
// if we go back to the same chatroom, the message should be still there
|
||||
[self startChatWith:user];
|
||||
UITableView *tv = [self findTableView:@"Chat list"];
|
||||
XCTAssertEqual([tv numberOfRowsInSection:0], 1);
|
||||
|
||||
[tester waitForViewWithAccessibilityLabel:LOCALIZED(@"Download")];
|
||||
|
||||
XCTAssertEqual([tv numberOfRowsInSection:0], 2);
|
||||
XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 0);
|
||||
}
|
||||
|
||||
- (void)testCancelUploadImage {
|
||||
[self uploadImage];
|
||||
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Cancel transfer")];
|
||||
XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 0);
|
||||
}
|
||||
|
||||
- (void)downloadImage {
|
||||
[self uploadImage];
|
||||
// wait for the upload to terminate...
|
||||
for (int i = 0; i < 15; i++) {
|
||||
[tester waitForTimeInterval:1.f];
|
||||
if ([[[LinphoneManager instance] fileTransferDelegates] count] == 0)
|
||||
break;
|
||||
}
|
||||
[tester waitForViewWithAccessibilityLabel:LOCALIZED(@"Download")];
|
||||
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Download")];
|
||||
[tester waitForTimeInterval:.5f]; // just wait a few secs to start download
|
||||
XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 1);
|
||||
}
|
||||
|
||||
- (void)testDownloadImage {
|
||||
[self downloadImage];
|
||||
[tester waitForAbsenceOfViewWithAccessibilityLabel:@"Cancel transfer"];
|
||||
XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 0);
|
||||
}
|
||||
|
||||
- (void)testCancelDownloadImage {
|
||||
[self downloadImage];
|
||||
[tester tapViewWithAccessibilityLabel:LOCALIZED(@"Cancel transfer")];
|
||||
XCTAssertEqual([[[LinphoneManager instance] fileTransferDelegates] count], 0);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@
|
|||
<a href="http://www.tortuga22.com">http://www.tortuga22.com</a><br />
|
||||
<em>Apache license</em></p>
|
||||
|
||||
<h3>Ryan Maxwell</h3>
|
||||
<p>UIAlertview+Blocks</p>
|
||||
<a href="https://github.com/ryanmaxwell/UIAlertView-Blocks">https://github.com/ryanmaxwell/UIAlertView-Blocks</a><br />
|
||||
<em>MIT license</em>
|
||||
|
||||
<h3>OrderedDictionary</h3>
|
||||
<p>Matt Gallagher<br />
|
||||
<a href="http://cocoawithlove.com">http://cocoawithlove.com</a></p>
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ username_length=4
|
|||
expires=1314000
|
||||
push_notification=1
|
||||
transport=tls
|
||||
sharing_server=https://www.linphone.org:444/upload.php
|
||||
sharing_server=https://www.linphone.org:444/lft.php
|
||||
ice=1
|
||||
stun=stun.linphone.org
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ username_length=4
|
|||
expires=1314000
|
||||
push_notification=1
|
||||
transport=tls
|
||||
sharing_server=https://www.linphone.org:444/upload.php
|
||||
sharing_server=https://www.linphone.org:444/lft.php
|
||||
ice=1
|
||||
stun=stun.linphone.org
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<section name="app">
|
||||
<entry name="pushnotification_preference" overwrite="true">1</entry>
|
||||
<entry name="sharing_server_preference" overwrite="true">https://www.linphone.org:444/upload.php</entry>
|
||||
<entry name="sharing_server_preference" overwrite="true">https://www.linphone.org:444/lft.php</entry>
|
||||
<entry name="ice_preference" overwrite="true">1</entry>
|
||||
<entry name="stun_preference" overwrite="true">stun.linphone.org</entry>
|
||||
<entry name="random_port_preference" overwrite="true">1</entry>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<section name="app">
|
||||
<entry name="pushnotification_preference" overwrite="true">1</entry>
|
||||
<entry name="sharing_server_preference" overwrite="true">https://www.linphone.org:444/upload.php</entry>
|
||||
<entry name="sharing_server_preference" overwrite="true">https://www.linphone.org:444/lft.php</entry>
|
||||
<entry name="ice_preference" overwrite="true">1</entry>
|
||||
<entry name="stun_preference" overwrite="true">stun.linphone.org</entry>
|
||||
<entry name="random_port_preference" overwrite="true">1</entry>
|
||||
|
|
|
|||
|
|
@ -218,36 +218,6 @@
|
|||
<key>IASKTextAlignment</key>
|
||||
<string>IASKUITextAlignmentRight</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>DefaultValue</key>
|
||||
<true/>
|
||||
<key>Key</key>
|
||||
<string>adaptive_rate_control_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Adaptive rate control</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>DefaultValue</key>
|
||||
<string>Simple</string>
|
||||
<key>Key</key>
|
||||
<string>adaptive_rate_algorithm_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Adaptive rate algorithm</string>
|
||||
<key>Titles</key>
|
||||
<array>
|
||||
<string>Simple</string>
|
||||
<string>Stateful</string>
|
||||
</array>
|
||||
<key>Type</key>
|
||||
<string>PSMultiValueSpecifier</string>
|
||||
<key>Values</key>
|
||||
<array>
|
||||
<string>Simple</string>
|
||||
<string>Stateful</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>DefaultValue</key>
|
||||
<integer>36</integer>
|
||||
|
|
|
|||
|
|
@ -106,6 +106,16 @@
|
|||
<key>IASKTextAlignment</key>
|
||||
<string>IASKUITextAlignmentRight</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>DefaultValue</key>
|
||||
<false/>
|
||||
<key>Key</key>
|
||||
<string>repeat_call_notification_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Repeat call notification</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -156,31 +156,41 @@
|
|||
</dict>
|
||||
<dict>
|
||||
<key>Key</key>
|
||||
<string>upload_bandwidth_preference</string>
|
||||
<string>adaptive_rate_control_group</string>
|
||||
<key>Title</key>
|
||||
<string>Upload bandwidth</string>
|
||||
<string>Adaptive rate control</string>
|
||||
<key>Type</key>
|
||||
<string>PSTextFieldSpecifier</string>
|
||||
<key>KeyboardType</key>
|
||||
<string>NumberPad</string>
|
||||
<key>DefaultValue</key>
|
||||
<integer>0</integer>
|
||||
<key>IASKTextAlignment</key>
|
||||
<string>IASKUITextAlignmentRight</string>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Key</key>
|
||||
<string>download_bandwidth_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Download bandwidth</string>
|
||||
<key>Type</key>
|
||||
<string>PSTextFieldSpecifier</string>
|
||||
<key>KeyboardType</key>
|
||||
<string>NumberPad</string>
|
||||
<key>DefaultValue</key>
|
||||
<integer>0</integer>
|
||||
<key>IASKTextAlignment</key>
|
||||
<string>IASKUITextAlignmentRight</string>
|
||||
<true/>
|
||||
<key>Key</key>
|
||||
<string>adaptive_rate_control_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Adaptive rate control</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>DefaultValue</key>
|
||||
<string>Simple</string>
|
||||
<key>Key</key>
|
||||
<string>adaptive_rate_algorithm_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Adaptive rate algorithm</string>
|
||||
<key>Titles</key>
|
||||
<array>
|
||||
<string>Simple</string>
|
||||
<string>Stateful</string>
|
||||
</array>
|
||||
<key>Type</key>
|
||||
<string>PSMultiValueSpecifier</string>
|
||||
<key>Values</key>
|
||||
<array>
|
||||
<string>Simple</string>
|
||||
<string>Stateful</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
|
|
|
|||
|
|
@ -242,14 +242,6 @@
|
|||
<key>Type</key>
|
||||
<string>PSChildPaneSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Key</key>
|
||||
<string>in_app_products_button</string>
|
||||
<key>Title</key>
|
||||
<string>Extra features</string>
|
||||
<key>Type</key>
|
||||
<string>IASKButtonSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Title</key>
|
||||
<string>Development debug actions</string>
|
||||
|
|
@ -276,7 +268,7 @@
|
|||
<key>Key</key>
|
||||
<string>release_button</string>
|
||||
<key>Title</key>
|
||||
<string>Exit</string>
|
||||
<string>Release core</string>
|
||||
<key>Type</key>
|
||||
<string>IASKButtonSpecifier</string>
|
||||
</dict>
|
||||
|
|
|
|||
|
|
@ -41,8 +41,28 @@
|
|||
<string>preview_preference</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Key</key>
|
||||
<string>video_preset_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Video preset</string>
|
||||
<key>Titles</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
<string>High FPS</string>
|
||||
<string>Custom</string>
|
||||
</array>
|
||||
<key>Type</key>
|
||||
<string>PSMultiValueSpecifier</string>
|
||||
<key>Values</key>
|
||||
<array>
|
||||
<string>default</string>
|
||||
<string>high-fps</string>
|
||||
<string>custom</string>
|
||||
</array>
|
||||
<key>DefaultValue</key>
|
||||
<integer>1</integer>
|
||||
<string>default</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Key</key>
|
||||
<string>video_preferred_size_preference</string>
|
||||
<key>Title</key>
|
||||
|
|
@ -61,6 +81,56 @@
|
|||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>DefaultValue</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Key</key>
|
||||
<string>video_preferred_fps_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Preferred FPS</string>
|
||||
<key>Type</key>
|
||||
<string>PSMultiValueSpecifier</string>
|
||||
<key>Titles</key>
|
||||
<array>
|
||||
<string>No preference</string>
|
||||
<string>5</string>
|
||||
<string>10</string>
|
||||
<string>15</string>
|
||||
<string>20</string>
|
||||
<string>25</string>
|
||||
<string>30</string>
|
||||
</array>
|
||||
<key>Values</key>
|
||||
<array>
|
||||
<integer>0</integer>
|
||||
<integer>5</integer>
|
||||
<integer>10</integer>
|
||||
<integer>15</integer>
|
||||
<integer>20</integer>
|
||||
<integer>25</integer>
|
||||
<integer>30</integer>
|
||||
</array>
|
||||
<key>DefaultValue</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Key</key>
|
||||
<string>download_bandwidth_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Bandwidth limit in kbits/s</string>
|
||||
<key>Type</key>
|
||||
<string>PSTextFieldSpecifier</string>
|
||||
<key>AutocapitalizationType</key>
|
||||
<string>None</string>
|
||||
<key>AutocorrectionType</key>
|
||||
<string>No</string>
|
||||
<key>KeyboardType</key>
|
||||
<string>NumberPad</string>
|
||||
<key>DefaultValue</key>
|
||||
<integer>380</integer>
|
||||
<key>IASKTextAlignment</key>
|
||||
<string>IASKUITextAlignmentRight</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Title</key>
|
||||
|
|
|
|||
|
|
@ -111,20 +111,17 @@
|
|||
630CF5571AF7CE1500539F7A /* UITextField+DoneButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 630CF5561AF7CE1500539F7A /* UITextField+DoneButton.m */; };
|
||||
631C4FB119D2A8F2004BFE77 /* UIDigitButtonLongPlus.m in Sources */ = {isa = PBXBuildFile; fileRef = 631C4FB019D2A8F2004BFE77 /* UIDigitButtonLongPlus.m */; };
|
||||
631C4FB719D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.m in Sources */ = {isa = PBXBuildFile; fileRef = 631C4FB619D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.m */; };
|
||||
6359DE7F1ADEB54200EA15C0 /* InAppProductsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6359DE7D1ADEB54200EA15C0 /* InAppProductsViewController.m */; };
|
||||
6359DE801ADEB54200EA15C0 /* InAppProductsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6359DE7E1ADEB54200EA15C0 /* InAppProductsViewController.xib */; };
|
||||
6359DE841ADEB64100EA15C0 /* InAppProductsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6359DE821ADEB64100EA15C0 /* InAppProductsCell.m */; };
|
||||
6359DE851ADEB64100EA15C0 /* InAppProductsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6359DE831ADEB64100EA15C0 /* InAppProductsCell.xib */; };
|
||||
6359DE8B1ADF9EB900EA15C0 /* InAppProductsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6359DE8A1ADF9EB900EA15C0 /* InAppProductsTableViewController.m */; };
|
||||
636316D11A1DEBCB0009B839 /* AboutViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 636316D31A1DEBCB0009B839 /* AboutViewController.xib */; };
|
||||
636316D41A1DEC650009B839 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 636316D61A1DEC650009B839 /* SettingsViewController.xib */; };
|
||||
636316D91A1DECC90009B839 /* PhoneMainView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 636316D71A1DECC90009B839 /* PhoneMainView.xib */; };
|
||||
636316DE1A1DEF2F0009B839 /* UIButtonShrinkable.m in Sources */ = {isa = PBXBuildFile; fileRef = 636316DD1A1DEF2F0009B839 /* UIButtonShrinkable.m */; };
|
||||
637157A11B283FE200C91677 /* FileTransferDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 637157A01B283FE200C91677 /* FileTransferDelegate.m */; };
|
||||
639CEAFD1A1DF4D9004DE38F /* UIStateBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEAFF1A1DF4D9004DE38F /* UIStateBar.xib */; };
|
||||
639CEB001A1DF4E4004DE38F /* UIHistoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB021A1DF4E4004DE38F /* UIHistoryCell.xib */; };
|
||||
639CEB031A1DF4EB004DE38F /* UICompositeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB051A1DF4EB004DE38F /* UICompositeViewController.xib */; };
|
||||
639CEB061A1DF4F1004DE38F /* UIChatRoomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB081A1DF4F1004DE38F /* UIChatRoomCell.xib */; };
|
||||
639CEB091A1DF4FA004DE38F /* UIChatCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB0B1A1DF4FA004DE38F /* UIChatCell.xib */; };
|
||||
63A4280A1B26F576000DAB93 /* libSKP_SILK_SDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 226183AA1472527D0037138E /* libSKP_SILK_SDK.a */; };
|
||||
63CD4B4F1A5AAC8C00B84282 /* DTAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63CD4B4E1A5AAC8C00B84282 /* DTAlertView.m */; };
|
||||
63D2680F1B174A5E00A2CC11 /* numpad_one_voicemail_default.png in Resources */ = {isa = PBXBuildFile; fileRef = 63D2680D1B174A5E00A2CC11 /* numpad_one_voicemail_default.png */; };
|
||||
63D268101B174A5E00A2CC11 /* numpad_one_voicemail_over.png in Resources */ = {isa = PBXBuildFile; fileRef = 63D2680E1B174A5E00A2CC11 /* numpad_one_voicemail_over.png */; };
|
||||
|
|
@ -305,7 +302,6 @@
|
|||
D36C43F7158F61EA0048BA40 /* call_state_play_over.png in Resources */ = {isa = PBXBuildFile; fileRef = D36C43F0158F61EA0048BA40 /* call_state_play_over.png */; };
|
||||
D36FB2D51589EF7C0036F6F2 /* UIPauseButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D36FB2D41589EF7C0036F6F2 /* UIPauseButton.m */; };
|
||||
D37295DB158B3C9600D2C0C7 /* video_off_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D37295DA158B3C9600D2C0C7 /* video_off_disabled.png */; };
|
||||
D374D3FD16071762003D25FF /* ImageSharing.m in Sources */ = {isa = PBXBuildFile; fileRef = D374D3FC16071762003D25FF /* ImageSharing.m */; };
|
||||
D377BBFA15A19DA6002B696B /* video_on_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = D377BBF915A19DA6002B696B /* video_on_disabled.png */; };
|
||||
D378906515AC373B00BD776C /* ContactDetailsLabelViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D378906315AC373B00BD776C /* ContactDetailsLabelViewController.m */; };
|
||||
D378AB2A15DCDB4A0098505D /* ImagePickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D378AB2915DCDB490098505D /* ImagePickerViewController.m */; };
|
||||
|
|
@ -891,7 +887,6 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
045B5CB218D72E9A0088350C /* libbzrtp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbzrtp.a; path = "liblinphone-sdk/apple-darwin/lib/libbzrtp.a"; sourceTree = "<group>"; };
|
||||
15017E6F1773578400784ACB /* libxml2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libxml2.a; path = "liblinphone-sdk/apple-darwin/lib/libxml2.a"; sourceTree = "<group>"; };
|
||||
152F22331B15E83B008C0621 /* libilbcrfc3951.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libilbcrfc3951.a; path = "liblinphone-sdk/apple-darwin/lib/libilbcrfc3951.a"; sourceTree = "<group>"; };
|
||||
152F22351B15E889008C0621 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; };
|
||||
1560821E18EEF26100765332 /* libmsopenh264.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmsopenh264.a; path = "liblinphone-sdk/apple-darwin/lib/mediastreamer/plugins/libmsopenh264.a"; sourceTree = "<group>"; };
|
||||
|
|
@ -1023,14 +1018,6 @@
|
|||
631C4FB519D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIDigitButtonLongVoiceMail.h; sourceTree = "<group>"; };
|
||||
631C4FB619D2C3A6004BFE77 /* UIDigitButtonLongVoiceMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIDigitButtonLongVoiceMail.m; sourceTree = "<group>"; };
|
||||
633E388219FFB0F400936D1C /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
6359DE7C1ADEB54200EA15C0 /* InAppProductsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsViewController.h; sourceTree = "<group>"; };
|
||||
6359DE7D1ADEB54200EA15C0 /* InAppProductsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsViewController.m; sourceTree = "<group>"; };
|
||||
6359DE7E1ADEB54200EA15C0 /* InAppProductsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = InAppProductsViewController.xib; sourceTree = "<group>"; };
|
||||
6359DE811ADEB64100EA15C0 /* InAppProductsCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsCell.h; sourceTree = "<group>"; };
|
||||
6359DE821ADEB64100EA15C0 /* InAppProductsCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsCell.m; sourceTree = "<group>"; };
|
||||
6359DE831ADEB64100EA15C0 /* InAppProductsCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = InAppProductsCell.xib; sourceTree = "<group>"; };
|
||||
6359DE891ADF9EB900EA15C0 /* InAppProductsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsTableViewController.h; sourceTree = "<group>"; };
|
||||
6359DE8A1ADF9EB900EA15C0 /* InAppProductsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsTableViewController.m; sourceTree = "<group>"; };
|
||||
636316D21A1DEBCB0009B839 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/AboutViewController.xib; sourceTree = "<group>"; };
|
||||
636316D51A1DEC650009B839 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SettingsViewController.xib; sourceTree = "<group>"; };
|
||||
636316D81A1DECC90009B839 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PhoneMainView.xib; sourceTree = "<group>"; };
|
||||
|
|
@ -1038,6 +1025,8 @@
|
|||
636316DB1A1DEDD80009B839 /* ru */ = {isa = PBXFileReference; fileEncoding = 2483028224; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/HistoryDetailsViewController.strings; sourceTree = "<group>"; };
|
||||
636316DC1A1DEECB0009B839 /* UIButtonShrinkable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIButtonShrinkable.h; sourceTree = "<group>"; };
|
||||
636316DD1A1DEF2F0009B839 /* UIButtonShrinkable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIButtonShrinkable.m; sourceTree = "<group>"; };
|
||||
6371579F1B283FE200C91677 /* FileTransferDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileTransferDelegate.h; path = Utils/FileTransferDelegate.h; sourceTree = "<group>"; };
|
||||
637157A01B283FE200C91677 /* FileTransferDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FileTransferDelegate.m; path = Utils/FileTransferDelegate.m; sourceTree = "<group>"; };
|
||||
639CEAFE1A1DF4D9004DE38F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UIStateBar.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/UICompositeViewController.xib; sourceTree = "<group>"; };
|
||||
|
|
@ -1257,8 +1246,6 @@
|
|||
D36FB2D31589EF7C0036F6F2 /* UIPauseButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIPauseButton.h; sourceTree = "<group>"; };
|
||||
D36FB2D41589EF7C0036F6F2 /* UIPauseButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIPauseButton.m; sourceTree = "<group>"; };
|
||||
D37295DA158B3C9600D2C0C7 /* video_off_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = video_off_disabled.png; path = Resources/video_off_disabled.png; sourceTree = "<group>"; };
|
||||
D374D3FB16071762003D25FF /* ImageSharing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageSharing.h; sourceTree = "<group>"; };
|
||||
D374D3FC16071762003D25FF /* ImageSharing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageSharing.m; sourceTree = "<group>"; };
|
||||
D377BBF915A19DA6002B696B /* video_on_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = video_on_disabled.png; path = Resources/video_on_disabled.png; sourceTree = "<group>"; };
|
||||
D378906215AC373B00BD776C /* ContactDetailsLabelViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactDetailsLabelViewController.h; sourceTree = "<group>"; };
|
||||
D378906315AC373B00BD776C /* ContactDetailsLabelViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactDetailsLabelViewController.m; sourceTree = "<group>"; };
|
||||
|
|
@ -1865,6 +1852,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
63A4280A1B26F576000DAB93 /* libSKP_SILK_SDK.a in Frameworks */,
|
||||
152F22361B15E889008C0621 /* libxml2.dylib in Frameworks */,
|
||||
152F22341B15E83B008C0621 /* libilbcrfc3951.a in Frameworks */,
|
||||
F0B026F31AA710AF00FF49F7 /* libiconv.dylib in Frameworks */,
|
||||
|
|
@ -2039,21 +2027,11 @@
|
|||
D38187D415FE346B00C3EDCA /* HistoryViewController.xib */,
|
||||
D378AB2815DCDB480098505D /* ImagePickerViewController.h */,
|
||||
D378AB2915DCDB490098505D /* ImagePickerViewController.m */,
|
||||
D374D3FB16071762003D25FF /* ImageSharing.h */,
|
||||
D374D3FC16071762003D25FF /* ImageSharing.m */,
|
||||
22405EFD1601C19000B92522 /* ImageViewController.h */,
|
||||
22405EFE1601C19100B92522 /* ImageViewController.m */,
|
||||
D37EE11016035793003608A6 /* ImageViewController.xib */,
|
||||
6359DE811ADEB64100EA15C0 /* InAppProductsCell.h */,
|
||||
6359DE821ADEB64100EA15C0 /* InAppProductsCell.m */,
|
||||
6359DE831ADEB64100EA15C0 /* InAppProductsCell.xib */,
|
||||
63E59A3D1ADE6ECB00646FB3 /* InAppProductsManager.h */,
|
||||
63E59A3E1ADE70D900646FB3 /* InAppProductsManager.m */,
|
||||
6359DE891ADF9EB900EA15C0 /* InAppProductsTableViewController.h */,
|
||||
6359DE8A1ADF9EB900EA15C0 /* InAppProductsTableViewController.m */,
|
||||
6359DE7C1ADEB54200EA15C0 /* InAppProductsViewController.h */,
|
||||
6359DE7D1ADEB54200EA15C0 /* InAppProductsViewController.m */,
|
||||
6359DE7E1ADEB54200EA15C0 /* InAppProductsViewController.xib */,
|
||||
D31AAF5C159B3919002C6B02 /* InCallTableViewController.h */,
|
||||
D31AAF5D159B3919002C6B02 /* InCallTableViewController.m */,
|
||||
D3F83EE91582021700336684 /* InCallViewController.h */,
|
||||
|
|
@ -2317,7 +2295,6 @@
|
|||
D30BF33216A427BC00AF0026 /* libtunnel.a */,
|
||||
7066FC0B13E830E400EFC6DC /* libvpx.a */,
|
||||
22AA8AFB13D7125500B30535 /* libx264.a */,
|
||||
15017E6F1773578400784ACB /* libxml2.a */,
|
||||
F0B89C2118DC89E30050B60E /* MediaPlayer.framework */,
|
||||
D37DC7171594AF3400B2A5EB /* MessageUI.framework */,
|
||||
226EF06B15FA256B005865C7 /* MobileCoreServices.framework */,
|
||||
|
|
@ -2343,6 +2320,8 @@
|
|||
D37EE15F160377D7003608A6 /* DTFoundation */,
|
||||
D32B9DFA15A2F131000B6DEC /* FastAddressBook.h */,
|
||||
D32B9DFB15A2F131000B6DEC /* FastAddressBook.m */,
|
||||
6371579F1B283FE200C91677 /* FileTransferDelegate.h */,
|
||||
637157A01B283FE200C91677 /* FileTransferDelegate.m */,
|
||||
D3ED40141602172200BF332B /* GrowingTextView */,
|
||||
D3807FC715C2894A005BE9BC /* InAppSettingsKit */,
|
||||
D3B90E1115C2CB5700F64F8C /* NinePatch.xcodeproj */,
|
||||
|
|
@ -3342,7 +3321,6 @@
|
|||
D38327F71580FE3A00FA0D23 /* settings_default.png in Resources */,
|
||||
D38327F81580FE3A00FA0D23 /* settings_selected.png in Resources */,
|
||||
D38327F91580FE3A00FA0D23 /* chat_default.png in Resources */,
|
||||
6359DE801ADEB54200EA15C0 /* InAppProductsViewController.xib in Resources */,
|
||||
D38327FA1580FE3A00FA0D23 /* chat_selected.png in Resources */,
|
||||
D3832800158100E400FA0D23 /* contacts_over.png in Resources */,
|
||||
D3832801158100E400FA0D23 /* history_over.png in Resources */,
|
||||
|
|
@ -3379,7 +3357,6 @@
|
|||
D3F83F581582223B00336684 /* numpad_five_default.png in Resources */,
|
||||
D3F83F5A1582223B00336684 /* numpad_five_over.png in Resources */,
|
||||
D3F83F5C1582223B00336684 /* numpad_six_default.png in Resources */,
|
||||
6359DE851ADEB64100EA15C0 /* InAppProductsCell.xib in Resources */,
|
||||
636316D91A1DECC90009B839 /* PhoneMainView.xib in Resources */,
|
||||
D3F83F5E1582223B00336684 /* numpad_six_over.png in Resources */,
|
||||
D3F83F601582223B00336684 /* numpad_seven_default.png in Resources */,
|
||||
|
|
@ -4052,18 +4029,15 @@
|
|||
D3807FFC15C2894A005BE9BC /* IASKPSTitleValueSpecifierViewCell.m in Sources */,
|
||||
D3807FFE15C2894A005BE9BC /* IASKSlider.m in Sources */,
|
||||
D380800015C2894A005BE9BC /* IASKSwitch.m in Sources */,
|
||||
6359DE8B1ADF9EB900EA15C0 /* InAppProductsTableViewController.m in Sources */,
|
||||
D380800215C2894A005BE9BC /* IASKTextField.m in Sources */,
|
||||
D380800515C28A7A005BE9BC /* UILinphone.m in Sources */,
|
||||
D380801315C299D0005BE9BC /* ColorSpaceUtilites.m in Sources */,
|
||||
6359DE7F1ADEB54200EA15C0 /* InAppProductsViewController.m in Sources */,
|
||||
637157A11B283FE200C91677 /* FileTransferDelegate.m in Sources */,
|
||||
D378AB2A15DCDB4A0098505D /* ImagePickerViewController.m in Sources */,
|
||||
6359DE841ADEB64100EA15C0 /* InAppProductsCell.m in Sources */,
|
||||
22405F001601C19200B92522 /* ImageViewController.m in Sources */,
|
||||
D3ED40191602172200BF332B /* HPGrowingTextView.m in Sources */,
|
||||
D3ED401B1602172200BF332B /* HPTextViewInternal.m in Sources */,
|
||||
D37EE162160377D7003608A6 /* DTActionSheet.m in Sources */,
|
||||
D374D3FD16071762003D25FF /* ImageSharing.m in Sources */,
|
||||
D35E91F4160CA10B0023116B /* UILinphoneTextField.m in Sources */,
|
||||
D35E91F8160CA4FF0023116B /* UILinphoneButton.m in Sources */,
|
||||
D306459E1611EC2A00BB571E /* UILoadingImageView.m in Sources */,
|
||||
|
|
|
|||
138
prepare.py
138
prepare.py
|
|
@ -27,12 +27,14 @@ import os
|
|||
import re
|
||||
import shutil
|
||||
import sys
|
||||
from subprocess import Popen
|
||||
sys.dont_write_bytecode = True
|
||||
sys.path.insert(0, 'submodules/cmake-builder')
|
||||
import prepare
|
||||
|
||||
|
||||
class IOSTarget(prepare.Target):
|
||||
|
||||
def __init__(self, arch):
|
||||
prepare.Target.__init__(self, 'ios-' + arch)
|
||||
current_path = os.path.dirname(os.path.realpath(__file__))
|
||||
|
|
@ -40,62 +42,77 @@ class IOSTarget(prepare.Target):
|
|||
self.toolchain_file = 'toolchains/toolchain-ios-' + arch + '.cmake'
|
||||
self.output = 'liblinphone-sdk/' + arch + '-apple-darwin.ios'
|
||||
self.additional_args = [
|
||||
'-DLINPHONE_BUILDER_EXTERNAL_SOURCE_PATH=' + current_path + '/submodules'
|
||||
'-DLINPHONE_BUILDER_EXTERNAL_SOURCE_PATH=' +
|
||||
current_path + '/submodules'
|
||||
]
|
||||
|
||||
def clean(self):
|
||||
if os.path.isdir('WORK'):
|
||||
shutil.rmtree('WORK', ignore_errors=False, onerror=self.handle_remove_read_only)
|
||||
shutil.rmtree(
|
||||
'WORK', ignore_errors=False, onerror=self.handle_remove_read_only)
|
||||
if os.path.isdir('liblinphone-sdk'):
|
||||
shutil.rmtree('liblinphone-sdk', ignore_errors=False, onerror=self.handle_remove_read_only)
|
||||
shutil.rmtree(
|
||||
'liblinphone-sdk', ignore_errors=False, onerror=self.handle_remove_read_only)
|
||||
|
||||
|
||||
class IOSi386Target(IOSTarget):
|
||||
|
||||
def __init__(self):
|
||||
IOSTarget.__init__(self, 'i386')
|
||||
|
||||
|
||||
class IOSx8664Target(IOSTarget):
|
||||
|
||||
def __init__(self):
|
||||
IOSTarget.__init__(self, 'x86_64')
|
||||
|
||||
|
||||
class IOSarmv7Target(IOSTarget):
|
||||
|
||||
def __init__(self):
|
||||
IOSTarget.__init__(self, 'armv7')
|
||||
|
||||
|
||||
class IOSarm64Target(IOSTarget):
|
||||
|
||||
def __init__(self):
|
||||
IOSTarget.__init__(self, 'arm64')
|
||||
|
||||
|
||||
targets = {}
|
||||
targets[ 'i386'] = IOSi386Target()
|
||||
targets['i386'] = IOSi386Target()
|
||||
targets['x86_64'] = IOSx8664Target()
|
||||
targets[ 'armv7'] = IOSarmv7Target()
|
||||
targets[ 'arm64'] = IOSarm64Target()
|
||||
targets['armv7'] = IOSarmv7Target()
|
||||
targets['arm64'] = IOSarm64Target()
|
||||
|
||||
archs_device = ['arm64', 'armv7']
|
||||
archs_simu = ['i386', 'x86_64']
|
||||
platforms = ['all', 'devices', 'simulators'] + archs_device + archs_simu
|
||||
|
||||
|
||||
class PlatformListAction(argparse.Action):
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
if values:
|
||||
for value in values:
|
||||
if value not in platforms:
|
||||
message = ("invalid platform: {0!r} (choose from {1})".format(value, ', '.join([repr(platform) for platform in platforms])))
|
||||
message = ("invalid platform: {0!r} (choose from {1})".format(
|
||||
value, ', '.join([repr(platform) for platform in platforms])))
|
||||
raise argparse.ArgumentError(self, message)
|
||||
setattr(namespace, self.dest, values)
|
||||
|
||||
|
||||
def warning(platforms):
|
||||
gpl_third_parties_enabled = False
|
||||
regex = re.compile("^ENABLE_GPL_THIRD_PARTIES:BOOL=ON")
|
||||
f = open('WORK/ios-{arch}/cmake/CMakeCache.txt'.format(arch=platforms[0]), 'r')
|
||||
f = open(
|
||||
'WORK/ios-{arch}/cmake/CMakeCache.txt'.format(arch=platforms[0]), 'r')
|
||||
for line in f:
|
||||
if regex.match(line):
|
||||
gpl_third_parties_enabled = True
|
||||
break
|
||||
f.close()
|
||||
|
||||
|
||||
if gpl_third_parties_enabled:
|
||||
print("""
|
||||
***************************************************************************
|
||||
|
|
@ -121,17 +138,52 @@ def warning(platforms):
|
|||
""")
|
||||
|
||||
|
||||
def main(argv = None):
|
||||
def extract_libs_list():
|
||||
l = []
|
||||
# name = libspeexdsp.a; path = "liblinphone-sdk/apple-darwin/lib/libspeexdsp.a"; sourceTree = "<group>"; };
|
||||
regex = re.compile("name = (lib(\S+)\.a); path = \"liblinphone-sdk/apple-darwin/")
|
||||
f = open('linphone.xcodeproj/project.pbxproj', 'r')
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
for line in lines:
|
||||
m = regex.search(line)
|
||||
if m is not None:
|
||||
l += [m.group(1)]
|
||||
return list(set(l))
|
||||
|
||||
|
||||
def install_git_hook():
|
||||
git_hook_path = ".git{sep}hooks{sep}pre-commit".format(sep=os.sep)
|
||||
if os.path.isdir(".git{sep}hooks".format(sep=os.sep)) and not os.path.isfile(git_hook_path):
|
||||
print("Installing Git pre-commit hook")
|
||||
shutil.copyfile(".git-pre-commit", git_hook_path)
|
||||
os.chmod(git_hook_path, 0755)
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
argparser = argparse.ArgumentParser(description="Prepare build of Linphone and its dependencies.")
|
||||
argparser.add_argument('-c', '-C', '--clean', help="Clean a previous build instead of preparing a build.", action='store_true')
|
||||
argparser.add_argument('-d', '--debug', help="Prepare a debug build.", action='store_true')
|
||||
argparser.add_argument('-f', '--force', help="Force preparation, even if working directory already exist.", action='store_true')
|
||||
argparser.add_argument('-L', '--list-cmake-variables', help="List non-advanced CMake cache variables.", action='store_true', dest='list_cmake_variables')
|
||||
argparser.add_argument('platform', nargs='*', action=PlatformListAction, default=['all'], help="The platform to build for (default is all), one of: {0}.".format(', '.join([repr(platform) for platform in platforms])))
|
||||
argparser = argparse.ArgumentParser(
|
||||
description="Prepare build of Linphone and its dependencies.")
|
||||
argparser.add_argument(
|
||||
'-c', '-C', '--clean', help="Clean a previous build instead of preparing a build.", action='store_true')
|
||||
argparser.add_argument(
|
||||
'-d', '--debug', help="Prepare a debug build, eg. add debug symbols and use no optimizations.", action='store_true')
|
||||
argparser.add_argument(
|
||||
'-dv', '--debug-verbose', help="Activate ms_debug logs.", action='store_true')
|
||||
argparser.add_argument(
|
||||
'-f', '--force', help="Force preparation, even if working directory already exist.", action='store_true')
|
||||
argparser.add_argument('-L', '--list-cmake-variables',
|
||||
help="List non-advanced CMake cache variables.", action='store_true',
|
||||
dest='list_cmake_variables')
|
||||
argparser.add_argument('platform', nargs='*', action=PlatformListAction, default=[
|
||||
'x86_64', 'devices'],
|
||||
help="The platform to build for (default is 'x86_64 devices'). Space separated"
|
||||
" architectures in list: {0}.".format(', '.join([repr(platform) for platform in platforms])))
|
||||
args, additional_args = argparser.parse_known_args()
|
||||
|
||||
install_git_hook()
|
||||
|
||||
selected_platforms = []
|
||||
for platform in args.platform:
|
||||
if platform == 'all':
|
||||
|
|
@ -152,14 +204,18 @@ def main(argv = None):
|
|||
if args.clean:
|
||||
target.clean()
|
||||
else:
|
||||
if args.debug:
|
||||
if args.debug_verbose:
|
||||
additional_args += ["-DENABLE_DEBUG_LOGS=YES"]
|
||||
retcode = prepare.run(target, args.debug, False, args.list_cmake_variables, args.force, additional_args)
|
||||
retcode = prepare.run(
|
||||
target, args.debug, False, args.list_cmake_variables, args.force, additional_args)
|
||||
if retcode != 0:
|
||||
if retcode == 51:
|
||||
p = Popen(["make", "help-prepare-options"])
|
||||
return retcode
|
||||
makefile_platforms += [platform]
|
||||
|
||||
if makefile_platforms:
|
||||
libs_list = extract_libs_list()
|
||||
packages = os.listdir('WORK/ios-' + makefile_platforms[0] + '/Build')
|
||||
packages.sort()
|
||||
arch_targets = ""
|
||||
|
|
@ -167,6 +223,12 @@ def main(argv = None):
|
|||
arch_targets += """
|
||||
{arch}: all-{arch}
|
||||
|
||||
package-in-list-%:
|
||||
if ! grep -q " $* " <<< " $(packages) "; then \\
|
||||
echo "$* not in list of available packages: $(packages)"; \\
|
||||
exit 3; \\
|
||||
fi
|
||||
|
||||
{arch}-build:
|
||||
@for package in $(packages); do \\
|
||||
$(MAKE) {arch}-build-$$package; \\
|
||||
|
|
@ -182,16 +244,16 @@ def main(argv = None):
|
|||
$(MAKE) {arch}-veryclean-$$package; \\
|
||||
done
|
||||
|
||||
{arch}-build-%:
|
||||
{arch}-build-%: package-in-list-%
|
||||
rm -f WORK/ios-{arch}/Stamp/EP_$*/EP_$*-update; \\
|
||||
$(MAKE) -C WORK/ios-{arch}/cmake EP_$*
|
||||
|
||||
{arch}-clean-%:
|
||||
{arch}-clean-%: package-in-list-%
|
||||
$(MAKE) -C WORK/ios-{arch}/Build/$* clean; \\
|
||||
rm -f WORK/ios-{arch}/Stamp/EP_$*/EP_$*-build; \\
|
||||
rm -f WORK/ios-{arch}/Stamp/EP_$*/EP_$*-install;
|
||||
|
||||
{arch}-veryclean-%:
|
||||
{arch}-veryclean-%: package-in-list-%
|
||||
cat WORK/ios-{arch}/Build/$*/install_manifest.txt | xargs rm; \\
|
||||
rm -rf WORK/ios-{arch}/Build/$*/*; \\
|
||||
rm -f WORK/ios-{arch}/Stamp/EP_$*/*; \\
|
||||
|
|
@ -226,7 +288,7 @@ def main(argv = None):
|
|||
multiarch = ""
|
||||
for arch in makefile_platforms[1:]:
|
||||
multiarch += \
|
||||
""" if test -f "$${arch}_path"; then \\
|
||||
""" if test -f "$${arch}_path"; then \\
|
||||
all_paths=`echo $$all_paths $${arch}_path`; \\
|
||||
all_archs="$$all_archs,{arch}" ; \\
|
||||
else \\
|
||||
|
|
@ -236,6 +298,7 @@ def main(argv = None):
|
|||
makefile = """
|
||||
archs={archs}
|
||||
packages={packages}
|
||||
libs_list={libs_list}
|
||||
LINPHONE_IPHONE_VERSION=$(shell git describe --always)
|
||||
|
||||
.PHONY: all
|
||||
|
|
@ -249,19 +312,19 @@ all-%:
|
|||
done
|
||||
$(MAKE) -C WORK/ios-$*/cmake
|
||||
|
||||
build-%:
|
||||
build-%: package-in-list-%
|
||||
@for arch in $(archs); do \\
|
||||
echo "==== starting build of $* for arch $$arch ===="; \\
|
||||
$(MAKE) $$arch-build-$*; \\
|
||||
done
|
||||
|
||||
clean-%:
|
||||
clean-%: package-in-list-%
|
||||
@for arch in $(archs); do \\
|
||||
echo "==== starting clean of $* for arch $$arch ===="; \\
|
||||
$(MAKE) $$arch-clean-$*; \\
|
||||
done
|
||||
|
||||
veryclean-%:
|
||||
veryclean-%: package-in-list-%
|
||||
@for arch in $(archs); do \\
|
||||
echo "==== starting veryclean of $* for arch $$arch ===="; \\
|
||||
$(MAKE) $$arch-veryclean-$*; \\
|
||||
|
|
@ -292,9 +355,17 @@ libs: $(addprefix all-,$(archs))
|
|||
echo "[$$all_archs] Mixing `basename $$archive` in $$destpath"; \\
|
||||
lipo -create $$all_paths -output $$destpath; \\
|
||||
done && \\
|
||||
if ! test -f liblinphone-sdk/apple-darwin/lib/libtunnel.a ; then \\
|
||||
cp -f submodules/binaries/libdummy.a liblinphone-sdk/apple-darwin/lib/libtunnel.a ; \\
|
||||
fi
|
||||
for lib in {libs_list} ; do \\
|
||||
if [ $${{lib:0:5}} = "libms" ] ; then \\
|
||||
library_path=liblinphone-sdk/apple-darwin/lib/mediastreamer/plugins/$$lib ; \\
|
||||
else \\
|
||||
library_path=liblinphone-sdk/apple-darwin/lib/$$lib ; \\
|
||||
fi ; \\
|
||||
if ! test -f $$library_path ; then \\
|
||||
echo "[$$all_archs] Generating dummy $$lib static library." ; \\
|
||||
cp -f submodules/binaries/libdummy.a $$library_path ; \\
|
||||
fi \\
|
||||
done
|
||||
|
||||
ipa: build
|
||||
xcodebuild -configuration Release \\
|
||||
|
|
@ -318,7 +389,12 @@ push-transifex:
|
|||
zipres:
|
||||
@tar -czf ios_assets.tar.gz Resources iTunesArtwork
|
||||
|
||||
help:
|
||||
help-prepare-options:
|
||||
@echo "prepare.py was previously executed with the following options:"
|
||||
@echo " {options}"
|
||||
|
||||
help: help-prepare-options
|
||||
@echo ""
|
||||
@echo "(please read the README.md file first)"
|
||||
@echo ""
|
||||
@echo "Available architectures: {archs}"
|
||||
|
|
@ -339,7 +415,9 @@ help:
|
|||
@echo ""
|
||||
@echo " * sdk : re-add all generated libraries to the SDK. Use this only after a full build."
|
||||
@echo " * libs : after a rebuild of a subpackage, will mix the new libs in liblinphone-sdk/apple-darwin directory"
|
||||
""".format(archs=' '.join(makefile_platforms), arch_opts='|'.join(makefile_platforms), first_arch=makefile_platforms[0], arch_targets=arch_targets, packages=' '.join(packages), multiarch=multiarch)
|
||||
""".format(archs=' '.join(makefile_platforms), arch_opts='|'.join(makefile_platforms),
|
||||
first_arch=makefile_platforms[0], options=' '.join(sys.argv),
|
||||
arch_targets=arch_targets, packages=' '.join(packages), libs_list=' '.join(libs_list), multiarch=multiarch)
|
||||
f = open('Makefile', 'w')
|
||||
f.write(makefile)
|
||||
f.close()
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 611762072933bf7bcbac9848bfead5a367a22ded
|
||||
Subproject commit 7780031ed6742e6653c3718ed506c851d129f86f
|
||||
6
submodules/binaries/dummy.c
Normal file
6
submodules/binaries/dummy.c
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
//regenerate libdummy.a using:
|
||||
// for arch in arm64 armv7 i386 x86_64; do
|
||||
// clang -c dummy.c -o dummy-$arch.a -arch $arch
|
||||
// done
|
||||
// lipo -create -output libdummy.a dummy-*.a
|
||||
void dummy_does_nothing() {}
|
||||
Binary file not shown.
|
|
@ -155,7 +155,7 @@ init:
|
|||
mkdir -p $(prefix)/include
|
||||
mkdir -p $(prefix)/lib/pkgconfig
|
||||
|
||||
veryclean: veryclean-linphone
|
||||
veryclean: veryclean-linphone
|
||||
rm -rf $(BUILDER_BUILD_DIR)
|
||||
|
||||
list-packages:
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ $(LIBILBC_BUILD_DIR)/Makefile: $(LIBILBC_SRC_DIR)/configure
|
|||
$(LIBILBC_SRC_DIR)/configure -prefix=$(prefix) --host=$(host) $(library_mode)
|
||||
|
||||
build-libilbc: $(LIBILBC_BUILD_DIR)/Makefile
|
||||
cd $(LIBILBC_BUILD_DIR) && make && make install
|
||||
cd $(LIBILBC_BUILD_DIR) && make && make install && \
|
||||
mv $(prefix)/lib/libilbc.a $(prefix)/lib/libilbcrfc3951.a
|
||||
|
||||
clean-libilbc:
|
||||
cd $(LIBILBC_BUILD_DIR) && make clean
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit cf6ad6e18ce9707e8236a6ab2c0fd789bdb9287d
|
||||
Subproject commit 3955daa45fa1f0eeb13b041560f78cfa7450968b
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit bc20f11963878a1f32511de59b05490093e5c9b8
|
||||
Subproject commit a6bb1eb6dab5541cdded6a1f0326539234954c5d
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit ad1d7c12c9b459660b34d63408b144bf5890f3b6
|
||||
Subproject commit b843685bd8e03b047bc85239397bd1961ff9a9a0
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 172e97a83aa2a868fd3dbbd6e7d57ad7d55f3054
|
||||
Subproject commit 40c29ef7736feb11af1e34f587788e49fa18b5c8
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 06504344a367c033598a9dcaa6ff8387269e5a9a
|
||||
Subproject commit dd9dd3e81719972232d9d4df7bc5e7c5282722bb
|
||||
Loading…
Add table
Reference in a new issue