forked from mirrors/linphone-iphone
Merge branch 'release/4.4'
This commit is contained in:
commit
8d10ccb3b1
44 changed files with 1037 additions and 1025 deletions
|
|
@ -57,7 +57,8 @@ enum NetworkType: Int {
|
|||
let paths = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)
|
||||
var writablePath = paths[0]
|
||||
writablePath = writablePath.appending("/\(filePath)")
|
||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "file path is \(writablePath)")
|
||||
let message:String = "file path is \(writablePath)"
|
||||
Log.directLog(BCTBX_LOG_MESSAGE, text: message)
|
||||
return writablePath
|
||||
//file name is recording_contact-name_dayName-day-monthName-year-hour-minutes-seconds
|
||||
//The recording prefix is used to identify recordings in the cache directory.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#import "TPKeyboardAvoidingScrollView.h"
|
||||
#import "PhoneMainView.h"
|
||||
|
||||
@interface AssistantView : UIViewController <UITextFieldDelegate, UICompositeViewDelegate> {
|
||||
@interface AssistantView : UIViewController <UITextFieldDelegate, UICompositeViewDelegate, UITextViewDelegate> {
|
||||
|
||||
@private
|
||||
LinphoneAccountCreator *account_creator;
|
||||
|
|
@ -33,6 +33,7 @@
|
|||
size_t number_of_configs_before;
|
||||
BOOL mustRestoreView;
|
||||
long phone_number_length;
|
||||
BOOL acceptTerms;
|
||||
}
|
||||
|
||||
@property(nonatomic) UICompositeViewDescription *outgoingView;
|
||||
|
|
@ -70,6 +71,10 @@
|
|||
@property (weak, nonatomic) IBOutlet UIButton *downloadButton;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *urlLabel;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *createAccountNextButtonPositionConstraint;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *acceptButton;
|
||||
- (IBAction)onAcceptTermsClick:(id)sender;
|
||||
@property (weak, nonatomic) IBOutlet UITextView *acceptText;
|
||||
|
||||
|
||||
+ (NSString *)StringForXMLRPCError:(const char *)err;
|
||||
+ (NSString *)errorForLinphoneAccountCreatorPhoneNumberStatus:(LinphoneAccountCreatorPhoneNumberStatus)status;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ typedef enum _ViewElement {
|
|||
historyViews = [[NSMutableArray alloc] init];
|
||||
currentView = nil;
|
||||
mustRestoreView = NO;
|
||||
acceptTerms = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
|
@ -119,12 +120,28 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
_outgoingView = DialerView.compositeViewDescription;
|
||||
_qrCodeButton.hidden = !ENABLE_QRCODE;
|
||||
[self resetLiblinphone:FALSE];
|
||||
[self enableWelcomeViewButtons];
|
||||
NSString *message = NSLocalizedString(@"I accept Belledonne Communications’ terms of use and privacy policy", nil);
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:message attributes:@{NSForegroundColorAttributeName : [UIColor systemGrayColor]}];
|
||||
[attributedString addAttribute:NSLinkAttributeName
|
||||
value:@"https://www.linphone.org/general-terms"
|
||||
range:[[attributedString string] rangeOfString:NSLocalizedString(@"terms of use", nil)]];
|
||||
[attributedString addAttribute:NSLinkAttributeName
|
||||
value:@"https://www.linphone.org/privacy-policy"
|
||||
range:[[attributedString string] rangeOfString:NSLocalizedString(@"privacy policy", nil)]];
|
||||
|
||||
NSDictionary *linkAttributes = @{NSForegroundColorAttributeName : [UIColor redColor],
|
||||
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle)};
|
||||
|
||||
_acceptText.linkTextAttributes = linkAttributes;
|
||||
_acceptText.attributedText = attributedString;
|
||||
_acceptText.editable = NO;
|
||||
_acceptText.delegate = self;
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||
|
||||
}
|
||||
|
||||
- (void)fitContent {
|
||||
|
|
@ -143,6 +160,11 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
[self fitContent];
|
||||
}
|
||||
|
||||
#pragma mark - UITextViewDelegate
|
||||
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction {
|
||||
return [[UIApplication sharedApplication] openURL:URL];
|
||||
}
|
||||
|
||||
#pragma mark - Utils
|
||||
|
||||
- (void)resetLiblinphone:(BOOL)core {
|
||||
|
|
@ -269,6 +291,12 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
return NSLocalizedString(@"Unknown error, please try again later.", nil);
|
||||
}
|
||||
|
||||
- (void)enableWelcomeViewButtons {
|
||||
UIImage *image = acceptTerms ? [UIImage imageNamed:@"checkbox_checked.png"] : [UIImage imageNamed:@"checkbox_unchecked.png"];
|
||||
[_acceptButton setImage:image forState:UIControlStateNormal];
|
||||
_gotoRemoteProvisioningButton.enabled = _gotoLinphoneLoginButton.enabled = _gotoCreateAccountButton.enabled = _gotoLoginButton.enabled = acceptTerms;
|
||||
}
|
||||
|
||||
+ (NSString *)errorForLinphoneAccountCreatorPhoneNumberStatus:(LinphoneAccountCreatorPhoneNumberStatus)status {
|
||||
switch (status) {
|
||||
case LinphoneAccountCreatorPhoneNumberStatusTooShort: /**< Phone number too short */
|
||||
|
|
@ -602,7 +630,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
|
||||
[self changeView:_remoteProvisioningLoginView back:FALSE animation:TRUE];
|
||||
|
||||
linphone_proxy_config_destroy(default_conf);
|
||||
linphone_proxy_config_unref(default_conf);
|
||||
}
|
||||
|
||||
- (void)resetTextFields {
|
||||
|
|
@ -690,10 +718,6 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
account_creator, inputEntry.length > 0 ? inputEntry.UTF8String : NULL, prefix.UTF8String);
|
||||
if (s != LinphoneAccountCreatorPhoneNumberStatusOk) {
|
||||
linphone_account_creator_set_phone_number(account_creator, NULL, NULL);
|
||||
// if phone is empty and username is empty, this is wrong
|
||||
if (linphone_account_creator_get_username(account_creator) == NULL) {
|
||||
s = LinphoneAccountCreatorPhoneNumberStatusTooShort;
|
||||
}
|
||||
}
|
||||
|
||||
createPhone.errorLabel.text = [AssistantView errorForLinphoneAccountCreatorPhoneNumberStatus:s];
|
||||
|
|
@ -1654,6 +1678,11 @@ void assistant_is_account_linked(LinphoneAccountCreator *creator, LinphoneAccoun
|
|||
}
|
||||
}
|
||||
|
||||
- (IBAction)onAcceptTermsClick:(id)sender {
|
||||
acceptTerms = !acceptTerms;
|
||||
[self enableWelcomeViewButtons];
|
||||
}
|
||||
|
||||
#pragma mark - select country delegate
|
||||
|
||||
- (void)didSelectCountry:(NSDictionary *)country {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AssistantView">
|
||||
<connections>
|
||||
<outlet property="acceptButton" destination="tZu-nz-jXM" id="qiZ-p1-Fes"/>
|
||||
<outlet property="acceptText" destination="R4J-fD-JSt" id="T8d-pv-nCc"/>
|
||||
<outlet property="accountLabel" destination="vh7-65-1js" id="IU4-gv-v6m"/>
|
||||
<outlet property="activationEmailText" destination="mbT-xm-bKk" id="fho-Ip-bTQ"/>
|
||||
<outlet property="activationSMSText" destination="9AN-gT-I7D" id="GSl-Iw-JjR"/>
|
||||
|
|
@ -42,7 +45,7 @@
|
|||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="WELCOME" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="126" userLabel="titleLabel">
|
||||
<rect key="frame" x="36" y="0.0" width="303" height="59"/>
|
||||
<rect key="frame" x="36" y="0.0" width="303" height="36"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Account setup assistant"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="light" pointSize="24"/>
|
||||
<nil key="textColor"/>
|
||||
|
|
@ -50,7 +53,7 @@
|
|||
<size key="shadowOffset" width="-1" height="-1"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="This assistant will help you configure and use your SIP account." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="Yci-5h-O4o" userLabel="subtitleLabel">
|
||||
<rect key="frame" x="36" y="66" width="303" height="58"/>
|
||||
<rect key="frame" x="36" y="36" width="303" height="58"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Account setup assistant"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="58" id="5LG-5A-dY3"/>
|
||||
|
|
@ -60,8 +63,40 @@
|
|||
<nil key="highlightedColor"/>
|
||||
<size key="shadowOffset" width="-1" height="-1"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="plw-Mp-teD" userLabel="acceptView">
|
||||
<rect key="frame" x="36" y="94" width="303" height="58"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tZu-nz-jXM" userLabel="acceptButton">
|
||||
<rect key="frame" x="20" y="2" width="54" height="54"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="54" id="4WQ-mk-JlN"/>
|
||||
</constraints>
|
||||
<state key="normal" image="checkbox_unchecked.png"/>
|
||||
<connections>
|
||||
<action selector="onAcceptTermsClick:" destination="-1" eventType="touchUpInside" id="grZ-W7-Lyz"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" text="I accept Belledonne Communications’ terms of use and privacy policy" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="R4J-fD-JSt" userLabel="acceptText">
|
||||
<rect key="frame" x="68" y="0.0" width="235" height="58"/>
|
||||
<color key="textColor" systemColor="systemGrayColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="tZu-nz-jXM" firstAttribute="top" secondItem="plw-Mp-teD" secondAttribute="top" constant="2" id="34h-dq-qBh"/>
|
||||
<constraint firstAttribute="bottom" secondItem="R4J-fD-JSt" secondAttribute="bottom" id="P1m-ak-sM2"/>
|
||||
<constraint firstItem="R4J-fD-JSt" firstAttribute="top" secondItem="plw-Mp-teD" secondAttribute="top" id="XMu-hP-ZJe"/>
|
||||
<constraint firstItem="R4J-fD-JSt" firstAttribute="leading" secondItem="plw-Mp-teD" secondAttribute="leading" constant="68" id="dSo-Mw-hmv"/>
|
||||
<constraint firstAttribute="trailing" secondItem="R4J-fD-JSt" secondAttribute="trailing" id="hcC-zD-4QJ"/>
|
||||
<constraint firstItem="tZu-nz-jXM" firstAttribute="leading" secondItem="plw-Mp-teD" secondAttribute="leading" constant="20" id="rOn-Of-kjI"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tZu-nz-jXM" secondAttribute="bottom" constant="2" id="tzO-fa-ite"/>
|
||||
<constraint firstAttribute="height" constant="58" id="zjY-mm-MaQ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="wordWrap" translatesAutoresizingMaskIntoConstraints="NO" id="36" userLabel="createAccountButton" customClass="UIRoundBorderedButton">
|
||||
<rect key="frame" x="40" y="153" width="299" height="40"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Create account">
|
||||
<bool key="isElement" value="YES"/>
|
||||
</accessibility>
|
||||
|
|
@ -70,7 +105,10 @@
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="CREATE ACCOUNT">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" systemColor="systemGray2Color"/>
|
||||
</state>
|
||||
<state key="highlighted" backgroundImage="color_F.png"/>
|
||||
<connections>
|
||||
|
|
@ -80,14 +118,17 @@
|
|||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="wordWrap" translatesAutoresizingMaskIntoConstraints="NO" id="38" userLabel="linphoneLoginButton" customClass="UIRoundBorderedButton">
|
||||
<rect key="frame" x="40" y="227" width="299" height="40"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Use Linphone account">
|
||||
<bool key="isElement" value="YES"/>
|
||||
<bool key="isElement" value="NO"/>
|
||||
</accessibility>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="40" id="NkG-qe-o3R"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="USE LINPHONE ACCOUNT">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" systemColor="systemGray2Color"/>
|
||||
</state>
|
||||
<state key="highlighted" backgroundImage="color_F.png">
|
||||
<color key="titleColor" red="0.67030966281890869" green="0.71867996454238892" blue="0.75078284740447998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -106,7 +147,10 @@
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="USE SIP ACCOUNT">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" systemColor="systemGray2Color"/>
|
||||
</state>
|
||||
<state key="highlighted" backgroundImage="color_F.png">
|
||||
<color key="titleColor" red="0.67030966281890869" green="0.71867996454238892" blue="0.75078284740447998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -125,7 +169,10 @@
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="FETCH REMOTE CONFIGURATION">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" systemColor="systemGray2Color"/>
|
||||
</state>
|
||||
<state key="highlighted" backgroundImage="color_F.png">
|
||||
<color key="titleColor" red="0.67030966281890869" green="0.71867996454238892" blue="0.75078284740447998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -138,13 +185,16 @@
|
|||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="38" firstAttribute="leading" secondItem="39" secondAttribute="leading" id="23x-IR-Mtg"/>
|
||||
<constraint firstItem="plw-Mp-teD" firstAttribute="top" secondItem="Yci-5h-O4o" secondAttribute="bottom" id="94M-05-soq"/>
|
||||
<constraint firstItem="39" firstAttribute="top" secondItem="38" secondAttribute="bottom" constant="34" id="CyI-RI-Fpo"/>
|
||||
<constraint firstItem="126" firstAttribute="top" secondItem="33" secondAttribute="top" id="Dck-Yc-Nhv"/>
|
||||
<constraint firstItem="39" firstAttribute="leading" secondItem="Kbn-dL-C5h" secondAttribute="leading" id="JTU-gj-eeY"/>
|
||||
<constraint firstItem="126" firstAttribute="leading" secondItem="33" secondAttribute="leading" constant="36" id="Mwl-ls-3tB"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Kbn-dL-C5h" secondAttribute="bottom" constant="10" id="PWn-9N-k5j"/>
|
||||
<constraint firstItem="plw-Mp-teD" firstAttribute="top" secondItem="Yci-5h-O4o" secondAttribute="bottom" id="RUw-sM-ywE"/>
|
||||
<constraint firstItem="36" firstAttribute="leading" secondItem="38" secondAttribute="leading" id="Yd2-4o-VP3"/>
|
||||
<constraint firstItem="36" firstAttribute="top" secondItem="Yci-5h-O4o" secondAttribute="bottom" constant="29" id="awh-hc-hk8"/>
|
||||
<constraint firstItem="36" firstAttribute="top" secondItem="plw-Mp-teD" secondAttribute="bottom" constant="1" id="b8b-dc-3cx"/>
|
||||
<constraint firstItem="plw-Mp-teD" firstAttribute="leading" secondItem="33" secondAttribute="leading" constant="36" id="caQ-q5-EyX"/>
|
||||
<constraint firstItem="38" firstAttribute="top" secondItem="36" secondAttribute="bottom" constant="34" id="drU-e1-uCL"/>
|
||||
<constraint firstItem="36" firstAttribute="trailing" secondItem="38" secondAttribute="trailing" id="gNw-r2-XIi"/>
|
||||
<constraint firstItem="39" firstAttribute="trailing" secondItem="Kbn-dL-C5h" secondAttribute="trailing" id="gpT-pW-S1w"/>
|
||||
|
|
@ -153,13 +203,14 @@
|
|||
<constraint firstItem="36" firstAttribute="leading" secondItem="33" secondAttribute="leading" constant="40" id="nWj-20-FOd"/>
|
||||
<constraint firstItem="Kbn-dL-C5h" firstAttribute="top" secondItem="39" secondAttribute="bottom" constant="35" id="niQ-BM-5yR"/>
|
||||
<constraint firstAttribute="trailing" secondItem="36" secondAttribute="trailing" constant="36" id="uIa-qF-c8m"/>
|
||||
<constraint firstItem="Yci-5h-O4o" firstAttribute="top" secondItem="126" secondAttribute="bottom" constant="7" id="v51-4n-Jq1"/>
|
||||
<constraint firstItem="Yci-5h-O4o" firstAttribute="top" secondItem="126" secondAttribute="bottom" id="v51-4n-Jq1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="plw-Mp-teD" secondAttribute="trailing" constant="36" id="wSJ-2t-lWy"/>
|
||||
<constraint firstItem="126" firstAttribute="centerX" secondItem="33" secondAttribute="centerX" id="z6G-VJ-BQy"/>
|
||||
<constraint firstItem="38" firstAttribute="trailing" secondItem="39" secondAttribute="trailing" id="z7W-lC-fXR"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="203.5" y="189"/>
|
||||
<point key="canvasLocation" x="202.40000000000001" y="188.90554722638683"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" id="44" userLabel="createAccountView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="739"/>
|
||||
|
|
@ -201,7 +252,7 @@
|
|||
<constraint firstAttribute="height" constant="30" id="pz8-ke-WQV"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Select your country">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="highlighted" title="Choose your country" backgroundImage="color_F.png"/>
|
||||
<connections>
|
||||
|
|
@ -210,7 +261,7 @@
|
|||
</button>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="109" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="+1" textAlignment="center" minimumFontSize="5" translatesAutoresizingMaskIntoConstraints="NO" id="aG8-DH-06s" userLabel="countryCodeField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="190" width="54" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" keyboardType="phonePad"/>
|
||||
<connections>
|
||||
|
|
@ -221,7 +272,7 @@
|
|||
</textField>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="107" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="74" userLabel="phoneField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="95" y="190" width="242" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Username"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="phonePad" returnKeyType="next"/>
|
||||
|
|
@ -293,7 +344,7 @@
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="100" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="OLm-Nz-ouj" userLabel="usernameField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="23" width="299" height="34"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Username"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" returnKeyType="next"/>
|
||||
|
|
@ -344,7 +395,7 @@
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="103" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="IXr-i2-LEh" userLabel="emailField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="22" width="291" height="34"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Email"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="emailAddress" returnKeyType="done"/>
|
||||
|
|
@ -373,7 +424,7 @@
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="101" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="t14-fe-grq" userLabel="passwordField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="105" width="291" height="34"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Password "/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" returnKeyType="next" secureTextEntry="YES"/>
|
||||
|
|
@ -402,7 +453,7 @@
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="102" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="kHS-3H-oHM" userLabel="password2Field" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="183" width="291" height="34"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Password confirmation"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" returnKeyType="next" secureTextEntry="YES"/>
|
||||
|
|
@ -458,7 +509,7 @@
|
|||
</accessibility>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="CREATE ACCOUNT">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.71885228157043457" green="0.71883076429367065" blue="0.71884298324584961" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -586,7 +637,7 @@
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="108" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Activation code" textAlignment="center" minimumFontSize="17" clearButtonMode="always" translatesAutoresizingMaskIntoConstraints="NO" id="ULe-kp-qZn">
|
||||
<rect key="frame" x="38" y="194" width="299" height="71"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="26"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="numberPad" returnKeyType="done"/>
|
||||
</textField>
|
||||
|
|
@ -600,7 +651,7 @@
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="ACTIVATE YOUR ACCOUNT">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.71885228157043457" green="0.71883076429367065" blue="0.71884298324584961" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -692,7 +743,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="FINISH CONFIGURATION">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.71885228157043457" green="0.71883076429367065" blue="0.71884298324584961" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -756,7 +807,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
<constraint firstAttribute="height" constant="30" id="X9C-Ll-LuK"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Select your country">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="highlighted" title="Choose your country" backgroundImage="color_F.png"/>
|
||||
<connections>
|
||||
|
|
@ -765,7 +816,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</button>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="109" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="+1" textAlignment="center" minimumFontSize="5" translatesAutoresizingMaskIntoConstraints="NO" id="iEA-YK-kua" userLabel="countryCodeField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="179" width="54" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" keyboardType="phonePad"/>
|
||||
<connections>
|
||||
|
|
@ -776,7 +827,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</textField>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="107" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="Pcj-jL-x9P" userLabel="phoneField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="95" y="179" width="242" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Username"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="phonePad" returnKeyType="next"/>
|
||||
|
|
@ -824,7 +875,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="100" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="YRW-ex-VZy" userLabel="usernameField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="20" width="299" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Username"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="QcL-i5-g1D"/>
|
||||
|
|
@ -857,7 +908,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="101" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="ap4-xh-CVK" userLabel="passwordField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="93" width="299" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Password"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="BWP-n1-3OS"/>
|
||||
|
|
@ -882,7 +933,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</connections>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration">
|
||||
<accessibilityTraits key="traits" notEnabled="YES"/>
|
||||
</accessibility>
|
||||
|
|
@ -928,7 +979,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="LOGIN">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.71885228157043457" green="0.71883076429367065" blue="0.71884298324584961" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -1033,7 +1084,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="100" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="FJ1-Xt-g7g" userLabel="usernameField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="153" width="298" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Username"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="Xxt-U5-krh"/>
|
||||
|
|
@ -1066,7 +1117,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="101" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="zEa-Dj-QiH" userLabel="passwordField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="227" width="298" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Password"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="ywR-ZJ-1YN"/>
|
||||
|
|
@ -1099,7 +1150,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="104" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="5kh-Wo-SMY" userLabel="domainField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="301" width="298" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Domain"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="Evx-tD-kkq"/>
|
||||
|
|
@ -1153,7 +1204,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="106" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="7Cb-fa-CY5" userLabel="displayNameField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="375" width="298" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Display name"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="Mr8-Nc-w1K"/>
|
||||
|
|
@ -1184,7 +1235,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="LOGIN">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.71885228157043457" green="0.71883076429367065" blue="0.71884298324584961" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -1288,7 +1339,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="105" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="Ffg-Of-xyh" userLabel="urlField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="123" width="299" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="URL"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="7OB-M5-kU2"/>
|
||||
|
|
@ -1319,7 +1370,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="FETCH AND APPLY">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.71885228157043457" green="0.71883076429367065" blue="0.71884298324584961" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -1339,7 +1390,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="QR CODE">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.71885228160000003" green="0.71883076430000004" blue="0.71884298319999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -1412,7 +1463,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="100" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="qgP-7X-pUs" userLabel="usernameField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="153" width="299" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Username"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="f5B-bE-Uf0"/>
|
||||
|
|
@ -1435,7 +1486,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="101" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="hfJ-yu-wVn" userLabel="passwordField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="217" width="299" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Password"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="cfl-mf-gkE"/>
|
||||
|
|
@ -1458,7 +1509,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="104" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" adjustsFontSizeToFit="NO" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="gfr-KY-4vo" userLabel="domainField" customClass="UIAssistantTextField">
|
||||
<rect key="frame" x="38" y="281" width="299" height="30"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Domain"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="RNp-Me-1Fq"/>
|
||||
|
|
@ -1480,7 +1531,7 @@ Once it is done, come back here and click on the button.</string>
|
|||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<state key="normal" title="LOGIN">
|
||||
<color key="titleColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="titleColor" systemColor="labelColor"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.71885228157043457" green="0.71883076429367065" blue="0.71884298324584961" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -1539,6 +1590,22 @@ Once it is done, come back here and click on the button.</string>
|
|||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="checkbox_unchecked.png" width="27.200000762939453" height="27.200000762939453"/>
|
||||
<image name="color_F.png" width="2" height="2"/>
|
||||
<systemColor name="labelColor">
|
||||
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
<systemColor name="secondarySystemBackgroundColor">
|
||||
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemGray2Color">
|
||||
<color red="0.68235294117647061" green="0.68235294117647061" blue="0.69803921568627447" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemGrayColor">
|
||||
<color red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
|
@ -45,7 +46,7 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="540" height="66"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Enter a number or an address" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" minimumFontSize="5" translatesAutoresizingMaskIntoConstraints="NO" id="4" userLabel="addressField" customClass="UIAddressTextField">
|
||||
<textField opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Enter a number or an address" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" minimumFontSize="15" translatesAutoresizingMaskIntoConstraints="NO" id="4" userLabel="addressField" customClass="UIAddressTextField">
|
||||
<rect key="frame" x="31" y="0.0" width="426" height="66"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -70,7 +71,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
</view>
|
||||
<imageView userInteractionEnabled="NO" tag="2" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="dialer_background.png" translatesAutoresizingMaskIntoConstraints="NO" id="AH0-S5-0Ku" userLabel="logoImage">
|
||||
<rect key="frame" x="100" y="279" width="340" height="294"/>
|
||||
|
|
@ -238,7 +239,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="182" userLabel="bottomBar">
|
||||
<rect key="frame" x="0.0" y="786" width="540" height="66"/>
|
||||
|
|
@ -287,7 +288,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
|
|
@ -338,5 +339,11 @@
|
|||
<image name="numpad_over_background.png" width="2" height="2"/>
|
||||
<image name="numpad_star_default.png" width="84.800003051757812" height="81.599998474121094"/>
|
||||
<image name="numpad_star_over.png" width="84.800003051757812" height="81.599998474121094"/>
|
||||
<systemColor name="secondarySystemBackgroundColor">
|
||||
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
||||
|
|
|
|||
|
|
@ -33,11 +33,10 @@ import AVFoundation
|
|||
* CallManager is a class that manages application calls and supports callkit.
|
||||
* There is only one CallManager by calling CallManager.instance().
|
||||
*/
|
||||
@objc class CallManager: NSObject {
|
||||
@objc class CallManager: NSObject, CoreDelegate {
|
||||
static var theCallManager: CallManager?
|
||||
let providerDelegate: ProviderDelegate! // to support callkit
|
||||
let callController: CXCallController! // to support callkit
|
||||
let manager: CoreManagerDelegate! // callbacks of the linphonecore
|
||||
var lc: Core?
|
||||
@objc var speakerBeforePause : Bool = false
|
||||
@objc var speakerEnabled : Bool = false
|
||||
|
|
@ -47,12 +46,14 @@ import AVFoundation
|
|||
var referedFromCall: String?
|
||||
var referedToCall: String?
|
||||
var endCallkit: Bool = false
|
||||
static var speaker_already_enabled : Bool = false
|
||||
var globalState : GlobalState = .Off
|
||||
var actionsToPerformOnceWhenCoreIsOn : [(()->Void)] = []
|
||||
|
||||
|
||||
fileprivate override init() {
|
||||
providerDelegate = ProviderDelegate()
|
||||
callController = CXCallController()
|
||||
manager = CoreManagerDelegate()
|
||||
}
|
||||
|
||||
@objc static func instance() -> CallManager {
|
||||
|
|
@ -64,7 +65,7 @@ import AVFoundation
|
|||
|
||||
@objc func setCore(core: OpaquePointer) {
|
||||
lc = Core.getSwiftObject(cObject: core)
|
||||
lc?.addDelegate(delegate: manager)
|
||||
lc?.addDelegate(delegate: self)
|
||||
}
|
||||
|
||||
@objc static func getAppData(call: OpaquePointer) -> CallAppData? {
|
||||
|
|
@ -275,7 +276,7 @@ import AVFoundation
|
|||
|
||||
if (CallManager.instance().nextCallIsTransfer) {
|
||||
let call = CallManager.instance().lc!.currentCall
|
||||
try call?.transfer(referTo: addr.asString())
|
||||
try call?.transferTo(referTo: addr)
|
||||
CallManager.instance().nextCallIsTransfer = false
|
||||
} else {
|
||||
//We set the record file name here because we can't do it after the call is started.
|
||||
|
|
@ -331,18 +332,6 @@ import AVFoundation
|
|||
providerDelegate.uuids.removeAll()
|
||||
}
|
||||
|
||||
// To be removed.
|
||||
static func configAudioSession(audioSession: AVAudioSession) {
|
||||
do {
|
||||
try audioSession.setCategory(AVAudioSession.Category.playAndRecord, mode: AVAudioSession.Mode.voiceChat, options: AVAudioSession.CategoryOptions(rawValue: AVAudioSession.CategoryOptions.allowBluetooth.rawValue | AVAudioSession.CategoryOptions.allowBluetoothA2DP.rawValue))
|
||||
try audioSession.setMode(AVAudioSession.Mode.voiceChat)
|
||||
try audioSession.setPreferredSampleRate(48000.0)
|
||||
try AVAudioSession.sharedInstance().setActive(true, options: [])
|
||||
} catch {
|
||||
Log.directLog(BCTBX_LOG_WARNING, text: "CallKit: Unable to config audio session because : \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
@objc func terminateCall(call: OpaquePointer?) {
|
||||
if (call == nil) {
|
||||
Log.directLog(BCTBX_LOG_ERROR, text: "Can not terminate null call!")
|
||||
|
|
@ -355,9 +344,6 @@ import AVFoundation
|
|||
} catch {
|
||||
Log.directLog(BCTBX_LOG_ERROR, text: "Failed to terminate call failed because \(error)")
|
||||
}
|
||||
if (UIApplication.shared.applicationState == .background) {
|
||||
CoreManager.instance().stopLinphoneCore()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func markCallAsDeclined(callId: String) {
|
||||
|
|
@ -409,32 +395,32 @@ import AVFoundation
|
|||
}
|
||||
|
||||
@objc func performActionWhenCoreIsOn(action: @escaping ()->Void ) {
|
||||
if (manager.globalState == .On) {
|
||||
if (globalState == .On) {
|
||||
action()
|
||||
} else {
|
||||
manager.actionsToPerformOnceWhenCoreIsOn.append(action)
|
||||
actionsToPerformOnceWhenCoreIsOn.append(action)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CoreManagerDelegate: CoreDelegate {
|
||||
static var speaker_already_enabled : Bool = false
|
||||
var globalState : GlobalState = .Off
|
||||
var actionsToPerformOnceWhenCoreIsOn : [(()->Void)] = []
|
||||
|
||||
override func onGlobalStateChanged(lc: Core, gstate: GlobalState, message: String) {
|
||||
if (gstate == .On) {
|
||||
@objc func acceptVideo(call: OpaquePointer, confirm: Bool) {
|
||||
let sCall = Call.getSwiftObject(cObject: call)
|
||||
let params = try? lc?.createCallParams(call: sCall)
|
||||
params?.videoEnabled = confirm
|
||||
try? sCall.acceptUpdate(params: params)
|
||||
}
|
||||
|
||||
func onGlobalStateChanged(core: Core, state: GlobalState, message: String) {
|
||||
if (state == .On) {
|
||||
actionsToPerformOnceWhenCoreIsOn.forEach {
|
||||
$0()
|
||||
}
|
||||
actionsToPerformOnceWhenCoreIsOn.removeAll()
|
||||
}
|
||||
globalState = gstate
|
||||
globalState = state
|
||||
}
|
||||
|
||||
override func onRegistrationStateChanged(lc: Core, cfg: ProxyConfig, cstate: RegistrationState, message: String) {
|
||||
if lc.proxyConfigList.count == 1 && (cstate == .Failed || cstate == .Cleared){
|
||||
|
||||
func onRegistrationStateChanged(core: Core, proxyConfig: ProxyConfig, state: RegistrationState, message: String) {
|
||||
if core.proxyConfigList.count == 1 && (state == .Failed || state == .Cleared){
|
||||
// terminate callkit immediately when registration failed or cleared, supporting single proxy configuration
|
||||
CallManager.instance().endCallkit = true
|
||||
for call in CallManager.instance().providerDelegate.uuids {
|
||||
|
|
@ -445,15 +431,15 @@ class CoreManagerDelegate: CoreDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
override func onCallStateChanged(lc: Core, call: Call, cstate: Call.State, message: String) {
|
||||
func onCallStateChanged(core: Core, call: Call, state cstate: Call.State, message: String) {
|
||||
let addr = call.remoteAddress;
|
||||
let displayName = FastAddressBook.displayName(for: addr?.getCobject) ?? "Unknow"
|
||||
let callLog = call.callLog
|
||||
let callId = callLog?.callId
|
||||
let video = UIApplication.shared.applicationState == .active && (lc.videoActivationPolicy?.automaticallyAccept ?? false) && (call.remoteParams?.videoEnabled ?? false)
|
||||
let video = UIApplication.shared.applicationState == .active && (core.videoActivationPolicy?.automaticallyAccept ?? false) && (call.remoteParams?.videoEnabled ?? false)
|
||||
// we keep the speaker auto-enabled state in this static so that we don't
|
||||
// force-enable it on ICE re-invite if the user disabled it.
|
||||
CoreManagerDelegate.speaker_already_enabled = false
|
||||
CallManager.speaker_already_enabled = false
|
||||
|
||||
if (call.userData == nil) {
|
||||
let appData = CallAppData()
|
||||
|
|
@ -507,7 +493,7 @@ class CoreManagerDelegate: CoreDelegate {
|
|||
if (CallManager.instance().speakerBeforePause) {
|
||||
CallManager.instance().speakerBeforePause = false
|
||||
CallManager.instance().enableSpeaker(enable: true)
|
||||
CoreManagerDelegate.speaker_already_enabled = true
|
||||
CallManager.speaker_already_enabled = true
|
||||
}
|
||||
break
|
||||
case .OutgoingInit,
|
||||
|
|
@ -533,7 +519,7 @@ class CoreManagerDelegate: CoreDelegate {
|
|||
case .End,
|
||||
.Error:
|
||||
UIDevice.current.isProximityMonitoringEnabled = false
|
||||
CoreManagerDelegate.speaker_already_enabled = false
|
||||
CallManager.speaker_already_enabled = false
|
||||
if (CallManager.instance().lc!.callsNb == 0) {
|
||||
CallManager.instance().enableSpeaker(enable: false)
|
||||
// disable this because I don't find anygood reason for it: _bluetoothAvailable = FALSE;
|
||||
|
|
@ -600,9 +586,9 @@ class CoreManagerDelegate: CoreDelegate {
|
|||
}
|
||||
|
||||
if (cstate == .IncomingReceived || cstate == .OutgoingInit || cstate == .Connected || cstate == .StreamsRunning) {
|
||||
if ((call.currentParams?.videoEnabled ?? false) && !CoreManagerDelegate.speaker_already_enabled && !CallManager.instance().bluetoothEnabled) {
|
||||
if ((call.currentParams?.videoEnabled ?? false) && !CallManager.speaker_already_enabled && !CallManager.instance().bluetoothEnabled) {
|
||||
CallManager.instance().enableSpeaker(enable: true)
|
||||
CoreManagerDelegate.speaker_already_enabled = true
|
||||
CallManager.speaker_already_enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -685,9 +685,7 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
|
|||
onCancelClick:^() {
|
||||
LOGI(@"User declined video proposal");
|
||||
if (call == linphone_core_get_current_call(LC)) {
|
||||
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
|
||||
linphone_call_accept_update(call, params);
|
||||
linphone_call_params_destroy(params);
|
||||
[CallManager.instance acceptVideoWithCall:call confirm:FALSE];
|
||||
[videoDismissTimer invalidate];
|
||||
videoDismissTimer = nil;
|
||||
}
|
||||
|
|
@ -695,10 +693,7 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
|
|||
onConfirmationClick:^() {
|
||||
LOGI(@"User accept video proposal");
|
||||
if (call == linphone_core_get_current_call(LC)) {
|
||||
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
|
||||
linphone_call_params_enable_video(params, TRUE);
|
||||
linphone_call_accept_update(call, params);
|
||||
linphone_call_params_destroy(params);
|
||||
[CallManager.instance acceptVideoWithCall:call confirm:TRUE];
|
||||
[videoDismissTimer invalidate];
|
||||
videoDismissTimer = nil;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,4 +49,6 @@
|
|||
- (IBAction)onBackClick:(id)sender;
|
||||
- (IBAction)onQuitClick:(id)sender;
|
||||
|
||||
- (void)removeCallbacks;
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -132,6 +132,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[self removeCallbacks];
|
||||
}
|
||||
|
||||
- (void)removeCallbacks {
|
||||
if (!_room || !_chatRoomCbs)
|
||||
return;
|
||||
|
||||
|
|
@ -299,7 +303,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
cell.uri = _contacts[indexPath.row];
|
||||
LinphoneAddress *addr = linphone_address_new(cell.uri.UTF8String);
|
||||
cell.nameLabel.text = [FastAddressBook displayNameForAddress:addr];
|
||||
cell.nameLabel.text = (addr == nil? cell.uri : [FastAddressBook displayNameForAddress:addr]);
|
||||
[cell.avatarImage setImage:[FastAddressBook imageForAddress:addr] bordered:YES withRoundedRadius:YES];
|
||||
cell.controllerView = self;
|
||||
if(![_admins containsObject:cell.uri]) {
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
|
||||
@protocol ChatConversationDelegate <NSObject>
|
||||
|
||||
- (BOOL)startImageUpload:(UIImage *)image assetId:(NSString *)phAssetId withQuality:(float)quality;
|
||||
- (BOOL)startFileUpload:(NSData *)data assetId:(NSString *)phAssetId;
|
||||
- (BOOL)resendFile:(NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message;
|
||||
- (BOOL)startImageUpload:(UIImage *)image withQuality:(float)quality andMessage:(NSString *)message;
|
||||
- (BOOL)startFileUpload:(NSData *)data withName:(NSString *)name;
|
||||
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url;
|
||||
- (void)tableViewIsScrolling;
|
||||
|
|
|
|||
|
|
@ -193,12 +193,11 @@ static const int BASIC_EVENT_LIST=15;
|
|||
- (BOOL)isFirstIndexInTableView:(NSIndexPath *)indexPath chat:(LinphoneChatMessage *)chat {
|
||||
LinphoneEventLog *previousEvent = nil;
|
||||
NSInteger indexOfPreviousEvent = indexPath.row - 1;
|
||||
while (!previousEvent && indexOfPreviousEvent > -1) {
|
||||
LinphoneEventLog *tmp = [[eventList objectAtIndex:indexOfPreviousEvent] pointerValue];
|
||||
if (linphone_event_log_get_type(tmp) == LinphoneEventLogTypeConferenceChatMessage) {
|
||||
previousEvent = tmp;
|
||||
if (indexOfPreviousEvent > -1) {
|
||||
previousEvent = [[eventList objectAtIndex:indexOfPreviousEvent] pointerValue];
|
||||
if (linphone_event_log_get_type(previousEvent) != LinphoneEventLogTypeConferenceChatMessage) {
|
||||
return TRUE;
|
||||
}
|
||||
--indexOfPreviousEvent;
|
||||
}
|
||||
if (!previousEvent)
|
||||
return TRUE;
|
||||
|
|
@ -256,11 +255,11 @@ static const int BASIC_EVENT_LIST=15;
|
|||
kCellId = NSStringFromClass(UIChatBubblePhotoCell.class);
|
||||
else
|
||||
kCellId = NSStringFromClass(UIChatBubbleTextCell.class);
|
||||
|
||||
|
||||
// To use less memory and to avoid overlapping. To be improved.
|
||||
UIChatBubbleTextCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
|
||||
if (!cell) {
|
||||
cell = [[NSClassFromString(kCellId) alloc] initWithIdentifier:kCellId];
|
||||
}
|
||||
cell = [[NSClassFromString(kCellId) alloc] initWithIdentifier:kCellId];
|
||||
|
||||
[cell setEvent:event];
|
||||
if (chat) {
|
||||
cell.isFirst = [self isFirstIndexInTableView:indexPath chat:chat];
|
||||
|
|
@ -363,9 +362,9 @@ static const CGFloat MESSAGE_SPACING_PERCENTAGE = 1.f;
|
|||
- (void)removeSelectionUsing:(void (^)(NSIndexPath *))remover {
|
||||
[super removeSelectionUsing:^(NSIndexPath *indexPath) {
|
||||
LinphoneEventLog *event = [[eventList objectAtIndex:indexPath.row] pointerValue];
|
||||
// TODO: fix workaround
|
||||
//linphone_event_log_delete_from_database(event);
|
||||
linphone_chat_room_delete_message(_chatRoom, linphone_event_log_get_chat_message(event));
|
||||
if (linphone_event_log_get_chat_message(event)) {
|
||||
linphone_chat_room_delete_message(_chatRoom, linphone_event_log_get_chat_message(event));
|
||||
}
|
||||
NSInteger index = indexPath.row + _currentIndex + (totalEventList.count - eventList.count);
|
||||
if (index < totalEventList.count)
|
||||
[totalEventList removeObjectAtIndex:index];
|
||||
|
|
|
|||
|
|
@ -92,6 +92,11 @@
|
|||
|
||||
+ (void)markAsRead:(LinphoneChatRoom *)chatRoom;
|
||||
+ (void)autoDownload:(LinphoneChatMessage *)message;
|
||||
+(NSString *)getKeyFromFileType:(NSString *)fileType fileName:(NSString *)name;
|
||||
+ (NSURL *)getCacheFileUrl:(NSString *)name;
|
||||
+ (void)writeFileInCache:(NSData *)data name:(NSString *)name;
|
||||
+ (NSData *)getCacheFileData:(NSString *)name;
|
||||
+ (void)writeMediaToGallery:(NSString *)name fileType:(NSString *)fileType;
|
||||
|
||||
- (void)configureForRoom:(BOOL)editing;
|
||||
- (IBAction)onBackClick:(id)event;
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
linphone_chat_room_cbs_set_participant_removed(_chatRoomCbs, on_chat_room_participant_removed);
|
||||
linphone_chat_room_cbs_set_participant_admin_status_changed(_chatRoomCbs, on_chat_room_participant_admin_status_changed);
|
||||
linphone_chat_room_cbs_set_chat_message_received(_chatRoomCbs, on_chat_room_chat_message_received);
|
||||
linphone_chat_room_cbs_set_chat_message_sent(_chatRoomCbs, on_chat_room_chat_message_sent);
|
||||
linphone_chat_room_cbs_set_chat_message_sending(_chatRoomCbs, on_chat_room_chat_message_sending);
|
||||
linphone_chat_room_cbs_set_is_composing_received(_chatRoomCbs, on_chat_room_is_composing_received);
|
||||
linphone_chat_room_cbs_set_conference_joined(_chatRoomCbs, on_chat_room_conference_joined);
|
||||
linphone_chat_room_cbs_set_conference_left(_chatRoomCbs, on_chat_room_conference_left);
|
||||
|
|
@ -337,33 +337,17 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
//file shared from photo lib
|
||||
NSString *fileName = dict[@"url"];
|
||||
[_messageField setText:dict[@"message"]];
|
||||
NSString *key = [[fileName componentsSeparatedByString:@"."] firstObject];
|
||||
NSMutableDictionary <NSString *, PHAsset *> * assetDict = [LinphoneUtils photoAssetsDictionary];
|
||||
PHAsset *phasset = [assetDict objectForKey:key];
|
||||
if (!phasset) {
|
||||
// for the images or videos not really in the photo album
|
||||
[self confirmShare:[self nsDataRead] url:nil fileName:fileName assetId:nil];
|
||||
} else if ([fileName hasSuffix:@"JPG"] || [fileName hasSuffix:@"PNG"] || [fileName hasSuffix:@"jpg"] || [fileName hasSuffix:@"png"]) {
|
||||
UIImage *image = [[UIImage alloc] initWithData:[self nsDataRead]];
|
||||
[self chooseImageQuality:image assetId:[phasset localIdentifier]];
|
||||
} else if ([fileName hasSuffix:@"MOV"] || [fileName hasSuffix:@"mov"]) {
|
||||
[self confirmShare:[self nsDataRead] url:nil fileName:nil assetId:[phasset localIdentifier]];
|
||||
} else {
|
||||
LOGE(@"Unable to parse file %@",fileName);
|
||||
}
|
||||
|
||||
[self confirmShare:[self nsDataRead] url:nil fileName:fileName];
|
||||
[defaults removeObjectForKey:@"photoData"];
|
||||
} else if (dictFile) {
|
||||
NSString *fileName = dictFile[@"url"];
|
||||
[_messageField setText:dictFile[@"message"]];
|
||||
[self confirmShare:[self nsDataRead] url:nil fileName:fileName assetId:nil];
|
||||
|
||||
[self confirmShare:[self nsDataRead] url:nil fileName:fileName];
|
||||
[defaults removeObjectForKey:@"icloudData"];
|
||||
} else if (dictUrl) {
|
||||
NSString *url = dictUrl[@"url"];
|
||||
[_messageField setText:dictUrl[@"message"]];
|
||||
[self confirmShare:nil url:url fileName:nil assetId:nil];
|
||||
|
||||
[self confirmShare:nil url:url fileName:nil];
|
||||
[defaults removeObjectForKey:@"url"];
|
||||
}
|
||||
}
|
||||
|
|
@ -378,6 +362,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
[self configureForRoom:self.editing];
|
||||
if (_chatRoom && _markAsRead) {
|
||||
if (IPAD) {
|
||||
[VIEW(ChatsListView).tableController loadData];
|
||||
}
|
||||
|
||||
[ChatConversationView markAsRead:_chatRoom];
|
||||
}
|
||||
_markAsRead = TRUE;
|
||||
|
|
@ -413,7 +401,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
}
|
||||
|
||||
- (BOOL)sendMessage:(NSString *)message withExterlBodyUrl:(NSURL *)externalUrl withInternalURL:(NSURL *)internalUrl {
|
||||
- (BOOL)sendMessage:(NSString *)message withExterlBodyUrl:(NSURL *)externalUrl {
|
||||
if (_chatRoom == NULL) {
|
||||
LOGW(@"Cannot send message: No chatroom");
|
||||
return FALSE;
|
||||
|
|
@ -424,11 +412,6 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
linphone_chat_message_set_external_body_url(msg, [[externalUrl absoluteString] UTF8String]);
|
||||
}
|
||||
|
||||
if (internalUrl) {
|
||||
// internal url is saved in the appdata for display and later save
|
||||
[LinphoneManager setValueInMessageAppData:[internalUrl absoluteString] forKey:@"localimage" inMessage:msg];
|
||||
}
|
||||
|
||||
// we must ref & unref message because in case of error, it will be destroy otherwise
|
||||
linphone_chat_message_send(msg);
|
||||
|
||||
|
|
@ -470,7 +453,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
});
|
||||
}
|
||||
|
||||
- (void)confirmShare:(NSData *)data url:(NSString *)url fileName:(NSString *)fileName assetId:(NSString *)phAssetId {
|
||||
- (void)confirmShare:(NSData *)data url:(NSString *)url fileName:(NSString *)fileName {
|
||||
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:@""];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[sheet addButtonWithTitle:NSLocalizedString(@"Send to this friend", nil)
|
||||
|
|
@ -479,11 +462,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
[self sendMessageInMessageField];
|
||||
}
|
||||
if (url)
|
||||
[self sendMessage:url withExterlBodyUrl:nil withInternalURL:nil];
|
||||
else if (fileName)
|
||||
[self startFileUpload:data withName:fileName];
|
||||
[self sendMessage:url withExterlBodyUrl:nil];
|
||||
else
|
||||
[self startFileUpload:data assetId:phAssetId];}];
|
||||
[self startFileUpload:data withName:fileName];
|
||||
}];
|
||||
|
||||
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Cancel", nil) block:nil];
|
||||
[sheet showInView:PhoneMainView.instance.view];
|
||||
|
|
@ -564,7 +546,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
|
||||
- (void)sendMessageInMessageField {
|
||||
if ([self sendMessage:[_messageField text] withExterlBodyUrl:nil withInternalURL:nil]) {
|
||||
if ([self sendMessage:[_messageField text] withExterlBodyUrl:nil]) {
|
||||
scrollOnGrowingEnabled = FALSE;
|
||||
[_messageField setText:@""];
|
||||
scrollOnGrowingEnabled = TRUE;
|
||||
|
|
@ -647,15 +629,15 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
if ([_imagesArray count] > 0) {
|
||||
int i = 0;
|
||||
for (i = 0; i < [_imagesArray count] - 1; ++i) {
|
||||
[self startImageUpload:[_imagesArray objectAtIndex:i] assetId:[_assetIdsArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue];
|
||||
[self startImageUpload:[_imagesArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:NULL];
|
||||
}
|
||||
if (isOneToOne) {
|
||||
[self startImageUpload:[_imagesArray objectAtIndex:i] assetId:[_assetIdsArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue];
|
||||
[self startImageUpload:[_imagesArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:NULL];
|
||||
if (![[self.messageField text] isEqualToString:@""]) {
|
||||
[self sendMessage:[_messageField text] withExterlBodyUrl:nil withInternalURL:nil];
|
||||
[self sendMessage:[_messageField text] withExterlBodyUrl:nil];
|
||||
}
|
||||
} else {
|
||||
[self startImageUpload:[_imagesArray objectAtIndex:i] assetId:[_assetIdsArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:[self.messageField text]];
|
||||
[self startImageUpload:[_imagesArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:[self.messageField text]];
|
||||
}
|
||||
|
||||
[self clearMessageView];
|
||||
|
|
@ -757,28 +739,15 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
|
||||
#pragma mark ChatRoomDelegate
|
||||
|
||||
- (BOOL)startImageUpload:(UIImage *)image assetId:(NSString *)phAssetId withQuality:(float)quality {
|
||||
- (BOOL)startImageUpload:(UIImage *)image withQuality:(float)quality andMessage:(NSString *)message {
|
||||
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
[fileTransfer upload:image withassetId:phAssetId forChatRoom:_chatRoom withQuality:quality];
|
||||
if (message)
|
||||
[fileTransfer setText:message];
|
||||
[fileTransfer uploadImage:image forChatRoom:_chatRoom withQuality:quality];
|
||||
[_tableController scrollToBottom:true];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL)startImageUpload:(UIImage *)image assetId:(NSString *)phAssetId withQuality:(float)quality andMessage:(NSString *)message {
|
||||
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
[fileTransfer setText:message];
|
||||
[fileTransfer upload:image withassetId:phAssetId forChatRoom:_chatRoom withQuality:quality];
|
||||
[_tableController scrollToBottom:true];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL)startFileUpload:(NSData *)data assetId:(NSString *)phAssetId {
|
||||
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
[fileTransfer uploadVideo:data withassetId:phAssetId forChatRoom:_chatRoom];
|
||||
[_tableController scrollToBottom:true];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL)startFileUpload:(NSData *)data withName:(NSString *)name {
|
||||
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
[fileTransfer uploadFile:data forChatRoom:_chatRoom withName:name];
|
||||
|
|
@ -786,8 +755,17 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL)resendFile: (NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message {
|
||||
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
if (message)
|
||||
[fileTransfer setText:message];
|
||||
[fileTransfer uploadData:data forChatRoom:_chatRoom type:type subtype:type name:name key:key];
|
||||
[_tableController scrollToBottom:true];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url {
|
||||
[self sendMessage:message withExterlBodyUrl:[NSURL URLWithString:url] withInternalURL:nil];
|
||||
[self sendMessage:message withExterlBodyUrl:[NSURL URLWithString:url]];
|
||||
}
|
||||
|
||||
#pragma mark ImagePickerDelegate
|
||||
|
|
@ -836,6 +814,88 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
}
|
||||
}
|
||||
|
||||
+ (void)writeMediaToGallery:(NSString *)name fileType:(NSString *)fileType {
|
||||
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if ([fileManager fileExistsAtPath:filePath]) {
|
||||
NSData* data = [NSData dataWithContentsOfFile:filePath];
|
||||
|
||||
// define a block , not called immediately. To avoid crash when saving photo before PHAuthorizationStatusNotDetermined.
|
||||
void (^block)(void)= ^ {
|
||||
if ([fileType isEqualToString:@"image"] ) {
|
||||
// we're finished, save the image and update the message
|
||||
UIImage *image = [UIImage imageWithData:data];
|
||||
if (!image) {
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
[view showFileDownloadError];
|
||||
return;
|
||||
}
|
||||
__block PHObjectPlaceholder *placeHolder;
|
||||
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
||||
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
|
||||
placeHolder = [request placeholderForCreatedAsset];
|
||||
} completionHandler:^(BOOL success, NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (error) {
|
||||
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
|
||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write image to photo library",nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {}];
|
||||
|
||||
[errView addAction:defaultAction];
|
||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||
} else {
|
||||
LOGI(@"Image saved to [%@]", [placeHolder localIdentifier]);
|
||||
}
|
||||
});
|
||||
}];
|
||||
} else if([fileType isEqualToString:@"video"]) {
|
||||
__block PHObjectPlaceholder *placeHolder;
|
||||
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
||||
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]];
|
||||
placeHolder = [request placeholderForCreatedAsset];
|
||||
} completionHandler:^(BOOL success, NSError * _Nullable error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (error) {
|
||||
LOGE(@"Cannot save video data downloaded [%@]", [error localizedDescription]);
|
||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write video to photo library", nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {}];
|
||||
|
||||
[errView addAction:defaultAction];
|
||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||
} else {
|
||||
LOGI(@"video saved to [%@]", [placeHolder localIdentifier]);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
};
|
||||
|
||||
// When you save an image or video to a photo library, make sure that it is allowed. Otherwise, there will be a backup error.
|
||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||
block();
|
||||
} else {
|
||||
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||
block();
|
||||
} else {
|
||||
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Photo's permission", nil) message:NSLocalizedString(@"Photo not authorized", nil) delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil] show];
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) writeVideoToGallery:(NSURL *)url {
|
||||
NSString *localIdentifier;
|
||||
|
|
@ -1110,7 +1170,7 @@ void on_chat_room_chat_message_received(LinphoneChatRoom *cr, const LinphoneEven
|
|||
[view.tableController scrollToLastUnread:TRUE];
|
||||
}
|
||||
|
||||
void on_chat_room_chat_message_sent(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) {
|
||||
void on_chat_room_chat_message_sending(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) {
|
||||
ChatConversationView *view = (__bridge ChatConversationView *)linphone_chat_room_cbs_get_user_data(linphone_chat_room_get_current_callbacks(cr));
|
||||
[view.tableController addEventEntry:(LinphoneEventLog *)event_log];
|
||||
[view.tableController scrollToBottom:true];
|
||||
|
|
@ -1175,6 +1235,23 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
|||
[PhoneMainView.instance fullScreen:NO];
|
||||
}
|
||||
|
||||
+ (NSData *)getCacheFileData: (NSString *)name {
|
||||
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
return [NSData dataWithContentsOfFile:filePath];
|
||||
}
|
||||
|
||||
+ (NSURL *)getCacheFileUrl: (NSString *)name {
|
||||
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
return [NSURL fileURLWithPath:filePath];
|
||||
}
|
||||
|
||||
+ (void)writeFileInCache:(NSData *)data name:(NSString *)name {
|
||||
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
[[NSFileManager defaultManager] createFileAtPath:filePath
|
||||
contents:data
|
||||
attributes:nil];
|
||||
}
|
||||
|
||||
- (NSURL *)getICloudFileUrl:(NSString *)name {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
return [NSURL fileURLWithPath:[LinphoneManager documentFile:name]];
|
||||
|
|
@ -1320,118 +1397,30 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
|||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||
}
|
||||
|
||||
+ (NSString *)getKeyFromFileType:(NSString *)fileType fileName:(NSString *)name{
|
||||
if ([fileType isEqualToString:@"video"]) {
|
||||
return @"localvideo";
|
||||
} else if ([fileType isEqualToString:@"image"] || [name hasSuffix:@"JPG"] || [name hasSuffix:@"PNG"] || [name hasSuffix:@"jpg"] || [name hasSuffix:@"png"]) {
|
||||
return @"localimage";
|
||||
}
|
||||
return @"localfile";
|
||||
}
|
||||
|
||||
/* There are three cases: auto download in foreground, auto download in background, on click download*/
|
||||
+ (void)autoDownload:(LinphoneChatMessage *)message {
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
//TODO: migrate with "linphone_iphone_file_transfer_recv"
|
||||
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(message);
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
// get download path
|
||||
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if ([fileManager fileExistsAtPath:filePath]) {
|
||||
NSData* data = [NSData dataWithContentsOfFile:filePath];
|
||||
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
|
||||
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(message);
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
|
||||
NSString *key = [ChatConversationView getKeyFromFileType:fileType fileName:name];
|
||||
|
||||
// define a block , not called immediately. To avoid crash when saving photo before PHAuthorizationStatusNotDetermined.
|
||||
void (^block)(void)= ^ {
|
||||
if ([fileType isEqualToString:@"image"]) {
|
||||
// we're finished, save the image and update the message
|
||||
UIImage *image = [UIImage imageWithData:data];
|
||||
if (!image) {
|
||||
[view showFileDownloadError];
|
||||
return;
|
||||
}
|
||||
__block NSString *createdAssetId = nil;
|
||||
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
|
||||
createdAssetId = [PHAssetCreationRequest creationRequestForAssetFromImage:image].placeholderForCreatedAsset.localIdentifier;
|
||||
} error:nil];
|
||||
if (createdAssetId != nil) {
|
||||
LOGI(@"Image saved to [%@]", createdAssetId);
|
||||
[LinphoneManager setValueInMessageAppData:createdAssetId
|
||||
forKey:@"localimage"
|
||||
inMessage:message];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];
|
||||
});
|
||||
} else {
|
||||
LOGE(@"Cannot save image data downloaded");
|
||||
[LinphoneManager setValueInMessageAppData:nil forKey:@"localimage" inMessage:message];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write image to photo library",
|
||||
nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {}];
|
||||
|
||||
[errView addAction:defaultAction];
|
||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
} else if ([fileType isEqualToString:@"video"]) {
|
||||
// until image is properly saved, keep a reminder on it so that the
|
||||
// chat bubble is aware of the fact that image is being saved to device
|
||||
__block NSString *createdAssetId = nil;
|
||||
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
|
||||
createdAssetId = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]].placeholderForCreatedAsset.localIdentifier;
|
||||
} error:nil];
|
||||
if (createdAssetId != nil) {
|
||||
LOGI(@"video saved to [%@]", createdAssetId);
|
||||
[LinphoneManager setValueInMessageAppData:createdAssetId
|
||||
forKey:@"localvideo"
|
||||
inMessage:message];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];
|
||||
});
|
||||
} else {
|
||||
LOGE(@"Cannot save video data downloaded");
|
||||
[LinphoneManager setValueInMessageAppData:nil forKey:@"localvideo" inMessage:message];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write video to photo library",
|
||||
nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {}];
|
||||
|
||||
[errView addAction:defaultAction];
|
||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// When you save an image or video to a photo library, make sure that it is allowed. Otherwise, there will be a backup error.
|
||||
if ([fileType isEqualToString:@"image"] || [fileType isEqualToString:@"video"]) {
|
||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||
block();
|
||||
} else {
|
||||
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||
block();
|
||||
} else {
|
||||
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Photo's permission", nil) message:NSLocalizedString(@"Photo not authorized", nil) delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil] show];
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
NSString *key = @"localfile";
|
||||
//write file to path
|
||||
if([view writeFileInICloud:data fileURL:[view getICloudFileUrl:name]]) {
|
||||
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:message];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];});
|
||||
} else {
|
||||
LOGE(@"[Auto download error] can not save the file %@", name);
|
||||
}
|
||||
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:message];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];
|
||||
if ([ConfigManager.instance lpConfigBoolForKeyWithKey:@"auto_write_to_gallery_preference"]) {
|
||||
[ChatConversationView writeMediaToGallery:name fileType:fileType];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
-(void) documentMenu:(UIDocumentMenuViewController *)documentMenu didPickDocumentPicker:(UIDocumentPickerViewController *)documentPicker {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,12 @@
|
|||
if (PhoneMainView.instance.currentView == ChatConversationView.compositeViewDescription) {
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
[view removeCallBacks];
|
||||
} else if (PhoneMainView.instance.currentView == ChatConversationInfoView.compositeViewDescription) {
|
||||
ChatConversationInfoView *view = VIEW(ChatConversationInfoView);
|
||||
[view removeCallbacks];
|
||||
} else if (PhoneMainView.instance.currentView == RecordingsListView.compositeViewDescription || PhoneMainView.instance.currentView == DevicesListView.compositeViewDescription) {
|
||||
// To avoid crash
|
||||
[PhoneMainView.instance changeCurrentView:DialerView.compositeViewDescription];
|
||||
}
|
||||
[CoreManager.instance stopLinphoneCore];
|
||||
}
|
||||
|
|
@ -649,21 +655,15 @@
|
|||
LOGI(@"User declined video proposal");
|
||||
if (call != linphone_core_get_current_call(LC))
|
||||
return;
|
||||
|
||||
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
|
||||
linphone_call_accept_update(call, params);
|
||||
linphone_call_params_destroy(params);
|
||||
[CallManager.instance acceptVideoWithCall:call confirm:FALSE];
|
||||
} else if ([response.actionIdentifier isEqual:@"Accept"]) {
|
||||
LOGI(@"User accept video proposal");
|
||||
if (call != linphone_core_get_current_call(LC))
|
||||
return;
|
||||
|
||||
[[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications];
|
||||
[PhoneMainView.instance changeCurrentView:CallView.compositeViewDescription];
|
||||
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
|
||||
linphone_call_params_enable_video(params, TRUE);
|
||||
linphone_call_accept_update(call, params);
|
||||
linphone_call_params_destroy(params);
|
||||
[PhoneMainView.instance changeCurrentView:CallView.compositeViewDescription];
|
||||
[CallManager.instance acceptVideoWithCall:call confirm:TRUE];
|
||||
} else if ([response.actionIdentifier isEqual:@"Confirm"]) {
|
||||
if (linphone_core_get_current_call(LC) == call)
|
||||
linphone_call_set_authentication_token_verified(call, YES);
|
||||
|
|
@ -694,6 +694,7 @@
|
|||
[PhoneMainView.instance changeCurrentView:ChatsListView.compositeViewDescription];
|
||||
}
|
||||
} else if ([response.notification.request.content.categoryIdentifier isEqual:@"video_request"]) {
|
||||
if (!call) return;
|
||||
[PhoneMainView.instance changeCurrentView:CallView.compositeViewDescription];
|
||||
NSTimer *videoDismissTimer = nil;
|
||||
UIConfirmationDialog *sheet = [UIConfirmationDialog ShowWithMessage:response.notification.request.content.body
|
||||
|
|
@ -703,21 +704,14 @@
|
|||
LOGI(@"User declined video proposal");
|
||||
if (call != linphone_core_get_current_call(LC))
|
||||
return;
|
||||
|
||||
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
|
||||
linphone_call_accept_update(call, params);
|
||||
linphone_call_params_destroy(params);
|
||||
[CallManager.instance acceptVideoWithCall:call confirm:FALSE];
|
||||
[videoDismissTimer invalidate];
|
||||
}
|
||||
onConfirmationClick:^() {
|
||||
LOGI(@"User accept video proposal");
|
||||
if (call != linphone_core_get_current_call(LC))
|
||||
return;
|
||||
|
||||
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
|
||||
linphone_call_params_enable_video(params, TRUE);
|
||||
linphone_call_accept_update(call, params);
|
||||
linphone_call_params_destroy(params);
|
||||
[CallManager.instance acceptVideoWithCall:call confirm:TRUE];
|
||||
[videoDismissTimer invalidate];
|
||||
}
|
||||
inController:PhoneMainView.instance];
|
||||
|
|
|
|||
|
|
@ -338,7 +338,8 @@
|
|||
[self setCString:linphone_core_get_file_transfer_server(LC) forKey:@"file_transfer_server_url_preference"];
|
||||
int maxSize = linphone_core_get_max_size_for_auto_download_incoming_files(LC);
|
||||
[self setObject:maxSize==0 ? @"Always" : (maxSize==-1 ? @"Nerver" : @"Customize") forKey:@"auto_download_mode"];
|
||||
[self setInteger:maxSize forKey:@"auto_download_incoming_files_max_size"];
|
||||
[self setInteger:maxSize forKey:@"auto_download_incoming_files_max_size"];
|
||||
[self setBool:[lm lpConfigBoolForKey:@"auto_write_to_gallery_preference" withDefault:YES] forKey:@"auto_write_to_gallery_mode"];
|
||||
}
|
||||
|
||||
// network section
|
||||
|
|
@ -547,11 +548,10 @@
|
|||
linphone_address_set_domain(linphoneAddress, [domain UTF8String]);
|
||||
linphone_address_set_display_name(linphoneAddress, (displayName.length ? displayName.UTF8String : NULL));
|
||||
const char *identity = linphone_address_as_string(linphoneAddress);
|
||||
linphone_address_destroy(linphoneAddress);
|
||||
const char *password = [accountPassword UTF8String];
|
||||
const char *ha1 = [accountHa1 UTF8String];
|
||||
|
||||
if (linphone_proxy_config_set_identity(proxyCfg, identity) == -1) {
|
||||
if (linphone_proxy_config_set_identity_address(proxyCfg, linphoneAddress) == -1) {
|
||||
error = NSLocalizedString(@"Invalid username or domain", nil);
|
||||
goto bad_proxy;
|
||||
}
|
||||
|
|
@ -586,7 +586,7 @@
|
|||
[LinphoneManager.instance configurePushTokenForProxyConfig:proxyCfg];
|
||||
|
||||
linphone_proxy_config_enable_register(proxyCfg, is_enabled);
|
||||
linphone_proxy_config_enable_avpf(proxyCfg, use_avpf);
|
||||
linphone_proxy_config_set_avpf_mode(proxyCfg, use_avpf);
|
||||
linphone_proxy_config_set_expires(proxyCfg, expire);
|
||||
if (is_default) {
|
||||
linphone_core_set_default_proxy_config(LC, proxyCfg);
|
||||
|
|
@ -636,7 +636,9 @@
|
|||
bad_proxy:
|
||||
if (proxy)
|
||||
ms_free(proxy);
|
||||
|
||||
if (linphoneAddress)
|
||||
linphone_address_destroy(linphoneAddress);
|
||||
|
||||
// in case of error, show an alert to the user
|
||||
if (error != nil) {
|
||||
linphone_proxy_config_done(proxyCfg);
|
||||
|
|
@ -778,6 +780,7 @@
|
|||
}
|
||||
linphone_core_set_max_size_for_auto_download_incoming_files(LC, maxSize);
|
||||
[lm lpConfigSetString:[self stringForKey:@"auto_download_mode"] forKey:@"auto_download_mode"];
|
||||
[lm lpConfigSetBool:[self boolForKey:@"auto_write_to_gallery_mode"] forKey:@"auto_write_to_gallery_preference"];
|
||||
|
||||
// network section
|
||||
BOOL edgeOpt = [self boolForKey:@"edge_opt_preference"];
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ static int check_should_migrate_images(void *data, int argc, char **argv, char *
|
|||
withDefault:@"sip.linphone.org"]
|
||||
.UTF8String) != 0) {
|
||||
LOGI(@"Migrating proxy config to use AVPF");
|
||||
linphone_proxy_config_enable_avpf(proxy, TRUE);
|
||||
linphone_proxy_config_set_avpf_mode(proxy, LinphoneAVPFEnabled);
|
||||
}
|
||||
proxies = proxies->next;
|
||||
}
|
||||
|
|
@ -511,7 +511,7 @@ static void migrateWizardToAssistant(const char *entry, void *user_data) {
|
|||
+ (void)dumpLcConfig {
|
||||
if (theLinphoneCore) {
|
||||
LpConfig *conf = LinphoneManager.instance.configDb;
|
||||
char *config = lp_config_dump(conf);
|
||||
char *config = linphone_config_dump(conf);
|
||||
LOGI(@"\n%s", config);
|
||||
ms_free(config);
|
||||
}
|
||||
|
|
@ -720,8 +720,8 @@ static void linphone_iphone_popup_password_request(LinphoneCore *lc, LinphoneAut
|
|||
// let the wizard handle its own errors
|
||||
if ([PhoneMainView.instance currentView] != AssistantView.compositeViewDescription) {
|
||||
const char * realmC = linphone_auth_info_get_realm(auth_info);
|
||||
const char * usernameC = linphone_auth_info_get_username(auth_info);
|
||||
const char * domainC = linphone_auth_info_get_domain(auth_info);
|
||||
const char * usernameC = linphone_auth_info_get_username(auth_info) ? : "";
|
||||
const char * domainC = linphone_auth_info_get_domain(auth_info) ? : "";
|
||||
static UIAlertController *alertView = nil;
|
||||
|
||||
// avoid having multiple popups
|
||||
|
|
@ -1365,6 +1365,8 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
|
|||
|
||||
if (theLinphoneCore != nil) { // just in case application terminate before linphone core initialization
|
||||
|
||||
// rare case, remove duplicated fileTransferDelegates to avoid crash
|
||||
[_fileTransferDelegates setArray:[[NSSet setWithArray:_fileTransferDelegates] allObjects]];
|
||||
for (FileTransferDelegate *ftd in _fileTransferDelegates) {
|
||||
[ftd stopAndDestroy];
|
||||
}
|
||||
|
|
@ -1682,7 +1684,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
|
|||
factory = factoryIpad;
|
||||
}
|
||||
_configDb = linphone_config_new_for_shared_core(kLinphoneMsgNotificationAppGroupId.UTF8String, @"linphonerc".UTF8String, factory.UTF8String);
|
||||
lp_config_clean_entry(_configDb, "misc", "max_calls");
|
||||
linphone_config_clean_entry(_configDb, "misc", "max_calls");
|
||||
}
|
||||
#pragma mark - Audio route Functions
|
||||
|
||||
|
|
@ -2015,7 +2017,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
|
|||
|
||||
- (void)configureVbrCodecs {
|
||||
PayloadType *pt;
|
||||
int bitrate = lp_config_get_int(
|
||||
int bitrate = linphone_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);
|
||||
|
|
@ -2070,7 +2072,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
|
|||
- (void)lpConfigSetString:(NSString *)value forKey:(NSString *)key inSection:(NSString *)section {
|
||||
if (!key)
|
||||
return;
|
||||
lp_config_set_string(_configDb, [section UTF8String], [key UTF8String], value ? [value UTF8String] : NULL);
|
||||
linphone_config_set_string(_configDb, [section UTF8String], [key UTF8String], value ? [value UTF8String] : NULL);
|
||||
}
|
||||
- (NSString *)lpConfigStringForKey:(NSString *)key {
|
||||
return [self lpConfigStringForKey:key withDefault:nil];
|
||||
|
|
@ -2084,7 +2086,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
|
|||
- (NSString *)lpConfigStringForKey:(NSString *)key inSection:(NSString *)section withDefault:(NSString *)defaultValue {
|
||||
if (!key)
|
||||
return defaultValue;
|
||||
const char *value = lp_config_get_string(_configDb, [section UTF8String], [key UTF8String], NULL);
|
||||
const char *value = linphone_config_get_string(_configDb, [section UTF8String], [key UTF8String], NULL);
|
||||
return value ? [NSString stringWithUTF8String:value] : defaultValue;
|
||||
}
|
||||
|
||||
|
|
@ -2094,7 +2096,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
|
|||
- (void)lpConfigSetInt:(int)value forKey:(NSString *)key inSection:(NSString *)section {
|
||||
if (!key)
|
||||
return;
|
||||
lp_config_set_int(_configDb, [section UTF8String], [key UTF8String], (int)value);
|
||||
linphone_config_set_int(_configDb, [section UTF8String], [key UTF8String], (int)value);
|
||||
}
|
||||
- (int)lpConfigIntForKey:(NSString *)key {
|
||||
return [self lpConfigIntForKey:key withDefault:-1];
|
||||
|
|
@ -2108,7 +2110,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
|
|||
- (int)lpConfigIntForKey:(NSString *)key inSection:(NSString *)section withDefault:(int)defaultValue {
|
||||
if (!key)
|
||||
return defaultValue;
|
||||
return lp_config_get_int(_configDb, [section UTF8String], [key UTF8String], (int)defaultValue);
|
||||
return linphone_config_get_int(_configDb, [section UTF8String], [key UTF8String], (int)defaultValue);
|
||||
}
|
||||
|
||||
- (void)lpConfigSetBool:(BOOL)value forKey:(NSString *)key {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
|
@ -30,6 +28,7 @@
|
|||
<outlet property="messageImageView" destination="yMW-cT-bpU" id="MNr-F2-abQ"/>
|
||||
<outlet property="messageText" destination="cx9-0K-P9L" id="kPh-s4-Ioy"/>
|
||||
<outlet property="playButton" destination="cvc-tl-Pcf" id="eKJ-2T-LUl"/>
|
||||
<outlet property="plusLongGestureRecognizer" destination="daf-cW-dRj" id="O5u-t0-uMe"/>
|
||||
<outlet property="resendRecognizer" destination="5ZI-Ip-lGl" id="G2r-On-6mV"/>
|
||||
<outlet property="totalView" destination="8I3-n2-0kS" id="aa8-j9-saW"/>
|
||||
</connections>
|
||||
|
|
@ -85,6 +84,29 @@
|
|||
</imageView>
|
||||
</subviews>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UzU-cc-LbF" userLabel="fileView">
|
||||
<rect key="frame" x="13" y="10" width="230" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WkE-rP-Y0R" userLabel="fileName">
|
||||
<rect key="frame" x="0.0" y="0.0" width="180" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="backgroundColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IGl-nl-xIE" userLabel="fileButton">
|
||||
<rect key="frame" x="180" y="0.0" width="50" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="1" green="0.39905477280000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<state key="normal" title="Open"/>
|
||||
<connections>
|
||||
<action selector="onFileClick:" destination="-1" eventType="touchUpInside" id="JRN-AA-UEJ"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GmN-7v-uuO" userLabel="imageSubView">
|
||||
<rect key="frame" x="31" y="50" width="299" height="87"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
|
|
@ -93,7 +115,7 @@
|
|||
<rect key="frame" x="10" y="51" width="277" height="4"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
</progressView>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="N75-gL-R6t" userLabel="downloadButton" customClass="UIRoundBorderedButton">
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="N75-gL-R6t" userLabel="downloadButton" customClass="UIRoundBorderedButton">
|
||||
<rect key="frame" x="87" y="58" width="113" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Download"/>
|
||||
|
|
@ -105,7 +127,7 @@
|
|||
<action selector="onDownloadClick:" destination="-1" eventType="touchUpInside" id="8BO-9E-iOX"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6dl-Nz-rdv" userLabel="cancelButton" customClass="UIRoundBorderedButton">
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6dl-Nz-rdv" userLabel="cancelButton" customClass="UIRoundBorderedButton">
|
||||
<rect key="frame" x="87" y="58" width="113" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Cancel"/>
|
||||
|
|
@ -120,8 +142,8 @@
|
|||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cvc-tl-Pcf" userLabel="playButton" customClass="UIRoundBorderedButton">
|
||||
<rect key="frame" x="158" y="106" width="50" height="25"/>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cvc-tl-Pcf" userLabel="playButton" customClass="UIRoundBorderedButton">
|
||||
<rect key="frame" x="157" y="106" width="50" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Cancel"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
|
|
@ -145,33 +167,11 @@
|
|||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Delivery failed"/>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UzU-cc-LbF" userLabel="fileView">
|
||||
<rect key="frame" x="13" y="10" width="230" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WkE-rP-Y0R" userLabel="fileName">
|
||||
<rect key="frame" x="0.0" y="0.0" width="180" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="backgroundColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IGl-nl-xIE" userLabel="fileButton">
|
||||
<rect key="frame" x="180" y="0.0" width="50" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="1" green="0.39905477280000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<state key="normal" title="Open"/>
|
||||
<connections>
|
||||
<action selector="onFileClick:" destination="-1" eventType="touchUpInside" id="JRN-AA-UEJ"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
</subviews>
|
||||
<connections>
|
||||
<outletCollection property="gestureRecognizers" destination="5ZI-Ip-lGl" appends="YES" id="1iY-46-rRR"/>
|
||||
<outletCollection property="gestureRecognizers" destination="aDF-hC-ddO" appends="YES" id="FIv-pl-I8J"/>
|
||||
<outletCollection property="gestureRecognizers" destination="daf-cW-dRj" appends="YES" id="qgk-YT-Grl"/>
|
||||
</connections>
|
||||
</view>
|
||||
</subviews>
|
||||
|
|
@ -189,14 +189,19 @@
|
|||
<action selector="onImageClick:" destination="-1" id="feN-LT-89b"/>
|
||||
</connections>
|
||||
</tapGestureRecognizer>
|
||||
<pongPressGestureRecognizer allowableMovement="10" minimumPressDuration="0.5" id="daf-cW-dRj" userLabel="plusClick">
|
||||
<connections>
|
||||
<action selector="onPlusClick:" destination="-1" id="oFW-FN-6xV"/>
|
||||
</connections>
|
||||
</pongPressGestureRecognizer>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="avatar.png" width="259" height="259"/>
|
||||
<image name="chat_read.png" width="25" height="25"/>
|
||||
<image name="avatar.png" width="414.39999389648438" height="414.39999389648438"/>
|
||||
<image name="chat_read.png" width="20" height="20"/>
|
||||
<image name="color_A.png" width="2" height="2"/>
|
||||
<image name="color_G.png" width="2" height="2"/>
|
||||
<image name="color_I.png" width="2" height="2"/>
|
||||
<image name="color_M.png" width="2" height="2"/>
|
||||
<image name="linphone_logo.png" width="26" height="26"/>
|
||||
<image name="linphone_logo.png" width="41.599998474121094" height="42.400001525878906"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
|
||||
// Update to default state
|
||||
LinphoneProxyConfig *config = linphone_core_get_default_proxy_config(LC);
|
||||
messagesUnreadCount = lp_config_get_int(linphone_core_get_config(LC), "app", "voice_mail_messages_count", 0);
|
||||
messagesUnreadCount = linphone_config_get_int(linphone_core_get_config(LC), "app", "voice_mail_messages_count", 0);
|
||||
|
||||
[self proxyConfigUpdate:config];
|
||||
[self updateUI:linphone_core_get_calls_nb(LC)];
|
||||
|
|
@ -149,7 +149,7 @@
|
|||
LOGI(@"Received new NOTIFY from voice mail: there is/are now %d message(s) unread", messagesUnreadCount);
|
||||
|
||||
// save in lpconfig for future
|
||||
lp_config_set_int(linphone_core_get_config(LC), "app", "voice_mail_messages_count", messagesUnreadCount);
|
||||
linphone_config_set_int(linphone_core_get_config(LC), "app", "voice_mail_messages_count", messagesUnreadCount);
|
||||
|
||||
[self updateVoicemail];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
@property(strong, nonatomic) IBOutlet UITapGestureRecognizer *imageGestureRecognizer;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *fileButton;
|
||||
@property (weak, nonatomic) IBOutlet UIView *fileView;
|
||||
@property (strong, nonatomic) IBOutlet UILongPressGestureRecognizer *plusLongGestureRecognizer;
|
||||
|
||||
- (void)setEvent:(LinphoneEventLog *)event;
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)message;
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
- (IBAction)onResendClick:(id)event;
|
||||
- (IBAction)onPlayClick:(id)sender;
|
||||
- (IBAction)onFileClick:(id)sender;
|
||||
- (IBAction)onPlusClick:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
chatTableView = VIEW(ChatConversationView).tableController;
|
||||
videoDefaultSize = CGSizeMake(320, 240);
|
||||
assetIsLoaded = FALSE;
|
||||
self.contentView.userInteractionEnabled = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
|
@ -71,31 +72,26 @@
|
|||
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)amessage {
|
||||
_imageGestureRecognizer.enabled = NO;
|
||||
_plusLongGestureRecognizer.enabled = NO;
|
||||
_messageImageView.image = nil;
|
||||
_finalImage.image = nil;
|
||||
_finalImage.hidden = TRUE;
|
||||
_fileTransferProgress.progress = 0;
|
||||
assetIsLoaded = FALSE;
|
||||
[self disconnectFromFileDelegate];
|
||||
|
||||
/* As the cell UI will be reset, fileTransDelegate need to be reconnected. Otherwise, the UIProgressView will not work */
|
||||
[self disconnectFromFileDelegate];
|
||||
if (amessage) {
|
||||
const LinphoneContent *c = linphone_chat_message_get_file_transfer_information(amessage);
|
||||
if (c) {
|
||||
const char *name = linphone_content_get_name(c);
|
||||
for (FileTransferDelegate *aftd in [LinphoneManager.instance fileTransferDelegates]) {
|
||||
if (linphone_chat_message_get_file_transfer_information(aftd.message) &&
|
||||
(linphone_chat_message_is_outgoing(aftd.message) == linphone_chat_message_is_outgoing(amessage)) &&
|
||||
strcmp(name, linphone_content_get_name(
|
||||
linphone_chat_message_get_file_transfer_information(aftd.message))) == 0) {
|
||||
LOGI(@"Chat message [%p] with file transfer delegate [%p], connecting to it!", amessage, aftd);
|
||||
[self connectToFileDelegate:aftd];
|
||||
break;
|
||||
}
|
||||
for (FileTransferDelegate *aftd in [LinphoneManager.instance fileTransferDelegates]) {
|
||||
if (aftd.message == amessage && linphone_chat_message_get_state(amessage) == LinphoneChatMessageStateFileTransferInProgress) {
|
||||
LOGI(@"Chat message [%p] with file transfer delegate [%p], connecting to it!", amessage, aftd);
|
||||
[self connectToFileDelegate:aftd];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[super setChatMessage:amessage];
|
||||
[super setChatMessageForCbs:amessage];
|
||||
}
|
||||
|
||||
- (void) loadImageAsset:(PHAsset*) asset image:(UIImage *)image {
|
||||
|
|
@ -106,6 +102,7 @@
|
|||
_messageImageView.hidden = YES;
|
||||
_finalImage.hidden = NO;
|
||||
_fileView.hidden = YES;
|
||||
_plusLongGestureRecognizer.enabled = YES;
|
||||
[self layoutSubviews];
|
||||
});
|
||||
}
|
||||
|
|
@ -128,10 +125,13 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
}];
|
||||
}
|
||||
|
||||
- (void) loadFileAsset {
|
||||
- (void) loadFileAsset:(NSString *)name {
|
||||
NSString *text = [NSString stringWithFormat:@"📎 %@",name];
|
||||
_fileName.text = text;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
_fileName.hidden = _fileView.hidden = _fileButton.hidden = NO;
|
||||
_imageGestureRecognizer.enabled = NO;
|
||||
_plusLongGestureRecognizer.enabled = NO;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -143,6 +143,7 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
[_messageImageView stopLoading];
|
||||
_messageImageView.hidden = YES;
|
||||
_imageGestureRecognizer.enabled = YES;
|
||||
_plusLongGestureRecognizer.enabled = YES;
|
||||
_finalImage.hidden = NO;
|
||||
[self layoutSubviews];
|
||||
});
|
||||
|
|
@ -153,195 +154,194 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
LOGW(@"Cannot update message room cell: NULL message");
|
||||
return;
|
||||
}
|
||||
[super update];
|
||||
[super update];
|
||||
const char *url = linphone_chat_message_get_external_body_url(self.message);
|
||||
BOOL is_external =
|
||||
(url && (strstr(url, "http") == url)) || linphone_chat_message_get_file_transfer_information(self.message);
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:self.message];
|
||||
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:self.message];
|
||||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
|
||||
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:self.message];
|
||||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
|
||||
assert(is_external || localImage || localVideo || localFile);
|
||||
|
||||
|
||||
if (!(localImage || localVideo || localFile)) {
|
||||
// If the file has been downloaded in background, save it in the folders and display it.
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
//TODO: migrate with "linphone_iphone_file_transfer_recv"
|
||||
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(self.message);
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
// get download path
|
||||
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if ([fileManager fileExistsAtPath:filePath]) {
|
||||
NSData* data = [NSData dataWithContentsOfFile:filePath];
|
||||
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
|
||||
|
||||
// define a block , not called immediately. To avoid crash when saving photo before PHAuthorizationStatusNotDetermined.
|
||||
void (^block)(void)= ^ {
|
||||
if ([fileType isEqualToString:@"image"]) {
|
||||
// we're finished, save the image and update the message
|
||||
UIImage *image = [UIImage imageWithData:data];
|
||||
if (!image) {
|
||||
[view showFileDownloadError];
|
||||
return;
|
||||
}
|
||||
__block PHObjectPlaceholder *placeHolder;
|
||||
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
||||
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
|
||||
placeHolder = [request placeholderForCreatedAsset];
|
||||
} completionHandler:^(BOOL success, NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (error) {
|
||||
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
|
||||
[LinphoneManager setValueInMessageAppData:nil forKey:@"localimage" inMessage:self.message];
|
||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write image to photo library",
|
||||
nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {}];
|
||||
|
||||
[errView addAction:defaultAction];
|
||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||
} else {
|
||||
LOGI(@"Image saved to [%@]", [placeHolder localIdentifier]);
|
||||
[LinphoneManager setValueInMessageAppData:[placeHolder localIdentifier]
|
||||
forKey:@"localimage"
|
||||
inMessage:self.message];
|
||||
[self updateButtons:[LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:self.message] localVideo:localVideo localFile:localFile];
|
||||
}
|
||||
});
|
||||
}];
|
||||
} else if([fileType isEqualToString:@"video"]) {
|
||||
// until image is properly saved, keep a reminder on it so that the
|
||||
// chat bubble is aware of the fact that image is being saved to device
|
||||
|
||||
__block PHObjectPlaceholder *placeHolder;
|
||||
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
||||
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]];
|
||||
placeHolder = [request placeholderForCreatedAsset];
|
||||
} completionHandler:^(BOOL success, NSError * _Nullable error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (error) {
|
||||
LOGE(@"Cannot save video data downloaded [%@]", [error localizedDescription]);
|
||||
[LinphoneManager setValueInMessageAppData:nil forKey:@"localvideo" inMessage:self.message];
|
||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write video to photo library",
|
||||
nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {}];
|
||||
|
||||
[errView addAction:defaultAction];
|
||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||
} else {
|
||||
LOGI(@"video saved to [%@]", [placeHolder localIdentifier]);
|
||||
[LinphoneManager setValueInMessageAppData:[placeHolder localIdentifier]
|
||||
forKey:@"localvideo"
|
||||
inMessage:self.message];
|
||||
[self updateButtons:localImage localVideo:[LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:self.message] localFile:localFile];
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
};
|
||||
|
||||
// When you save an image or video to a photo library, make sure that it is allowed. Otherwise, there will be a backup error.
|
||||
if ([fileType isEqualToString:@"image"] || [fileType isEqualToString:@"video"]) {
|
||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||
block();
|
||||
} else {
|
||||
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||
block();
|
||||
} else {
|
||||
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Photo's permission", nil) message:NSLocalizedString(@"Photo not authorized", nil) delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil] show];
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
LinphoneContent *fileContent = linphone_chat_message_get_file_transfer_information(self.message);
|
||||
if (fileContent == nil) {
|
||||
LOGW(@"file content is null");
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL is_outgoing = linphone_chat_message_is_outgoing(self.message);
|
||||
if (!is_outgoing) {
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(self.message);
|
||||
if (state != LinphoneChatMessageStateFileTransferDone && state != LinphoneChatMessageStateDisplayed) {
|
||||
if (state == LinphoneChatMessageStateFileTransferInProgress) {
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = NO;
|
||||
_downloadButton.hidden = YES;
|
||||
_playButton.hidden = YES;
|
||||
_fileName.hidden = _fileView.hidden = _fileButton.hidden =YES;
|
||||
} else {
|
||||
NSString *key = @"localfile";
|
||||
//write file to path
|
||||
if([view writeFileInICloud:data fileURL:[view getICloudFileUrl:name]]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:self.message];
|
||||
[self updateButtons:localImage localVideo:localVideo localFile:[LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message]];
|
||||
});
|
||||
} else {
|
||||
LOGE(@"[Auto download error] can not save the file %@", name);
|
||||
}
|
||||
_downloadButton.hidden = NO;
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = YES;
|
||||
_playButton.hidden = YES;
|
||||
_fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(fileContent)];
|
||||
NSString *fileName = [NSString stringWithUTF8String:linphone_content_get_name(fileContent)];
|
||||
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:fileName];
|
||||
|
||||
[self updateButtons:localImage localVideo:localVideo localFile:localFile];
|
||||
}
|
||||
|
||||
- (void)updateButtons: (NSString *)localImage localVideo:(NSString *)localVideo localFile:(NSString *)localFile {
|
||||
LinphoneContent *fileContent = linphone_chat_message_get_file_transfer_information(self.message);
|
||||
NSString *type = fileContent ? [NSString stringWithUTF8String:linphone_content_get_type(fileContent)] : nil;
|
||||
if (!(localImage || localVideo || localFile)) {
|
||||
_playButton.hidden = YES;
|
||||
_fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
|
||||
_messageImageView.hidden = _cancelButton.hidden = (_ftd.message == nil);
|
||||
_downloadButton.hidden = !_cancelButton.hidden;
|
||||
_fileTransferProgress.hidden = NO;
|
||||
} else {
|
||||
// file is being saved on device - just wait for it
|
||||
if ([localImage isEqualToString:@"saving..."] || [localVideo isEqualToString:@"saving..."] || [localFile isEqualToString:@"saving..."]) {
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = _playButton.hidden = _fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
|
||||
} else {
|
||||
if(!assetIsLoaded) {
|
||||
assetIsLoaded = TRUE;
|
||||
if (localImage) {
|
||||
// we did not load the image yet, so start doing so
|
||||
if (_messageImageView.image == nil) {
|
||||
[self loadFirstImage:localImage type:PHAssetMediaTypeImage];
|
||||
_imageGestureRecognizer.enabled = YES;
|
||||
}
|
||||
}
|
||||
else if (localVideo) {
|
||||
if (_messageImageView.image == nil) {
|
||||
[self loadFirstImage:localVideo type:PHAssetMediaTypeVideo];
|
||||
_imageGestureRecognizer.enabled = NO;
|
||||
}
|
||||
}
|
||||
else if (localFile) {
|
||||
if ([type isEqualToString:@"video"]) {
|
||||
UIImage* image = [UIChatBubbleTextCell getImageFromVideoUrl:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
[self loadImageAsset:nil image:image];
|
||||
_imageGestureRecognizer.enabled = NO;
|
||||
} else if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
|
||||
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
||||
// already downloaded
|
||||
if (!assetIsLoaded) {
|
||||
assetIsLoaded = TRUE;
|
||||
NSString *key = [ChatConversationView getKeyFromFileType:fileType fileName:fileName];
|
||||
if ([key isEqualToString:@"localimage"]) {
|
||||
// we did not load the image yet, so start doing so
|
||||
if (_messageImageView.image == nil) {
|
||||
NSData* data = [NSData dataWithContentsOfFile:filePath];
|
||||
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||
if (image) {
|
||||
[self loadImageAsset:nil image:image];
|
||||
_imageGestureRecognizer.enabled = YES;
|
||||
} else {
|
||||
NSString *text = [NSString stringWithFormat:@"📎 %@",localFile];
|
||||
_fileName.text = text;
|
||||
[self loadFileAsset];
|
||||
// compability with other platforms
|
||||
[self loadFileAsset:fileName];
|
||||
}
|
||||
}
|
||||
} else if ([key isEqualToString:@"localvideo"]) {
|
||||
if (_messageImageView.image == nil) {
|
||||
UIImage* image = [UIChatBubbleTextCell getImageFromVideoUrl:[ChatConversationView getCacheFileUrl:fileName]];
|
||||
if (image) {
|
||||
[self loadImageAsset:nil image:image];
|
||||
_imageGestureRecognizer.enabled = NO;
|
||||
} else {
|
||||
// compability with other platforms
|
||||
[self loadFileAsset:fileName];
|
||||
}
|
||||
}
|
||||
} else if ([key isEqualToString:@"localfile"]) {
|
||||
if ([fileType isEqualToString:@"video"]) {
|
||||
UIImage* image = [UIChatBubbleTextCell getImageFromVideoUrl:[ChatConversationView getCacheFileUrl:fileName]];
|
||||
[self loadImageAsset:nil image:image];
|
||||
_imageGestureRecognizer.enabled = NO;
|
||||
} else if ([fileName hasSuffix:@"JPG"] || [fileName hasSuffix:@"PNG"] || [fileName hasSuffix:@"jpg"] || [fileName hasSuffix:@"png"]) {
|
||||
NSData *data = [ChatConversationView getCacheFileData:fileName];
|
||||
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||
[self loadImageAsset:nil image:image];
|
||||
_imageGestureRecognizer.enabled = YES;
|
||||
} else {
|
||||
[self loadFileAsset:fileName];
|
||||
}
|
||||
}
|
||||
|
||||
if (!(localImage || localVideo || localFile)) {
|
||||
// If the file has been downloaded in background, save it in the folders and display it.
|
||||
[LinphoneManager setValueInMessageAppData:fileName forKey:key inMessage:self.message];
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
if ([ConfigManager.instance lpConfigBoolForKeyWithKey:@"auto_write_to_gallery_preference"]) {
|
||||
[ChatConversationView writeMediaToGallery:fileName fileType:fileType];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
[self uploadingImage:fileType localFile:localFile];
|
||||
} else {
|
||||
// support previous methode:
|
||||
if (!(localImage || localVideo || localFile)) {
|
||||
_playButton.hidden = YES;
|
||||
_fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
|
||||
_messageImageView.hidden = _cancelButton.hidden = (_ftd.message == nil);
|
||||
_downloadButton.hidden = !_cancelButton.hidden;
|
||||
_fileTransferProgress.hidden = NO;
|
||||
} else {
|
||||
// file is being saved on device - just wait for it
|
||||
if ([localImage isEqualToString:@"saving..."] || [localVideo isEqualToString:@"saving..."] || [localFile isEqualToString:@"saving..."]) {
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = _playButton.hidden = _fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
|
||||
} else {
|
||||
if(!assetIsLoaded) {
|
||||
assetIsLoaded = TRUE;
|
||||
if (localImage) {
|
||||
// we did not load the image yet, so start doing so
|
||||
if (_messageImageView.image == nil) {
|
||||
[self loadFirstImage:localImage type:PHAssetMediaTypeImage];
|
||||
_imageGestureRecognizer.enabled = YES;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
UIImage *image = [chatTableView.imagesInChatroom objectForKey:localImage];
|
||||
NSString *name = [NSString stringWithFormat:@"%li-%f.jpg", (long)image.hash, [NSDate timeIntervalSinceReferenceDate]];
|
||||
NSData *data = UIImageJPEGRepresentation(image, 1);
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
[LinphoneManager setValueInMessageAppData:name forKey:@"localimage" inMessage:self.message];
|
||||
});
|
||||
}
|
||||
} else if (localVideo) {
|
||||
if (_messageImageView.image == nil) {
|
||||
[self loadFirstImage:localVideo type:PHAssetMediaTypeVideo];
|
||||
_imageGestureRecognizer.enabled = NO;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithLocalIdentifiers:[NSArray arrayWithObject:localVideo] options:nil];
|
||||
if (![assets firstObject])
|
||||
return;
|
||||
PHAsset *asset = [assets firstObject];
|
||||
if (asset.mediaType != PHAssetMediaTypeVideo)
|
||||
return;
|
||||
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
|
||||
options.version = PHImageRequestOptionsVersionCurrent;
|
||||
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
|
||||
|
||||
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
|
||||
AVURLAsset *urlAsset = (AVURLAsset *)asset;
|
||||
NSData *data = [NSData dataWithContentsOfURL:urlAsset.URL];
|
||||
NSString *name = [NSString stringWithFormat:@"IMG-%f.MOV", [NSDate timeIntervalSinceReferenceDate]];
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
[LinphoneManager setValueInMessageAppData:name forKey:@"localvideo" inMessage:self.message];
|
||||
|
||||
}];
|
||||
});
|
||||
}
|
||||
} else if (localFile) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
NSURL *url = [VIEW(ChatConversationView) getICloudFileUrl:localFile];
|
||||
NSData *data = [NSData dataWithContentsOfURL:url];
|
||||
[ChatConversationView writeFileInCache:data name:localFile];
|
||||
});
|
||||
|
||||
if ([fileType isEqualToString:@"video"]) {
|
||||
UIImage* image = [UIChatBubbleTextCell getImageFromVideoUrl:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
[self loadImageAsset:nil image:image];
|
||||
_imageGestureRecognizer.enabled = NO;
|
||||
} else if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
|
||||
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||
[self loadImageAsset:nil image:image];
|
||||
_imageGestureRecognizer.enabled = YES;
|
||||
} else {
|
||||
[self loadFileAsset:fileName];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[self uploadingImage:fileType localFile:localFile];
|
||||
}
|
||||
// we are uploading the image
|
||||
if (_ftd.message != nil) {
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = super.notDelivered ? YES : NO;
|
||||
_downloadButton.hidden = YES;
|
||||
_playButton.hidden = YES;
|
||||
_fileName.hidden = _fileView.hidden = _fileButton.hidden =YES;
|
||||
} else {
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = YES;
|
||||
_playButton.hidden = ![type isEqualToString:@"video"];
|
||||
_fileName.hidden = _fileView.hidden = _fileButton.hidden = localFile ? NO : YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)uploadingImage:(NSString *)fileType localFile:(NSString *)localFile {
|
||||
// we are uploading the image
|
||||
if (_ftd.message != nil) {
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = super.notDelivered ? YES : NO;
|
||||
_downloadButton.hidden = YES;
|
||||
_playButton.hidden = YES;
|
||||
_fileName.hidden = _fileView.hidden = _fileButton.hidden =YES;
|
||||
} else {
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = YES;
|
||||
_playButton.hidden = ![fileType isEqualToString:@"video"];
|
||||
_fileName.hidden = _fileView.hidden = _fileButton.hidden = localFile ? NO : YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadFirstImage:(NSString *)key type:(PHAssetMediaType)type {
|
||||
|
|
@ -390,11 +390,29 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
}
|
||||
|
||||
- (IBAction)onPlayClick:(id)sender {
|
||||
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:self.message];
|
||||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
|
||||
if (localVideo && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localVideo]]) {
|
||||
AVPlayer *player = [AVPlayer playerWithURL:[ChatConversationView getCacheFileUrl:localVideo]];
|
||||
[self playVideoByPlayer:player];
|
||||
return;
|
||||
} else if (localFile && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localFile]]) {
|
||||
AVPlayer *player = [AVPlayer playerWithURL:[ChatConversationView getCacheFileUrl:localFile]];
|
||||
[self playVideoByPlayer:player];
|
||||
return;
|
||||
}
|
||||
|
||||
PHAsset *asset = [_messageImageView asset];
|
||||
if (!asset) {
|
||||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
|
||||
AVPlayer *player = [AVPlayer playerWithURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
NSURL *url = [VIEW(ChatConversationView) getICloudFileUrl:localFile];
|
||||
AVPlayer *player = [AVPlayer playerWithURL:url];
|
||||
[self playVideoByPlayer:player];
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
NSData *data = [NSData dataWithContentsOfURL:url];
|
||||
[ChatConversationView writeFileInCache:data name:localFile];
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
|
||||
|
|
@ -409,10 +427,34 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
}];
|
||||
}
|
||||
|
||||
- (IBAction)onPlusClick:(id)sender {
|
||||
UILongPressGestureRecognizer *gesture = (UILongPressGestureRecognizer *)sender;
|
||||
if (gesture.state != UIGestureRecognizerStateBegan) {
|
||||
// allow only one click once time
|
||||
return;
|
||||
}
|
||||
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:@""];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[sheet addButtonWithTitle:NSLocalizedString(@"Save to Gallery", nil)
|
||||
block:^() {
|
||||
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(self.message);
|
||||
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
[ChatConversationView writeMediaToGallery:name fileType:[NSString stringWithUTF8String:linphone_content_get_type(content)?:""]];
|
||||
}];
|
||||
|
||||
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Cancel", nil) block:nil];
|
||||
[sheet showInView:PhoneMainView.instance.view];
|
||||
});
|
||||
}
|
||||
|
||||
- (IBAction)onFileClick:(id)sender {
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
NSString *name = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
|
||||
[view openFileWithURL:[view getICloudFileUrl:name]];
|
||||
if([[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name]]) {
|
||||
[view openFileWithURL:[ChatConversationView getCacheFileUrl:name]];
|
||||
} else {
|
||||
[view openFileWithURL:[view getICloudFileUrl:name]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -445,17 +487,29 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
if (![_messageImageView isLoading]) {
|
||||
ImageView *view = VIEW(ImageView);
|
||||
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:self.message];
|
||||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
|
||||
NSString *imageName = NULL;
|
||||
if (localImage && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localImage]]) {
|
||||
imageName = localImage;
|
||||
} else if (localFile && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localFile]]) {
|
||||
if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
|
||||
imageName = localFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (imageName) {
|
||||
NSData *data = [NSData dataWithContentsOfFile:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:imageName]];
|
||||
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||
if (image)
|
||||
[view setImage:image];
|
||||
else
|
||||
LOGE(@"Can't read image");
|
||||
return;
|
||||
}
|
||||
|
||||
PHAsset *asset = [_messageImageView asset];
|
||||
if (!asset) {
|
||||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:self.message];
|
||||
if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
|
||||
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||
if (image)
|
||||
[view setImage:image];
|
||||
else
|
||||
LOGE(@"Can't read image");
|
||||
}
|
||||
return;
|
||||
}
|
||||
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
|
||||
|
|
@ -516,6 +570,7 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
} else {
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
[view.tableController updateEventEntry:self.event];
|
||||
[view.tableController scrollToBottom:true];
|
||||
}
|
||||
}
|
||||
- (void)onFileTransferRecvUpdate:(NSNotification *)notif {
|
||||
|
|
@ -527,6 +582,7 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
} else {
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
[view.tableController updateEventEntry:self.event];
|
||||
[view.tableController scrollToBottom:true];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
+ (UIImage *)getImageFromVideoUrl:(NSURL *)url;
|
||||
|
||||
- (void)setEvent:(LinphoneEventLog *)event;
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)message;
|
||||
- (void)setChatMessageForCbs:(LinphoneChatMessage *)message;
|
||||
|
||||
- (void)onDelete;
|
||||
- (void)onResend;
|
||||
|
|
|
|||
|
|
@ -57,12 +57,13 @@
|
|||
//[_imdmLabel addGestureRecognizer:resendRecognizer2];
|
||||
//_imdmLabel.userInteractionEnabled = YES;
|
||||
|
||||
self.contentView.userInteractionEnabled = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self setEvent:NULL];
|
||||
[self setChatMessage:NULL];
|
||||
[self setChatMessageForCbs:NULL];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
|
@ -76,10 +77,10 @@
|
|||
LOGE(@"Impossible to create a ChatBubbleText whit a non message event");
|
||||
return;
|
||||
}
|
||||
[self setChatMessage:linphone_event_log_get_chat_message(event)];
|
||||
[self setChatMessageForCbs:linphone_event_log_get_chat_message(event)];
|
||||
}
|
||||
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)amessage {
|
||||
- (void)setChatMessageForCbs:(LinphoneChatMessage *)amessage {
|
||||
if (!amessage || amessage == _message) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -275,74 +276,33 @@
|
|||
|
||||
if (linphone_chat_message_get_file_transfer_information(_message) != NULL) {
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:_message];
|
||||
NSNumber *uploadQuality =[LinphoneManager getMessageAppDataForKey:@"uploadQuality" inMessage:_message];
|
||||
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:_message];
|
||||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:_message];
|
||||
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:_message];
|
||||
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:_message];
|
||||
|
||||
/*FileTransferDelegate *thiz = [FileTransferDelegate messageDelegate:_message];
|
||||
if (thiz) {
|
||||
[thiz stop]
|
||||
}*/
|
||||
[self onDelete];
|
||||
if(localImage){
|
||||
ChatConversationTableView *tableView = VIEW(ChatConversationView).tableController;
|
||||
UIImage *img = [tableView.imagesInChatroom objectForKey:localImage];
|
||||
if (img) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
[_chatRoomDelegate startImageUpload:img assetId:localImage withQuality:(uploadQuality ? [uploadQuality floatValue] : 0.9)];
|
||||
});
|
||||
} else {
|
||||
PHFetchResult<PHAsset *> *assets = [LinphoneManager getPHAssets:localImage];
|
||||
|
||||
if (![assets firstObject])
|
||||
return;
|
||||
PHAsset *asset = [assets firstObject];
|
||||
if (asset.mediaType != PHAssetMediaTypeImage)
|
||||
return;
|
||||
|
||||
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
|
||||
options.synchronous = TRUE;
|
||||
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:options
|
||||
resultHandler:^(UIImage *image, NSDictionary * info) {
|
||||
if (image) {
|
||||
dispatch_async(dispatch_get_main_queue(),
|
||||
^(void) {
|
||||
[_chatRoomDelegate startImageUpload:img assetId:localImage withQuality:(uploadQuality ? [uploadQuality floatValue] : 0.9)];
|
||||
});
|
||||
} else {
|
||||
LOGE(@"Can't read image");
|
||||
}
|
||||
}];
|
||||
}
|
||||
} else if (localVideo) {
|
||||
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithLocalIdentifiers:[NSArray arrayWithObject:localVideo] options:nil];
|
||||
if (![assets firstObject])
|
||||
return;
|
||||
PHAsset *asset = [assets firstObject];
|
||||
if (asset.mediaType != PHAssetMediaTypeVideo)
|
||||
return;
|
||||
|
||||
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
|
||||
options.version = PHImageRequestOptionsVersionCurrent;
|
||||
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
|
||||
|
||||
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
|
||||
AVURLAsset *urlAsset = (AVURLAsset *)asset;
|
||||
|
||||
NSURL *url = urlAsset.URL;
|
||||
NSData *data = [NSData dataWithContentsOfURL:url];
|
||||
dispatch_async(dispatch_get_main_queue(),
|
||||
^(void) {
|
||||
[_chatRoomDelegate startFileUpload:data assetId:localVideo];
|
||||
});
|
||||
}];
|
||||
|
||||
} else if (localFile) {
|
||||
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
[_chatRoomDelegate startFileUpload:data withName:localFile];
|
||||
}
|
||||
if(localImage){
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
[_chatRoomDelegate resendFile:[ChatConversationView getCacheFileData:localImage] withName:localImage type:@"image" key:@"localimage" message:self.textMessage];
|
||||
});
|
||||
} else if (localVideo) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
[_chatRoomDelegate resendFile:[ChatConversationView getCacheFileData:localVideo] withName:localVideo type:@"video" key:@"localvideo" message:self.textMessage];
|
||||
});
|
||||
} else if (localFile) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^ {
|
||||
[_chatRoomDelegate resendFile:[ChatConversationView getCacheFileData:localFile] withName:localFile type:@"image" key:@"localfile" message:self.textMessage];
|
||||
});
|
||||
}
|
||||
} else {
|
||||
[self onDelete];
|
||||
[self onDelete];
|
||||
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:self.textMessage withExternalUrl:nil];
|
||||
[_chatRoomDelegate resendChat:self.textMessage withExternalUrl:nil];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -352,6 +312,7 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
|
|||
LinphoneEventLog *event = (LinphoneEventLog *)linphone_chat_message_cbs_get_user_data(linphone_chat_message_get_callbacks(msg));
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
[view.tableController updateEventEntry:event];
|
||||
[view.tableController scrollToBottom:true];
|
||||
}
|
||||
|
||||
static void participant_imdn_status(LinphoneChatMessage* msg, const LinphoneParticipantImdnState *state) {
|
||||
|
|
@ -403,6 +364,14 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
return [self ViewHeightForMessageText:chat withWidth:width textForImdn:nil];
|
||||
}
|
||||
|
||||
+ (CGSize)ViewHeightForFile:(int)width {
|
||||
CGSize fileSize = CGSizeMake(230, 50);
|
||||
CGSize size = [self getMediaMessageSizefromOriginalSize:fileSize withWidth:width];
|
||||
size.width = MAX(size.width + CELL_MESSAGE_X_MARGIN, CELL_MIN_WIDTH);
|
||||
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN, CELL_MIN_HEIGHT);
|
||||
return size;
|
||||
}
|
||||
|
||||
+ (CGSize)ViewHeightForMessageText:(LinphoneChatMessage *)chat withWidth:(int)width textForImdn:(NSString *)imdnText{
|
||||
NSString *messageText = [UIChatBubbleTextCell TextMessageForChat:chat];
|
||||
static UIFont *messageFont = nil;
|
||||
|
|
@ -442,53 +411,75 @@ static const CGFloat CELL_IMAGE_X_MARGIN = 100;
|
|||
font:messageFont];
|
||||
size.height += textSize.height;
|
||||
}
|
||||
|
||||
if(localFile) {
|
||||
UIImage *image = nil;
|
||||
NSString *type = [NSString stringWithUTF8String:linphone_content_get_type(fileContent)];
|
||||
if ([type isEqualToString:@"video"]) {
|
||||
image = [self getImageFromVideoUrl:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
} else if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
|
||||
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
image = [[UIImage alloc] initWithData:data];
|
||||
}
|
||||
|
||||
if (image) {
|
||||
size = [self getMediaMessageSizefromOriginalSize:image.size withWidth:width];
|
||||
// add size for message text
|
||||
size.height += textSize.height;
|
||||
size.width = MAX(textSize.width, size.width);
|
||||
} else {
|
||||
CGSize fileSize = CGSizeMake(230, 50);
|
||||
size = [self getMediaMessageSizefromOriginalSize:fileSize withWidth:width];
|
||||
}
|
||||
} else {
|
||||
if (!localImage && !localVideo) {
|
||||
//We are loading the image
|
||||
return CGSizeMake(CELL_MIN_WIDTH + CELL_MESSAGE_X_MARGIN, CELL_MIN_HEIGHT + CELL_MESSAGE_Y_MARGIN + textSize.height + 20);
|
||||
}
|
||||
PHFetchResult<PHAsset *> *assets;
|
||||
if(localImage)
|
||||
assets = [LinphoneManager getPHAssets:localImage];
|
||||
else
|
||||
assets = [PHAsset fetchAssetsWithLocalIdentifiers:[NSArray arrayWithObject:localVideo] options:nil];
|
||||
if (![assets firstObject]) {
|
||||
return CGSizeMake(CELL_MIN_WIDTH, CELL_MIN_WIDTH + CELL_MESSAGE_Y_MARGIN + textSize.height);
|
||||
} else {
|
||||
PHAsset *asset = [assets firstObject];
|
||||
CGSize originalImageSize = CGSizeMake([asset pixelWidth], [asset pixelHeight]);
|
||||
size = [self getMediaMessageSizefromOriginalSize:originalImageSize withWidth:width];
|
||||
|
||||
// add size for message text
|
||||
size.height += textSize.height;
|
||||
size.width = MAX(textSize.width, size.width);
|
||||
}
|
||||
}
|
||||
}
|
||||
CGSize originalImageSize = CGSizeMake(230, 50);
|
||||
if (localFile) {
|
||||
UIImage *image = nil;
|
||||
NSString *type = [NSString stringWithUTF8String:linphone_content_get_type(fileContent)];
|
||||
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localFile];
|
||||
if ([type isEqualToString:@"video"]) {
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]) {
|
||||
image = [self getImageFromVideoUrl:[ChatConversationView getCacheFileUrl:localFile]];
|
||||
} else {
|
||||
image = [self getImageFromVideoUrl:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
}
|
||||
} else if ([localFile hasSuffix:@"JPG"] || [localFile hasSuffix:@"PNG"] || [localFile hasSuffix:@"jpg"] || [localFile hasSuffix:@"png"]) {
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]) {
|
||||
NSData *data = [NSData dataWithContentsOfFile:filePath];
|
||||
image = [[UIImage alloc] initWithData:data];
|
||||
} else {
|
||||
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
|
||||
image = [[UIImage alloc] initWithData:data];
|
||||
}
|
||||
} else {
|
||||
return [self ViewHeightForFile:width];
|
||||
}
|
||||
|
||||
size.width = MAX(size.width + CELL_MESSAGE_X_MARGIN, CELL_MIN_WIDTH);
|
||||
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN, CELL_MIN_HEIGHT);
|
||||
return size;
|
||||
originalImageSize = image.size;
|
||||
} else {
|
||||
if (!localImage && !localVideo) {
|
||||
//We are loading the image
|
||||
return CGSizeMake(CELL_MIN_WIDTH + CELL_MESSAGE_X_MARGIN, CELL_MIN_HEIGHT + CELL_MESSAGE_Y_MARGIN + textSize.height + 20);
|
||||
}
|
||||
|
||||
if (localImage && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localImage]]) {
|
||||
NSData* data = [ChatConversationView getCacheFileData:localImage];
|
||||
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||
if (!image) {
|
||||
return [self ViewHeightForFile:width];
|
||||
}
|
||||
originalImageSize = image.size;
|
||||
} else if (localVideo && [[NSFileManager defaultManager] fileExistsAtPath:[[LinphoneManager cacheDirectory] stringByAppendingPathComponent:localVideo]]) {
|
||||
UIImage *image = [UIChatBubbleTextCell getImageFromVideoUrl:[ChatConversationView getCacheFileUrl:localVideo]];
|
||||
if (!image) {
|
||||
return [self ViewHeightForFile:width];
|
||||
}
|
||||
originalImageSize = image.size;
|
||||
} else {
|
||||
// support previous versions
|
||||
PHFetchResult<PHAsset *> *assets;
|
||||
if(localImage)
|
||||
assets = [LinphoneManager getPHAssets:localImage];
|
||||
else
|
||||
assets = [PHAsset fetchAssetsWithLocalIdentifiers:[NSArray arrayWithObject:localVideo] options:nil];
|
||||
|
||||
if (![assets firstObject]) {
|
||||
return CGSizeMake(CELL_MIN_WIDTH, CELL_MIN_WIDTH + CELL_MESSAGE_Y_MARGIN + textSize.height);
|
||||
} else {
|
||||
PHAsset *asset = [assets firstObject];
|
||||
originalImageSize = CGSizeMake([asset pixelWidth], [asset pixelHeight]);
|
||||
}
|
||||
}
|
||||
}
|
||||
size = [self getMediaMessageSizefromOriginalSize:originalImageSize withWidth:width];
|
||||
// add size for message text
|
||||
size.height += textSize.height;
|
||||
size.width = MAX(textSize.width, size.width);
|
||||
}
|
||||
|
||||
size.width = MAX(size.width + CELL_MESSAGE_X_MARGIN, CELL_MIN_WIDTH);
|
||||
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN, CELL_MIN_HEIGHT);
|
||||
return size;
|
||||
}
|
||||
|
||||
+ (CGSize)ViewSizeForMessage:(LinphoneChatMessage *)chat withWidth:(int)width {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ INIT_WITH_COMMON_CF {
|
|||
LinphoneCallParams *call_params = linphone_core_create_call_params(LC,call);
|
||||
linphone_call_params_enable_video(call_params, FALSE);
|
||||
linphone_core_update_call(LC, call, call_params);
|
||||
linphone_call_params_destroy(call_params);
|
||||
linphone_call_params_unref(call_params);
|
||||
} else {
|
||||
LOGW(@"Cannot toggle video button, because no current call");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
#import "UIConfirmationDialog.h"
|
||||
#import "Utils.h"
|
||||
#import "LaunchScreen.h"
|
||||
#import "DevicesListView.h"
|
||||
|
||||
#define DYNAMIC_CAST(x, cls) \
|
||||
({ \
|
||||
|
|
|
|||
|
|
@ -174,9 +174,9 @@ extension ProviderDelegate: CXProviderDelegate {
|
|||
Log.directLog(BCTBX_LOG_MESSAGE, text: "CallKit: answer call with call-id: \(String(describing: callId)) and UUID: \(uuid.description).")
|
||||
|
||||
let call = CallManager.instance().callByCallId(callId: callId)
|
||||
CallManager.instance().lc?.configureAudioSession()
|
||||
if (call == nil || call?.state != Call.State.IncomingReceived) {
|
||||
// The application is not yet registered or the call is not yet received, mark the call as accepted. The audio session must be configured here.
|
||||
CallManager.configAudioSession(audioSession: AVAudioSession.sharedInstance())
|
||||
callInfo?.accepted = true
|
||||
callInfos.updateValue(callInfo!, forKey: uuid)
|
||||
CallManager.instance().providerDelegate.endCallNotExist(uuid: uuid, timeout: .now() + 10)
|
||||
|
|
@ -242,6 +242,7 @@ extension ProviderDelegate: CXProviderDelegate {
|
|||
action.fail()
|
||||
}
|
||||
|
||||
CallManager.instance().lc?.configureAudioSession()
|
||||
try CallManager.instance().doCall(addr: addr!, isSas: callInfo?.sasEnabled ?? false)
|
||||
} catch {
|
||||
Log.directLog(BCTBX_LOG_ERROR, text: "CallKit: Call started failed because \(error)")
|
||||
|
|
|
|||
|
|
@ -84,6 +84,10 @@
|
|||
NSArray *parsedName = [LinphoneUtils parseRecordingName:file];
|
||||
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
|
||||
[dateFormat setDateFormat:@"EEEE, MMM d, yyyy"];
|
||||
if ([parsedName count] < 2) {
|
||||
LOGW(@"Can not parse this recoding file: %@", file);
|
||||
continue;
|
||||
}
|
||||
NSString *dayPretty = [dateFormat stringFromDate:[parsedName objectAtIndex:1]];
|
||||
NSMutableArray *recOfDay = [recordings objectForKey:dayPretty];
|
||||
if (recOfDay) {
|
||||
|
|
|
|||
|
|
@ -23,12 +23,14 @@
|
|||
|
||||
@interface FileTransferDelegate : NSObject
|
||||
|
||||
- (void)upload:(UIImage *)image withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality;
|
||||
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key;
|
||||
- (void)uploadImage:(UIImage *)image forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality;
|
||||
- (void)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name;
|
||||
- (void)uploadVideo:(NSData *)data withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom;
|
||||
- (void)cancel;
|
||||
- (BOOL)download:(LinphoneChatMessage *)message;
|
||||
- (void)stopAndDestroy;
|
||||
+ (FileTransferDelegate *)messageDelegate:(LinphoneChatMessage *)message;
|
||||
|
||||
@property() LinphoneChatMessage *message;
|
||||
@property() NSString *text;
|
||||
|
|
|
|||
|
|
@ -43,189 +43,41 @@
|
|||
return nil;
|
||||
}
|
||||
|
||||
static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, const LinphoneContent *content,
|
||||
const LinphoneBuffer *buffer) {
|
||||
static void file_transfer_progress_indication_recv(LinphoneChatMessage *message, LinphoneContent* content, size_t offset, size_t total) {
|
||||
FileTransferDelegate *thiz = [FileTransferDelegate messageDelegate:message];
|
||||
size_t size = linphone_buffer_get_size(buffer);
|
||||
|
||||
if (!thiz.data) {
|
||||
thiz.data = [[NSMutableData alloc] initWithCapacity:linphone_content_get_file_size(content)];
|
||||
}
|
||||
if (offset == total) {
|
||||
NSString *name = [NSString stringWithUTF8String: linphone_content_get_name(content) ? : ""];
|
||||
LOGI(@"Transfer of %@ (%d bytes): download finished", name, total);
|
||||
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
|
||||
NSString *key = [ChatConversationView getKeyFromFileType:fileType fileName:name];
|
||||
|
||||
if (size == 0) {
|
||||
LOGI(@"Transfer of %s (%d bytes): download finished", linphone_content_get_name(content), size);
|
||||
assert([thiz.data length] == linphone_content_get_file_size(content));
|
||||
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
void (^block)(void)= ^ {
|
||||
if ([fileType isEqualToString:@"image"]) {
|
||||
// we're finished, save the image and update the message
|
||||
UIImage *image = [UIImage imageWithData:thiz.data];
|
||||
if (!image) {
|
||||
[view showFileDownloadError];
|
||||
[thiz stopAndDestroy];
|
||||
return;
|
||||
}
|
||||
|
||||
CFBridgingRetain(thiz);
|
||||
[[LinphoneManager.instance fileTransferDelegates] removeObject:thiz];
|
||||
|
||||
// until image is properly saved, keep a reminder on it so that the
|
||||
// chat bubble is aware of the fact that image is being saved to device
|
||||
[LinphoneManager setValueInMessageAppData:@"saving..." forKey:@"localimage" inMessage:message];
|
||||
__block PHObjectPlaceholder *placeHolder;
|
||||
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
||||
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
|
||||
placeHolder = [request placeholderForCreatedAsset];
|
||||
} completionHandler:^(BOOL success, NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (error) {
|
||||
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
|
||||
[LinphoneManager setValueInMessageAppData:nil forKey:@"localimage" inMessage:message];
|
||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write image to photo library",
|
||||
nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {}];
|
||||
|
||||
[errView addAction:defaultAction];
|
||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||
} else {
|
||||
LOGI(@"Image saved to [%@]", [placeHolder localIdentifier]);
|
||||
[LinphoneManager setValueInMessageAppData:[placeHolder localIdentifier]
|
||||
forKey:@"localimage"
|
||||
inMessage:message];
|
||||
}
|
||||
[NSNotificationCenter.defaultCenter
|
||||
postNotificationName:kLinphoneFileTransferRecvUpdate
|
||||
object:thiz
|
||||
userInfo:@{
|
||||
@"state" : @(LinphoneChatMessageStateDelivered), // we dont want to
|
||||
// trigger
|
||||
// FileTransferDone here
|
||||
@"image" : image,
|
||||
@"progress" : @(1.f),
|
||||
}];
|
||||
|
||||
[thiz stopAndDestroy];
|
||||
CFRelease((__bridge CFTypeRef)thiz);
|
||||
});
|
||||
}];
|
||||
} else if([fileType isEqualToString:@"video"]) {
|
||||
CFBridgingRetain(thiz);
|
||||
[[LinphoneManager.instance fileTransferDelegates] removeObject:thiz];
|
||||
NSString *name =[NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
NSString *filePath = [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name];
|
||||
[[NSFileManager defaultManager] createFileAtPath:filePath
|
||||
contents:thiz.data
|
||||
attributes:nil];
|
||||
// until image is properly saved, keep a reminder on it so that the
|
||||
// chat bubble is aware of the fact that image is being saved to device
|
||||
[LinphoneManager setValueInMessageAppData:@"saving..." forKey:@"localvideo" inMessage:message];
|
||||
|
||||
__block PHObjectPlaceholder *placeHolder;
|
||||
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
||||
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]];
|
||||
placeHolder = [request placeholderForCreatedAsset];
|
||||
} completionHandler:^(BOOL success, NSError * _Nullable error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (error) {
|
||||
LOGE(@"Cannot save video data downloaded [%@]", [error localizedDescription]);
|
||||
[LinphoneManager setValueInMessageAppData:nil forKey:@"localvideo" inMessage:message];
|
||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||
message:NSLocalizedString(@"Cannot write video to photo library",
|
||||
nil)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {}];
|
||||
|
||||
[errView addAction:defaultAction];
|
||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||
} else {
|
||||
LOGI(@"video saved to [%@]", [placeHolder localIdentifier]);
|
||||
[LinphoneManager setValueInMessageAppData:[placeHolder localIdentifier]
|
||||
forKey:@"localvideo"
|
||||
inMessage:message];
|
||||
}
|
||||
[NSNotificationCenter.defaultCenter
|
||||
postNotificationName:kLinphoneFileTransferRecvUpdate
|
||||
object:thiz
|
||||
userInfo:@{
|
||||
@"state" : @(LinphoneChatMessageStateDelivered), // we dont want to
|
||||
// trigger
|
||||
// FileTransferDone here
|
||||
@"progress" : @(1.f),
|
||||
}];
|
||||
|
||||
[thiz stopAndDestroy];
|
||||
CFRelease((__bridge CFTypeRef)thiz);
|
||||
});
|
||||
}];
|
||||
}
|
||||
};
|
||||
// When you save an image or video to a photo library, make sure that it is allowed. Otherwise, there will be a backup error.
|
||||
if ([fileType isEqualToString:@"image"] || [fileType isEqualToString:@"video"]) {
|
||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||
block();
|
||||
} else {
|
||||
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||
block();
|
||||
} else {
|
||||
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Photo's permission", nil) message:NSLocalizedString(@"Photo not authorized", nil) delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil] show];
|
||||
[thiz stopAndDestroy];
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
[[LinphoneManager.instance fileTransferDelegates] removeObject:thiz];
|
||||
NSString *key = @"localfile" ;
|
||||
NSString *name =[NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||
[LinphoneManager setValueInMessageAppData:@"saving..." forKey:key inMessage:message];
|
||||
|
||||
//write file to path
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if([view writeFileInICloud:thiz.data fileURL:[view getICloudFileUrl:name]]) {
|
||||
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:message];
|
||||
|
||||
[NSNotificationCenter.defaultCenter
|
||||
postNotificationName:kLinphoneFileTransferRecvUpdate
|
||||
object:thiz
|
||||
userInfo:@{
|
||||
@"state" : @(LinphoneChatMessageStateDelivered), // we dont want to trigger
|
||||
@"progress" : @(1.f), // FileTransferDone here
|
||||
}];
|
||||
}
|
||||
[thiz stopAndDestroy];
|
||||
});
|
||||
}
|
||||
} else {
|
||||
LOGD(@"Transfer of %s (%d bytes): already %ld sent, adding %ld", linphone_content_get_name(content),
|
||||
linphone_content_get_file_size(content), [thiz.data length], size);
|
||||
[thiz.data appendBytes:linphone_buffer_get_string_content(buffer) length:size];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[LinphoneManager setValueInMessageAppData:name
|
||||
forKey:key
|
||||
inMessage:message];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([ConfigManager.instance lpConfigBoolForKeyWithKey:@"auto_write_to_gallery_preference"]) {
|
||||
[ChatConversationView writeMediaToGallery:name fileType:fileType];
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
LOGD(@"Transfer of %s (%d bytes): already %ld recv", linphone_content_get_name(content),
|
||||
total, offset);
|
||||
[NSNotificationCenter.defaultCenter
|
||||
postNotificationName:kLinphoneFileTransferRecvUpdate
|
||||
object:thiz
|
||||
userInfo:@{
|
||||
@"state" : @(linphone_chat_message_get_state(message)),
|
||||
@"progress" : @([thiz.data length] * 1.f / linphone_content_get_file_size(content)),
|
||||
@"progress" : @(offset * 1.f / total),
|
||||
}];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *message, const LinphoneContent *content,
|
||||
size_t offset, size_t size) {
|
||||
static void file_transfer_progress_indication_send(LinphoneChatMessage *message, LinphoneContent* content, size_t offset, size_t total) {
|
||||
FileTransferDelegate *thiz = [FileTransferDelegate messageDelegate:message];
|
||||
size_t total = thiz.data.length;
|
||||
if (thiz.data) {
|
||||
if (total) {
|
||||
size_t remaining = total - offset;
|
||||
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
|
|
@ -237,109 +89,85 @@ static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *m
|
|||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneFileTransferSendUpdate
|
||||
object:thiz
|
||||
userInfo:dict];
|
||||
|
||||
LinphoneBuffer *buffer = NULL;
|
||||
@try {
|
||||
buffer = linphone_buffer_new_from_data([thiz.data subdataWithRange:NSMakeRange(offset, size)].bytes, size);
|
||||
} @catch (NSException *exception) {
|
||||
LOGE(@"Exception: %@", exception);
|
||||
}
|
||||
|
||||
// this is the last time we will be notified, so destroy ourselve
|
||||
if (remaining <= size) {
|
||||
if (offset == total) {
|
||||
LOGI(@"Upload ended");
|
||||
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(thiz.message), NULL);
|
||||
|
||||
thiz.message = NULL;
|
||||
[thiz stopAndDestroy];
|
||||
//workaround fix : avoid chatconversationtableview scrolling
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneFileTransferSendUpdate
|
||||
object:thiz
|
||||
userInfo:@{@"state" : @(LinphoneChatMessageStateDelivered),
|
||||
}];
|
||||
}
|
||||
return buffer;
|
||||
} else {
|
||||
LOGE(@"Transfer of %s (%d bytes): %d Error - no upload data in progress!", linphone_content_get_name(content),
|
||||
total, offset);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key keyData:(NSString *)keyData qualityData:(NSNumber *)qualityData {
|
||||
[LinphoneManager.instance.fileTransferDelegates addObject:self];
|
||||
|
||||
LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_core(chatRoom));
|
||||
_data = [NSMutableData dataWithData:data];
|
||||
linphone_content_set_type(content, [type UTF8String]);
|
||||
linphone_content_set_subtype(content, [subtype UTF8String]);
|
||||
linphone_content_set_name(content, [name UTF8String]);
|
||||
linphone_content_set_size(content, _data.length);
|
||||
_message = linphone_chat_room_create_file_transfer_message(chatRoom, content);
|
||||
BOOL isOneToOneChat = linphone_chat_room_get_capabilities(chatRoom) & LinphoneChatRoomCapabilitiesOneToOne;
|
||||
if (!isOneToOneChat && ![_text isEqualToString:@""])
|
||||
linphone_chat_message_add_text_content(_message, [_text UTF8String]);
|
||||
linphone_content_unref(content);
|
||||
|
||||
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(_message),
|
||||
linphone_iphone_file_transfer_send);
|
||||
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key{
|
||||
if ([[LinphoneManager.instance fileTransferDelegates] containsObject:self]) {
|
||||
LOGW(@"fileTransferDelegates has already added %p", self);
|
||||
return;
|
||||
}
|
||||
[LinphoneManager.instance.fileTransferDelegates addObject:self];
|
||||
|
||||
// internal url is saved in the appdata for display and later save
|
||||
[LinphoneManager setValueInMessageAppData:keyData forKey:key inMessage:_message];
|
||||
[LinphoneManager setValueInMessageAppData:qualityData forKey:@"uploadQuality" inMessage:_message];
|
||||
|
||||
LOGI(@"%p Uploading content from message %p", self, _message);
|
||||
linphone_chat_message_send(_message);
|
||||
LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_core(chatRoom));
|
||||
linphone_content_set_type(content, [type UTF8String]);
|
||||
linphone_content_set_subtype(content, [subtype UTF8String]);
|
||||
linphone_content_set_name(content, [name UTF8String]);
|
||||
linphone_content_set_file_path(content, [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:name].UTF8String);
|
||||
_message = linphone_chat_room_create_file_transfer_message(chatRoom, content);
|
||||
BOOL isOneToOneChat = linphone_chat_room_get_capabilities(chatRoom) & LinphoneChatRoomCapabilitiesOneToOne;
|
||||
if (!isOneToOneChat && (_text!=nil && ![_text isEqualToString:@""]))
|
||||
linphone_chat_message_add_text_content(_message, [_text UTF8String]);
|
||||
linphone_content_unref(content);
|
||||
|
||||
linphone_chat_message_cbs_set_file_transfer_progress_indication(linphone_chat_message_get_callbacks(_message), file_transfer_progress_indication_send);
|
||||
|
||||
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:_message];
|
||||
|
||||
LOGI(@"%p Uploading content from message %p", self, _message);
|
||||
linphone_chat_message_send(_message);
|
||||
}
|
||||
|
||||
- (void)upload:(UIImage *)image withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality {
|
||||
NSString *name = [NSString stringWithFormat:@"%li-%f.jpg", (long)image.hash, [NSDate timeIntervalSinceReferenceDate]];
|
||||
if (phAssetId)
|
||||
[self uploadData:UIImageJPEGRepresentation(image, quality) forChatRoom:chatRoom type:@"image" subtype:@"jpeg" name:name key:@"localimage" keyData:phAssetId qualityData:[NSNumber numberWithFloat:quality]];
|
||||
else
|
||||
[self uploadData:UIImageJPEGRepresentation(image, quality) forChatRoom:chatRoom type:@"image" subtype:@"jpeg" name:name key:@"localimage" keyData:nil qualityData:nil];
|
||||
- (void)uploadImage:(UIImage *)image forChatRoom:(LinphoneChatRoom *)chatRoom withQuality:(float)quality {
|
||||
NSString *name = [NSString stringWithFormat:@"%li-%f.jpg", (long)image.hash, [NSDate timeIntervalSinceReferenceDate]];
|
||||
NSData *data = UIImageJPEGRepresentation(image, quality);
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
[self uploadData:data forChatRoom:chatRoom type:@"image" subtype:@"jpg" name:name key:@"localimage"];
|
||||
}
|
||||
|
||||
- (void)uploadVideo:(NSData *)data withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom {
|
||||
NSString *name = [NSString stringWithFormat:@"IMG-%f.MOV", [NSDate timeIntervalSinceReferenceDate]];
|
||||
if (phAssetId)
|
||||
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:nil name:name key:@"localvideo" keyData:phAssetId qualityData:nil];
|
||||
else
|
||||
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:nil name:name key:@"localvideo" keyData:@"ending..." qualityData:nil];
|
||||
NSString *name = [NSString stringWithFormat:@"IMG-%f.MOV", [NSDate timeIntervalSinceReferenceDate]];
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:@"mov" name:name key:@"localvideo"];
|
||||
}
|
||||
|
||||
- (void)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name {
|
||||
// we will write local files into ours folder of icloud
|
||||
ChatConversationView *view = VIEW(ChatConversationView);
|
||||
NSURL *url = [view getICloudFileUrl:name];
|
||||
if ([view writeFileInICloud:data fileURL:url]) {
|
||||
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
|
||||
if ([[asset tracksWithMediaType:AVMediaTypeVideo] count] > 0) {
|
||||
// if it's a video
|
||||
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:nil name:name key:@"localfile" keyData:name qualityData:nil];
|
||||
} else {
|
||||
[self uploadData:data forChatRoom:chatRoom type:@"file" subtype:nil name:name key:@"localfile" keyData:name qualityData:nil];
|
||||
}
|
||||
}
|
||||
[ChatConversationView writeFileInCache:data name:name];
|
||||
NSURL *url = [ChatConversationView getCacheFileUrl:name];
|
||||
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
|
||||
NSString *fileType = [[asset tracksWithMediaType:AVMediaTypeVideo] count] > 0 ? @"video" : @"file";
|
||||
NSString *key = [ChatConversationView getKeyFromFileType:fileType fileName:name];
|
||||
|
||||
[self uploadData:data forChatRoom:chatRoom type:fileType subtype:name.lastPathComponent name:name key:key];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (BOOL)download:(LinphoneChatMessage *)message {
|
||||
if ([[LinphoneManager.instance fileTransferDelegates] containsObject:self]) {
|
||||
LOGW(@"fileTransferDelegates has already added %p", self);
|
||||
return FALSE;
|
||||
}
|
||||
[[LinphoneManager.instance fileTransferDelegates] addObject:self];
|
||||
|
||||
_message = message;
|
||||
|
||||
const char *url = linphone_chat_message_get_external_body_url(_message);
|
||||
LOGI(@"%p Downloading content in %p from %s", self, message, url);
|
||||
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(_message);
|
||||
if (content == nil) return FALSE;
|
||||
|
||||
if (url == nil)
|
||||
return FALSE;
|
||||
LOGI(@"%p Downloading content in %p ", self, message);
|
||||
|
||||
linphone_chat_message_cbs_set_file_transfer_recv(linphone_chat_message_get_callbacks(_message),
|
||||
linphone_iphone_file_transfer_recv);
|
||||
|
||||
linphone_chat_message_download_file(_message);
|
||||
linphone_chat_message_cbs_set_file_transfer_progress_indication(linphone_chat_message_get_callbacks(_message), file_transfer_progress_indication_recv);
|
||||
linphone_content_set_file_path(content, [[LinphoneManager cacheDirectory] stringByAppendingPathComponent:[NSString stringWithUTF8String:linphone_content_get_name(content)]].UTF8String);
|
||||
linphone_chat_message_download_content(_message, content);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -350,8 +178,7 @@ static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *m
|
|||
LinphoneChatMessage *msg = _message;
|
||||
_message = NULL;
|
||||
LOGI(@"%p Cancelling transfer from %p", self, msg);
|
||||
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(msg), NULL);
|
||||
linphone_chat_message_cbs_set_file_transfer_recv(linphone_chat_message_get_callbacks(msg), NULL);
|
||||
linphone_chat_message_cbs_set_file_transfer_progress_indication(linphone_chat_message_get_callbacks(msg), NULL);
|
||||
// when we cancel file transfer, this will automatically trigger NotDelivered callback... recalling ourself a
|
||||
// second time so we have to unset message BEFORE calling this
|
||||
linphone_chat_message_cancel_file_transfer(msg);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
}
|
||||
|
||||
+ (void)directLog:(OrtpLogLevel)level text:(NSString *)text {
|
||||
bctbx_log(BCTBX_LOG_DOMAIN, level, "%s", text.cString);
|
||||
bctbx_log(BCTBX_LOG_DOMAIN, level, "%s", [text cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
}
|
||||
|
||||
#pragma mark - Logs Functions callbacks
|
||||
|
|
|
|||
18
Classes/fr.lproj/RecordingsListView.strings
Normal file
18
Classes/fr.lproj/RecordingsListView.strings
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
/* Class = "UIButton"; accessibilityLabel = "Select all"; ObjectID = "16S-9G-2cb"; */
|
||||
"16S-9G-2cb.accessibilityLabel" = "Select all";
|
||||
|
||||
/* Class = "UIButton"; accessibilityLabel = "Edit"; ObjectID = "CWx-9g-0JG"; */
|
||||
"CWx-9g-0JG.accessibilityLabel" = "Edit";
|
||||
|
||||
/* Class = "UIButton"; accessibilityLabel = "Delete all"; ObjectID = "CqG-tB-maQ"; */
|
||||
"CqG-tB-maQ.accessibilityLabel" = "Delete all";
|
||||
|
||||
/* Class = "UIButton"; accessibilityLabel = "Back"; ObjectID = "rAc-tI-AVp"; */
|
||||
"rAc-tI-AVp.accessibilityLabel" = "Back";
|
||||
|
||||
/* Class = "UIButton"; accessibilityLabel = "Delete all"; ObjectID = "zDs-pW-vyA"; */
|
||||
"zDs-pW-vyA.accessibilityLabel" = "Delete all";
|
||||
|
||||
/* Class = "UILabel"; text = "No recording found"; ObjectID = "zXd-Ic-rwm"; */
|
||||
"zXd-Ic-rwm.text" = "No recording found";
|
||||
2
Podfile
2
Podfile
|
|
@ -5,7 +5,7 @@ source "https://github.com/CocoaPods/Specs.git"
|
|||
|
||||
def all_pods
|
||||
if ENV['PODFILE_PATH'].nil?
|
||||
pod 'linphone-sdk', '4.4.3'
|
||||
pod 'linphone-sdk', '~> 4.5.0-beta'
|
||||
else
|
||||
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
<entry name="realm" overwrite="true">sip.linphone.org</entry>
|
||||
<entry name="nat_policy_ref" overwrite="true">nat_policy_default_values</entry>
|
||||
<entry name="push_notification_allowed" overwrite="true">1</entry>
|
||||
<entry name="conference_factory_uri" overwrite="true">sip:conference-factory@sip.linphone.org</entry>
|
||||
</section>
|
||||
|
||||
<section name="nat_policy_default_values">
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
<entry name="realm" overwrite="true">sip.linphone.org</entry>
|
||||
<entry name="nat_policy_ref" overwrite="true">nat_policy_default_values</entry>
|
||||
<entry name="push_notification_allowed" overwrite="true">1</entry>
|
||||
<entry name="conference_factory_uri" overwrite="true">sip:conference-factory@sip.linphone.org</entry>
|
||||
</section>
|
||||
|
||||
<section name="nat_policy_default_values">
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -26,6 +26,16 @@
|
|||
<string>Customize</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>DefaultValue</key>
|
||||
<true/>
|
||||
<key>Key</key>
|
||||
<string>auto_write_to_gallery_mode</string>
|
||||
<key>Title</key>
|
||||
<string>Auto write to gallery</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Key</key>
|
||||
<string>auto_download_incoming_files_max_size</string>
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -103,6 +103,7 @@
|
|||
615A28402180A2620060F920 /* invite_linphone@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 615A283F2180A2620060F920 /* invite_linphone@2x.png */; };
|
||||
615A28422180C0870060F920 /* recording.png in Resources */ = {isa = PBXBuildFile; fileRef = 615A28412180C0820060F920 /* recording.png */; };
|
||||
615A28442180C0900060F920 /* recording@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 615A28432180C08F0060F920 /* recording@2x.png */; };
|
||||
617B4A60260A2B7800A87337 /* RecordingsListView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 617B4A62260A2B7800A87337 /* RecordingsListView.xib */; };
|
||||
6180D6FE21EE41A800AD9CB6 /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6180D6FD21EE41A800AD9CB6 /* QuickLook.framework */; };
|
||||
61AE364F20C00B370089D9D3 /* ShareViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61AE364E20C00B370089D9D3 /* ShareViewController.m */; };
|
||||
61AE365220C00B370089D9D3 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61AE365020C00B370089D9D3 /* MainInterface.storyboard */; };
|
||||
|
|
@ -678,7 +679,6 @@
|
|||
CF1DE92D210A0F5D00A0A97E /* UILinphoneAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = CF1DE924210A0F5A00A0A97E /* UILinphoneAudioPlayer.m */; };
|
||||
CF1DE92E210A0F5D00A0A97E /* UILinphoneAudioPlayer.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF1DE92B210A0F5B00A0A97E /* UILinphoneAudioPlayer.xib */; };
|
||||
CF7602D7210867E800749F76 /* RecordingsListView.m in Sources */ = {isa = PBXBuildFile; fileRef = CF7602D5210867E800749F76 /* RecordingsListView.m */; };
|
||||
CF7602D8210867E800749F76 /* RecordingsListView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF7602D6210867E800749F76 /* RecordingsListView.xib */; };
|
||||
CF7602E221086EB200749F76 /* RecordingsListTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = CF7602E021086EB200749F76 /* RecordingsListTableView.m */; };
|
||||
CF7602E72108759A00749F76 /* UIRecordingCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CF7602E52108759A00749F76 /* UIRecordingCell.m */; };
|
||||
CF7602E82108759A00749F76 /* UIRecordingCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF7602E62108759A00749F76 /* UIRecordingCell.xib */; };
|
||||
|
|
@ -959,6 +959,8 @@
|
|||
615A283F2180A2620060F920 /* invite_linphone@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "invite_linphone@2x.png"; sourceTree = "<group>"; };
|
||||
615A28412180C0820060F920 /* recording.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = recording.png; sourceTree = "<group>"; };
|
||||
615A28432180C08F0060F920 /* recording@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "recording@2x.png"; sourceTree = "<group>"; };
|
||||
617B4A61260A2B7800A87337 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/RecordingsListView.xib; sourceTree = "<group>"; };
|
||||
617B4A64260A2B8500A87337 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/RecordingsListView.strings; sourceTree = "<group>"; };
|
||||
6180D6FD21EE41A800AD9CB6 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = System/Library/Frameworks/QuickLook.framework; sourceTree = SDKROOT; };
|
||||
6187B1B524B3271500D580FB /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/AboutView.strings; sourceTree = "<group>"; };
|
||||
6187B1B624B3271500D580FB /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/AssistantLinkView.strings; sourceTree = "<group>"; };
|
||||
|
|
@ -1715,7 +1717,6 @@
|
|||
CF1DE92C210A0F5C00A0A97E /* UILinphoneAudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UILinphoneAudioPlayer.h; sourceTree = "<group>"; };
|
||||
CF7602D4210867E800749F76 /* RecordingsListView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordingsListView.h; sourceTree = "<group>"; };
|
||||
CF7602D5210867E800749F76 /* RecordingsListView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordingsListView.m; sourceTree = "<group>"; };
|
||||
CF7602D6210867E800749F76 /* RecordingsListView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RecordingsListView.xib; sourceTree = "<group>"; };
|
||||
CF7602DF21086EB100749F76 /* RecordingsListTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordingsListTableView.h; sourceTree = "<group>"; };
|
||||
CF7602E021086EB200749F76 /* RecordingsListTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RecordingsListTableView.m; sourceTree = "<group>"; };
|
||||
CF7602E42108759A00749F76 /* UIRecordingCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIRecordingCell.h; sourceTree = "<group>"; };
|
||||
|
|
@ -2100,7 +2101,7 @@
|
|||
CF7602E021086EB200749F76 /* RecordingsListTableView.m */,
|
||||
CF7602D4210867E800749F76 /* RecordingsListView.h */,
|
||||
CF7602D5210867E800749F76 /* RecordingsListView.m */,
|
||||
CF7602D6210867E800749F76 /* RecordingsListView.xib */,
|
||||
617B4A62260A2B7800A87337 /* RecordingsListView.xib */,
|
||||
D35E759C159460B50066B1C1 /* SettingsView.h */,
|
||||
D35E759D159460B50066B1C1 /* SettingsView.m */,
|
||||
636316D61A1DEC650009B839 /* SettingsView.xib */,
|
||||
|
|
@ -3498,7 +3499,7 @@
|
|||
8CE24F4C1F8234A30077AC0A /* next_default@2x.png in Resources */,
|
||||
244523B11E8266CC0037A187 /* chat_read.png in Resources */,
|
||||
61AEBEC62191E47500F35E7F /* chevron_list_close.png in Resources */,
|
||||
CF7602D8210867E800749F76 /* RecordingsListView.xib in Resources */,
|
||||
617B4A60260A2B7800A87337 /* RecordingsListView.xib in Resources */,
|
||||
639E9CAC1C0DB80300019A75 /* UIContactDetailsCell.xib in Resources */,
|
||||
633FEE511D3CD5590014B822 /* deselect_all@2x.png in Resources */,
|
||||
8CF25D951F9F336100BEA0C1 /* check_unselected@2x.png in Resources */,
|
||||
|
|
@ -4359,6 +4360,15 @@
|
|||
name = ShopView.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
617B4A62260A2B7800A87337 /* RecordingsListView.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
617B4A61260A2B7800A87337 /* Base */,
|
||||
617B4A64260A2B8500A87337 /* fr */,
|
||||
);
|
||||
name = RecordingsListView.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
61AE365020C00B370089D9D3 /* MainInterface.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
|
|
@ -4875,7 +4885,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMPRESS_PNG_FILES = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -4904,14 +4914,14 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)";
|
||||
LINK_WITH_STANDARD_LIBRARIES = YES;
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
OTHER_CFLAGS = (
|
||||
"-DBCTBX_LOG_DOMAIN=\\\"ios\\\"",
|
||||
"-DCHECK_VERSION_UPDATE=FALSE",
|
||||
"-DENABLE_QRCODE=TRUE",
|
||||
"-DENABLE_SMS_INVITE=TRUE",
|
||||
"$(inherited)",
|
||||
"-DLINPHONE_SDK_VERSION=\\\"4.4.3\\\"",
|
||||
"-DLINPHONE_SDK_VERSION=\\\"4.5.0-beta.31+1a68848\\\"",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone;
|
||||
|
|
@ -5001,7 +5011,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMPRESS_PNG_FILES = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5027,14 +5037,14 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)";
|
||||
LINK_WITH_STANDARD_LIBRARIES = YES;
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
OTHER_CFLAGS = (
|
||||
"-DBCTBX_LOG_DOMAIN=\\\"ios\\\"",
|
||||
"-DCHECK_VERSION_UPDATE=FALSE",
|
||||
"-DENABLE_QRCODE=TRUE",
|
||||
"-DENABLE_SMS_INVITE=TRUE",
|
||||
"$(inherited)",
|
||||
"-DLINPHONE_SDK_VERSION=\\\"4.4.3\\\"",
|
||||
"-DLINPHONE_SDK_VERSION=\\\"4.5.0-beta.31+1a68848\\\"",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone;
|
||||
|
|
@ -5123,7 +5133,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMPRESS_PNG_FILES = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5149,14 +5159,14 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)";
|
||||
LINK_WITH_STANDARD_LIBRARIES = YES;
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
OTHER_CFLAGS = (
|
||||
"-DBCTBX_LOG_DOMAIN=\\\"ios\\\"",
|
||||
"-DCHECK_VERSION_UPDATE=FALSE",
|
||||
"-DENABLE_QRCODE=TRUE",
|
||||
"-DENABLE_SMS_INVITE=TRUE",
|
||||
"$(inherited)",
|
||||
"-DLINPHONE_SDK_VERSION=\\\"4.4.3\\\"",
|
||||
"-DLINPHONE_SDK_VERSION=\\\"4.5.0-beta.31+1a68848\\\"",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone;
|
||||
|
|
@ -5244,7 +5254,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMPRESS_PNG_FILES = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5270,14 +5280,14 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)";
|
||||
LINK_WITH_STANDARD_LIBRARIES = YES;
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
OTHER_CFLAGS = (
|
||||
"-DBCTBX_LOG_DOMAIN=\\\"ios\\\"",
|
||||
"-DCHECK_VERSION_UPDATE=FALSE",
|
||||
"-DENABLE_QRCODE=TRUE",
|
||||
"-DENABLE_SMS_INVITE=TRUE",
|
||||
"$(inherited)",
|
||||
"-DLINPHONE_SDK_VERSION=\\\"4.4.3\\\"",
|
||||
"-DLINPHONE_SDK_VERSION=\\\"4.5.0-beta.31+1a68848\\\"",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone;
|
||||
|
|
@ -5317,7 +5327,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5329,7 +5339,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = linphoneExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone.linphoneExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|
@ -5359,7 +5369,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5370,7 +5380,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = linphoneExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone.linphoneExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|
@ -5400,7 +5410,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5411,7 +5421,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = linphoneExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone.linphoneExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|
@ -5442,7 +5452,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5453,7 +5463,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = linphoneExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone.linphoneExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|
@ -5536,7 +5546,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5553,7 +5563,7 @@
|
|||
INFOPLIST_FILE = "$(SRCROOT)/msgNotificationService/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
|
|
@ -5592,7 +5602,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5605,7 +5615,7 @@
|
|||
INFOPLIST_FILE = "$(SRCROOT)/msgNotificationService/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
|
|
@ -5644,7 +5654,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5657,7 +5667,7 @@
|
|||
INFOPLIST_FILE = "$(SRCROOT)/msgNotificationService/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
|
|
@ -5696,7 +5706,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5709,7 +5719,7 @@
|
|||
INFOPLIST_FILE = "$(SRCROOT)/msgNotificationService/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
|
|
@ -5747,7 +5757,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5764,7 +5774,7 @@
|
|||
INFOPLIST_FILE = msgNotificationContent/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
|
|
@ -5802,7 +5812,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5815,7 +5825,7 @@
|
|||
INFOPLIST_FILE = msgNotificationContent/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
|
|
@ -5853,7 +5863,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5866,7 +5876,7 @@
|
|||
INFOPLIST_FILE = msgNotificationContent/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
|
|
@ -5904,7 +5914,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = Z2V957B3D6;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
|
@ -5917,7 +5927,7 @@
|
|||
INFOPLIST_FILE = msgNotificationContent/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.3.2;
|
||||
MARKETING_VERSION = 4.4.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited)";
|
||||
|
|
|
|||
|
|
@ -30,45 +30,42 @@ enum LinphoneError: Error {
|
|||
class LinphoneLoggingServiceManager: LoggingServiceDelegate {
|
||||
init(config: Config, log: LoggingService?, domain: String) throws {
|
||||
if let log = log {
|
||||
super.init()
|
||||
let debugLevel = config.getInt(section: "app", key: "debugenable_preference", defaultValue: LogLevel.Debug.rawValue)
|
||||
let debugEnabled = (debugLevel >= LogLevel.Debug.rawValue && debugLevel < LogLevel.Error.rawValue)
|
||||
|
||||
if (debugEnabled) {
|
||||
Factory.Instance.logCollectionPath = Factory.Instance.getDownloadDir(context: UnsafeMutablePointer<Int8>(mutating: (APP_GROUP_ID as NSString).utf8String))
|
||||
Factory.Instance.enableLogCollection(state: LogCollectionState.Enabled)
|
||||
log.domain = domain
|
||||
log.logLevel = LogLevel(rawValue: debugLevel)
|
||||
log.addDelegate(delegate: self)
|
||||
}
|
||||
Factory.Instance.logCollectionPath = Factory.Instance.getDownloadDir(context: UnsafeMutablePointer<Int8>(mutating: (APP_GROUP_ID as NSString).utf8String))
|
||||
Factory.Instance.enableLogCollection(state: debugEnabled ? LogCollectionState.Enabled : LogCollectionState.Disabled)
|
||||
log.domain = domain
|
||||
log.logLevel = debugLevel==0 ? LogLevel.Fatal : LogLevel(rawValue: debugLevel)
|
||||
log.addDelegate(delegate: self)
|
||||
} else {
|
||||
throw LinphoneError.loggingServiceUninitialized
|
||||
}
|
||||
}
|
||||
|
||||
override func onLogMessageWritten(logService: LoggingService, domain: String, lev: LogLevel, message: String) {
|
||||
let level: String
|
||||
func onLogMessageWritten(logService: LoggingService, domain: String, level: LogLevel, message: String) {
|
||||
let levelStr: String
|
||||
|
||||
switch lev {
|
||||
switch level {
|
||||
case .Debug:
|
||||
level = "Debug"
|
||||
levelStr = "Debug"
|
||||
case .Trace:
|
||||
level = "Trace"
|
||||
levelStr = "Trace"
|
||||
case .Message:
|
||||
level = "Message"
|
||||
levelStr = "Message"
|
||||
case .Warning:
|
||||
level = "Warning"
|
||||
levelStr = "Warning"
|
||||
case .Error:
|
||||
level = "Error"
|
||||
levelStr = "Error"
|
||||
case .Fatal:
|
||||
level = "Fatal"
|
||||
levelStr = "Fatal"
|
||||
default:
|
||||
level = "unknown"
|
||||
levelStr = "unknown"
|
||||
}
|
||||
|
||||
#if USE_CRASHLYTICS
|
||||
Crashlytics.crashlytics().log("\(level) [\(domain)] \(message)\n")
|
||||
Crashlytics.crashlytics().log("\(levelStr) [\(domain)] \(message)\n")
|
||||
#endif
|
||||
NSLog("\(level) [\(domain)] \(message)\n")
|
||||
NSLog("\(levelStr) [\(domain)] \(message)\n")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,13 +31,11 @@ var needToStop: Bool = false
|
|||
var coreStopped: Bool = false
|
||||
var log: LoggingService!
|
||||
|
||||
class NotificationViewController: UIViewController, UNNotificationContentExtension {
|
||||
class NotificationViewController: UIViewController, UNNotificationContentExtension, ChatMessageDelegate, CoreDelegate {
|
||||
|
||||
var lc: Core?
|
||||
var config: Config!
|
||||
var logDelegate: LinphoneLoggingServiceManager!
|
||||
var msgDelegate: LinphoneChatMessageManager!
|
||||
var coreDelegate: LinphoneCoreManager!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
|
@ -82,7 +80,7 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
|
|||
}
|
||||
|
||||
if (needToStop) {
|
||||
log.error(msg: "core stopped by app")
|
||||
log.error(message: "core stopped by app")
|
||||
throw LinphoneError.timeout
|
||||
} else {
|
||||
completion(.dismiss)
|
||||
|
|
@ -90,7 +88,7 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
|
|||
}
|
||||
|
||||
} catch {
|
||||
log.error(msg: "error: \(error)")
|
||||
log.error(message: "error: \(error)")
|
||||
completion(.dismissAndForwardAction)
|
||||
}
|
||||
}
|
||||
|
|
@ -120,65 +118,59 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
|
|||
let local = try lc!.createAddress(address: localAddress)
|
||||
let room = lc!.findChatRoom(peerAddr: peer, localAddr: local)
|
||||
if let room = room {
|
||||
msgDelegate = LinphoneChatMessageManager()
|
||||
let chatMsg = try room.createMessage(message: replyText)
|
||||
chatMsg.addDelegate(delegate: msgDelegate)
|
||||
room.sendChatMessage(msg: chatMsg)
|
||||
chatMsg.addDelegate(delegate: self)
|
||||
chatMsg.send()
|
||||
room.markAsRead()
|
||||
}
|
||||
|
||||
for i in 0...50 where !isReplySent && !needToStop {
|
||||
log.debug(msg: "reply \(i)")
|
||||
log.debug(message: "reply \(i)")
|
||||
lc!.iterate()
|
||||
usleep(10000)
|
||||
}
|
||||
}
|
||||
|
||||
func startCore() throws {
|
||||
config = Config.newForSharedCore(appGroupId: APP_GROUP_ID, configFilename: "linphonerc", factoryPath: "")
|
||||
config = Config.newForSharedCore(appGroupId: APP_GROUP_ID, configFilename: "linphonerc", factoryConfigFilename: "")
|
||||
log = LoggingService.Instance /*enable liblinphone logs.*/
|
||||
logDelegate = try! LinphoneLoggingServiceManager(config: config, log: log, domain: "msgNotificationContent")
|
||||
lc = try! Factory.Instance.createSharedCoreWithConfig(config: config, systemContext: nil, appGroupId: APP_GROUP_ID, mainCore: false)
|
||||
|
||||
coreDelegate = LinphoneCoreManager()
|
||||
lc!.addDelegate(delegate: coreDelegate)
|
||||
lc!.addDelegate(delegate: self)
|
||||
|
||||
try lc!.start()
|
||||
log.message(msg: "core started")
|
||||
log.message(message: "core started")
|
||||
|
||||
if (needToStop) {
|
||||
log.error(msg: "core stopped by app")
|
||||
log.error(message: "core stopped by app")
|
||||
throw LinphoneError.timeout
|
||||
}
|
||||
}
|
||||
|
||||
func stopCore() {
|
||||
lc!.stopAsync()
|
||||
log.message(msg: "stop core")
|
||||
log.message(message: "stop core")
|
||||
for i in 0...100 where !coreStopped {
|
||||
log.debug(msg: "stop \(i)")
|
||||
log.debug(message: "stop \(i)")
|
||||
lc!.iterate()
|
||||
usleep(50000)
|
||||
}
|
||||
}
|
||||
|
||||
class LinphoneCoreManager: CoreDelegate {
|
||||
override func onGlobalStateChanged(lc: Core, gstate: GlobalState, message: String) {
|
||||
log.message(msg: "global state changed: \(gstate) : \(message) \n")
|
||||
if (gstate == .Shutdown) {
|
||||
needToStop = true
|
||||
} else if (gstate == .Off) {
|
||||
coreStopped = true
|
||||
}
|
||||
}
|
||||
}
|
||||
func onGlobalStateChanged(core: Core, state gstate: GlobalState, message: String) {
|
||||
log.message(message: "global state changed: \(gstate) : \(message) \n")
|
||||
if (gstate == .Shutdown) {
|
||||
needToStop = true
|
||||
} else if (gstate == .Off) {
|
||||
coreStopped = true
|
||||
}
|
||||
}
|
||||
|
||||
class LinphoneChatMessageManager: ChatMessageDelegate {
|
||||
override func onMsgStateChanged(msg: ChatMessage, state: ChatMessage.State) {
|
||||
log.message(msg: "msg state changed: \(state)\n")
|
||||
if (state == .Delivered) {
|
||||
isReplySent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
func onMsgStateChanged(message: ChatMessage, state: ChatMessage.State) {
|
||||
log.message(message: "msg state changed: \(state)\n")
|
||||
if (state == .Delivered) {
|
||||
isReplySent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,15 +58,15 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
|
||||
if let bestAttemptContent = bestAttemptContent {
|
||||
createCore()
|
||||
NotificationService.log.message(msg: "received push payload : \(bestAttemptContent.userInfo.debugDescription)")
|
||||
NotificationService.log.message(message: "received push payload : \(bestAttemptContent.userInfo.debugDescription)")
|
||||
|
||||
if let chatRoomInviteAddr = bestAttemptContent.userInfo["chat-room-addr"] as? String, !chatRoomInviteAddr.isEmpty {
|
||||
NotificationService.log.message(msg: "fetch chat room for invite, addr: \(chatRoomInviteAddr)")
|
||||
NotificationService.log.message(message: "fetch chat room for invite, addr: \(chatRoomInviteAddr)")
|
||||
let chatRoom = lc!.getNewChatRoomFromConfAddr(chatRoomAddr: chatRoomInviteAddr)
|
||||
|
||||
if let chatRoom = chatRoom {
|
||||
stopCore()
|
||||
NotificationService.log.message(msg: "chat room invite received")
|
||||
NotificationService.log.message(message: "chat room invite received")
|
||||
bestAttemptContent.title = NSLocalizedString("GC_MSG", comment: "")
|
||||
if (chatRoom.hasCapability(mask:ChatRoomCapabilities.OneToOne.rawValue)) {
|
||||
if (chatRoom.peerAddress?.displayName.isEmpty != true) {
|
||||
|
|
@ -83,13 +83,15 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
return
|
||||
}
|
||||
} else if let callId = bestAttemptContent.userInfo["call-id"] as? String {
|
||||
NotificationService.log.message(msg: "fetch msg for callid ["+callId+"]")
|
||||
NotificationService.log.message(message: "fetch msg for callid ["+callId+"]")
|
||||
let message = lc!.getNewMessageFromCallid(callId: callId)
|
||||
|
||||
if let message = message {
|
||||
let msgData = parseMessage(message: message)
|
||||
|
||||
if !message.isUsingUserDefaults, let badge = updateBadge() as NSNumber? {
|
||||
// Extension only upates app's badge when main shared core is Off = extension's core is On.
|
||||
// Otherwise, the app will update the badge.
|
||||
if lc?.globalState == GlobalState.On, let badge = updateBadge() as NSNumber? {
|
||||
bestAttemptContent.badge = badge
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +116,7 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
contentHandler(bestAttemptContent)
|
||||
return
|
||||
} else {
|
||||
NotificationService.log.message(msg: "Message not found for callid ["+callId+"]")
|
||||
NotificationService.log.message(message: "Message not found for callid ["+callId+"]")
|
||||
}
|
||||
}
|
||||
serviceExtensionTimeWillExpire()
|
||||
|
|
@ -124,7 +126,7 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
override func serviceExtensionTimeWillExpire() {
|
||||
// Called just before the extension will be terminated by the system.
|
||||
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
|
||||
NotificationService.log.warning(msg: "serviceExtensionTimeWillExpire")
|
||||
NotificationService.log.warning(message: "serviceExtensionTimeWillExpire")
|
||||
stopCore()
|
||||
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
|
||||
NSLog("[msgNotificationService] serviceExtensionTimeWillExpire")
|
||||
|
|
@ -174,15 +176,15 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
}
|
||||
}
|
||||
|
||||
NotificationService.log.message(msg: "msg: \(content) \n")
|
||||
NotificationService.log.message(message: "msg: \(content) \n")
|
||||
return msgData;
|
||||
}
|
||||
|
||||
func createCore() {
|
||||
NSLog("[msgNotificationService] create core")
|
||||
let config = Config.newForSharedCore(appGroupId: APP_GROUP_ID, configFilename: "linphonerc", factoryPath: "")
|
||||
let config = Config.newForSharedCore(appGroupId: APP_GROUP_ID, configFilename: "linphonerc", factoryConfigFilename: "")
|
||||
|
||||
if (NotificationService.log == nil || NotificationService.log.getDelegate() == nil) {
|
||||
if (NotificationService.log == nil) {
|
||||
NotificationService.log = LoggingService.Instance /*enable liblinphone logs.*/
|
||||
NotificationService.logDelegate = try! LinphoneLoggingServiceManager(config: config!, log: NotificationService.log, domain: "msgNotificationService")
|
||||
}
|
||||
|
|
@ -190,7 +192,7 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
}
|
||||
|
||||
func stopCore() {
|
||||
NotificationService.log.message(msg: "stop core")
|
||||
NotificationService.log.message(message: "stop core")
|
||||
if let lc = lc {
|
||||
lc.stop()
|
||||
}
|
||||
|
|
@ -201,14 +203,14 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
count += lc!.unreadChatMessageCount
|
||||
count += lc!.missedCallsCount
|
||||
count += lc!.callsNb
|
||||
NotificationService.log.message(msg: "badge: \(count)\n")
|
||||
NotificationService.log.message(message: "badge: \(count)\n")
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
func getDisplayNameFromSipAddress(sipAddr: String?) -> String? {
|
||||
if let sipAddr = sipAddr {
|
||||
NotificationService.log.message(msg: "looking for display name for \(sipAddr)")
|
||||
NotificationService.log.message(message: "looking for display name for \(sipAddr)")
|
||||
|
||||
if (sipAddr == "") { return nil }
|
||||
|
||||
|
|
@ -216,17 +218,21 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
let addressBook = defaults?.dictionary(forKey: "addressBook")
|
||||
|
||||
if (addressBook == nil) {
|
||||
NotificationService.log.message(msg: "address book not found in userDefaults")
|
||||
NotificationService.log.message(message: "address book not found in userDefaults")
|
||||
return nil
|
||||
}
|
||||
|
||||
if let displayName = addressBook?[sipAddr] as? String {
|
||||
NotificationService.log.message(msg: "display name for \(sipAddr): \(displayName)")
|
||||
return displayName
|
||||
} else {
|
||||
NotificationService.log.message(msg: "display name for \(sipAddr) not found in userDefaults")
|
||||
return nil
|
||||
if let simpleAddr = lc?.interpretUrl(url: sipAddr) {
|
||||
simpleAddr.clean()
|
||||
let nomalSipaddr = simpleAddr.asString()
|
||||
if let displayName = addressBook?[nomalSipaddr] as? String {
|
||||
NotificationService.log.message(message: "display name for \(sipAddr): \(displayName)")
|
||||
return displayName
|
||||
}
|
||||
}
|
||||
|
||||
NotificationService.log.message(message: "display name for \(sipAddr) not found in userDefaults")
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue