New conference API & Participant list in Guest conf merge

This commit is contained in:
Christophe Deschamps 2021-09-16 09:41:23 +02:00
commit 8183282466
70 changed files with 2257 additions and 548 deletions

View file

@ -64,4 +64,16 @@ enum NetworkType: Int {
//The recording prefix is used to identify recordings in the cache directory.
//We will use name_dayName-day-monthName-year to separate recordings by days, then hour-minutes-seconds to order them in each day.
}
@objc static func removeFile(file: String) {
let fileManager = FileManager.default
do {
try fileManager.removeItem(atPath: file)
Log.directLog(BCTBX_LOG_MESSAGE, text: "File :\(file) removed")
} catch {
print("Could not remove file : \(file) \(error)")
}
}
}

View file

@ -1,17 +1,15 @@
<?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="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<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="ChatConversationImdnView">
<connections>
<outlet property="msgAvatarImage" destination="LGG-kB-TaR" id="U4L-qV-ea2"/>
<outlet property="msgBackgroundColorImage" destination="wJQ-zl-d5O" id="D3d-vT-rFx"/>
<outlet property="msgBottomBar" destination="Mxm-1h-7dz" id="wS1-AL-B5M"/>
<outlet property="msgDateLabel" destination="jaE-4d-bbo" id="W3u-tE-pGo"/>
<outlet property="msgText" destination="V21-2s-obu" id="iTL-AZ-o7h"/>
<outlet property="msgView" destination="VK8-0e-Hsa" id="sWi-sR-kan"/>
<outlet property="tableView" destination="HjO-C8-Itr" id="cuC-QY-xbT"/>
<outlet property="view" destination="1g1-pp-Uhi" id="Km4-Mj-txf"/>
@ -19,19 +17,19 @@
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="1g1-pp-Uhi" userLabel="iphone6MetricsView">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7Tm-Jz-Rvb">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view alpha="0.90000000000000002" contentMode="scaleToFill" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X8x-9L-bCY" userLabel="topBar">
<rect key="frame" x="0.0" y="0.0" width="375" height="66"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="66"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="5" contentMode="left" fixedFrame="YES" text="Delivery status" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="bc0-Ql-lPE" userLabel="addressLabel">
<rect key="frame" x="112" y="0.0" width="150" height="66"/>
<rect key="frame" x="123" y="0.0" width="166" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Contact name">
<accessibilityTraits key="traits" none="YES"/>
@ -41,7 +39,7 @@
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JYS-Be-ffH" userLabel="backButton" customClass="UIInterfaceStyleButton">
<rect key="frame" x="0.0" y="0.0" width="75" height="66"/>
<rect key="frame" x="0.0" y="0.0" width="82" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Back"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
@ -56,55 +54,21 @@
</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>
<view clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VK8-0e-Hsa" userLabel="msgView">
<rect key="frame" x="8" y="74" width="359" height="89"/>
<rect key="frame" x="8" y="74" width="398" height="123"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" alpha="0.20000000298023224" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="wJQ-zl-d5O" userLabel="backgroundColorImage">
<rect key="frame" x="0.0" y="0.0" width="359" height="89"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="LGG-kB-TaR" userLabel="avatarImage" customClass="UIRoundedImageView">
<rect key="frame" x="7" y="7" width="40" height="40"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Contact avatar">
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
<bool key="isElement" value="YES"/>
</accessibility>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" fixedFrame="YES" text="11:35 John Doe" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jaE-4d-bbo" userLabel="contactDateLabel">
<rect key="frame" x="55" y="8" width="279" height="14"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Contact name"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" red="0.98766469960000003" green="0.27512490750000002" blue="0.029739789660000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="Mxm-1h-7dz" userLabel="bottomBarColor">
<rect key="frame" x="0.0" y="88" width="359" height="1"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
</imageView>
<textView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" editable="NO" text="Lore ipsum..." translatesAutoresizingMaskIntoConstraints="NO" id="V21-2s-obu" userLabel="messageText" customClass="UITextViewNoDefine">
<rect key="frame" x="52" y="29" width="296" height="49"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
<dataDetectorType key="dataDetectorTypes" link="YES"/>
</textView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<tableView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" allowsSelectionDuringEditing="YES" allowsMultipleSelectionDuringEditing="YES" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="HjO-C8-Itr">
<rect key="frame" x="8" y="171" width="359" height="496"/>
<rect key="frame" x="8" y="229" width="398" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<color key="separatorColor" red="0.67030966280000004" green="0.71867996450000005" blue="0.75078284740000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</tableView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -112,10 +76,14 @@
</view>
</objects>
<resources>
<image name="avatar.png" width="414.39999389648438" height="414.39999389648438"/>
<image name="back_default.png" width="38.400001525878906" height="35.200000762939453"/>
<image name="back_disabled.png" width="38.400001525878906" height="35.200000762939453"/>
<image name="color_A.png" width="2" height="2"/>
<image name="color_E.png" width="2" height="2"/>
<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>

View file

@ -31,12 +31,22 @@
<outlet property="pictureButton" destination="73" id="84"/>
<outlet property="popupMenu" destination="gdT-1Q-vU2" id="M7Q-tv-zRF"/>
<outlet property="portraitView" destination="6" id="xJJ-1H-6N6"/>
<outlet property="replyView" destination="wve-MK-7ME" id="fhJ-ne-9Xx"/>
<outlet property="sendButton" destination="15" id="27"/>
<outlet property="tableController" destination="29" id="32"/>
<outlet property="toggleMenuButton" destination="CPn-Oc-9PX" id="QdS-xO-bfA"/>
<outlet property="toggleRecord" destination="aTi-pm-fAG" id="RYV-0Q-v5p"/>
<outlet property="toggleSelectionButton" destination="c9z-aq-2UP" id="kiK-wF-8iU"/>
<outlet property="topBar" destination="7" id="JH8-F4-Bdq"/>
<outlet property="view" destination="6" id="11"/>
<outlet property="vrDeleteButton" destination="wi9-en-JCZ" id="09B-Bm-ECJ"/>
<outlet property="vrDurationLabel" destination="dMW-Ix-4k0" id="Ugl-f5-r2m"/>
<outlet property="vrInnerView" destination="eXD-Gd-FXA" id="wBh-N1-Au9"/>
<outlet property="vrPlayButton" destination="FNM-bb-AlC" id="NOD-GE-eIA"/>
<outlet property="vrView" destination="Tru-Zm-4EZ" id="Rx2-ls-nMc"/>
<outlet property="vrWave" destination="m9m-2e-T7E" id="F07-qS-Yj6"/>
<outlet property="vrWaveMask" destination="TzM-ND-yp4" id="FKT-Gu-CyA"/>
<outlet property="vrWaveMaskPlayer" destination="OTf-Od-TDn" id="g9D-K1-Gf0"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
@ -209,7 +219,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<tableView clipsSubviews="YES" tag="13" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="none" allowsSelection="NO" allowsSelectionDuringEditing="YES" allowsMultipleSelectionDuringEditing="YES" rowHeight="60" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="8" userLabel="messagesTableView">
<rect key="frame" x="0.0" y="0.0" width="414" height="634"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="574"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<gestureRecognizers/>
@ -221,7 +231,7 @@
</connections>
</tableView>
<view hidden="YES" tag="14" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fx4-ao-53M" userLabel="composeIndicatorView">
<rect key="frame" x="0.0" y="634" width="414" height="22"/>
<rect key="frame" x="0.0" y="574" width="414" height="22"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="15" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="%@ is composing..." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="fpY-Fv-ht2" userLabel="composeLabel">
@ -236,7 +246,7 @@
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="16" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No conversation." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p7C-WH-uR1" userLabel="emptyTableLabel">
<rect key="frame" x="0.0" y="0.0" width="414" height="625"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="574"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
@ -260,6 +270,19 @@
<action selector="onPictureClick:" destination="-1" eventType="touchUpInside" id="87"/>
</connections>
</button>
<button opaque="NO" tag="9019" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aTi-pm-fAG" userLabel="audioRecordingButton">
<rect key="frame" x="66" y="0.0" width="56" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Send picture"/>
<inset key="imageEdgeInsets" minX="15" minY="20" maxX="15" maxY="20"/>
<state key="normal" image="vr_off.png">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="selected" image="vr_on.png"/>
<connections>
<action selector="onVrStart:" destination="-1" eventType="touchUpInside" id="6QP-19-E8o"/>
</connections>
</button>
<button opaque="NO" tag="21" contentMode="scaleToFill" fixedFrame="YES" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="15" userLabel="sendButton">
<rect key="frame" x="349" y="0.0" width="66" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
@ -275,7 +298,7 @@
</connections>
</button>
<view tag="20" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pqa-tg-5ml" userLabel="messageField" customClass="HPGrowingTextView">
<rect key="frame" x="72" y="13" width="269" height="40"/>
<rect key="frame" x="130" y="13" width="208" height="40"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<accessibility key="accessibilityConfiguration" label="Message field"/>
@ -287,7 +310,59 @@
</subviews>
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
</view>
<view clipsSubviews="YES" alpha="0.90000000000000002" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3qd-ys-t2L" userLabel="imagesView">
<view hidden="YES" tag="28021" contentMode="scaleToFill" id="Tru-Zm-4EZ" userLabel="VoiceRecording">
<rect key="frame" x="0.0" y="596" width="414" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
<subviews>
<button opaque="NO" tag="28022" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wi9-en-JCZ">
<rect key="frame" x="12" y="13" width="24" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<state key="normal" image="delete_default.png"/>
<connections>
<action selector="onVrDelete:" destination="-1" eventType="touchUpInside" id="yV4-iY-mvE"/>
</connections>
</button>
<view tag="28023" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eXD-Gd-FXA">
<rect key="frame" x="50" y="8" width="302" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<view tag="28024" contentMode="scaleToFill" id="OTf-Od-TDn" userLabel="vr_wave_mask_playback">
<rect key="frame" x="0.0" y="0.0" width="240" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.93333333330000001" green="0.93333333330000001" blue="0.93333333330000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" tag="28025" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="vr_wave.png" translatesAutoresizingMaskIntoConstraints="NO" id="m9m-2e-T7E">
<rect key="frame" x="8" y="8" width="232" height="28"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</imageView>
<view tag="28026" contentMode="scaleToFill" id="TzM-ND-yp4" userLabel="vr_wave_mask_record">
<rect key="frame" x="0.0" y="0.0" width="240" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<label opaque="NO" userInteractionEnabled="NO" tag="28027" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dMW-Ix-4k0">
<rect key="frame" x="245" y="12" width="49" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
<button opaque="NO" tag="28028" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FNM-bb-AlC">
<rect key="frame" x="366" y="13" width="35" height="35"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<state key="normal" image="vr_play.png"/>
<connections>
<action selector="onvrPlayPauseStop:" destination="-1" eventType="touchUpInside" id="Wka-en-Ic8"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="0.93333333330000001" green="0.93333333330000001" blue="0.93333333330000001" alpha="1" colorSpace="calibratedRGB"/>
</view>
<view clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3qd-ys-t2L" userLabel="imagesView">
<rect key="frame" x="0.0" y="625" width="414" height="0.0"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
@ -313,6 +388,11 @@
<action selector="onEncryptedDevicesClick:" destination="-1" eventType="touchUpInside" id="K1W-Ao-IDg"/>
</connections>
</button>
<view hidden="YES" tag="290392" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wve-MK-7ME" userLabel="ReplyView">
<rect key="frame" x="0.0" y="536" width="414" height="120"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
</view>
<tableView hidden="YES" clipsSubviews="YES" tag="6992" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="gdT-1Q-vU2" userLabel="popupMenu">
@ -551,8 +631,21 @@
<action selector="onPictureClick:" destination="-1" eventType="touchUpInside" id="Ag3-po-DGR"/>
</connections>
</button>
<button opaque="NO" tag="9019" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zub-Ow-smm" userLabel="audioRecordingButton">
<rect key="frame" x="66" y="0.0" width="66" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Send picture"/>
<state key="normal" image="vr_off.png">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="selected" image="vr_on.png"/>
<connections>
<action selector="onPictureClick:" destination="-1" eventType="touchUpInside" id="qhP-B0-dkG"/>
<action selector="onVrStart:" destination="-1" eventType="touchUpInside" id="yWJ-st-yz2"/>
</connections>
</button>
<view tag="20" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="C02-2r-vXK" userLabel="messageField" customClass="HPGrowingTextView">
<rect key="frame" x="32" y="13" width="257" height="40"/>
<rect key="frame" x="59" y="13" width="230" height="40"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" label="Message field"/>
@ -637,10 +730,14 @@
<image name="delete_disabled.png" width="34.400001525878906" height="44.799999237060547"/>
<image name="deselect_all.png" width="43.200000762939453" height="43.200000762939453"/>
<image name="ephemeral_messages_color_A.png" width="136" height="158.39999389648438"/>
<image name="more_menu_default.png" width="10.319999694824219" height="13.680000305175781"/>
<image name="more_menu_default.png" width="7.1999998092651367" height="9.3599996566772461"/>
<image name="security_1_indicator.png" width="27.5" height="32.5"/>
<image name="select_all_default.png" width="43.200000762939453" height="43.200000762939453"/>
<image name="select_all_disabled.png" width="43.200000762939453" height="43.200000762939453"/>
<image name="vr_off.png" width="40" height="40"/>
<image name="vr_on.png" width="40" height="40"/>
<image name="vr_play.png" width="200" height="200"/>
<image name="vr_wave.png" width="1078" height="90"/>
<systemColor name="secondarySystemBackgroundColor">
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>

View file

@ -1,7 +1,10 @@
<?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" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -10,6 +13,8 @@
<outlet property="addButton" destination="Z5G-IF-PBY" id="Tzw-rz-Bwe"/>
<outlet property="addGroupChatButton" destination="glf-ni-nqe" id="0hy-5m-7C7"/>
<outlet property="backToCallButton" destination="Fac-hy-za4" id="8I3-TM-oJ7"/>
<outlet property="cancelForwardButton" destination="Kxx-SO-CB0" id="LFJ-NQ-YrU"/>
<outlet property="forwardTitle" destination="waa-HU-xFW" id="Qqs-p4-k9A"/>
<outlet property="tableController" destination="4" id="18"/>
<outlet property="toggleSelectionButton" destination="uqG-2T-VOa" id="cAk-tz-5Z0"/>
<outlet property="view" destination="5" id="14"/>
@ -18,19 +23,19 @@
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="WKv-mw-S2B" userLabel="iphone6MetricsView">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5">
<rect key="frame" x="0.0" y="42" width="375" height="559"/>
<rect key="frame" x="0.0" y="42" width="414" height="788"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view alpha="0.90000000000000002" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7" userLabel="topBar">
<rect key="frame" x="0.0" y="0.0" width="375" height="66"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="66"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Z5G-IF-PBY" userLabel="addButton" customClass="UIInterfaceStyleButton">
<rect key="frame" x="0.0" y="0.0" width="75" height="66"/>
<rect key="frame" x="0.0" y="0.0" width="82" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="New discussion"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
@ -45,7 +50,7 @@
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="glf-ni-nqe" userLabel="addGroupButton" customClass="UIInterfaceStyleButton">
<rect key="frame" x="75" y="0.0" width="75" height="66"/>
<rect key="frame" x="82" y="0.0" width="83" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="New discussion"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
@ -60,7 +65,7 @@
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KhE-c3-2Zj" userLabel="cancelButton" customClass="UIInterfaceStyleButton">
<rect key="frame" x="0.0" y="0.0" width="75" height="66"/>
<rect key="frame" x="0.0" y="0.0" width="82" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Delete all"/>
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
@ -74,8 +79,22 @@
<action selector="onEditionChangeClick:" destination="-1" eventType="touchUpInside" id="hKF-q1-5DJ"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Kxx-SO-CB0" userLabel="cancelForwardButton" customClass="UIInterfaceStyleButton">
<rect key="frame" x="0.0" y="0.0" width="82" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Delete all"/>
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
<state key="normal" image="cancel_forward.png">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="disabled" image="cancel_edit_disabled.png"/>
<state key="highlighted" backgroundImage="color_E.png"/>
<connections>
<action selector="onCancelForwardClicked:" destination="-1" eventType="touchUpInside" id="2gp-RW-sJE"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Fac-hy-za4" userLabel="backToCallButton" customClass="UIBackToCallButton">
<rect key="frame" x="150" y="0.0" width="75" height="66"/>
<rect key="frame" x="165" y="0.0" width="83" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<state key="normal" image="call_back_default.png">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -88,7 +107,7 @@
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" reversesTitleShadowWhenHighlighted="YES" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="uqG-2T-VOa" userLabel="toggleSelectionButton" customClass="UIInterfaceStyleButton">
<rect key="frame" x="225" y="0.0" width="75" height="66"/>
<rect key="frame" x="248" y="0.0" width="83" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Select all"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
@ -104,7 +123,7 @@
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Rxo-0W-iqY" userLabel="deleteButton" customClass="UIInterfaceStyleButton">
<rect key="frame" x="300" y="0.0" width="75" height="66"/>
<rect key="frame" x="331" y="0.0" width="83" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Delete all"/>
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
@ -118,7 +137,7 @@
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qem-Y1-v78" userLabel="editButton" customClass="UIInterfaceStyleButton">
<rect key="frame" x="300" y="0.0" width="75" height="66"/>
<rect key="frame" x="331" y="0.0" width="83" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Edit"/>
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
@ -133,12 +152,12 @@
</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>
<tableView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" allowsSelectionDuringEditing="YES" allowsMultipleSelectionDuringEditing="YES" rowHeight="60" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="6" userLabel="tableView">
<rect key="frame" x="0.0" y="66" width="375" height="493"/>
<rect key="frame" x="0.0" y="66" width="414" height="722"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<inset key="scrollIndicatorInsets" minX="0.0" minY="0.0" maxX="0.0" maxY="10"/>
<color key="separatorColor" red="0.67030966281890869" green="0.71867996454238892" blue="0.75078284740447998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
@ -146,31 +165,39 @@
<outlet property="delegate" destination="4" id="12"/>
</connections>
</tableView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="waa-HU-xFW" userLabel="forwardTitle">
<rect key="frame" x="0.0" y="66" width="414" height="66"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No conversations" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MSn-PY-yf1" userLabel="emptyTableLabel">
<rect key="frame" x="0.0" y="66" width="375" height="493"/>
<rect key="frame" x="0.0" y="66" width="414" height="722"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view hidden="YES" tag="8" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cpj-Jc-imm" userLabel="waitView">
<rect key="frame" x="0.0" y="0.0" width="375" height="559"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="788"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<activityIndicatorView opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="DjR-Dv-uoX" userLabel="activityIndicatorView">
<rect key="frame" x="179" y="267" width="20" height="20"/>
<rect key="frame" x="198" y="380" width="20" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</activityIndicatorView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<gestureRecognizers/>
</view>
</subviews>
</view>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<point key="canvasLocation" x="52" y="93.103448275862078"/>
<point key="canvasLocation" x="50.724637681159422" y="93.080357142857139"/>
</view>
<tableViewController autoresizesArchivedViewToFullSize="NO" id="4" userLabel="tableController" customClass="ChatsListTableView">
<extendedEdge key="edgesForExtendedLayout"/>
@ -190,6 +217,7 @@
<image name="call_back_disabled.png" width="61.599998474121094" height="44"/>
<image name="cancel_edit_default.png" width="47.200000762939453" height="47.200000762939453"/>
<image name="cancel_edit_disabled.png" width="47.200000762939453" height="47.200000762939453"/>
<image name="cancel_forward.png" width="80" height="80"/>
<image name="chat_add_default.png" width="50.400001525878906" height="44.799999237060547"/>
<image name="chat_add_group.png" width="64" height="42.400001525878906"/>
<image name="color_E.png" width="2" height="2"/>
@ -198,5 +226,11 @@
<image name="deselect_all.png" width="43.200000762939453" height="43.200000762939453"/>
<image name="select_all_default.png" width="43.200000762939453" height="43.200000762939453"/>
<image name="select_all_disabled.png" width="43.200000762939453" height="43.200000762939453"/>
<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>

View file

@ -651,9 +651,31 @@ import AVFoundation
}
}
// Audio messages
@objc func activateAudioSession() {
lc?.activateAudioSession(actived: true)
}
@objc func getSpeakerSoundCard() -> String? {
var speakerCard: String? = nil
var earpieceCard: String? = nil
lc?.audioDevices.forEach { device in
if (device.hasCapability(capability: .CapabilityPlay)) {
if (device.type == .Speaker) {
speakerCard = device.id
} else if (device.type == .Earpiece) {
earpieceCard = device.id
}
}
}
return speakerCard != nil ? speakerCard : earpieceCard
}
// Conference
@objc func hostConference() -> Bool {
return conference != nil
}
@ -748,7 +770,9 @@ import AVFoundation
guard let core = lc else {
return false
}
return isInConference() && (getConference()?.currentParams?.isVideoEnabled == true || core.currentCall?.currentParams?.videoEnabled == true)
let result = isInConference() && (getConference()?.currentParams?.isVideoEnabled == true || core.currentCall?.currentParams?.videoEnabled == true)
NSLog("cdes \(result) \(core.currentCall?.currentParams?.videoEnabled)")
return result
}

View file

@ -683,9 +683,8 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
#pragma mark - ActionSheet Functions
- (void)displayAskToEnableVideoCall:(LinphoneCall *)call {
if (linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call))) {
return;
} else if (CallManager.instance.inVideoConf) {
if (CallManager.instance.inVideoConf) { // we are hosting a video conf, so just accept people wanting to activate video.
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
linphone_call_params_enable_video(params, TRUE);
linphone_call_accept_update(call, params);

View file

@ -36,13 +36,11 @@
@property(nonatomic) bctbx_list_t *receivedList;
@property(nonatomic) bctbx_list_t *notReceivedList;
@property(nonatomic) bctbx_list_t *errorList;
@property(nonatomic) UIChatBubbleTextCell *cell;
@property(nonatomic) NSTimer *ephemeralDisplayTimer;
@property (weak, nonatomic) IBOutlet UIView *msgView;
@property (weak, nonatomic) IBOutlet UIImageView *msgBackgroundColorImage;
@property (weak, nonatomic) IBOutlet UIRoundedImageView *msgAvatarImage;
@property (weak, nonatomic) IBOutlet UIImageView *msgBottomBar;
@property (weak, nonatomic) IBOutlet UILabel *msgDateLabel;
@property (weak, nonatomic) IBOutlet UITextViewNoDefine *msgText;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
- (IBAction)onBackClick:(id)sender;

View file

@ -22,6 +22,7 @@
#import "ChatConversationImdnView.h"
#import "PhoneMainView.h"
#import "UIChatBubbleTextCell.h"
#import "UIChatBubblePhotoCell.h"
#import "UIChatConversationImdnTableViewCell.h"
@implementation ChatConversationImdnView
@ -52,21 +53,40 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
const LinphoneAddress *addr = linphone_chat_message_get_from_address(_msg);
BOOL outgoing = linphone_chat_message_is_outgoing(_msg);
_msgDateLabel.text = [NSString stringWithFormat:@"%@ - %@",
[LinphoneUtils timeToString:linphone_chat_message_get_time(_msg) withFormat:LinphoneDateChatBubble],
[FastAddressBook displayNameForAddress:addr]];
_msgAvatarImage.image = outgoing ? [LinphoneUtils selfAvatar] : [FastAddressBook imageForAddress:addr];
_msgText.text = messageText;
_msgBackgroundColorImage.image = _msgBottomBar.image = [UIImage imageNamed:(outgoing ? @"color_A.png" : @"color_D.png")];
_msgDateLabel.textColor = [UIColor colorWithPatternImage:_msgBackgroundColorImage.image];
int index = [VIEW(ChatConversationView).tableController indexOfMesssage:_msg];
if (index < 0)
[PhoneMainView.instance popToView:ChatConversationView.compositeViewDescription];
_cell = (UIChatBubbleTextCell *)[VIEW(ChatConversationView).tableController tableView:VIEW(ChatConversationView).tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
_cell.frame = CGRectMake(-10,0,_msgView.frame.size.width,_msgView.frame.size.height);
_cell.isFirst = true;
_cell.isLast = true;
[_cell update];
_cell.popupMenuAllowed = false;
for (UIView *v in [_msgView subviews]) {
[v removeFromSuperview];
}
[_msgView addSubview:_cell];
_tableView.delegate = self;
_tableView.dataSource = self;
[self updateImdnList];
[self fitContent];
[self startEphemeralDisplayTimer];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(ephemeralDeleted:)
name:kLinphoneEphemeralMessageDeletedInRoom
object:nil];
}
-(void) viewWillDisappear:(BOOL)animated {
[self stopEphemeralDisplayTimer];
[NSNotificationCenter.defaultCenter removeObserver:self];
[super viewWillDisappear:animated];
}
- (void)updateImdnList {
@ -81,15 +101,12 @@ static UICompositeViewDescription *compositeDescription = nil;
}
- (void)fitContent {
[self setMessageText];
BOOL outgoing = linphone_chat_message_is_outgoing(_msg);
_msgBackgroundColorImage.image = _msgBottomBar.image = [UIImage imageNamed:(outgoing ? @"color_A.png" : @"color_D.png")];
_msgDateLabel.textColor = [UIColor colorWithPatternImage:_msgBackgroundColorImage.image];
CGSize messageSize = [UIChatBubbleTextCell ViewHeightForMessage:_msg withWidth:self.view.frame.size.width];
[_msgView setFrame:CGRectMake(_msgView.frame.origin.x,
_msgView.frame.origin.y,
_msgView.frame.size.width,
[UIChatBubbleTextCell ViewHeightForMessageText:_msg withWidth:self.view.frame.size.width textForImdn:messageText].height)];
self.view.frame.size.width,
messageSize.height+5)];
[_tableView setFrame:CGRectMake(_tableView.frame.origin.x,
_msgView.frame.origin.y + _msgView.frame.size.height + 10,
@ -101,18 +118,7 @@ static UICompositeViewDescription *compositeDescription = nil;
[self fitContent];
}
- (void)setMessageText {
const char *utf8Text= linphone_chat_message_get_text_content(_msg);
LinphoneContent *fileContent = linphone_chat_message_get_file_transfer_information(_msg);
messageText = nil;
if (utf8Text) {
messageText = [NSString stringWithUTF8String:utf8Text];
if (fileContent)
messageText = [NSString stringWithFormat:@"%@\n%@", messageText, [NSString stringWithUTF8String: linphone_content_get_name(fileContent)]];
} else {
messageText = [NSString stringWithUTF8String: linphone_content_get_name(fileContent)];
}
}
#pragma mark - TableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
@ -278,4 +284,38 @@ static UICompositeViewDescription *compositeDescription = nil;
[PhoneMainView.instance popCurrentView];
}
#pragma mark ephemeral messages
-(void) startEphemeralDisplayTimer {
_ephemeralDisplayTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(updateEphemeralTimes)
userInfo:nil
repeats:YES];
}
-(void) updateEphemeralTimes {
NSDateComponentsFormatter *f= [[NSDateComponentsFormatter alloc] init];
f.unitsStyle = NSDateComponentsFormatterUnitsStylePositional;
f.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
if (linphone_chat_message_is_ephemeral(_msg)) {
long duration = linphone_chat_message_get_ephemeral_expire_time(_msg) == 0 ?
linphone_chat_room_get_ephemeral_lifetime(linphone_chat_message_get_chat_room(_msg)) :
linphone_chat_message_get_ephemeral_expire_time(_msg)-[NSDate date].timeIntervalSince1970;
f.allowedUnits = (duration > 86400 ? kCFCalendarUnitDay : 0)|(duration > 3600 ? kCFCalendarUnitHour : 0)|kCFCalendarUnitMinute|kCFCalendarUnitSecond;
_cell.ephemeralTime.text = [f stringFromTimeInterval:duration];
_cell.ephemeralTime.hidden = NO;
_cell.ephemeralIcon.hidden = NO;
}
}
-(void) stopEphemeralDisplayTimer {
[_ephemeralDisplayTimer invalidate];
}
- (void)ephemeralDeleted:(NSNotification *)notif {
[PhoneMainView.instance popToView:ChatConversationView.compositeViewDescription];
}
@end

View file

@ -39,10 +39,10 @@
@protocol ChatConversationDelegate <NSObject>
- (BOOL)resendMultiFiles:(FileContext *)newFileContext message:(NSString *)message;
- (BOOL)resendFile:(NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message;
- (BOOL)startFileUpload:(NSData *)data withName:(NSString *)name;
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url;
- (BOOL)resendMultiFiles:(FileContext *)newFileContext message:(NSString *)message rootMessage:(LinphoneChatMessage *)rootMessage;
- (BOOL)resendFile:(NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message rootMessage:(LinphoneChatMessage *)rootMessage;
- (BOOL)startFileUpload:(NSData *)data withName:(NSString *)name rootMessage:(LinphoneChatMessage *)rootMessage;
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url rootMessage:(LinphoneChatMessage *)rootMessage;
- (void)tableViewIsScrolling;
@end
@ -64,5 +64,9 @@
- (void)scrollToLastUnread:(BOOL)animated;
- (void)updateEventEntry:(LinphoneEventLog *)event;
- (void)refreshData;
- (void)reloadData;
- (void) dismissMessagesPopups;
- (void) scrollToMessage:(LinphoneChatMessage *)message;
- (int) indexOfMesssage:(LinphoneChatMessage *)message;
@end

View file

@ -49,6 +49,7 @@
}
-(void) viewWillDisappear:(BOOL)animated {
[self dismissMessagesPopups];
[self stopEphemeralDisplayTimer];
[NSNotificationCenter.defaultCenter removeObserver:self];
[super viewWillDisappear:animated];
@ -204,6 +205,39 @@
animated:animated];
}
- (void) scrollToMessage:(LinphoneChatMessage *)message {
int index = [self indexOfMesssage:message];
if (index < 0)
return;
[self.tableView.layer removeAllAnimations];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]
atScrollPosition:UITableViewScrollPositionTop
animated:true];
}
-(int) indexOfMesssage:(LinphoneChatMessage *)message {
if (eventList.count == 0 || _chatRoom == nil)
return -1;
int index = -1;
size_t count = eventList.count;
for (int i = (int)count - 1; i > 0; --i) {
LinphoneEventLog *event = [[eventList objectAtIndex:i] pointerValue];
if (!(linphone_event_log_get_type(event) == LinphoneEventLogTypeConferenceChatMessage))
continue;;
LinphoneChatMessage *chat = linphone_event_log_get_chat_message(event);
if (chat == message) {
index = i;
break;
}
}
return index;
}
#pragma mark - Property Functions
- (void)setChatRoom:(LinphoneChatRoom *)room {
@ -275,6 +309,15 @@ static const int BASIC_EVENT_LIST=15;
if (!_chatRoom && [[cell reuseIdentifier] isEqualToString:@"UIChatBubblePhotoCell"]) {
[(UIChatBubbleTextCell *)cell clearEncryptedFiles];
}
if ([cell isKindOfClass:[UIChatBubbleTextCell class]] ||[cell isKindOfClass:[UIChatBubblePhotoCell class]])
[(UIChatBubbleTextCell *)cell dismissPopup];
}
-(void) dismissMessagesPopups {
for (UITableViewCell *cell in self.tableView.visibleCells) {
if (![[cell reuseIdentifier] isEqualToString:NSStringFromClass(UIChatNotifiedEventCell.class)])
[(UIChatBubbleTextCell *)cell dismissPopup];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@ -301,6 +344,8 @@ static const int BASIC_EVENT_LIST=15;
[cell setChatRoomDelegate:_chatRoomDelegate];
[super accessoryForCell:cell atPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.tableController = self;
cell.popupMenuAllowed = true;
return cell;
} else {
kCellId = NSStringFromClass(UIChatNotifiedEventCell.class);

View file

@ -32,7 +32,8 @@
#import "UIImageViewDeletable.h"
#import "UIConfirmationDialog.h"
#import "UIInterfaceStyleButton.h"
#import "linphoneapp-Swift.h"
#import "UIChatReplyBubbleView.h"
#include "linphone/linphonecore.h"
@ -49,7 +50,7 @@
@interface ChatConversationView
: TPMultiLayoutViewController <HPGrowingTextViewDelegate, UICompositeViewDelegate, ImagePickerDelegate, ChatConversationDelegate,
UIDocumentInteractionControllerDelegate, UISearchBarDelegate, UIImageViewDeletableDelegate,QLPreviewControllerDelegate, UICollectionViewDataSource,UIDocumentMenuDelegate,UIDocumentPickerDelegate,UITableViewDataSource, UITableViewDelegate> {
UIDocumentInteractionControllerDelegate, UISearchBarDelegate, UIImageViewDeletableDelegate,QLPreviewControllerDelegate, UICollectionViewDataSource,UICollectionViewDelegate,UIDocumentMenuDelegate,UIDocumentPickerDelegate,UITableViewDataSource, UITableViewDelegate> {
OrderedDictionary *imageQualities;
BOOL scrollOnGrowingEnabled;
BOOL composingVisible;
@ -92,6 +93,36 @@
@property (weak, nonatomic) IBOutlet UIInterfaceStyleButton *toggleMenuButton;
@property (weak, nonatomic) IBOutlet UIImageView *ephemeralndicator;
// Voice recording
@property (strong, nonatomic) IBOutlet UIView *vrView;
@property (weak, nonatomic) IBOutlet UIView *vrInnerView;
@property (weak, nonatomic) IBOutlet UIButton *vrDeleteButton;
@property (weak, nonatomic) IBOutlet UIButton *vrPlayButton;
@property (weak, nonatomic) IBOutlet UIImageView *vrWave;
@property (weak, nonatomic) IBOutlet UIView *vrWaveMask;
@property (weak, nonatomic) IBOutlet UIView *vrWaveMaskPlayer;
@property (weak, nonatomic) IBOutlet UILabel *vrDurationLabel;
@property NSTimer *vrRecordTimer;
@property NSTimer *vrPlayerTimer;
@property (weak, nonatomic) IBOutlet UIButton *toggleRecord;
@property BOOL isVoiceRecording;
@property BOOL isPendingVoiceRecord;
@property BOOL isPlayingVoiceRecording;
@property LinphoneRecorder *voiceRecorder;
@property LinphonePlayer *sharedVoicePlayer;
@property BOOL showVoiceRecorderView;
@property BOOL preservePendingActions;
// Reply
@property (weak, nonatomic) IBOutlet UIView *replyView;
@property BOOL showReplyView;
@property UIChatReplyBubbleView *replyBubble;
// Forward
@property LinphoneChatMessage *pendingForwardMessage;
+ (void)markAsRead:(LinphoneChatRoom *)chatRoom;
+ (void)autoDownload:(LinphoneChatMessage *)message;
+(NSString *)getKeyFromFileType:(NSString *)fileType fileName:(NSString *)name;
@ -123,4 +154,10 @@
- (NSURL *)getICloudFileUrl:(NSString *)name;
- (void)removeCallBacks;
-(void) startSharedPlayer:(const char *)path;
-(void) stopSharedPlayer;
-(BOOL) sharedPlayedIsPlaying:(const char *)path;
-(void) initiateReplyViewForMessage:(LinphoneChatMessage *)message;
@end

View file

@ -120,6 +120,7 @@
[NSNumber numberWithFloat:0.5], NSLocalizedString(@"Average", nil),
[NSNumber numberWithFloat:0.0], NSLocalizedString(@"Minimum", nil), nil];
composingVisible = false;
[self initSharedPlayer];
}
return self;
}
@ -136,7 +137,7 @@ static UICompositeViewDescription *compositeDescription = nil;
if (compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:self.class
statusBar:StatusBarView.class
tabBar:TabBarView.class
tabBar:nil
sideMenu:SideMenuView.class
fullscreen:false
isLeftFragment:NO
@ -186,7 +187,14 @@ static UICompositeViewDescription *compositeDescription = nil;
[_tableController setChatRoomDelegate:self];
[_imagesCollectionView registerClass:[UIImageViewDeletable class] forCellWithReuseIdentifier:NSStringFromClass([UIImageViewDeletable class])];
[_imagesCollectionView setDataSource:self];
[_imagesCollectionView setDelegate:self];
[_toggleSelectionButton setImage:[UIImage imageNamed:@"select_all_default.png"] forState:UIControlStateSelected];
_vrInnerView.layer.cornerRadius = 5.0f;
_vrInnerView.layer.masksToBounds = YES;
_vrWaveMaskPlayer.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"color_L"]]; // rgba(1,88,7,0.2);
_showVoiceRecorderView = false;
}
- (void)refreshData {
@ -202,6 +210,10 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(applicationWillEnterBackground)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
@ -222,6 +234,16 @@ static UICompositeViewDescription *compositeDescription = nil;
selector:@selector(onLinphoneCoreReady:)
name:kLinphoneGlobalStateUpdate
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(endVoicePlayingIfDoingSO:)
name:kLinphoneVoiceMessagePlayerLostFocus
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(endVoicePlayingIfDoingSO:)
name:kLinphoneVoiceMessagePlayerEOF
object:nil];
if ([_fileContext count] > 0) {
[UIView animateWithDuration:0
delay:0
@ -229,13 +251,14 @@ static UICompositeViewDescription *compositeDescription = nil;
animations:^{
// resizing imagesView
CGRect imagesFrame = [_imagesView frame];
imagesFrame.origin.y = [_messageView frame].origin.y - 100;
imagesFrame.size.height = 100;
imagesFrame.origin.y = [_messageView frame].origin.y - 120;
imagesFrame.size.height = 120;
[_imagesView setFrame:imagesFrame];
// resizing chatTable
CGRect tableViewFrame = [_tableController.tableView frame];
tableViewFrame.size.height -= 100;
tableViewFrame.size.height -= 120;
[_tableController.tableView setFrame:tableViewFrame];
[self updateFramesInclRecordingAndReplyView];
}
completion:nil];
}
@ -245,10 +268,30 @@ static UICompositeViewDescription *compositeDescription = nil;
CGRect popupFrame = _popupMenu.frame;
popupFrame.size.height = 44 * [_popupMenu numberOfRowsInSection:0];
_popupMenu.frame = popupFrame;
// Voice recording & Replies
_vrView.hidden = true;
_toggleRecord.enabled = linphone_core_get_calls_nb(LC) == 0;
_replyView.hidden = true;
_preservePendingActions = false;
_toggleRecord.enabled = linphone_core_get_calls_nb(LC) == 0;
}
- (void)viewWillDisappear:(BOOL)animated {
if (!_preservePendingActions)
[self cancelVoiceRecording];
if (!_preservePendingActions)
[self closePendingReply];
else if (_isVoiceRecording)
[self stopVoiceRecording];
[super viewWillDisappear:animated];
[self removeCallBacks];
@ -256,7 +299,9 @@ static UICompositeViewDescription *compositeDescription = nil;
[_messageField resignFirstResponder];
[self setComposingVisible:false withDelay:0]; // will hide the "user is composing.." message
[self stopAllPlays];
[NSNotificationCenter.defaultCenter removeObserver:self];
PhoneMainView.instance.currentRoom = NULL;
}
@ -287,10 +332,24 @@ static UICompositeViewDescription *compositeDescription = nil;
_backButton.hidden = _tableController.isEditing;
[_tableController scrollToBottom:true];
[self refreshImageDrawer];
[self stopAllPlays];
}
#pragma mark -
- (void)applicationWillEnterBackground{
if (!_preservePendingActions)
[self cancelVoiceRecording];
else if (_isVoiceRecording)
[self stopVoiceRecording];
if (!_preservePendingActions)
[self closePendingReply];
[self stopAllPlays];
}
- (void)configureForRoom:(BOOL)editing {
if (!_chatRoom) {
_chatView.hidden = YES;
@ -347,6 +406,7 @@ static UICompositeViewDescription *compositeDescription = nil;
[self setupPopupMenu];
_ephemeralndicator.hidden = !linphone_chat_room_ephemeral_enabled(_chatRoom);
}
[self handlePendingTransferIfAny];
}
@ -374,7 +434,7 @@ static UICompositeViewDescription *compositeDescription = nil;
}
-(NSData *) nsDataRead {
NSString* groupName = [NSString stringWithFormat:@"group.%@.linphoneExtension",[[NSBundle mainBundle] bundleIdentifier]];
NSString* groupName = @"group.com.clavys.frogtrust.store";
NSString *path =[[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:groupName] path];
NSString *fullCacheFilePathPath = [NSString stringWithFormat:@"%@/%@",path,@"nsData"];
return[NSData dataWithContentsOfFile:fullCacheFilePathPath];
@ -382,7 +442,8 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)shareFile {
NSString* groupName = [NSString stringWithFormat:@"group.%@.linphoneExtension",[[NSBundle mainBundle] bundleIdentifier]];
NSString* groupName = @"group.com.clavys.frogtrust.store";
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:groupName];
NSDictionary *dict = [defaults valueForKey:@"photoData"];
@ -429,6 +490,9 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)callUpdateEvent:(NSNotification *)notif {
[self updateSuperposedButtons];
_toggleRecord.enabled = linphone_core_get_calls_nb(LC) == 0;
[_tableController.tableView reloadData];
}
- (void)update {
@ -456,17 +520,20 @@ static UICompositeViewDescription *compositeDescription = nil;
}
}
- (BOOL)sendMessage:(NSString *)message withExterlBodyUrl:(NSURL *)externalUrl {
- (BOOL)sendMessage:(NSString *)message withExterlBodyUrl:(NSURL *)externalUrl rootMessage:(LinphoneChatMessage *)rootMessage {
if (_chatRoom == NULL) {
LOGW(@"Cannot send message: No chatroom");
return FALSE;
}
LinphoneChatMessage *msg = linphone_chat_room_create_message(_chatRoom, [message UTF8String]);
LinphoneChatMessage *msg = rootMessage;
if (message && message.length > 0)
linphone_chat_message_add_utf8_text_content(msg, message.UTF8String);
if (externalUrl) {
linphone_chat_message_set_external_body_url(msg, [[externalUrl absoluteString] UTF8String]);
}
// we must ref & unref message because in case of error, it will be destroy otherwise
linphone_chat_message_send(msg);
@ -509,15 +576,15 @@ static UICompositeViewDescription *compositeDescription = nil;
- (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)
[sheet addButtonWithTitle:NSLocalizedString(@"send to this conversation", nil)
block:^() {
if (![[self.messageField text] isEqualToString:@""]) {
[self sendMessageInMessageField];
[self sendMessageInMessageField:linphone_chat_room_create_empty_message(_chatRoom)];
}
if (url)
[self sendMessage:url withExterlBodyUrl:nil];
[self sendMessage:url withExterlBodyUrl:nil rootMessage:linphone_chat_room_create_empty_message(_chatRoom)];
else
[self startFileUpload:data withName:fileName];
[self startFileUpload:data withName:fileName rootMessage:linphone_chat_room_create_empty_message(_chatRoom)];
}];
[sheet addCancelButtonWithTitle:NSLocalizedString(@"Cancel", nil) block:nil];
@ -600,8 +667,8 @@ static UICompositeViewDescription *compositeDescription = nil;
_addressLabel.frame = frame;
}
- (void)sendMessageInMessageField {
if ([self sendMessage:[_messageField text] withExterlBodyUrl:nil]) {
- (void)sendMessageInMessageField:(LinphoneChatMessage *)rootMessage {
if ([self sendMessage:[_messageField text] withExterlBodyUrl:nil rootMessage:rootMessage]) {
scrollOnGrowingEnabled = FALSE;
[_messageField setText:@""];
scrollOnGrowingEnabled = TRUE;
@ -657,6 +724,7 @@ static UICompositeViewDescription *compositeDescription = nil;
CGRect tableRect = [_tableController.view frame];
tableRect.size.height -= diff;
[_tableController.view setFrame:tableRect];
[self updateFramesInclRecordingAndReplyView];
// if we're showing the compose message, update it position
if (![_composeLabel isHidden]) {
@ -681,28 +749,48 @@ static UICompositeViewDescription *compositeDescription = nil;
}
- (IBAction)onSendClick:(id)event {
if (!linphone_core_is_network_reachable(LC)) {
//[PhoneMainView.instance presentViewController:[LinphoneUtils networkErrorView:@"send a message"] animated:YES completion:nil];
//return;
}
LinphoneChatMessage *rootMessage = _replyBubble ? linphone_chat_room_create_reply_message(_chatRoom, _replyBubble.message) : linphone_chat_room_create_empty_message(_chatRoom);
if (_replyBubble) {
[self closePendingReply];
}
if (_isPendingVoiceRecord && _voiceRecorder && linphone_recorder_get_file(_voiceRecorder)) {
LinphoneContent * voiceContent = linphone_recorder_create_content(_voiceRecorder);
_isPendingVoiceRecord = false;
[self cancelVoiceRecording];
[self stopVoiceRecordPlayer];
linphone_chat_message_add_content(rootMessage, voiceContent);
}
if ([_fileContext count] > 0) {
if (linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesConference) {
[self startMultiFilesUpload];
[self startMultiFilesUpload:rootMessage];
} else {
int i = 0;
for (i = 0; i < [_fileContext count]-1; ++i) {
[self startUploadData:[_fileContext.datasArray objectAtIndex:i] withType:[_fileContext.typesArray objectAtIndex:i] withName:[_fileContext.namesArray objectAtIndex:i] andMessage:NULL];
[self startUploadData:[_fileContext.datasArray objectAtIndex:i] withType:[_fileContext.typesArray objectAtIndex:i] withName:[_fileContext.namesArray objectAtIndex:i] andMessage:NULL rootMessage:rootMessage];
}
if (isOneToOne) {
[self startUploadData:[_fileContext.datasArray objectAtIndex:i] withType:[_fileContext.typesArray objectAtIndex:i] withName:[_fileContext.namesArray objectAtIndex:i] andMessage:NULL];
[self startUploadData:[_fileContext.datasArray objectAtIndex:i] withType:[_fileContext.typesArray objectAtIndex:i] withName:[_fileContext.namesArray objectAtIndex:i] andMessage:NULL rootMessage:rootMessage];
if (![[self.messageField text] isEqualToString:@""]) {
[self sendMessage:[_messageField text] withExterlBodyUrl:nil];
[self sendMessage:[_messageField text] withExterlBodyUrl:nil rootMessage:rootMessage];
}
} else {
[self startUploadData:[_fileContext.datasArray objectAtIndex:i] withType:[_fileContext.typesArray objectAtIndex:i] withName:[_fileContext.namesArray objectAtIndex:i] andMessage:[self.messageField text]];
[self startUploadData:[_fileContext.datasArray objectAtIndex:i] withType:[_fileContext.typesArray objectAtIndex:i] withName:[_fileContext.namesArray objectAtIndex:i] andMessage:[self.messageField text] rootMessage:rootMessage];
}
}
[self clearMessageView];
return;
}
[self sendMessageInMessageField];
[self sendMessageInMessageField:rootMessage];
}
- (IBAction)onListTap:(id)sender {
@ -759,14 +847,11 @@ static UICompositeViewDescription *compositeDescription = nil;
}
- (IBAction)onMessageChange:(id)sender {
if ([[_messageField text] length] > 0) {
[_sendButton setEnabled:TRUE];
} else {
[_sendButton setEnabled:FALSE];
}
[self setSendButtonState];
}
- (IBAction)onPictureClick:(id)event {
_preservePendingActions = true;
[_messageField resignFirstResponder];
[ImagePickerView SelectImageFromDevice:self atPosition:_pictureButton inView:self.view withDocumentMenuDelegate:self];
@ -800,15 +885,15 @@ static UICompositeViewDescription *compositeDescription = nil;
#pragma mark ChatRoomDelegate
- (BOOL)startMultiFilesUpload {
- (BOOL)startMultiFilesUpload:(LinphoneChatMessage *)rootMessage {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
[fileTransfer setText:[self.messageField text]];
[fileTransfer uploadFileContent:_fileContext forChatRoom:_chatRoom];
[fileTransfer uploadFileContent:_fileContext forChatRoom:_chatRoom rootMessage:rootMessage];
[_tableController scrollToBottom:true];
return TRUE;
}
- (BOOL)startUploadData:(NSData *)data withType:(NSString*)type withName:(NSString *)name andMessage:(NSString *)message {
- (BOOL)startUploadData:(NSData *)data withType:(NSString*)type withName:(NSString *)name andMessage:(NSString *)message rootMessage:(LinphoneChatMessage *)rootMessage {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
if (message)
[fileTransfer setText:message];
@ -818,38 +903,38 @@ static UICompositeViewDescription *compositeDescription = nil;
} else if ([type isEqualToString:@"image"]) {
key = @"localimage";
}
[fileTransfer uploadData:data forChatRoom:_chatRoom type:type subtype:type name:name key:key];
[fileTransfer uploadData:data forChatRoom:_chatRoom type:type subtype:type name:name key:key rootMessage:rootMessage];
[_tableController scrollToBottom:true];
return TRUE;
}
- (BOOL)startFileUpload:(NSData *)data withName:(NSString *)name {
- (BOOL)startFileUpload:(NSData *)data withName:(NSString *)name rootMessage:(LinphoneChatMessage *)rootMessage {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
[fileTransfer uploadFile:data forChatRoom:_chatRoom withName:name];
[fileTransfer uploadFile:data forChatRoom:_chatRoom withName:name rootMessage:rootMessage];
[_tableController scrollToBottom:true];
return TRUE;
}
- (BOOL)resendMultiFiles:(FileContext *)newFileContext message:(NSString *)message {
- (BOOL)resendMultiFiles:(FileContext *)newFileContext message:(NSString *)message rootMessage:(LinphoneChatMessage *)rootMessage {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
if (message)
[fileTransfer setText:message];
[fileTransfer uploadFileContent:newFileContext forChatRoom:_chatRoom];
[fileTransfer uploadFileContent:newFileContext forChatRoom:_chatRoom rootMessage:rootMessage];
[_tableController scrollToBottom:true];
return TRUE;
}
- (BOOL)resendFile: (NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message {
- (BOOL)resendFile: (NSData *)data withName:(NSString *)name type:(NSString *)type key:(NSString *)key message:(NSString *)message rootMessage:(LinphoneChatMessage *)rootMessage{
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
if (message)
[fileTransfer setText:message];
[fileTransfer uploadData:data forChatRoom:_chatRoom type:type subtype:type name:name key:key];
[fileTransfer uploadData:data forChatRoom:_chatRoom type:type subtype:type name:name key:key rootMessage:rootMessage];
[_tableController scrollToBottom:true];
return TRUE;
}
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url {
[self sendMessage:message withExterlBodyUrl:[NSURL URLWithString:url]];
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url rootMessage:(LinphoneChatMessage *)rootMessage {
[self sendMessage:message withExterlBodyUrl:[NSURL URLWithString:url] rootMessage:rootMessage];
}
#pragma mark ImagePickerDelegate
@ -1077,6 +1162,7 @@ static UICompositeViewDescription *compositeDescription = nil;
[_messageView frame].origin.y - tableFrame.origin.y - composeIndicatorCompensation;
[_tableController.view setFrame:tableFrame];
// Scroll to bottom
NSInteger lastSection = [_tableController.tableView numberOfSections] - 1;
if (lastSection >= 0) {
@ -1102,9 +1188,14 @@ static UICompositeViewDescription *compositeDescription = nil;
tableViewFrame.size.height = imagesFrame.origin.y - tableViewFrame.origin.y;
[_tableController.tableView setFrame:tableViewFrame];
}
if (_showVoiceRecorderView)
_vrView.hidden = true; // force recalculate
if (_showReplyView)
_replyView.hidden = true; // force recalculate
[self updateFramesInclRecordingAndReplyView];
}
completion:^(BOOL finished){
}];
}
@ -1158,6 +1249,7 @@ static UICompositeViewDescription *compositeDescription = nil;
tableFrame.size.height =
[_messageView frame].origin.y - tableFrame.origin.y - composeIndicatorCompensation;
[_tableController.view setFrame:tableFrame];
}
if ([_fileContext count] > 0){
@ -1170,6 +1262,7 @@ static UICompositeViewDescription *compositeDescription = nil;
CGRect tableViewFrame = [_tableController.tableView frame];
tableViewFrame.size.height = imagesFrame.origin.y - tableViewFrame.origin.y;
[_tableController.tableView setFrame:tableViewFrame];
}
// Scroll
@ -1183,10 +1276,15 @@ static UICompositeViewDescription *compositeDescription = nil;
animated:FALSE];
}
}
if (_showVoiceRecorderView)
_vrView.hidden = true; // force recalculate
if (_showReplyView)
_replyView.hidden = true; // force recalculate
[self updateFramesInclRecordingAndReplyView];
}
completion:^(BOOL finished){
}];
}
@ -1381,26 +1479,31 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
return [_fileContext count];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? CGSizeMake(60, 60) : CGSizeMake(120, 120);
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UIImageViewDeletable *imgView = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([UIImageViewDeletable class]) forIndexPath:indexPath];
CGRect imgFrame = imgView.frame;
imgFrame.origin.y = 5;
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
imgFrame.size.height = 50;
imgFrame.size.height = 60;
} else {
imgFrame.size.height = 100;
imgFrame.size.height = 120;
}
[imgView.image setImage:[UIImage resizeImage:[_fileContext.previewsArray objectAtIndex:[indexPath item]] withMaxWidth:imgFrame.size.width andMaxHeight:imgFrame.size.height]];
[imgView setUuid:[_fileContext.uuidsArray objectAtIndex:[indexPath item]]];
[imgView setDeleteDelegate:self];
[imgView setFrame:imgFrame];
[_sendButton setEnabled:TRUE];
[self setSendButtonState];
return imgView;
}
- (void)refreshImageDrawer {
int heightDiff = UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? 55 : 105;
int heightDiff = UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? 65 : 125;
if ([_fileContext count] == 0) {
[UIView animateWithDuration:0
@ -1416,10 +1519,10 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
CGRect tableViewFrame = [_tableController.tableView frame];
tableViewFrame.size.height = imagesFrame.origin.y - tableViewFrame.origin.y;
[_tableController.tableView setFrame:tableViewFrame];
[self updateFramesInclRecordingAndReplyView];
}
completion:nil];
if ([_messageField.text isEqualToString:@""])
[_sendButton setEnabled:FALSE];
[self setSendButtonState];
} else {
// resizing imagesView
CGRect imagesFrame = [_imagesView frame];
@ -1430,6 +1533,7 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
CGRect tableViewFrame = [_tableController.tableView frame];
tableViewFrame.size.height = imagesFrame.origin.y - tableViewFrame.origin.y;
[_tableController.tableView setFrame:tableViewFrame];
[self updateFramesInclRecordingAndReplyView];
[_imagesCollectionView reloadData];
}
}
@ -1488,7 +1592,7 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
NSFileCoordinator *co =[[NSFileCoordinator alloc] init];
NSError *error = nil;
[co coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL * _Nonnull newURL) {
UIImage *image = [ChatConversationView drawText:[newURL lastPathComponent] image:[ChatConversationView getBasicImage] textSize:10];
UIImage *image = [UIChatBubbleTextCell getImageFromFileName:[newURL lastPathComponent]];
[_fileContext addObject:[NSData dataWithContentsOfURL:newURL] name:[newURL lastPathComponent] type:@"file" image:image];
[self refreshImageDrawer];
}];
@ -1592,4 +1696,322 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
}
// Voice redcording
- (IBAction)onVrDelete:(id)sender {
[self cancelVoiceRecording];
[self stopVoiceRecordPlayer];
}
- (IBAction)onvrPlayPauseStop:(id)sender {
if (_isVoiceRecording) {
[self stopVoiceRecording];
} else {
if (_isPlayingVoiceRecording)
[self stopVoiceRecordPlayer];
else
[self playRecordedMessage];
}
}
- (IBAction)onVrStart:(id)sender {
if (_isVoiceRecording) {
[self stopVoiceRecording];
} else {
[self startVoiceRecording];
}
}
-(void) createVoiceRecorder {
LinphoneRecorderParams *p = linphone_core_create_recorder_params(LC);
linphone_recorder_params_set_file_format(p, LinphoneRecorderFileFormatWav);
_voiceRecorder = linphone_core_create_recorder(LC, p);
}
-(void) cancelVoiceRecording {
_showVoiceRecorderView = false;
_toggleRecord.selected = false;
[self updateFramesInclRecordingAndReplyView];
_isPendingVoiceRecord = false;
_isVoiceRecording = false;
if (_voiceRecorder && linphone_recorder_get_state(_voiceRecorder) != LinphoneRecorderClosed) {
linphone_recorder_close(_voiceRecorder);
const char *recordingFile = linphone_recorder_get_file(_voiceRecorder);
if (recordingFile) {
[AppManager removeFileWithFile:[NSString stringWithUTF8String:recordingFile]];
}
}
[self setSendButtonState];
}
-(void) stopVoiceRecording {
if (_voiceRecorder && linphone_recorder_get_state(_voiceRecorder) == LinphoneRecorderRunning) {
LOGI(@"[Chat Message Sending] Pausing / closing voice recorder");
linphone_recorder_pause(_voiceRecorder);
linphone_recorder_close(_voiceRecorder);
_vrDurationLabel.text = [self formattedDuration:linphone_recorder_get_duration(_voiceRecorder)];
}
_isVoiceRecording = false;
if ([LinphoneManager.instance lpConfigBoolForKey:@"voice_recording_send_right_away" withDefault:false]) {
[self onSendClick:nil];
}
[_vrPlayButton setImage:[UIImage imageNamed:@"vr_play"] forState:UIControlStateNormal];
_toggleRecord.selected = false;
_vrWaveMask.frame = CGRectZero;
[_vrRecordTimer invalidate];
_isPendingVoiceRecord = linphone_recorder_get_duration(_voiceRecorder) > 0;
[self setSendButtonState];
}
-(void) startVoiceRecording {
if (!_voiceRecorder)
[self createVoiceRecorder];
[CallManager.instance activateAudioSession];
_toggleRecord.selected = true;
[_vrPlayButton setImage:[UIImage imageNamed:@"vr_stop"] forState:UIControlStateNormal];
_showVoiceRecorderView = true;
[self updateFramesInclRecordingAndReplyView];
_isVoiceRecording = true;
_vrWaveMaskPlayer.frame = CGRectZero;
switch (linphone_recorder_get_state(_voiceRecorder)) {
case LinphoneRecorderClosed: {
NSString *filename = [NSString stringWithFormat:@"%@/voice-recording-%@.wav",[LinphoneManager imagesDirectory], [NSUUID UUID].UUIDString];
linphone_recorder_open(_voiceRecorder, filename.UTF8String);
linphone_recorder_start(_voiceRecorder);
LOGW(@"[Chat Message Sending] Recorder is closed opening it with %@",filename);
break;
};
case LinphoneRecorderRunning: {
LOGW(@"[Chat Message Sending] Recorder is already recording");
break;
}
case LinphoneRecorderPaused: {
LOGW(@"[Chat Message Sending] Recorder isn't closed, resuming recording");
linphone_recorder_start(_voiceRecorder);
}
}
_vrWaveMask.frame = _vrWave.frame;
_vrDurationLabel.text = [self formattedDuration:linphone_recorder_get_duration(_voiceRecorder)];
_vrRecordTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(voiceRecordTimerUpdate)
userInfo:nil
repeats:YES];
}
-(void) voiceRecordTimerUpdate {
int recorderDuration = linphone_recorder_get_duration(_voiceRecorder);
if (recorderDuration > [LinphoneManager.instance lpConfigIntForKey:@"voice_recording_max_duration" withDefault:60000]) {
LOGW(@"[Chat Message Sending] Max duration for voice recording exceeded, stopping. (max = %d)",[LinphoneManager.instance lpConfigIntForKey:@"voice_recording_max_duration" withDefault:60000]);
[self stopVoiceRecording];
} else {
_vrDurationLabel.text = [self formattedDuration:linphone_recorder_get_duration(_voiceRecorder)];
CGRect r = _vrWaveMask.frame;
r.origin.x += 30;
r.size.width -= 30;
if (r.origin.x > _vrWave.frame.size.width) {
r = _vrWave.frame;
_vrWaveMask.frame = r;
} else {
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
_vrWaveMask.frame = r;
}completion:^(BOOL finished) {}];
}
}
}
// Playback Shared Player (new recording & chat bubble)
- (void) initSharedPlayer {
LOGI(@"[Voice Message] Creating shared player");
_sharedVoicePlayer = linphone_core_create_local_player(LC, [CallManager.instance getSpeakerSoundCard].UTF8String, nil, nil);
LinphonePlayerCbs *cbs = linphone_factory_create_player_cbs(linphone_factory_get());
linphone_player_cbs_set_eof_reached(cbs, on_shared_player_eof_reached);
linphone_player_cbs_set_user_data(cbs, (__bridge void*)self);
linphone_player_add_callbacks(_sharedVoicePlayer, cbs);
}
-(void) startSharedPlayer:(const char *)path {
LOGI(@"[Voice Message] Starting shared player path = %s",path);
if (linphone_player_get_user_data(_sharedVoicePlayer)) {
LOGI(@"[Voice Message] a play was requested (%s), but there is already one going (%s)",path,(const char *)linphone_player_get_user_data(_sharedVoicePlayer) );
NSDictionary* userInfo = @{@"path": [NSString stringWithUTF8String:linphone_player_get_user_data(_sharedVoicePlayer)]};
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneVoiceMessagePlayerLostFocus object:nil userInfo:userInfo];
}
[CallManager.instance changeRouteToSpeaker];
linphone_player_set_user_data(_sharedVoicePlayer, (void *)path);
linphone_player_open(_sharedVoicePlayer, path);
linphone_player_start(_sharedVoicePlayer);
}
-(void) stopSharedPlayer {
LOGI(@"[Voice Message] Stopping shared player path = %s",linphone_player_get_user_data(_sharedVoicePlayer) ? (const char *)linphone_player_get_user_data(_sharedVoicePlayer) : "nil");
linphone_player_pause(_sharedVoicePlayer);
linphone_player_seek(_sharedVoicePlayer,0);
linphone_player_close(_sharedVoicePlayer);
linphone_player_set_user_data(_sharedVoicePlayer, nil);
}
-(BOOL) sharedPlayedIsPlaying:(const char *)path {
return path && linphone_player_get_user_data(_sharedVoicePlayer) && !strcmp(path,linphone_player_get_user_data(_sharedVoicePlayer));
}
void on_shared_player_eof_reached(LinphonePlayer *p) {
LOGI(@"[Voice Message] End of file reached for player");
const char * currentPlayedFile = (const char *) linphone_player_get_user_data(p);
if (currentPlayedFile) {
NSDictionary* userInfo = @{@"path": [NSString stringWithUTF8String:currentPlayedFile]};
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneVoiceMessagePlayerEOF object:nil userInfo:userInfo];
}
}
// Playback of new recordings
-(void) playRecordedMessage {
[_vrPlayButton setImage:[UIImage imageNamed:@"vr_stop"] forState:UIControlStateNormal];
_vrDurationLabel.text = [self formattedDuration:linphone_player_get_duration(_sharedVoicePlayer)];
_vrWaveMask.frame = CGRectZero;
CGRect r = CGRectZero;
r.size.height = _vrInnerView.frame.size.height;
_vrWaveMaskPlayer.frame = r;
_vrPlayerTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(voicePlayTimerUpdate)
userInfo:nil
repeats:YES];
[self startSharedPlayer:linphone_recorder_get_file(_voiceRecorder)];
[self animPlayerOnce];
_isPlayingVoiceRecording = true;
}
-(void) voicePlayTimerUpdate {
_vrDurationLabel.text = [self formattedDuration:linphone_player_get_duration(_sharedVoicePlayer)];
[self animPlayerOnce];
}
-(void) animPlayerOnce {
CGRect r = _vrWaveMaskPlayer.frame;
r.size.width += _vrInnerView.frame.size.width / ((linphone_player_get_duration(_sharedVoicePlayer) / 1000)+1) ;
if (r.size.width > _vrInnerView.frame.size.width) {
r.size.width = _vrInnerView.frame.size.width;
}
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
_vrWaveMaskPlayer.frame = r;
}completion:^(BOOL finished) {}];
}
-(void) endVoicePlayingIfDoingSO:(NSNotification *)notif {
if (_isPlayingVoiceRecording)
[self stopVoiceRecordPlayer];
}
-(void) stopVoiceRecordPlayer {
[self stopSharedPlayer];
[_vrPlayButton setImage:[UIImage imageNamed:@"vr_play"] forState:UIControlStateNormal];
_isPlayingVoiceRecording = false;
[_vrPlayerTimer invalidate];
_vrWaveMaskPlayer.frame = CGRectZero;
}
-(NSString *)formattedDuration:(long)valueMs {
return [NSString stringWithFormat:@"%02ld:%02ld", valueMs/ 60000, (valueMs % 60000) / 1000 ];
}
-(void) updateFramesInclRecordingAndReplyView { // place below the messages table.
BOOL showHideVoice = _showVoiceRecorderView != !_vrView.hidden;
if (showHideVoice)
_vrView.hidden = !_showVoiceRecorderView;
CGRect vrFrame = _vrView.frame;
CGRect tableFrame = _tableController.tableView.frame;
if (showHideVoice) {
tableFrame.size.height = _showVoiceRecorderView ? tableFrame.size.height - vrFrame.size.height : tableFrame.size.height + vrFrame.size.height;
_tableController.tableView.frame = tableFrame;
[_tableController.tableView reloadData];
}
vrFrame.origin.y = tableFrame.origin.y+tableFrame.size.height;
_vrView.frame = vrFrame;
BOOL showHideReply = _showReplyView != !_replyView.hidden;
if (showHideReply)
_replyView.hidden = !_showReplyView;
CGRect repFrame = _replyView.frame;
tableFrame = _tableController.tableView.frame;
if (showHideReply) {
tableFrame.size.height = _showReplyView ? tableFrame.size.height - repFrame.size.height : tableFrame.size.height + repFrame.size.height;
_tableController.tableView.frame = tableFrame;
[_tableController.tableView reloadData];
}
repFrame.origin.y = _showVoiceRecorderView ? vrFrame.origin.y + vrFrame.size.height : tableFrame.origin.y+tableFrame.size.height;
_replyView.frame = repFrame;
}
-(void) stopAllPlays {
if (linphone_player_get_user_data(_sharedVoicePlayer)) {
NSDictionary* userInfo = @{@"path": [NSString stringWithUTF8String:linphone_player_get_user_data(_sharedVoicePlayer)]};
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneVoiceMessagePlayerLostFocus object:nil userInfo:userInfo];
}
}
// send button state
-(void) setSendButtonState {
_sendButton.enabled = !_isVoiceRecording && ((_isPendingVoiceRecord && linphone_recorder_get_duration(_voiceRecorder) > 0) || [[_messageField text] length] > 0 || _fileContext.count > 0);
}
// Reply
-(void) closePendingReply {
if (_replyBubble != nil) {
_showReplyView = false;
[_replyBubble.view removeFromSuperview];
[self updateFramesInclRecordingAndReplyView];
_replyBubble = nil;
}
}
-(void) initiateReplyViewForMessage:(LinphoneChatMessage *)message {
if (_replyBubble != nil)
[self closePendingReply];
_replyBubble = [[UIChatReplyBubbleView alloc] initWithNibName:@"UIChatReplyBubbleView" bundle:nil];
[self addChildViewController:_replyBubble];
[_replyView addSubview:_replyBubble.view];
[_replyBubble didMoveToParentViewController:self];
[_replyBubble configureForMessage:message withDimissBlock:^{
[self closePendingReply];
} hideDismiss:false withClickBlock:^{}];
_showReplyView = true;
[self updateFramesInclRecordingAndReplyView];
[self.tableController scrollToMessage:message];
}
-(void) handlePendingTransferIfAny {
if (self.pendingForwardMessage) {
LinphoneChatMessage *message = self.pendingForwardMessage;
self.pendingForwardMessage = nil;
UIConfirmationDialog *d = [UIConfirmationDialog ShowWithMessage:NSLocalizedString(@"Transfer this message to this conversation ?",nil)
cancelMessage:nil
confirmMessage:NSLocalizedString(@"TRANSFER",nil)
onCancelClick:^() {}
onConfirmationClick:^() {
linphone_chat_message_send(linphone_chat_room_create_forward_message(_chatRoom, message));
}];
d.forwardImage.hidden = NO;
[d setSpecialColor];
}
}
@end

View file

@ -28,6 +28,7 @@
@property (weak, nonatomic) IBOutlet UIView *waitView;
@property bctbx_list_t *data;
- (void)loadData;
- (void)markCellAsRead:(LinphoneChatRoom *)chatRoom;
@end

View file

@ -160,6 +160,13 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
[cell setChatRoom:(LinphoneChatRoom *)bctbx_list_nth_data(_data, (int)[indexPath row])];
[super accessoryForCell:cell atPath:indexPath];
BOOL forwardMode = VIEW(ChatConversationView).pendingForwardMessage != nil;
cell.forwardIcon.hidden = !forwardMode;
if (forwardMode) {
cell.ephemeral.hidden = true;
cell.imdmIcon.hidden = true;
}
return cell;
}

View file

@ -34,6 +34,9 @@
@property(weak, nonatomic) IBOutlet UIBackToCallButton *backToCallButton;
@property (weak, nonatomic) IBOutlet UIView *waitView;
@property (weak, nonatomic) IBOutlet UIInterfaceStyleButton *toggleSelectionButton;
@property (weak, nonatomic) IBOutlet UILabel *forwardTitle;
@property (weak, nonatomic) IBOutlet UIInterfaceStyleButton *cancelForwardButton;
- (IBAction)onAddGroupChatClick:(id)event;
- (IBAction)onAddClick:(id)event;

View file

@ -53,8 +53,28 @@
[button addTarget:self action:@selector(crashButtonTapped:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];*/
BOOL forwardMode = VIEW(ChatConversationView).pendingForwardMessage != nil;
_tableController.editButton.hidden = forwardMode;
_forwardTitle.text = NSLocalizedString(@"Select a discussion or create a new one",nil);
_forwardTitle.hidden = !forwardMode;
_cancelForwardButton.hidden = !forwardMode;
_tableController.tableView.frame = CGRectMake(0, 66 + (forwardMode ? _forwardTitle.frame.size.height : 0), _tableController.tableView.frame.size.width, self.view.frame.size.height - 66 - ( forwardMode ? _forwardTitle.frame.size.height : 0 ));
_addButton.frame = CGRectMake(forwardMode ? 82 : 0 , _addButton.frame.origin.y, _addButton.frame.size.width, _addButton.frame.size.height);
_addGroupChatButton.frame = CGRectMake(forwardMode ? 164 : 82 , _addGroupChatButton.frame.origin.y, _addGroupChatButton.frame.size.width, _addGroupChatButton.frame.size.height);
}
- (void)ephemeralDeleted:(NSNotification *)notif {
//LinphoneChatRoom *r =[[notif.userInfo objectForKey:@"room"] intValue];
[self.tableController loadData];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
@ -150,8 +170,9 @@ static UICompositeViewDescription *compositeDescription = nil;
assert(NO);
}
- (void)ephemeralDeleted:(NSNotification *)notif {
[self.tableController loadData];
- (IBAction)onCancelForwardClicked:(id)sender {
VIEW(ChatConversationView).pendingForwardMessage = nil;
[PhoneMainView.instance popCurrentView];
}
@end

View file

@ -200,7 +200,7 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)onLoginClick:(id)sender {
if (!linphone_core_is_network_reachable(LC)) {
[PhoneMainView.instance presentViewController:[LinphoneUtils networkErrorView] animated:YES completion:nil];
[PhoneMainView.instance presentViewController:[LinphoneUtils networkErrorView:@"configure an account"] animated:YES completion:nil];
return;
}

@ -1 +0,0 @@
Subproject commit 99ae001ae51f4883d189e3f77544828ec035395d

View file

@ -60,6 +60,8 @@ extern NSString *const kLinphoneFileTransferRecvUpdate;
extern NSString *const kLinphoneQRCodeFound;
extern NSString *const kLinphoneChatCreateViewChange;
extern NSString *const kLinphoneEphemeralMessageDeletedInRoom;
extern NSString *const kLinphoneVoiceMessagePlayerEOF;
extern NSString *const kLinphoneVoiceMessagePlayerLostFocus;
extern NSString *const kLinphoneConfStateParticipantListChanged;
extern NSString *const kLinphoneConfStateChanged;

View file

@ -75,6 +75,8 @@ NSString *const kLinphoneFileTransferRecvUpdate = @"LinphoneFileTransferRecvUpda
NSString *const kLinphoneQRCodeFound = @"LinphoneQRCodeFound";
NSString *const kLinphoneChatCreateViewChange = @"LinphoneChatCreateViewChange";
NSString *const kLinphoneEphemeralMessageDeletedInRoom = @"LinphoneEphemeralMessageDeletedInRoom";
NSString *const kLinphoneVoiceMessagePlayerEOF = @"LinphoneVoiceMessagePlayerEOF";
NSString *const kLinphoneVoiceMessagePlayerLostFocus = @"LinphoneVoiceMessagePlayerLostFocus";
NSString *const kLinphoneConfStateChanged = @"kLinphoneConfStateChanged";
NSString *const kLinphoneConfStateParticipantListChanged = @"kLinphoneConfStateParticipantListChanged";
@ -1801,6 +1803,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
return;
if (linphone_core_local_permission_enabled(LC)) return;
if (![defaults boolForKey: alertSuppressionKey]) {
UIAlertController *noticeView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Local network usage", nil)
@ -1825,7 +1828,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
- (void)call:(const LinphoneAddress *)iaddr {
// First verify that network is available, abort otherwise.
if (!linphone_core_is_network_reachable(theLinphoneCore)) {
[PhoneMainView.instance presentViewController:[LinphoneUtils networkErrorView] animated:YES completion:nil];
[PhoneMainView.instance presentViewController:[LinphoneUtils networkErrorView:@"place a call"] animated:YES completion:nil];
return;
}
@ -2270,10 +2273,7 @@ void conference_device_changed(LinphoneConference *conference, const LinphonePar
void linphone_iphone_conference_state_changed(LinphoneCore *lc, LinphoneConference *conf,LinphoneConferenceState state) {
if (state == LinphoneConferenceStateCreated) {
LinphoneConferenceCbs * cbs = linphone_conference_get_current_callbacks(conf);
if (!cbs) {
cbs = linphone_factory_create_conference_cbs(linphone_factory_get());
}
LinphoneConferenceCbs * cbs = linphone_factory_create_conference_cbs(linphone_factory_get());
linphone_conference_cbs_set_participant_added(cbs, conference_participant_changed);
linphone_conference_cbs_set_participant_device_added(cbs, conference_device_changed);
linphone_conference_cbs_set_participant_device_removed(cbs, conference_device_changed);

View file

@ -29,15 +29,21 @@
<outlet property="innerView" destination="Y7i-Gm-AdY" id="PbL-8X-8Fi"/>
<outlet property="messageImageView" destination="yMW-cT-bpU" id="MNr-F2-abQ"/>
<outlet property="messageText" destination="cx9-0K-P9L" id="kPh-s4-Ioy"/>
<outlet property="photoCellContentView" destination="VAJ-tE-fsa" id="JXg-8d-aCi"/>
<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="replyTransferIcon" destination="DFk-Mg-EnD" id="gPH-xU-mAw"/>
<outlet property="replyTransferLabel" destination="l8e-ta-Fv5" id="9Ns-ZN-Wbl"/>
<outlet property="totalView" destination="8I3-n2-0kS" id="aa8-j9-saW"/>
<outlet property="vrPlayPause" destination="7Zn-bp-e0Y" id="ed8-ZL-VpS"/>
<outlet property="vrTimerLabel" destination="VUD-m6-g1J" id="tOj-bF-YHd"/>
<outlet property="vrView" destination="bhq-9n-zYF" id="PT7-3a-6tn"/>
<outlet property="vrWave" destination="B5G-6m-k8r" id="fXd-ze-WQg"/>
<outlet property="vrWaveMaskPlayback" destination="a7V-w2-tIE" id="vRZ-VF-sJV"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="UGz-WT-BUv">
<rect key="frame" x="0.0" y="0.0" width="428" height="321"/>
<rect key="frame" x="0.0" y="0.0" width="428" height="381"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="hD2-19-7IH" userLabel="avatarImage" customClass="UIRoundedImageView">
@ -57,134 +63,182 @@
<nil key="highlightedColor"/>
</label>
<view clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Y7i-Gm-AdY" userLabel="innerView">
<rect key="frame" x="39" y="20" width="382" height="297"/>
<rect key="frame" x="39" y="20" width="382" height="357"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Répondu" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l8e-ta-Fv5" userLabel="replyTransferLabel">
<rect key="frame" x="17" y="3" width="69" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="menu_reply_default.png" translatesAutoresizingMaskIntoConstraints="NO" id="DFk-Mg-EnD" userLabel="replyTransferIcon">
<rect key="frame" x="3" y="3" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<imageView userInteractionEnabled="NO" alpha="0.20000000298023224" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="U2P-5n-gg8" userLabel="backgroundColorImage">
<rect key="frame" x="0.0" y="0.0" width="365" height="297"/>
<rect key="frame" x="0.0" y="0.0" width="365" height="357"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
</imageView>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8I3-n2-0kS" userLabel="view">
<rect key="frame" x="27" y="10" width="301" height="252"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VAJ-tE-fsa">
<rect key="frame" x="0.0" y="10" width="382" height="347"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="linphone_logo.png" translatesAutoresizingMaskIntoConstraints="NO" id="yMW-cT-bpU" userLabel="image" customClass="UILoadingImageView">
<rect key="frame" x="0.0" y="0.0" width="301" height="161"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
<gestureRecognizers/>
</imageView>
</subviews>
</view>
<view clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" preservesSuperviewLayoutMargins="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VYJ-RC-Jmg" userLabel="finalAssetView">
<rect key="frame" x="7" y="10" width="351" height="252"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gzv-K4-5OL" userLabel="finalImage">
<rect key="frame" x="0.0" y="0.0" width="351" height="262"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<gestureRecognizers/>
</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"/>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8I3-n2-0kS" userLabel="view">
<rect key="frame" x="27" y="0.0" width="301" height="252"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<imageView contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="linphone_logo.png" translatesAutoresizingMaskIntoConstraints="NO" id="yMW-cT-bpU" userLabel="image" customClass="UILoadingImageView">
<rect key="frame" x="0.0" y="0.0" width="301" height="252"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
<gestureRecognizers/>
</imageView>
</subviews>
</view>
<view clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" preservesSuperviewLayoutMargins="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VYJ-RC-Jmg" userLabel="finalAssetView">
<rect key="frame" x="7" y="0.0" width="351" height="252"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gzv-K4-5OL" userLabel="finalImage">
<rect key="frame" x="0.0" y="0.0" width="351" height="262"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<gestureRecognizers/>
</imageView>
</subviews>
</view>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UzU-cc-LbF" userLabel="fileView">
<rect key="frame" x="13" y="0.0" width="230" 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"/>
<subviews>
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" fixedFrame="YES" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="USm-wC-GvG" userLabel="transferProgress">
<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="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"/>
<state key="normal" title="DOWNLOAD" backgroundImage="color_G.png">
<color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<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="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"/>
<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="40" width="299" height="87"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
<subviews>
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" fixedFrame="YES" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="USm-wC-GvG" userLabel="transferProgress">
<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="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"/>
<state key="normal" title="DOWNLOAD" backgroundImage="color_G.png">
<color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<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="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"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<state key="normal" title="CANCEL" backgroundImage="color_I.png">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="highlighted" backgroundImage="color_M.png"/>
<connections>
<action selector="onCancelClick:" destination="-1" eventType="touchUpInside" id="D9y-vf-I4Y"/>
</connections>
</button>
</subviews>
</view>
<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="96" 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"/>
<state key="normal" title="CANCEL" backgroundImage="color_I.png">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="PLAY" backgroundImage="color_I.png">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<state key="highlighted" backgroundImage="color_M.png"/>
<connections>
<action selector="onCancelClick:" destination="-1" eventType="touchUpInside" id="D9y-vf-I4Y"/>
<action selector="onPlayClick:" destination="-1" eventType="touchUpInside" id="B4y-PJ-4tO"/>
</connections>
</button>
<textView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" editable="NO" text="Lore ipsum..." translatesAutoresizingMaskIntoConstraints="NO" id="cx9-0K-P9L" userLabel="messageText" customClass="UITextViewNoDefine">
<rect key="frame" x="0.0" y="312" width="365" height="35"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
<dataDetectorType key="dataDetectorTypes" link="YES"/>
</textView>
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="chat_read.png" translatesAutoresizingMaskIntoConstraints="NO" id="LPj-VT-0fH" userLabel="imdmIcon">
<rect key="frame" x="372" y="337" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<accessibility key="accessibilityConfiguration" label="Delivery failed"/>
</imageView>
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ephemeral_messages_color_A.png" id="7JB-ZL-0lZ" userLabel="ephemeralIcon">
<rect key="frame" x="351" y="336" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
</imageView>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00:00" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="IRV-qN-sRj" userLabel="ephemeralTime">
<rect key="frame" x="282" y="336" width="65" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="9"/>
<color key="textColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view tag="28021" contentMode="scaleToFill" id="bhq-9n-zYF" userLabel="voiceRecording">
<rect key="frame" x="7" y="252" width="351" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
<subviews>
<view tag="28024" contentMode="scaleToFill" id="a7V-w2-tIE" userLabel="vr_wave_mask_playback">
<rect key="frame" x="8" y="10" width="335" height="42"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.93333333330000001" green="0.93333333330000001" blue="0.93333333330000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<button opaque="NO" tag="28028" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7Zn-bp-e0Y">
<rect key="frame" x="8" y="13" width="35" height="35"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<state key="normal" image="vr_play.png"/>
<connections>
<action selector="onVRPlayPauseClick:" destination="-1" eventType="touchUpInside" id="ffk-KD-q9Q"/>
</connections>
</button>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" tag="28025" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="vr_wave.png" translatesAutoresizingMaskIntoConstraints="NO" id="B5G-6m-k8r">
<rect key="frame" x="52" y="16" width="223" height="27"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" tag="28027" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="VUD-m6-g1J">
<rect key="frame" x="287" y="20" width="48" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<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"/>
<state key="normal" title="PLAY" backgroundImage="color_I.png">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<state key="highlighted" backgroundImage="color_M.png"/>
<connections>
<action selector="onPlayClick:" destination="-1" eventType="touchUpInside" id="B4y-PJ-4tO"/>
</connections>
</button>
<textView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" editable="NO" text="Lore ipsum..." translatesAutoresizingMaskIntoConstraints="NO" id="cx9-0K-P9L" userLabel="messageText" customClass="UITextViewNoDefine">
<rect key="frame" x="0.0" y="262" width="365" height="35"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
<dataDetectorType key="dataDetectorTypes" link="YES"/>
</textView>
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="chat_read.png" translatesAutoresizingMaskIntoConstraints="NO" id="LPj-VT-0fH" userLabel="imdmIcon">
<rect key="frame" x="372" y="287" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<accessibility key="accessibilityConfiguration" label="Delivery failed"/>
</imageView>
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ephemeral_messages_color_A.png" id="7JB-ZL-0lZ" userLabel="ephemeralIcon">
<rect key="frame" x="351" y="286" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
</imageView>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00:00" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="IRV-qN-sRj" userLabel="ephemeralTime">
<rect key="frame" x="282" y="286" width="65" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="9"/>
<color key="textColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</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>
@ -192,21 +246,11 @@
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="-118.40000000000001" y="244.22788605697153"/>
</view>
<tapGestureRecognizer id="5ZI-Ip-lGl" userLabel="resendClick">
<connections>
<action selector="onResendClick:" destination="-1" id="XOF-AF-Hes"/>
</connections>
</tapGestureRecognizer>
<tapGestureRecognizer id="aDF-hC-ddO" userLabel="imageClick">
<connections>
<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="414.39999389648438" height="414.39999389648438"/>
@ -217,5 +261,8 @@
<image name="color_M.png" width="2" height="2"/>
<image name="ephemeral_messages_color_A.png" width="136" height="158.39999389648438"/>
<image name="linphone_logo.png" width="41.599998474121094" height="42.400001525878906"/>
<image name="menu_reply_default.png" width="25" height="25"/>
<image name="vr_play.png" width="200" height="200"/>
<image name="vr_wave.png" width="1078" height="90"/>
</resources>
</document>

View file

@ -18,6 +18,8 @@
<outlet property="imdmIcon" destination="Nod-GX-0kg" id="Pa7-l6-pGh"/>
<outlet property="innerView" destination="vdk-RV-QRU" id="wQs-CR-Pm3"/>
<outlet property="messageText" destination="CYa-If-oB4" id="7xm-UF-1qB"/>
<outlet property="replyTransferIcon" destination="asp-BT-0GQ" id="20N-AN-DV1"/>
<outlet property="replyTransferLabel" destination="169-mW-EH1" id="KVp-dz-HS5"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
@ -41,6 +43,17 @@
<rect key="frame" x="39" y="20" width="143" height="40"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="menu_reply_default.png" translatesAutoresizingMaskIntoConstraints="NO" id="asp-BT-0GQ" userLabel="replyTransferIcon">
<rect key="frame" x="4" y="3" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Répondu" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="169-mW-EH1" userLabel="replyTransferLabel">
<rect key="frame" x="17" y="3" width="69" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" alpha="0.20000000000000001" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="ZIO-Cb-28G" userLabel="backgroundColorImage">
<rect key="frame" x="0.0" y="0.0" width="126" height="40"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
@ -80,5 +93,6 @@
<image name="chat_read.png" width="20" height="20"/>
<image name="color_A.png" width="2" height="2"/>
<image name="ephemeral_messages_color_A.png" width="136" height="158.39999389648438"/>
<image name="menu_reply_default.png" width="25" height="25"/>
</resources>
</document>

View file

@ -14,6 +14,7 @@
<outlet property="chatContentLabel" destination="21" id="24"/>
<outlet property="chatLatestTimeLabel" destination="r7A-Mk-LQX" id="J0r-yr-YLk"/>
<outlet property="ephemeral" destination="q18-yi-ol3" id="xhD-9e-BbP"/>
<outlet property="forwardIcon" destination="rbY-QS-6QH" id="09w-ky-Ezs"/>
<outlet property="imdmIcon" destination="aa2-Kl-c1H" id="rnr-XY-r9K"/>
<outlet property="securityImage" destination="kdl-Ln-eWv" id="S9v-cN-u4w"/>
<outlet property="unreadCountLabel" destination="ZXq-Do-7Ua" id="anx-Na-sYz"/>
@ -64,10 +65,6 @@
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="ephemeral_messages_color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="q18-yi-ol3">
<rect key="frame" x="338" y="51" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</imageView>
<view hidden="YES" autoresizesSubviews="NO" userInteractionEnabled="NO" tag="7" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7DE-KJ-9Q3" userLabel="unreadCountView" customClass="UIBouncingView">
<rect key="frame" x="338" y="12" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
@ -90,6 +87,14 @@
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="forward_message_default.png" id="rbY-QS-6QH" userLabel="transferIcon">
<rect key="frame" x="338" y="33" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="ephemeral_messages_color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="q18-yi-ol3">
<rect key="frame" x="338" y="54" width="21" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
@ -101,6 +106,7 @@
<image name="chat_list_indicator.png" width="28" height="28"/>
<image name="chat_read.png" width="20" height="20"/>
<image name="ephemeral_messages_color_A.png" width="136" height="158.39999389648438"/>
<image name="forward_message_default.png" width="187" height="148"/>
<image name="security_1_indicator.png" width="27.5" height="32.5"/>
</resources>
</document>

View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<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="UIChatReplyBubbleView" customModule="linphoneapp" customModuleProvider="target">
<connections>
<outlet property="contentCollection" destination="ZgY-Ye-8DD" id="hlD-Fw-g1z"/>
<outlet property="dismissButton" destination="KrT-j6-YOy" id="K5m-Mw-Cjx"/>
<outlet property="leftBar" destination="Iov-AL-8Xz" id="eKb-4B-unZ"/>
<outlet property="originalMessageGone" destination="B26-sw-o4w" id="Gwh-dh-GRN"/>
<outlet property="senderName" destination="uuW-tW-1Sj" id="Yao-6A-SBh"/>
<outlet property="textContent" destination="Czc-VH-qiH" id="e35-qw-Sz3"/>
<outlet property="view" destination="i5M-Pr-FkT" id="kJN-7M-ijh"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="350" height="120"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" tag="290394" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="uuW-tW-1Sj" userLabel="nameWithTextContent">
<rect key="frame" x="16" y="2" width="312" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" tag="290395" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="4" baselineAdjustment="alignBaselines" minimumFontSize="14" translatesAutoresizingMaskIntoConstraints="NO" id="Czc-VH-qiH" userLabel="textContent">
<rect key="frame" x="16" y="83" width="312" height="32"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="ZgY-Ye-8DD">
<rect key="frame" x="16" y="23" width="312" height="60"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="gR0-ml-XVX">
<size key="itemSize" width="55" height="55"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
</collectionView>
<view tag="290393" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Iov-AL-8Xz" userLabel="leftBar">
<rect key="frame" x="0.0" y="0.0" width="10" height="120"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Original message does not exist anymore" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="B26-sw-o4w" userLabel="originalMessageGone">
<rect key="frame" x="16" y="6" width="312" height="109"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<fontDescription key="fontDescription" type="italicSystem" pointSize="15"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" tag="290399" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KrT-j6-YOy" userLabel="dismiss">
<rect key="frame" x="327" y="51" width="20" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES"/>
<state key="normal" image="reply_cancel.png"/>
</button>
</subviews>
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="85.507246376811594" y="111.83035714285714"/>
</view>
</objects>
<resources>
<image name="reply_cancel.png" width="60" height="60"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

View file

@ -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" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" 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="18093"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -15,6 +13,7 @@
<outlet property="authView" destination="CCn-Oz-I0M" id="fSM-6k-paN"/>
<outlet property="cancelButton" destination="B1K-CB-3of" id="KKi-Xc-ldA"/>
<outlet property="confirmationButton" destination="SbQ-re-fGQ" id="yiv-a9-o8E"/>
<outlet property="forwardImage" destination="1Wh-Yi-cUe" id="YQq-bt-pk1"/>
<outlet property="securityImage" destination="bbo-g3-bGy" id="qZa-li-yrl"/>
<outlet property="titleLabel" destination="jLz-g1-cTe" id="qaj-OB-2r1"/>
<outlet property="view" destination="2Vb-Xy-rci" id="nNw-EJ-AY3"/>
@ -25,26 +24,26 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" alpha="0.89999999999999991" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="color_C.png" id="cqN-1f-6SE" userLabel="backgroundColor">
<imageView userInteractionEnabled="NO" alpha="0.89999999999999991" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_C.png" translatesAutoresizingMaskIntoConstraints="NO" id="cqN-1f-6SE" userLabel="backgroundColor">
<rect key="frame" x="0.0" y="0.0" width="377" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</imageView>
<view contentMode="scaleToFill" id="2BQ-o9-xv2">
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2BQ-o9-xv2">
<rect key="frame" x="28" y="139" width="320" height="365"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" insetsLayoutMarginsFromSafeArea="NO" image="security_2_indicator.png" id="bbo-g3-bGy" userLabel="securityImage">
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" image="security_2_indicator.png" translatesAutoresizingMaskIntoConstraints="NO" id="bbo-g3-bGy" userLabel="securityImage">
<rect key="frame" x="130" y="0.0" width="56" height="68"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Are you sure you want to delete all your selection?" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" id="jLz-g1-cTe" userLabel="titleLabel">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Are you sure you want to delete all your selection?" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="jLz-g1-cTe" userLabel="titleLabel">
<rect key="frame" x="-10" y="15" width="336" height="279"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="21"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="B1K-CB-3of" userLabel="cancelButton" customClass="UIRoundBorderedButton">
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="B1K-CB-3of" userLabel="cancelButton" customClass="UIRoundBorderedButton">
<rect key="frame" x="8" y="308" width="139" height="42"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<state key="normal" title="CANCEL" backgroundImage="color_H.png">
@ -56,11 +55,11 @@
<action selector="onCancelClick:" destination="-1" eventType="touchUpInside" id="LvF-N2-56g"/>
</connections>
</button>
<view hidden="YES" contentMode="scaleToFill" id="CCn-Oz-I0M" userLabel="authView">
<view hidden="YES" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CCn-Oz-I0M" userLabel="authView">
<rect key="frame" x="61" y="273" width="240" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="lWW-wB-FMR" userLabel="authButton">
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="lWW-wB-FMR" userLabel="authButton">
<rect key="frame" x="26" y="2" width="17" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<state key="normal" image="checkbox_unchecked.png"/>
@ -69,7 +68,7 @@
<action selector="onAuthClick:" destination="-1" eventType="touchUpInside" id="9A4-ZX-cXA"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Do not show again" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dQL-Sf-slc">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Do not show again" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dQL-Sf-slc">
<rect key="frame" x="55" y="2" width="176" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
@ -78,7 +77,7 @@
</label>
</subviews>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="SbQ-re-fGQ" userLabel="confirmationButton" customClass="UIRoundBorderedButton">
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SbQ-re-fGQ" userLabel="confirmationButton" customClass="UIRoundBorderedButton">
<rect key="frame" x="169" y="308" width="143" height="42"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<state key="normal" title="DELETE" backgroundImage="color_I.png">
@ -90,22 +89,27 @@
<action selector="onConfirmationClick:" destination="-1" eventType="touchUpInside" id="0np-r7-R0W"/>
</connections>
</button>
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="forward_message_default.png" translatesAutoresizingMaskIntoConstraints="NO" id="1Wh-Yi-cUe">
<rect key="frame" x="89" y="50" width="138" height="54"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
</view>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="simulatedStatusBarMetrics"/>
<point key="canvasLocation" x="872" y="261.76911544227886"/>
<point key="canvasLocation" x="871.20000000000005" y="261.31934032983509"/>
</view>
</objects>
<resources>
<image name="checkbox_checked.png" width="17" height="17"/>
<image name="checkbox_unchecked.png" width="17" height="17"/>
<image name="checkbox_checked.png" width="27.200000762939453" height="27.200000762939453"/>
<image name="checkbox_unchecked.png" width="27.200000762939453" height="27.200000762939453"/>
<image name="color_C.png" width="2" height="2"/>
<image name="color_F.png" width="2" height="2"/>
<image name="color_H.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="security_2_indicator.png" width="27" height="32"/>
<image name="forward_message_default.png" width="187" height="148"/>
<image name="security_2_indicator.png" width="27.5" height="32.5"/>
</resources>
</document>

View file

@ -41,9 +41,18 @@
@property(strong, nonatomic) IBOutlet UITapGestureRecognizer *imageGestureRecognizer;
@property (weak, nonatomic) IBOutlet UIButton *fileButton;
@property (weak, nonatomic) IBOutlet UIView *fileView;
@property (strong, nonatomic) IBOutlet UILongPressGestureRecognizer *plusLongGestureRecognizer;
@property(strong, nonatomic) NSMutableArray<UIChatContentView *> *contentViews;
// Video recordings
@property (weak, nonatomic) IBOutlet UIView *vrView;
@property (weak, nonatomic) IBOutlet UIButton *vrPlayPause;
@property (weak, nonatomic) IBOutlet UILabel *vrTimerLabel;
@property (weak, nonatomic) IBOutlet UIImageView *vrWave;
@property (weak, nonatomic) IBOutlet UIView *vrWaveMaskPlayback;
@property NSTimer *vrPlayerTimer;
@property NSString *voiceRecordingFile;
- (void)setEvent:(LinphoneEventLog *)event;
- (void)setChatMessage:(LinphoneChatMessage *)message;
@ -51,10 +60,8 @@
- (IBAction)onDownloadClick:(id)event;
- (IBAction)onImageClick:(id)event;
- (IBAction)onCancelClick:(id)sender;
- (IBAction)onResendClick:(id)event;
- (IBAction)onPlayClick:(id)sender;
- (IBAction)onFileClick:(id)sender;
- (IBAction)onPlusClick:(id)sender;
@end

View file

@ -26,6 +26,13 @@
#import <AudioToolbox/AudioToolbox.h>
#import <AVKit/AVKit.h>
#define voicePlayer VIEW(ChatConversationView).sharedVoicePlayer
#define chatView VIEW(ChatConversationView)
#define FILE_ICON_TAG 0
#define REALIMAGE_TAG 1
@implementation UIChatBubblePhotoCell {
FileTransferDelegate *_ftd;
CGSize imageSize, bubbleSize, videoDefaultSize;
@ -54,6 +61,13 @@
assetIsLoaded = FALSE;
self.contentView.userInteractionEnabled = NO;
_contentViews = [[NSMutableArray alloc] init];
self.vrView.layer.cornerRadius = 30.0f;
self.vrView.layer.masksToBounds = YES;
[self.innerView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onPopupMenuPressed)]];
self.messageText.userInteractionEnabled = false;
}
return self;
}
@ -73,7 +87,6 @@
- (void)setChatMessage:(LinphoneChatMessage *)amessage {
_imageGestureRecognizer.enabled = NO;
_plusLongGestureRecognizer.enabled = NO;
_messageImageView.image = nil;
_finalImage.image = nil;
_finalImage.hidden = TRUE;
@ -98,6 +111,7 @@
}
- (void) loadImageAsset:(PHAsset*) asset image:(UIImage *)image {
_finalImage.tag = REALIMAGE_TAG;
dispatch_async(dispatch_get_main_queue(), ^{
[_finalImage setImage:image];
[_messageImageView setAsset:asset];
@ -105,7 +119,6 @@
_messageImageView.hidden = YES;
_finalImage.hidden = NO;
_fileView.hidden = YES;
_plusLongGestureRecognizer.enabled = YES;
[self layoutSubviews];
});
}
@ -127,14 +140,10 @@
}
- (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;
_playButton.hidden = YES;
});
UIImage *image = [UIChatBubbleTextCell getImageFromFileName:name];
[self loadImageAsset:nil image:image];
_imageGestureRecognizer.enabled = YES;
_finalImage.tag = FILE_ICON_TAG;
}
- (void) loadPlaceholder {
@ -145,38 +154,63 @@
[_messageImageView stopLoading];
_messageImageView.hidden = YES;
_imageGestureRecognizer.enabled = YES;
_plusLongGestureRecognizer.enabled = YES;
_finalImage.hidden = NO;
[self layoutSubviews];
});
}
- (void)update {
if (self.message == nil) {
LOGW(@"Cannot update message room cell: NULL message");
return;
}
[super update];
_vrPlayPause.enabled = linphone_core_get_calls_nb(LC) == 0;
NSMutableDictionary<NSString *, NSString *> *encrptedFilePaths = NULL;
if ([VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId]) {
encrptedFilePaths = [LinphoneManager getMessageAppDataForKey:@"encryptedfiles" inMessage:self.message];
if (!encrptedFilePaths) {
encrptedFilePaths = [NSMutableDictionary dictionary];
}
}
_voiceRecordingFile = nil;
LinphoneContent *voiceContent = [UIChatBubbleTextCell voiceContent:self.message];
if (voiceContent) {
_voiceRecordingFile = [NSString stringWithUTF8String:[VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId] ? linphone_content_get_plain_file_path(voiceContent) : linphone_content_get_file_path(voiceContent)];
if ([VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId])
[encrptedFilePaths setValue:_voiceRecordingFile forKey:[NSString stringWithUTF8String:linphone_content_get_name(voiceContent)]];
[self setVoiceMessageDuration];
_vrWaveMaskPlayback.frame = CGRectZero;
_vrWaveMaskPlayback.backgroundColor = linphone_chat_message_is_outgoing(self.message) ? UIColor.orangeColor : UIColor.grayColor;
}
const bctbx_list_t *contents = linphone_chat_message_get_contents(self.message);
size_t contentCount = bctbx_list_size(contents);
if (voiceContent)
contentCount--;
BOOL multiParts = ((linphone_chat_message_get_text_content(self.message) != NULL) ? bctbx_list_size(contents) > 2 : bctbx_list_size(contents) > 1);
if (voiceContent && !multiParts) {
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = _playButton.hidden = _fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
return;
}
if (multiParts) {
if (!assetIsLoaded) {
NSMutableDictionary<NSString *, NSString *> *encrptedFilePaths = NULL;
if ([VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId]) {
encrptedFilePaths = [LinphoneManager getMessageAppDataForKey:@"encryptedfiles" inMessage:self.message];
if (!encrptedFilePaths) {
encrptedFilePaths = [NSMutableDictionary dictionary];
}
}
_imageGestureRecognizer.enabled = NO;
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = _playButton.hidden = _fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
const bctbx_list_t *it = contents;
int i;
for (it = contents, i=0; it != NULL; it=bctbx_list_next(it)){
LinphoneContent *content = (LinphoneContent *)it->data;
if (linphone_content_is_voice_recording(content)) { // Handled elsewhere
continue;
}
if (linphone_content_is_file_transfer(content) || linphone_content_is_file(content)){
UIChatContentView *contentView = [[UIChatContentView alloc] initWithFrame: CGRectMake(0,0,0,0)];
if([VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId] && (linphone_chat_message_is_outgoing(self.message) || linphone_content_is_file(content))) {
@ -214,8 +248,6 @@
return;
}
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);
@ -241,10 +273,15 @@
_playButton.hidden = YES;
_fileName.hidden = _fileView.hidden = _fileButton.hidden =YES;
} else {
_downloadButton.hidden = NO;
_downloadButton.hidden = YES;
UIChatContentView * contentView = [[UIChatContentView alloc] init];
[contentView setContent:fileContent message:self.message];
contentView.position = 0;
[_contentViews addObject:contentView];
_cancelButton.hidden = _fileTransferProgress.hidden = YES;
_playButton.hidden = YES;
_fileName.hidden = _fileView.hidden = _fileButton.hidden = YES;
[self layoutSubviews];
}
return;
}
@ -464,25 +501,6 @@
}];
}
- (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);
@ -510,21 +528,15 @@
}
}
- (void)onResendClick:(id)event {
if (_downloadButton.hidden == NO) {
// if download button is displayed, click on it
[self onDownloadClick:event];
} else if (_cancelButton.hidden == NO) {
[self onCancelClick:event];
} else {
[super onResend];
}
}
- (IBAction)onImageClick:(id)event {
if (_finalImage.tag == FILE_ICON_TAG) {
[self onFileClick:nil];
return;
}
LinphoneChatMessageState state = linphone_chat_message_get_state(self.message);
if (state == LinphoneChatMessageStateNotDelivered) {
[self onResendClick:event];
return;
} else {
if (![_messageImageView isLoading]) {
ImageView *view = VIEW(ImageView);
@ -662,7 +674,7 @@
CGFloat max_imagesh=0;
CGFloat max_imagesw=0;
CGFloat originy=0;
CGFloat originx=0;
CGFloat originx=-IMAGE_DEFAULT_MARGIN;
CGFloat availableWidth = chatTableView.tableView.frame.size.width-CELL_IMAGE_X_MARGIN;
NSMutableArray<NSURL *> *fileUrls = [[NSMutableArray alloc] init];
@ -713,16 +725,111 @@
textFrame.origin = CGPointMake(textFrame.origin.x, self.finalAssetView.frame.origin.y + self.finalAssetView.frame.size.height);
else
// When image hasn't be download
textFrame.origin = CGPointMake(textFrame.origin.x, _imageSubView.frame.size.height + _imageSubView.frame.origin.y - 10);
textFrame.origin = CGPointMake(textFrame.origin.x, _voiceRecordingFile ? _fileView.frame.origin.y : _imageSubView.frame.size.height + _imageSubView.frame.origin.y - 10);
if (!utf8Text) {
textFrame.size.height = 0;
} else {
textFrame.size.height = bubbleFrame.size.height - 90;//textFrame.origin.x;
}
if (_voiceRecordingFile) {
CGRect vrFrame = _vrView.frame;
vrFrame.origin.y = _contentViews.count == 0 && !utf8Text ? _fileView.frame.origin.y : textFrame.origin.y;
_vrView.frame = vrFrame;
textFrame.origin.y += VOICE_RECORDING_PLAYER_HEIGHT;
_vrView.hidden = NO;
} else {
_vrView.hidden = YES;
}
CGRect r = super.photoCellContentView.frame;
r.origin.y = linphone_chat_message_is_reply(super.message) ? super.replyView.view.frame.origin.y + super.replyView.view.frame.size.height + 10 : 7 ;
super.photoCellContentView.frame = r;
r = super.photoCellContentView.frame;
r.origin.y = linphone_chat_message_is_forward(super.message) ? super.contactDateLabel.frame.origin.y + super.contactDateLabel.frame.size.height + 3 : r.origin.y;
super.photoCellContentView.frame = r;
self.messageText.frame = textFrame;
}
// Voice messages
static AVAudioPlayer* utilityPlayer;
-(void) setVoiceMessageDuration {
NSError *error = nil;
AVAudioPlayer* utilityPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL URLWithString:_voiceRecordingFile] error:&error]; // Workaround as opening multiple linphone_players at the same time can cause crash (here for example layout refreshed whilst a voice memo is playing
_vrTimerLabel.text = [self formattedDuration:utilityPlayer.duration];
utilityPlayer = nil;
}
-(void) voicePlayTimerUpdate {
CGRect r = _vrWaveMaskPlayback.frame;
r.size.width += _vrView.frame.size.width / ((linphone_player_get_duration(voicePlayer) / 500)) ;
if (r.size.width > _vrView.frame.size.width) {
r.size.width = _vrView.frame.size.width;
}
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
_vrWaveMaskPlayback.frame = r;
}completion:^(BOOL finished) {}];
}
-(void) stopPlayer {
[NSNotificationCenter.defaultCenter removeObserver:self];
[chatView stopSharedPlayer];
[_vrPlayPause setImage:[UIImage imageNamed:@"vr_play"] forState:UIControlStateNormal];
[_vrPlayerTimer invalidate];
_vrWaveMaskPlayback.frame = CGRectZero;
}
-(NSString *)formattedDuration:(long)valueMs {
return [NSString stringWithFormat:@"%02ld:%02ld", valueMs/ 60, (valueMs % 60) ];
}
-(void) startPlayer {
[chatView startSharedPlayer:_voiceRecordingFile.UTF8String];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(stopPlayer)
name:kLinphoneVoiceMessagePlayerLostFocus
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(stopPlayer)
name:kLinphoneVoiceMessagePlayerEOF
object:nil];
[_vrPlayPause setImage:[UIImage imageNamed:@"vr_stop"] forState:UIControlStateNormal];
CGRect r = CGRectZero;
r.size.height = _vrView.frame.size.height - 14;
r.origin.y = 7;
_vrWaveMaskPlayback.frame = r;
_vrPlayerTimer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:@selector(voicePlayTimerUpdate)
userInfo:nil
repeats:YES];
[self voicePlayTimerUpdate];
}
- (IBAction)onVRPlayPauseClick:(id)sender {
if ([chatView sharedPlayedIsPlaying:_voiceRecordingFile.UTF8String])
[self stopPlayer];
else {
[self startPlayer];
}
}
// menu
-(void) onPopupMenuPressed {
[super onPopupMenuPressed];
}
@end

View file

@ -22,12 +22,16 @@
#import "UITextViewNoDefine.h"
#import "ChatConversationTableView.h"
#import "UIRoundedImageView.h"
#import "UIChatReplyBubbleView.h"
#define CELL_IMAGE_X_MARGIN 100
#define IMAGE_DEFAULT_WIDTH 120
#define IMAGE_DEFAULT_MARGIN 5
#define VOICE_RECORDING_PLAYER_HEIGHT 60
#define VOICE_RECORDING_PLAYER_WIDTH 300
@interface UIChatBubbleTextCell : UITableViewCell <UIDocumentPickerDelegate>
@interface UIChatBubbleTextCell : UITableViewCell <UIDocumentPickerDelegate, UITableViewDataSource,UITableViewDelegate>
@property(readonly, nonatomic) LinphoneEventLog *event;
@property(readonly, nonatomic) LinphoneChatMessage *message;
@ -47,6 +51,22 @@
@property (weak, nonatomic) IBOutlet UIView *innerView;
@property (weak, nonatomic) IBOutlet UILabel *ephemeralTime;
@property (weak, nonatomic) IBOutlet UIImageView *ephemeralIcon;
@property ChatConversationTableView *tableController;
@property BOOL popupMenuAllowed;
// Message popup menu
@property UITableView *popupMenu;
@property NSMutableArray *messageActionsTitles;
@property NSMutableArray *messageActionsIcons;
@property NSMutableArray *messageActionsBlocks;
// Message reply/transfer
@property UIChatReplyBubbleView *replyView;
@property UILabel *replyOrForward;
@property (weak, nonatomic) IBOutlet UIImageView *replyTransferIcon;
@property (weak, nonatomic) IBOutlet UILabel *replyTransferLabel;
@property (weak, nonatomic) IBOutlet UIView *photoCellContentView;
@property(nonatomic) BOOL isFirst;
@property(nonatomic) BOOL isLast;
@ -57,14 +77,13 @@
+ (CGSize)getMediaMessageSizefromOriginalSize:(CGSize)originalSize withWidth:(int)width;
+ (UIImage *)getImageFromVideoUrl:(NSURL *)url;
+ (UIImage *)getImageFromContent:(LinphoneContent *)content filePath:(NSString *)filePath;
+ (UIImage *)getImageFromFileName:(NSString *)fileName;
- (void)setEvent:(LinphoneEventLog *)event;
- (void)setChatMessageForCbs:(LinphoneChatMessage *)message;
- (void)clearEncryptedFiles;
- (void)onDelete;
- (void)onResend;
- (void)onLime;
- (void)update;
- (void)displayImdmStatus:(LinphoneChatMessageState)state;
@ -72,5 +91,7 @@
+ (NSString *)TextMessageForChat:(LinphoneChatMessage *)message;
+ (CGSize)computeBoundingBox:(NSString *)text size:(CGSize)size font:(UIFont *)font;
+ (NSString *)ContactDateForChat:(LinphoneChatMessage *)message;
+(LinphoneContent *) voiceContent:(LinphoneChatMessage *)message;
-(void) onPopupMenuPressed;
-(void) dismissPopup;
@end

View file

@ -20,6 +20,7 @@
#import "UIChatBubbleTextCell.h"
#import "LinphoneManager.h"
#import "PhoneMainView.h"
#import "Utils.h"
#import <AssetsLibrary/ALAsset.h>
#import <AssetsLibrary/ALAssetRepresentation.h>
@ -28,6 +29,8 @@
#pragma mark - Lifecycle Functions
- (id)initWithIdentifier:(NSString *)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
if ([identifier isEqualToString:NSStringFromClass(self.class)]) {
@ -40,22 +43,11 @@
[self addSubview:sub];
}
}
[_innerView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onPopupMenuPressed)]];
_messageText.userInteractionEnabled = false;
UITapGestureRecognizer *limeRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onLime)];
limeRecognizer.numberOfTapsRequired = 1;
//[_LIMEKO addGestureRecognizer:limeRecognizer];
//_LIMEKO.userInteractionEnabled = YES;
UITapGestureRecognizer *resendRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onResend)];
resendRecognizer.numberOfTapsRequired = 1;
[_bubbleView addGestureRecognizer:resendRecognizer];
_imdmIcon.userInteractionEnabled = YES;
UITapGestureRecognizer *resendRecognizer2 =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onResend)];
resendRecognizer2.numberOfTapsRequired = 1;
//[_imdmLabel addGestureRecognizer:resendRecognizer2];
//_imdmLabel.userInteractionEnabled = YES;
self.contentView.userInteractionEnabled = NO;
return self;
@ -205,11 +197,12 @@
_avatarImage.hidden = !_isFirst;
}
// Not use [UIImage imageNamed], it takes too much time
NSString *imageName = outgoing ? @"color_A.png" : @"color_D.png";
_backgroundColorImage.image =
[UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@",[[NSBundle mainBundle] bundlePath],imageName]];
_backgroundColorImage.image = nil;
_backgroundColorImage.backgroundColor = outgoing ? [UIColor color:@"A"] : [UIColor color:@"D"];
// set maskedCorners
if (@available(iOS 11.0, *)) {
_backgroundColorImage.layer.cornerRadius = 10;
@ -255,6 +248,7 @@
frame.origin.y = _isFirst ? 20 : 0;
_innerView.frame = frame;
[_messageText setAccessibilityLabel:outgoing ? @"Outgoing message" : @"Incoming message"];
if (outgoing &&
(state == LinphoneChatMessageStateDeliveredToUser || state == LinphoneChatMessageStateDisplayed ||
@ -262,6 +256,23 @@
[self displayImdmStatus:state];
} else
[self displayImdmStatus:LinphoneChatMessageStateInProgress];
if (linphone_chat_message_is_reply(_message)) {
if (_replyView == nil) {
_replyView = [[UIChatReplyBubbleView alloc] initWithNibName:@"UIChatReplyBubbleView" bundle:nil];
[self.innerView addSubview:_replyView.view];
}
_replyView.view.hidden = false;
CGRect replyFrame = CGRectMake(_contactDateLabel.frame.origin.x, _contactDateLabel.frame.origin.y+_contactDateLabel.frame.size.height,self.contactDateLabel.frame.size.width, REPLY_CHAT_BUBBLE_HEIGHT);
_replyView.view.frame = replyFrame;
[_replyView configureForMessage:linphone_chat_message_get_reply_message(_message) withDimissBlock:^{} hideDismiss:true withClickBlock:^{
[_tableController scrollToMessage:linphone_chat_message_get_reply_message(_message)];
}];
} else {
if (_replyView)
_replyView.view.hidden = true;
}
}
- (void)setEditing:(BOOL)editing {
@ -269,7 +280,6 @@
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
_messageText.userInteractionEnabled = !editing;
_resendRecognizer.enabled = !editing;
}
@ -300,76 +310,6 @@
}
}
- (void)onLime {
/*if (!_LIMEKO.hidden)
[self displayLIMEWarning];*/
}
- (void)onResend {
if (_message == nil || !linphone_chat_message_is_outgoing(_message))
return;
LinphoneChatMessageState state = linphone_chat_message_get_state(_message);
if (state != LinphoneChatMessageStateNotDelivered && state != LinphoneChatMessageStateFileTransferError)
return;
const bctbx_list_t *contents = linphone_chat_message_get_contents(_message);
BOOL multiParts = ((linphone_chat_message_get_text_content(self.message) != NULL) ? bctbx_list_size(contents) > 2 : bctbx_list_size(contents) > 1);
if (multiParts) {
FileContext *newfileContext = [[FileContext alloc] init];
[newfileContext clear];
NSMutableDictionary<NSString *, NSString *> *encrptedFilePaths = encrptedFilePaths = [LinphoneManager getMessageAppDataForKey:@"encryptedfiles" inMessage:_message];
int i;
const bctbx_list_t *it;
for (it = contents, i=0; it != NULL; it=bctbx_list_next(it)){
LinphoneContent *content = (LinphoneContent *)it->data;
if (linphone_content_is_file_transfer(content) || linphone_content_is_file(content)){
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
NSString *filePath = [encrptedFilePaths valueForKey:name];
if (filePath == NULL) {
filePath = [LinphoneManager validFilePath:name];
}
[newfileContext addObject:[NSData dataWithContentsOfFile:filePath] name:name type:[NSString stringWithUTF8String:linphone_content_get_type(content)]];
}
}
[self onDelete];
dispatch_async(dispatch_get_main_queue(), ^ {
const char *text = linphone_chat_message_get_text_content(_message);
[_chatRoomDelegate resendMultiFiles:newfileContext message: text? [NSString stringWithUTF8String:text]: NULL];
});
return;
}
if (linphone_chat_message_get_file_transfer_information(_message) != NULL) {
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:_message];
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:_message];
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:_message];
NSString *filePath = [LinphoneManager getMessageAppDataForKey:@"encryptedfile" inMessage:self.message];
[self onDelete];
dispatch_async(dispatch_get_main_queue(), ^ {
NSData *data = NULL;
if (filePath) {
data = [NSData dataWithContentsOfFile:filePath];
}
const char *text = linphone_chat_message_get_text_content(_message);
NSString *str = text ? [NSString stringWithUTF8String:text] : NULL;
if (localImage) {
[_chatRoomDelegate resendFile: (data?:[ChatConversationView getFileData:localImage]) withName:localImage type:@"image" key:@"localimage" message:str];
} else if (localVideo) {
[_chatRoomDelegate resendFile:(data?:[ChatConversationView getFileData:localVideo]) withName:localVideo type:@"video" key:@"localvideo" message:str];
} else {
[_chatRoomDelegate resendFile:(data?:[ChatConversationView getFileData:localFile]) withName:localFile type:@"image" key:@"localfile" message:str];
}
});
} else {
[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];
});
}
}
#pragma mark - State changed handling
static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
LOGI(@"State for message [%p] changed to %s", msg, linphone_chat_message_state_to_string(state));
@ -424,9 +364,15 @@ static const CGFloat CELL_MIN_HEIGHT = 65.0f;
static const CGFloat CELL_MIN_WIDTH = 190.0f;
static const CGFloat CELL_MESSAGE_X_MARGIN = 68 + 10.0f;
static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
static const CGFloat REPLY_CHAT_BUBBLE_HEIGHT = 120;
static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
+ (CGSize)ViewHeightForMessage:(LinphoneChatMessage *)chat withWidth:(int)width {
return [self ViewHeightForMessageText:chat withWidth:width textForImdn:nil];
CGSize size = [self ViewHeightForMessageText:chat withWidth:width textForImdn:nil];
size.height += linphone_chat_message_is_forward(chat) || linphone_chat_message_is_reply(chat) ? REPLY_OR_FORWARD_TAG_HEIGHT : 0;
size.height += linphone_chat_message_is_reply(chat) ? REPLY_CHAT_BUBBLE_HEIGHT+5 : 0;
return size;
}
+ (CGSize)ViewHeightForFile:(int)width {
@ -437,6 +383,41 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
return size;
}
+(NSString *)formattedDuration:(long)valueMs {
return [NSString stringWithFormat:@"%02ld:%02ld", valueMs/ 60, (valueMs % 60) ];
}
+(NSString *) recordingDuration:(NSString *) _voiceRecordingFile{
NSError *error = nil;
AVAudioPlayer* utilityPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL URLWithString:_voiceRecordingFile] error:&error]; // Workaround as opening multiple linphone_players at the same time can cause crash (here for example layout refreshed whilst a voice memo is playing
return [self formattedDuration:utilityPlayer.duration];
utilityPlayer = nil;
}
+ (UIImage *)getImageFromFileName:(NSString *)fileName {
NSString *extension = [[fileName.lowercaseString componentsSeparatedByString:@"."] lastObject];
UIImage *image;
NSString * text = fileName;
if ([fileName containsString:@"voice-recording"]) {
image = [UIImage imageNamed:@"file_voice_default"];
text = [self recordingDuration:[LinphoneManager validFilePath:fileName]];
} else {
if ([extension isEqualToString:@"pdf"])
image = [UIImage imageNamed:@"file_pdf_default"];
else if ([@[@"png", @"jpg", @"jpeg", @"bmp", @"heic"] containsObject:extension])
image = [UIImage imageNamed:@"file_picture_default"];
else if ([@[@"mkv", @"avi", @"mov", @"mp4"] containsObject:extension])
image = [UIImage imageNamed:@"file_video_default"];
else if ([@[@"wav", @"au", @"m4a"] containsObject:extension])
image = [UIImage imageNamed:@"file_audio_default"];
else
image = [UIImage imageNamed:@"file_default"];
}
return [SwiftUtil textToImageWithDrawText:text inImage:image];
}
+ (UIImage *)getImageFromContent:(LinphoneContent *)content filePath:(NSString *)filePath; {
NSString *type = [NSString stringWithUTF8String:linphone_content_get_type(content)];
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
@ -452,11 +433,23 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
image = [[UIImage alloc] initWithData:data];
}
if (image) return image;
UIImage *basicImage = [ChatConversationView getBasicImage];
image = [ChatConversationView drawText:[NSString stringWithFormat:@"📎 %@",name] image:basicImage textSize:25];
return image;
else return [self getImageFromFileName:name];
}
+(LinphoneContent *) voiceContent:(LinphoneChatMessage *)message {
for (const bctbx_list_t *it = linphone_chat_message_get_contents(message); it != NULL; it=bctbx_list_next(it)){
LinphoneContent *content = (LinphoneContent *)it->data;
if (linphone_content_is_voice_recording(content))
return content;
}
return nil;
}
+(CGSize) addVoicePlayerToSize:(CGSize)size withMargins:(BOOL)margins {
return CGSizeMake(MAX(size.width,VOICE_RECORDING_PLAYER_WIDTH + (margins ? CELL_MESSAGE_X_MARGIN: 0)), size.height + VOICE_RECORDING_PLAYER_HEIGHT+(margins ? CELL_MESSAGE_Y_MARGIN: 0));
}
+ (CGSize)ViewHeightForMessageText:(LinphoneChatMessage *)chat withWidth:(int)width textForImdn:(NSString *)imdnText {
NSString *messageText = [UIChatBubbleTextCell TextMessageForChat:chat];
@ -484,14 +477,51 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
CGFloat imagesh=0;
CGFloat max_imagesw=0;
CGFloat max_imagesh=0;
LinphoneContent *voiceContent = [self voiceContent:chat];
const bctbx_list_t *contents = linphone_chat_message_get_contents(chat);
BOOL multiParts = ((linphone_chat_message_get_text_content(chat) != NULL) ? bctbx_list_size(contents) > 2 : bctbx_list_size(contents) > 1);
size_t contentCount = bctbx_list_size(contents);
if (voiceContent)
contentCount--;
BOOL multiParts = ((linphone_chat_message_get_text_content(chat) != NULL) ? contentCount > 2 : contentCount > 1);
if (voiceContent && contentCount == 0) {
size = CGSizeMake(VOICE_RECORDING_PLAYER_WIDTH, VOICE_RECORDING_PLAYER_HEIGHT);
CGSize textSize = CGSizeMake(0, 0);
if (![messageText isEqualToString:@"🗻"]) {
textSize = [self computeBoundingBox:messageText
size:CGSizeMake(max_imagesw , CGFLOAT_MAX)
font:messageFont];
}
// 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;
}
if (multiParts) {
const bctbx_list_t *it = contents;
NSMutableDictionary<NSString *, NSString *> *encrptedFilePaths = [LinphoneManager getMessageAppDataForKey:@"encryptedfiles" inMessage:chat];
for (it = contents; it != NULL; it=bctbx_list_next(it)){
LinphoneContent *content = (LinphoneContent *)it->data;
if (linphone_content_is_voice_recording(content)) {
CGSize sSize = CGSizeMake(VOICE_RECORDING_PLAYER_WIDTH, VOICE_RECORDING_PLAYER_HEIGHT);
imagesw += sSize.width;
if (imagesw > width) {
imagesw = sSize.width;
max_imagesw = MAX(max_imagesw, imagesw);
max_imagesh += imagesh;
imagesh = sSize.height;
} else {
max_imagesw = MAX(max_imagesw, imagesw);
imagesh = MAX(imagesh, sSize.height);
}
continue;
}
UIImage *image;
if(!linphone_chat_message_is_outgoing(chat) && linphone_content_is_file_transfer(content)) {
// not yet downloaded
@ -538,22 +568,25 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN, CELL_MIN_HEIGHT) ;
return size;
}
LinphoneContent *fileContent = linphone_chat_message_get_file_transfer_information(chat);
if (url == nil && fileContent == NULL) {
// if here, either 1 file + text or just one file or just text.
BOOL justText = linphone_chat_message_get_text_content(chat) != NULL && contentCount == 1;
if (justText) { // Just text
size = [self computeBoundingBox:messageText
size:CGSizeMake(width - CELL_MESSAGE_X_MARGIN - 4, CGFLOAT_MAX)
font:messageFont];
} else {
size.width += 4;
} else { // Just file or file with text
LinphoneContent *fileContent = linphone_chat_message_get_file_transfer_information(chat);
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:chat];
NSString *localFile = [LinphoneManager getMessageAppDataForKey:@"localfile" inMessage:chat];
NSString *localVideo = [LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:chat];
NSString *filePath = [LinphoneManager getMessageAppDataForKey:@"encryptedfile" inMessage:chat];
NSString *fileName = [NSString stringWithUTF8String:linphone_content_get_name(fileContent)];
NSString *fileName = fileContent ? [NSString stringWithUTF8String:linphone_content_get_name(fileContent)] : nil;
CGSize textSize = CGSizeMake(0, 0);
if (![messageText isEqualToString:@"🗻"]) {
if (![messageText isEqualToString:@"🗻"] && messageText.length > 0) {
textSize = [self computeBoundingBox:messageText
size:CGSizeMake(width - CELL_MESSAGE_X_MARGIN - 4, CGFLOAT_MAX)
font:messageFont];
@ -582,28 +615,45 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
NSData *data = [NSData dataWithContentsOfURL:[VIEW(ChatConversationView) getICloudFileUrl:localFile]];
image = [[UIImage alloc] initWithData:data];
}
} else if (voiceContent){
return [self addVoicePlayerToSize:[self ViewHeightForFile:width] withMargins:true];
} else {
return [self ViewHeightForFile:width];
image = nil;
originalImageSize = CGSizeMake(140, 140);
}
originalImageSize = image.size;
if (image != nil)
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);
CGSize baseSize = CGSizeMake(120 + CELL_MESSAGE_X_MARGIN, 120 + CELL_MESSAGE_Y_MARGIN + textSize.height + (textSize.height != 0 ? 20 : 0));
if (voiceContent) {
baseSize = [self addVoicePlayerToSize:baseSize withMargins:true];
baseSize.height -= VOICE_RECORDING_PLAYER_HEIGHT;
baseSize.height += 10;
}
return baseSize;
}
if (localImage && [[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSData* data = [NSData dataWithContentsOfFile:filePath];
UIImage *image = [[UIImage alloc] initWithData:data];
if (!image) {
return [self ViewHeightForFile:width];
CGSize fileSize = [self ViewHeightForFile:width];
if (voiceContent) {
fileSize = [self addVoicePlayerToSize:fileSize withMargins:true];
}
return fileSize;
}
originalImageSize = image.size;
} else if (localVideo && [[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
UIImage *image = [UIChatBubbleTextCell getImageFromVideoUrl:[NSURL fileURLWithPath:filePath]];
if (!image) {
return [self ViewHeightForFile:width];
CGSize fileSize = [self ViewHeightForFile:width];
if (voiceContent) {
fileSize = [self addVoicePlayerToSize:fileSize withMargins:true];
}
return fileSize;
}
originalImageSize = image.size;
} else {
@ -615,7 +665,11 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
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);
CGSize baseSize = CGSizeMake(CELL_MIN_WIDTH, CELL_MIN_WIDTH + CELL_MESSAGE_Y_MARGIN + textSize.height);
if (voiceContent) {
baseSize = [self addVoicePlayerToSize:baseSize withMargins:true];
}
return baseSize;
} else {
PHAsset *asset = [assets firstObject];
originalImageSize = CGSizeMake([asset pixelWidth], [asset pixelHeight]);
@ -627,6 +681,11 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
size.height += textSize.height;
size.width = MAX(textSize.width, size.width);
}
if (voiceContent) {
size.width = MAX(size.width,VOICE_RECORDING_PLAYER_WIDTH);
size.height += VOICE_RECORDING_PLAYER_HEIGHT;
}
size.width = MAX(size.width + CELL_MESSAGE_X_MARGIN, CELL_MIN_WIDTH);
size.height = MAX(size.height + CELL_MESSAGE_Y_MARGIN, CELL_MIN_HEIGHT);
@ -670,15 +729,45 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
int origin_x;
bubbleFrame.size = [self.class ViewSizeForMessage:_message withWidth:available_width];
if (linphone_chat_message_is_reply(_message)) {
bubbleFrame.size.width = MAX(bubbleFrame.size.width, 300);
}
if (tableView.isEditing) {
origin_x = 0;
} else {
origin_x = (is_outgoing ? self.frame.size.width - bubbleFrame.size.width : 0);
}
CGRect r = _messageText.frame;
r.origin.y = linphone_chat_message_is_reply(_message) ? _replyView.view.frame.origin.y + _replyView.view.frame.size.height + 5 : 3;
_messageText.frame = r;
r = _messageText.frame;
r.origin.y = linphone_chat_message_is_forward(_message) ? _contactDateLabel.frame.origin.y + _contactDateLabel.frame.size.height + 5 : r.origin.y;
_messageText.frame = r;
_replyTransferIcon.hidden = ! linphone_chat_message_is_reply(_message) && !linphone_chat_message_is_forward(_message);
_replyTransferLabel.hidden = ! linphone_chat_message_is_reply(_message) && !linphone_chat_message_is_forward(_message);
if (linphone_chat_message_is_reply(_message)) {
CGRect replyFrame = CGRectMake(10, _replyTransferLabel.frame.origin.y+_replyTransferLabel.frame.size.height+5,MAX(self.contactDateLabel.frame.size.width-20,180), REPLY_CHAT_BUBBLE_HEIGHT);
_replyView.view.frame = replyFrame;
_replyTransferIcon.image = [UIImage imageNamed:@"menu_reply_default"];
_replyTransferLabel.text = NSLocalizedString(@"Answer",nil);
_replyTransferLabel.textColor = [UIColor lightGrayColor];
}
if (linphone_chat_message_is_forward(_message)) {
_replyTransferIcon.image = [UIImage imageNamed:@"menu_forward_default"];
_replyTransferLabel.text = NSLocalizedString(@"Transferred",nil);
_replyTransferLabel.textColor = [UIColor darkGrayColor];
}
bubbleFrame.origin.x = origin_x;
_bubbleView.frame = bubbleFrame;
}
}
@ -706,4 +795,173 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 44;
return mediaSize;
}
// Message popup menu
// Copy text -> if has text
// Transfer -> always
// Reply -> always
// IMDM Status -> out
// Delete -> always
-(void) buildActions {
LinphoneChatMessage *message = self.message;
_messageActionsTitles = [[NSMutableArray alloc] init];
_messageActionsBlocks = [[NSMutableArray alloc] init];
_messageActionsIcons = [[NSMutableArray alloc] init];
UIChatBubbleTextCell *thiz = self;
LinphoneChatMessageState state = linphone_chat_message_get_state(self.message);
if (state == LinphoneChatMessageStateNotDelivered || state == LinphoneChatMessageStateFileTransferError) {
[_messageActionsTitles addObject:NSLocalizedString(@"Resend", nil)];
[_messageActionsIcons addObject:@"menu_resend_default"];
[_messageActionsBlocks addObject:^{
[thiz dismissPopup];
if (!linphone_core_is_network_reachable(LC)) {
[PhoneMainView.instance presentViewController:[LinphoneUtils networkErrorView:@"send a message"] animated:YES completion:nil];
return;
}
linphone_chat_message_send(message);
}];
}
if (linphone_chat_message_get_utf8_text(message)) {
[_messageActionsTitles addObject:NSLocalizedString(@"Copy text", nil)];
[_messageActionsIcons addObject:@"menu_copy_text_default"];
[_messageActionsBlocks addObject:^{
[thiz dismissPopup];
[UIPasteboard.generalPasteboard setString:[NSString stringWithUTF8String:linphone_chat_message_get_text_content(message)]];
}];
}
[_messageActionsTitles addObject:NSLocalizedString(@"Forward", nil)];
[_messageActionsIcons addObject:@"menu_forward_default"];
[_messageActionsBlocks addObject:^{
[thiz dismissPopup];
VIEW(ChatConversationView).pendingForwardMessage = message;
[PhoneMainView.instance changeCurrentView:VIEW(ChatsListView).compositeViewDescription];
}];
[_messageActionsTitles addObject:NSLocalizedString(@"Reply", nil)];
[_messageActionsIcons addObject:@"menu_reply_default"];
[_messageActionsBlocks addObject:^{
[thiz dismissPopup];
[VIEW(ChatConversationView) initiateReplyViewForMessage:message];
}];
if (linphone_chat_message_is_outgoing(self.message) && linphone_chat_room_get_nb_participants(linphone_chat_message_get_chat_room(self.message)) > 1) {
[_messageActionsTitles addObject:NSLocalizedString(@"Infos", nil)];
[_messageActionsIcons addObject:@"menu_info"];
[_messageActionsBlocks addObject:^{
[thiz dismissPopup];
ChatConversationImdnView *view = VIEW(ChatConversationImdnView);
view.msg = message;
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
}];
}
[_messageActionsTitles addObject:NSLocalizedString(@"Delete", nil)];
[_messageActionsIcons addObject:@"menu_delete"];
[_messageActionsBlocks addObject:^{
[thiz dismissPopup];
linphone_chat_room_delete_message(linphone_chat_message_get_chat_room(message), message);
[VIEW(ChatConversationView).tableController reloadData];
}];
}
-(void) onPopupMenuPressed {
if (_popupMenu != nil)
[self dismissPopup];
if (!self.popupMenuAllowed)
return;
[VIEW(ChatConversationView).tableController dismissMessagesPopups];
self.innerView.layer.borderWidth = 3;
self.innerView.layer.borderColor = [UIColor color:@"A"].CGColor;
[self buildActions];
int width = 250;
int cellHeight = 44;
int numberOfItems = (int) _messageActionsTitles.count;
CGRect screenRect = UIScreen.mainScreen.bounds;
int menuHeight = numberOfItems * cellHeight;
CGRect frame = CGRectMake(
linphone_chat_message_is_outgoing(self.message) ? screenRect.size.width - width - 10 : 10,
(self.frame.origin.y + self.frame.size.height) - [VIEW(ChatConversationView).tableController .tableView contentOffset].y > screenRect.size.height /2 ? self.frame.origin.y - menuHeight - 10: self.frame.origin.y + self.frame.size.height,
width,
menuHeight);
_popupMenu = [[UITableView alloc]initWithFrame:frame];
_popupMenu.dataSource = self;
_popupMenu.delegate = self;
_popupMenu.layer.shadowColor = [UIColor lightGrayColor].CGColor;
_popupMenu.layer.shadowOpacity = 0.5;
_popupMenu.layer.shadowOffset = CGSizeZero;
_popupMenu.layer.shadowRadius = 5;
_popupMenu.layer.masksToBounds = false;
_popupMenu.tableFooterView = [UIView new];
_popupMenu.editing = NO;
_popupMenu.userInteractionEnabled = true;
[_popupMenu reloadData];
[VIEW(ChatConversationView).tableController.view addSubview:_popupMenu];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOutsideMenu:)];
tapGestureRecognizer.cancelsTouchesInView = NO;
tapGestureRecognizer.numberOfTapsRequired = 1;
[VIEW(ChatConversationView).tableController.view addGestureRecognizer:tapGestureRecognizer];
}
-(void) dismissPopup {
if (!_popupMenu)
return;
[_popupMenu removeFromSuperview];
_popupMenu = nil;
self.innerView.layer.borderWidth = 0;
[self setNeedsLayout];
}
-(void) tapOutsideMenu:(UITapGestureRecognizer *) g {
CGPoint p = [g locationInView:VIEW(ChatConversationView).tableController.view];
if (!CGRectContainsPoint(_popupMenu.frame,p)) {
[self dismissPopup];
}
}
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
void (^ myblock)(void) = [_messageActionsBlocks objectAtIndex:indexPath.row];
[self dismissPopup];
myblock();
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_messageActionsTitles count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell.imageView.image = [[UIImage imageNamed:[_messageActionsIcons objectAtIndex:indexPath.row]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
cell.textLabel.text = [_messageActionsTitles objectAtIndex:indexPath.row];
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
if ([[_messageActionsIcons objectAtIndex:indexPath.row] isEqualToString:@"menu_delete"]) {
cell.textLabel.textColor = UIColor.redColor;
cell.imageView.tintColor = UIColor.redColor;
} else {
cell.imageView.tintColor = PhoneMainView.instance.darkMode ? UIColor.whiteColor : UIColor.blackColor;
}
return cell;
}
@end

View file

@ -38,6 +38,8 @@
@property(weak, nonatomic) IBOutlet UILabel *unreadCountLabel;
@property (weak, nonatomic) IBOutlet UIImageView *imdmIcon;
@property (weak, nonatomic) IBOutlet UIImageView *ephemeral;
@property (weak, nonatomic) IBOutlet UIImageView *forwardIcon;
- (id)initWithIdentifier:(NSString*)identifier;

View file

@ -46,6 +46,7 @@
- (void)setChatRoom:(LinphoneChatRoom *)achat {
chatRoom = achat;
[self update];
[self.forwardIcon setImageNamed:@"forward_message_default" tintColor:PhoneMainView.instance.darkMode ? UIColor.whiteColor : UIColor.darkGrayColor];
}
#pragma mark -

View file

@ -31,19 +31,20 @@
if(!linphone_chat_message_is_outgoing(_message) && linphone_content_is_file_transfer(_content)) {
// has not yet downloaded
UIImage *basicImage = [ChatConversationView getBasicImage];
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)] ;
UIImage *image = [ChatConversationView drawText:name image:basicImage textSize:25];
UIImage *image = [UIChatBubbleTextCell getImageFromFileName:name];
[self setImage:image];
_downloadButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_downloadButton addTarget:self
action:@selector(onDownloadClick:)
forControlEvents:UIControlEventTouchUpInside];
_downloadButton.backgroundColor = [UIColor orangeColor];
UIFont *boldFont = [UIFont systemFontOfSize:10];
NSMutableAttributedString *boldText = [[NSMutableAttributedString alloc] initWithString:@"Download" attributes:@{ NSFontAttributeName : boldFont }];
UIFont *boldFont = [UIFont systemFontOfSize:12];
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentCenter;
NSMutableAttributedString *boldText = [[NSMutableAttributedString alloc] initWithString:@"Download" attributes:@{ NSFontAttributeName : boldFont, NSParagraphStyleAttributeName:paragraphStyle,NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle) }];
[_downloadButton setAttributedTitle:boldText forState:UIControlStateNormal];
_downloadButton.frame = CGRectMake(3, 3, 60, 30);
_downloadButton.frame = CGRectMake(0, 90, 120, 30);
[self addSubview:_downloadButton];
} else {
if (_filePath == NULL) {
@ -56,6 +57,7 @@
tapGestureRecognizer.numberOfTapsRequired = 1;
tapGestureRecognizer.enabled = YES;
[self addGestureRecognizer:tapGestureRecognizer];
self.userInteractionEnabled = true;
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of linphone-iphone
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIChatReplyBubbleView : UIViewController <UICollectionViewDataSource>
@property (weak, nonatomic) IBOutlet UILabel *senderName;
@property (weak, nonatomic) IBOutlet UIButton *dismissButton;
@property (weak, nonatomic) IBOutlet UIView *leftBar;
@property (weak, nonatomic) IBOutlet UIView *rightBar;
@property LinphoneChatMessage *message;
@property (weak, nonatomic) IBOutlet UILabel *textContent;
@property void (^ dismissAction)(void);
@property void (^ clickAction)(void);
@property (weak, nonatomic) IBOutlet UICollectionView *contentCollection;
@property NSArray *dataContent;
@property (weak, nonatomic) IBOutlet UILabel *originalMessageGone;
-(void) configureForMessage:(LinphoneChatMessage *)message withDimissBlock:(void (^)(void))dismissBlock hideDismiss:(BOOL)hideDismiss withClickBlock:(void (^)(void))clickBlock;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of linphone-iphone
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "UIChatReplyBubbleView.h"
#import "linphoneapp-Swift.h"
#import "Utils.h"
@interface UIChatReplyBubbleView ()
@end
@implementation UIChatReplyBubbleView
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
return self;
}
-(void) viewDidLoad {
_contentCollection.dataSource = self;
[_contentCollection registerClass:UICollectionViewCell.class forCellWithReuseIdentifier:@"dataContent"];
}
-(void) configureForMessage:(LinphoneChatMessage *)message withDimissBlock:(void (^)(void))dismissBlock hideDismiss:(BOOL)hideDismiss withClickBlock:(void (^)(void))clickBlock{
if (!message) {
_textContent.hidden = true;
_dismissButton.hidden = true;
_contentCollection.hidden = true;
_senderName.hidden = true;
_originalMessageGone.hidden = false;
return;
}
if (hideDismiss) {
self.view.layer.cornerRadius = 10;
self.view.layer.masksToBounds = true;
}
_originalMessageGone.hidden = true;
self.message = message;
self.dataContent = [self loadDataContent];
NSString *sender = [FastAddressBook displayNameForAddress:linphone_chat_message_get_from_address(message)];
_senderName.text = sender;
const char * text = linphone_chat_message_get_text_content(message);
if (text && strlen(text) == 0)
text = nil;
_textContent.text = text ? [NSString stringWithUTF8String:text] : @"";
_dismissButton.hidden = hideDismiss;
_dismissAction = dismissBlock;
_clickAction = clickBlock;
if (hideDismiss) {
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(onClick)];
[self.view addGestureRecognizer:singleFingerTap];
}
else
[_dismissButton addTarget:self action:@selector(dismissClick) forControlEvents:UIControlEventTouchUpInside];
self.view.backgroundColor = hideDismiss ? UIColor.whiteColor :(linphone_chat_message_is_outgoing(message) ? [[UIColor color:@"A"] colorWithAlphaComponent:0.2] : [[UIColor color:@"D"] colorWithAlphaComponent:0.2]);
_leftBar.backgroundColor = linphone_chat_message_is_outgoing(message) ? [UIColor color:@"A"] : [UIColor color:@"D"];
_leftBar.hidden = !hideDismiss;
_rightBar.backgroundColor = self.view.backgroundColor;
// Resize frame -> text or content only = 100, 145 otherwise
_contentCollection.hidden = self.dataContent.count == 0;
CGRect r = self.view.frame ;
r.size.width = self.view.superview.frame.size.width;
self.view.frame = r;
if (self.dataContent.count == 0) {
CGRect r = _textContent.frame;
r.origin.y = _contentCollection.frame.origin.y;
r.size.height = 87;
_textContent.frame = r;
}
if (text == nil) {
CGRect r = _contentCollection.frame;
r.origin.y = 30;
_contentCollection.frame = r;
}
}
-(NSArray *) loadDataContent {
NSMutableArray *result = [[NSMutableArray alloc] init];
const bctbx_list_t *contents = linphone_chat_message_get_contents(_message);
const char * text = linphone_chat_message_get_utf8_text(_message);
if (text && bctbx_list_size(contents) == 1)
return result;
for (const bctbx_list_t * it = contents; it != NULL; it=bctbx_list_next(it)){
LinphoneContent *content = (LinphoneContent *)it->data;
if (linphone_content_is_text(content))
continue;
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
NSMutableDictionary<NSString *, NSString *> *encrptedFilePaths = encrptedFilePaths = [LinphoneManager getMessageAppDataForKey:@"encryptedfiles" inMessage:_message];
NSString *filePath = encrptedFilePaths ? [encrptedFilePaths valueForKey:name] : nil;
if (filePath == NULL) {
filePath = [LinphoneManager validFilePath:name];
}
[result addObject:[UIChatBubbleTextCell getImageFromContent:content filePath:filePath]];
}
return result;
}
-(void) dismissClick {
_dismissAction();
}
-(void) onClick {
_clickAction();
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.dataContent.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"dataContent" forIndexPath:indexPath];
UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 60, 60)];
img.image = [self.dataContent objectAtIndex:indexPath.row];
[cell.contentView addSubview:img];
return cell;
}
@end

View file

@ -45,6 +45,7 @@ typedef void (^UIConfirmationBlock)(void);
@property(weak, nonatomic) IBOutlet UIRoundBorderedButton *cancelButton;
@property (weak, nonatomic) IBOutlet UIImageView *securityImage;
@property (weak, nonatomic) IBOutlet UIImageView *forwardImage;
@property(weak, nonatomic) IBOutlet UIRoundBorderedButton *confirmationButton;
@property (weak, nonatomic) IBOutlet UIView *authView;
@property(weak, nonatomic) IBOutlet UILabel *titleLabel;

View file

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -17,15 +15,15 @@
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="50" height="100"/>
<rect key="frame" x="0.0" y="0.0" width="120" height="120"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="y2f-LK-bVa">
<rect key="frame" x="0.0" y="0.0" width="50" height="100"/>
<rect key="frame" x="0.0" y="0.0" width="120" height="120"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="J60-eT-n9R">
<rect key="frame" x="30" y="0.0" width="20" height="20"/>
<rect key="frame" x="100" y="0.0" width="20" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" button="YES" image="YES"/>
@ -36,15 +34,15 @@
</connections>
</button>
</subviews>
<viewLayoutGuide key="safeArea" id="Q5M-cg-NOt"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<viewLayoutGuide key="safeArea" id="Q5M-cg-NOt"/>
<point key="canvasLocation" x="7" y="47"/>
</view>
</objects>
<resources>
<image name="delete_img.png" width="50" height="50"/>
<image name="delete_img.png" width="37.5" height="37.5"/>
</resources>
</document>

View file

@ -0,0 +1,9 @@
/* Class = "UILabel"; text = "Original message removed"; ObjectID = "B26-sw-o4w"; */
"B26-sw-o4w.text" = "Original message does not exist anymore.";
/* Class = "UILabel"; text = "Label"; ObjectID = "Czc-VH-qiH"; */
"Czc-VH-qiH.text" = "Label";
/* Class = "UILabel"; text = "Label"; ObjectID = "uuW-tW-1Sj"; */
"uuW-tW-1Sj.text" = "Label";

View file

@ -0,0 +1,9 @@
/* Class = "UILabel"; text = "Original message removed"; ObjectID = "B26-sw-o4w"; */
"B26-sw-o4w.text" = "Le message original n'existe plus.";
/* Class = "UILabel"; text = "Label"; ObjectID = "Czc-VH-qiH"; */
"Czc-VH-qiH.text" = "Label";
/* Class = "UILabel"; text = "Label"; ObjectID = "uuW-tW-1Sj"; */
"uuW-tW-1Sj.text" = "Label";

View file

@ -121,6 +121,7 @@
- (BOOL)isIphoneXDevice;
+ (int)iphoneStatusBarHeight;
-(BOOL) darkMode;
@end

View file

@ -830,7 +830,7 @@ static RootViewManager *rootViewManagerInstance = nil;
}
if (!linphone_core_is_network_reachable(LC)) {
[PhoneMainView.instance presentViewController:[LinphoneUtils networkErrorView] animated:YES completion:nil];
[PhoneMainView.instance presentViewController:[LinphoneUtils networkErrorView:@"send a message"] animated:YES completion:nil];
return;
}
@ -957,4 +957,15 @@ void main_view_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomSta
[controller dismissModalViewControllerAnimated:YES];
}
#pragma mark - Light/Dark mode
-(BOOL) darkMode {
if (@available(iOS 13.0, *)) {
UITraitCollection *collection = [UITraitCollection currentTraitCollection];
return collection.userInterfaceStyle == UIUserInterfaceStyleDark;
} else {
return false;
}
}
@end

69
Classes/SwiftUtil.swift Normal file
View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of linphone-iphone
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import UIKit
@objc class SwiftUtil: NSObject {
@objc static func textToImage(drawText text: String, inImage image: UIImage) -> UIImage {
let textColor = UIColor.black
let fontMax = UIFont.systemFont(ofSize: 30)
let backgroundColor = UIColor.white
let size = CGSize(width: 120, height: 120)
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(size, false, scale)
let context = UIGraphicsGetCurrentContext()
backgroundColor.setFill()
context!.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
image.draw(in: CGRect(origin: CGPoint(x: size.width/2 - (image.size.width)/2,y: 5), size: image.size))
let label = UILabel(frame: CGRect(x: 0,y: 0,width: size.width,height: 50))
label.numberOfLines = 0
label.font = fontMax
label.adjustsFontSizeToFitWidth = true
label.text = text
label.textColor = textColor
label.textAlignment = .center
label.allowsDefaultTighteningForTruncation = true
label.lineBreakMode = .byTruncatingTail
imageWithLabel(label: label).draw(in: CGRect(origin: CGPoint(x:0,y: 60), size: CGSize(width: size.width,height: 50)))
let view = UIView(frame: CGRect(x: 0,y: 0,width: size.width,height: 50))
view.addSubview(label)
label.sizeToFit()
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
static func imageWithLabel(label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.frame.size, false, 0.0)
label.layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return img
}
}

View file

@ -24,11 +24,10 @@
@interface FileTransferDelegate : NSObject
- (void)uploadFileContent: (FileContext *)context forChatRoom:(LinphoneChatRoom *)chatRoom;
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key;
- (void)uploadFileContent: (FileContext *)context forChatRoom:(LinphoneChatRoom *)chatRoom rootMessage:(LinphoneChatMessage *)rootMessage;
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key rootMessage:(LinphoneChatMessage *)rootMessage;
- (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)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name rootMessage:(LinphoneChatMessage *)rootMessage;
- (void)cancel;
- (BOOL)download:(LinphoneChatMessage *)message;
- (void)stopAndDestroy;

View file

@ -102,7 +102,7 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message,
}
}
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key{
- (void)uploadData:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom type:(NSString *)type subtype:(NSString *)subtype name:(NSString *)name key:(NSString *)key rootMessage:(LinphoneChatMessage *)rootMessage{
if ([[LinphoneManager.instance fileTransferDelegates] containsObject:self]) {
LOGW(@"fileTransferDelegates has already added %p", self);
return;
@ -115,7 +115,8 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message,
linphone_content_set_subtype(content, [subtype UTF8String]);
linphone_content_set_name(content, [name UTF8String]);
linphone_content_set_file_path(content, [[LinphoneManager imagesDirectory] stringByAppendingPathComponent:name].UTF8String);
_message = linphone_chat_room_create_file_transfer_message(chatRoom, content);
_message = rootMessage;
linphone_chat_message_add_file_content(_message, 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]);
@ -124,15 +125,17 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message,
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)uploadFileContent: (FileContext *)context forChatRoom:(LinphoneChatRoom *)chatRoom {
- (void)uploadFileContent: (FileContext *)context forChatRoom:(LinphoneChatRoom *)chatRoom rootMessage:(LinphoneChatMessage *)rootMessage{
[LinphoneManager.instance.fileTransferDelegates addObject:self];
_message = linphone_chat_room_create_empty_message(chatRoom);
_message = rootMessage;
NSMutableArray<NSString *> *names = [[NSMutableArray alloc] init];
NSMutableArray<NSString *> *types = [[NSMutableArray alloc] init];
@ -162,6 +165,7 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message,
// todo indication progress
[LinphoneManager setValueInMessageAppData:names forKey:@"multiparts" inMessage:_message];
[LinphoneManager setValueInMessageAppData:types forKey:@"multipartstypes" inMessage:_message];
LOGI(@"%p Uploading content from message %p", self, _message);
linphone_chat_message_send(_message);
}
@ -170,21 +174,17 @@ static void file_transfer_progress_indication_send(LinphoneChatMessage *message,
- (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);
[self uploadData:data forChatRoom:chatRoom type:@"image" subtype:@"jpg" name:name key:@"localimage"];
[self uploadData:data forChatRoom:chatRoom type:@"image" subtype:@"jpg" name:name key:@"localimage" rootMessage:nil];
}
- (void)uploadVideo:(NSData *)data withassetId:(NSString *)phAssetId forChatRoom:(LinphoneChatRoom *)chatRoom {
NSString *name = [NSString stringWithFormat:@"IMG-%f.MOV", [NSDate timeIntervalSinceReferenceDate]];
[self uploadData:data forChatRoom:chatRoom type:@"video" subtype:@"mov" name:name key:@"localvideo"];
}
- (void)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name {
- (void)uploadFile:(NSData *)data forChatRoom:(LinphoneChatRoom *)chatRoom withName:(NSString *)name rootMessage:(LinphoneChatMessage *)rootMessage {
NSURL *url = [ChatConversationView getFileUrl: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];
[self uploadData:data forChatRoom:chatRoom type:fileType subtype:name.lastPathComponent name:name key:key rootMessage:rootMessage];
}
- (BOOL)download:(LinphoneChatMessage *)message {

View file

@ -39,7 +39,7 @@
+ (UIImage *)resizeImage:(UIImage *)imageToResize newSize:(CGSize)newSize;
+ (LinphoneAddress *)normalizeSipOrPhoneAddress:(NSString *)addr;
+ (UIAlertController *)networkErrorView;
+ (UIAlertController *)networkErrorView:(NSString *)action;
typedef enum {
LinphoneDateHistoryList,
@ -74,6 +74,13 @@ typedef enum {
@end
@interface UIImageView (ImageWithTint)
- (void)setImageNamed:(NSString *)name tintColor:(UIColor *)color;
- (void)setImageNamed:(NSString *)name tintColorLetter:(NSString *)letter;
@end
@interface NSString (linphoneExt)
- (NSString *)md5;
@ -111,6 +118,8 @@ typedef enum {
- (UIColor *)darkerColor;
+(UIColor *)color:(NSString *)letter;
@end
@interface UIImage (ForceDecode)

View file

@ -516,12 +516,10 @@
return res;
}
+ (UIAlertController *)networkErrorView {
+ (UIAlertController *)networkErrorView:(NSString *)action {
UIAlertController *errView =
[UIAlertController alertControllerWithTitle:NSLocalizedString(@"Network Error", nil)
message:NSLocalizedString(@"There is no network connection available, "
@"enable WIFI or WWAN prior to place a call",
nil)
message:NSLocalizedString([@"There is no network connection available, enable WIFI or WWAN prior to " stringByAppendingString:action],nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
@ -577,6 +575,23 @@
@end
@implementation UIImageView (ImageWithTint)
- (void)setImageNamed:(NSString *)name tintColor:(UIColor *)color {
self.image = [[UIImage imageNamed:name] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
self.tintColor = color;
}
- (void)setImageNamed:(NSString *)name tintColorLetter:(NSString *)letter {
UIColor *color = [UIColor color:letter];
self.image = [[UIImage imageNamed:name] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
self.tintColor = color;
}
@end
@implementation NSString (md5)
- (NSString *)md5 {
@ -806,6 +821,19 @@
return [self lumColor:0.75];
}
static NSMutableDictionary *letterColors = nil;
+(UIColor *)color:(NSString *)letter {
if (letterColors == nil)
letterColors = [[NSMutableDictionary alloc] init];
if (![letterColors objectForKey:letter]) {
UIImage *colorImage = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/color_%@.png",[[NSBundle mainBundle] bundlePath],letter]];
[letterColors setObject:[UIColor colorWithPatternImage:colorImage] forKey:letter];
}
return [letterColors objectForKey:letter];
}
@end
@implementation UIImage (ForceDecode)

View file

@ -5,7 +5,7 @@ source "https://github.com/CocoaPods/Specs.git"
def all_pods
if ENV['PODFILE_PATH'].nil?
pod 'linphone-sdk', '~> 5.0.16'
pod 'linphone-sdk', '~> 5.1.0-alpha.75+d4a0bd2'
else
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
Resources/images/vr_off.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
Resources/images/vr_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -109,7 +109,7 @@
61AE364F20C00B370089D9D3 /* ShareViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61AE364E20C00B370089D9D3 /* ShareViewController.m */; };
61AE365220C00B370089D9D3 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61AE365020C00B370089D9D3 /* MainInterface.storyboard */; };
61AE365620C00B370089D9D3 /* linphoneExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 61AE364B20C00B370089D9D3 /* linphoneExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
61AEBEA321906AFC00F35E7F /* (null) in Frameworks */ = {isa = PBXBuildFile; };
61AEBEA321906AFC00F35E7F /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
61AEBEBD2191990A00F35E7F /* DevicesListView.m in Sources */ = {isa = PBXBuildFile; fileRef = 61AEBEBC2191990A00F35E7F /* DevicesListView.m */; };
61AEBEBF2191991F00F35E7F /* DevicesListView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 61AEBEBE2191991F00F35E7F /* DevicesListView.xib */; };
61AEBEC62191E47500F35E7F /* chevron_list_close.png in Resources */ = {isa = PBXBuildFile; fileRef = 61AEBEC52191E47500F35E7F /* chevron_list_close.png */; };
@ -622,7 +622,7 @@
63E27A321C4FECD000D332AE /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 63E27A311C4FECD000D332AE /* LaunchScreen.xib */; };
63E27A521C50EDB000D332AE /* hold.mkv in Resources */ = {isa = PBXBuildFile; fileRef = 63E27A511C50EB2700D332AE /* hold.mkv */; };
63E59A3F1ADE70D900646FB3 /* InAppProductsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E59A3E1ADE70D900646FB3 /* InAppProductsManager.m */; };
63E802DB1C625AEF000D5509 /* (null) in Resources */ = {isa = PBXBuildFile; };
63E802DB1C625AEF000D5509 /* BuildFile in Resources */ = {isa = PBXBuildFile; };
63EC8D391D7438660066547B /* AssistantLinkView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 63EC8D3B1D7438660066547B /* AssistantLinkView.xib */; };
63F1DF441BCE618E00EDED90 /* UIAddressTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 63F1DF431BCE618E00EDED90 /* UIAddressTextField.m */; };
63F1DF4B1BCE983200EDED90 /* CallConferenceTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63F1DF4A1BCE983200EDED90 /* CallConferenceTableView.m */; };
@ -675,11 +675,35 @@
C61B1BF22667D075001A4E4A /* menu_security_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C61B1BF12667D075001A4E4A /* menu_security_default.png */; };
C61B1BF42667D202001A4E4A /* more_menu_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C61B1BF32667D202001A4E4A /* more_menu_default.png */; };
C61B1BF72667EC6B001A4E4A /* ephemeral_messages_color_A.png in Resources */ = {isa = PBXBuildFile; fileRef = C61B1BF62667EC6B001A4E4A /* ephemeral_messages_color_A.png */; };
C622E3EF26A81290004F5434 /* vr_stop.png in Resources */ = {isa = PBXBuildFile; fileRef = C622E3E926A8128F004F5434 /* vr_stop.png */; };
C622E3F026A81290004F5434 /* vr_wave.png in Resources */ = {isa = PBXBuildFile; fileRef = C622E3EA26A8128F004F5434 /* vr_wave.png */; };
C622E3F126A81290004F5434 /* vr_on.png in Resources */ = {isa = PBXBuildFile; fileRef = C622E3EB26A8128F004F5434 /* vr_on.png */; };
C622E3F226A81290004F5434 /* vr_off.png in Resources */ = {isa = PBXBuildFile; fileRef = C622E3EC26A8128F004F5434 /* vr_off.png */; };
C622E3F326A81290004F5434 /* vr_pause.png in Resources */ = {isa = PBXBuildFile; fileRef = C622E3ED26A8128F004F5434 /* vr_pause.png */; };
C622E3F426A81290004F5434 /* vr_play.png in Resources */ = {isa = PBXBuildFile; fileRef = C622E3EE26A81290004F5434 /* vr_play.png */; };
C64A854E2667B67200252AD2 /* EphemeralSettingsView.m in Sources */ = {isa = PBXBuildFile; fileRef = C64A854D2667B67200252AD2 /* EphemeralSettingsView.m */; };
C64A85502667B67A00252AD2 /* EphemeralSettingsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C64A854F2667B67A00252AD2 /* EphemeralSettingsView.xib */; };
C64A85522667B74100252AD2 /* ephemeral_messages_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C64A85512667B74100252AD2 /* ephemeral_messages_default.png */; };
C666756F264C925800A0273C /* VFSUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6DA657B261C950C0020CB43 /* VFSUtil.swift */; };
C6667571264C925B00A0273C /* VFSUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6DA657B261C950C0020CB43 /* VFSUtil.swift */; };
C66B03BB26E8EB1A009B5EDC /* UIChatReplyBubbleView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C66B03BD26E8EB1A009B5EDC /* UIChatReplyBubbleView.xib */; };
C66B040A26EFDA55009B5EDC /* reply_cancel.png in Resources */ = {isa = PBXBuildFile; fileRef = C66B040926EFDA54009B5EDC /* reply_cancel.png */; };
C66B040E26F095D1009B5EDC /* cancel_forward.png in Resources */ = {isa = PBXBuildFile; fileRef = C66B040D26F095CE009B5EDC /* cancel_forward.png */; };
C6A1BB3526E8815400540D50 /* menu_info.png in Resources */ = {isa = PBXBuildFile; fileRef = C6A1BB3126E8815300540D50 /* menu_info.png */; };
C6A1BB3626E8815400540D50 /* menu_forward_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6A1BB3226E8815400540D50 /* menu_forward_default.png */; };
C6A1BB3726E8815400540D50 /* menu_copy_text_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6A1BB3326E8815400540D50 /* menu_copy_text_default.png */; };
C6A1BB3826E8815400540D50 /* menu_reply_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6A1BB3426E8815400540D50 /* menu_reply_default.png */; };
C6A1BB3A26E881E100540D50 /* menu_delete.png in Resources */ = {isa = PBXBuildFile; fileRef = C6A1BB3926E881E100540D50 /* menu_delete.png */; };
C6A1BB3E26E882D000540D50 /* UIChatReplyBubbleView.m in Sources */ = {isa = PBXBuildFile; fileRef = C6A1BB3C26E882D000540D50 /* UIChatReplyBubbleView.m */; };
C6A1BB4126E889AD00540D50 /* forward_message_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6A1BB4026E889AD00540D50 /* forward_message_default.png */; };
C6A1BB4326E88F7C00540D50 /* menu_resend_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6A1BB4226E88F7C00540D50 /* menu_resend_default.png */; };
C6A1BB4526E890BD00540D50 /* file_voice_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6A1BB4426E890BD00540D50 /* file_voice_default.png */; };
C6B4444226AAD0980076C517 /* file_video_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6B4443D26AAD0970076C517 /* file_video_default.png */; };
C6B4444326AAD0980076C517 /* file_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6B4443E26AAD0970076C517 /* file_default.png */; };
C6B4444426AAD0980076C517 /* file_picture_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6B4443F26AAD0970076C517 /* file_picture_default.png */; };
C6B4444526AAD0980076C517 /* file_audio_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6B4444026AAD0970076C517 /* file_audio_default.png */; };
C6B4444626AAD0980076C517 /* file_pdf_default.png in Resources */ = {isa = PBXBuildFile; fileRef = C6B4444126AAD0970076C517 /* file_pdf_default.png */; };
C6B4444826AADA530076C517 /* SwiftUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6B4444726AADA530076C517 /* SwiftUtil.swift */; };
C6DA657C261C950C0020CB43 /* VFSUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6DA657B261C950C0020CB43 /* VFSUtil.swift */; };
C90FAA7915AF54E6002091CB /* HistoryDetailsView.m in Sources */ = {isa = PBXBuildFile; fileRef = C90FAA7715AF54E6002091CB /* HistoryDetailsView.m */; };
CF15F21E20E4F9A3008B1DE6 /* UIImageViewDeletable.m in Sources */ = {isa = PBXBuildFile; fileRef = CF15F21C20E4F9A3008B1DE6 /* UIImageViewDeletable.m */; };
@ -1714,10 +1738,37 @@
C61B1BF12667D075001A4E4A /* menu_security_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_security_default.png; sourceTree = "<group>"; };
C61B1BF32667D202001A4E4A /* more_menu_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = more_menu_default.png; sourceTree = "<group>"; };
C61B1BF62667EC6B001A4E4A /* ephemeral_messages_color_A.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ephemeral_messages_color_A.png; sourceTree = "<group>"; };
C622E3E926A8128F004F5434 /* vr_stop.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = vr_stop.png; sourceTree = "<group>"; };
C622E3EA26A8128F004F5434 /* vr_wave.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = vr_wave.png; sourceTree = "<group>"; };
C622E3EB26A8128F004F5434 /* vr_on.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = vr_on.png; sourceTree = "<group>"; };
C622E3EC26A8128F004F5434 /* vr_off.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = vr_off.png; sourceTree = "<group>"; };
C622E3ED26A8128F004F5434 /* vr_pause.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = vr_pause.png; sourceTree = "<group>"; };
C622E3EE26A81290004F5434 /* vr_play.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = vr_play.png; sourceTree = "<group>"; };
C64A854C2667B66900252AD2 /* EphemeralSettingsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EphemeralSettingsView.h; sourceTree = "<group>"; };
C64A854D2667B67200252AD2 /* EphemeralSettingsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EphemeralSettingsView.m; sourceTree = "<group>"; };
C64A854F2667B67A00252AD2 /* EphemeralSettingsView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EphemeralSettingsView.xib; sourceTree = "<group>"; };
C64A85512667B74100252AD2 /* ephemeral_messages_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ephemeral_messages_default.png; sourceTree = "<group>"; };
C66B03BC26E8EB1A009B5EDC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UIChatReplyBubbleView.xib; sourceTree = "<group>"; };
C66B03C126E8EB82009B5EDC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/UIChatReplyBubbleView.strings; sourceTree = "<group>"; };
C66B03C326E8EB87009B5EDC /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/UIChatReplyBubbleView.strings; sourceTree = "<group>"; };
C66B040926EFDA54009B5EDC /* reply_cancel.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = reply_cancel.png; sourceTree = "<group>"; };
C66B040D26F095CE009B5EDC /* cancel_forward.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = cancel_forward.png; sourceTree = "<group>"; };
C6A1BB3126E8815300540D50 /* menu_info.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_info.png; sourceTree = "<group>"; };
C6A1BB3226E8815400540D50 /* menu_forward_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_forward_default.png; sourceTree = "<group>"; };
C6A1BB3326E8815400540D50 /* menu_copy_text_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_copy_text_default.png; sourceTree = "<group>"; };
C6A1BB3426E8815400540D50 /* menu_reply_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_reply_default.png; sourceTree = "<group>"; };
C6A1BB3926E881E100540D50 /* menu_delete.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_delete.png; sourceTree = "<group>"; };
C6A1BB3B26E882D000540D50 /* UIChatReplyBubbleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIChatReplyBubbleView.h; sourceTree = "<group>"; };
C6A1BB3C26E882D000540D50 /* UIChatReplyBubbleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIChatReplyBubbleView.m; sourceTree = "<group>"; };
C6A1BB4026E889AD00540D50 /* forward_message_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = forward_message_default.png; sourceTree = "<group>"; };
C6A1BB4226E88F7C00540D50 /* menu_resend_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_resend_default.png; sourceTree = "<group>"; };
C6A1BB4426E890BD00540D50 /* file_voice_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = file_voice_default.png; sourceTree = "<group>"; };
C6B4443D26AAD0970076C517 /* file_video_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = file_video_default.png; sourceTree = "<group>"; };
C6B4443E26AAD0970076C517 /* file_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = file_default.png; sourceTree = "<group>"; };
C6B4443F26AAD0970076C517 /* file_picture_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = file_picture_default.png; sourceTree = "<group>"; };
C6B4444026AAD0970076C517 /* file_audio_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = file_audio_default.png; sourceTree = "<group>"; };
C6B4444126AAD0970076C517 /* file_pdf_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = file_pdf_default.png; sourceTree = "<group>"; };
C6B4444726AADA530076C517 /* SwiftUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUtil.swift; sourceTree = "<group>"; };
C6DA657B261C950C0020CB43 /* VFSUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VFSUtil.swift; sourceTree = "<group>"; };
C90FAA7615AF54E6002091CB /* HistoryDetailsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HistoryDetailsView.h; sourceTree = "<group>"; };
C90FAA7715AF54E6002091CB /* HistoryDetailsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HistoryDetailsView.m; sourceTree = "<group>"; };
@ -1951,7 +2002,7 @@
files = (
61DD7E1F2372E88F001BDD01 /* CoreLocation.framework in Frameworks */,
6180D6FE21EE41A800AD9CB6 /* QuickLook.framework in Frameworks */,
61AEBEA321906AFC00F35E7F /* (null) in Frameworks */,
61AEBEA321906AFC00F35E7F /* BuildFile in Frameworks */,
D37DC7181594AF3400B2A5EB /* MessageUI.framework in Frameworks */,
61F1997520C6B1D5006B069A /* AVKit.framework in Frameworks */,
249660951FD6A35F001D55AA /* Photos.framework in Frameworks */,
@ -2166,6 +2217,9 @@
2214EB7012F84668002A5394 /* LinphoneUI */ = {
isa = PBXGroup;
children = (
C6A1BB3B26E882D000540D50 /* UIChatReplyBubbleView.h */,
C6A1BB3C26E882D000540D50 /* UIChatReplyBubbleView.m */,
C66B03BD26E8EB1A009B5EDC /* UIChatReplyBubbleView.xib */,
63F1DF421BCE618E00EDED90 /* UIAddressTextField.h */,
63F1DF431BCE618E00EDED90 /* UIAddressTextField.m */,
63C441C11BBC23ED0053DC5E /* UIAssistantTextField.h */,
@ -2285,7 +2339,7 @@
path = LinphoneUI;
sourceTree = "<group>";
};
29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
29B97314FDCFA39411CA2CEA = {
isa = PBXGroup;
children = (
8C23BCB71D82AAC3005F19BB /* linphone.entitlements */,
@ -2447,6 +2501,27 @@
633FEBE11D3CD5570014B822 /* images */ = {
isa = PBXGroup;
children = (
C66B040D26F095CE009B5EDC /* cancel_forward.png */,
C66B040926EFDA54009B5EDC /* reply_cancel.png */,
C6A1BB4426E890BD00540D50 /* file_voice_default.png */,
C6A1BB4226E88F7C00540D50 /* menu_resend_default.png */,
C6A1BB4026E889AD00540D50 /* forward_message_default.png */,
C6A1BB3926E881E100540D50 /* menu_delete.png */,
C6A1BB3326E8815400540D50 /* menu_copy_text_default.png */,
C6A1BB3226E8815400540D50 /* menu_forward_default.png */,
C6A1BB3126E8815300540D50 /* menu_info.png */,
C6A1BB3426E8815400540D50 /* menu_reply_default.png */,
C6B4444026AAD0970076C517 /* file_audio_default.png */,
C6B4443E26AAD0970076C517 /* file_default.png */,
C6B4444126AAD0970076C517 /* file_pdf_default.png */,
C6B4443F26AAD0970076C517 /* file_picture_default.png */,
C6B4443D26AAD0970076C517 /* file_video_default.png */,
C622E3EC26A8128F004F5434 /* vr_off.png */,
C622E3EB26A8128F004F5434 /* vr_on.png */,
C622E3ED26A8128F004F5434 /* vr_pause.png */,
C622E3EE26A81290004F5434 /* vr_play.png */,
C622E3E926A8128F004F5434 /* vr_stop.png */,
C622E3EA26A8128F004F5434 /* vr_wave.png */,
C61B1BF62667EC6B001A4E4A /* ephemeral_messages_color_A.png */,
C61B1BF32667D202001A4E4A /* more_menu_default.png */,
C61B1BF12667D075001A4E4A /* menu_security_default.png */,
@ -3043,6 +3118,7 @@
63423C091C4501D000D9A050 /* Contact.m */,
8C1B67081E6718BC001EA2FE /* AudioHelper.h */,
8C1B67051E671826001EA2FE /* AudioHelper.m */,
C6B4444726AADA530076C517 /* SwiftUtil.swift */,
);
name = Utils;
sourceTree = "<group>";
@ -3357,7 +3433,7 @@
fr,
hu,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
mainGroup = 29B97314FDCFA39411CA2CEA;
productRefGroup = 19C28FACFE9D520D11CA2CBB /* Products */;
projectDirPath = "";
projectRoot = "";
@ -3378,6 +3454,7 @@
633FEF3F1D3CD55A0014B822 /* security_pending@2x.png in Resources */,
24BFAAA4209B0630004F47A7 /* linphone_logo.png in Resources */,
633FEDC41D3CD5590014B822 /* call_hangup_disabled.png in Resources */,
C66B03BB26E8EB1A009B5EDC /* UIChatReplyBubbleView.xib in Resources */,
633FEDA81D3CD5590014B822 /* backspace_default.png in Resources */,
636316D11A1DEBCB0009B839 /* AboutView.xib in Resources */,
8CBD7BA620B6B82400E5DCC0 /* UIChatConversationInfoTableViewCell.xib in Resources */,
@ -3408,6 +3485,7 @@
615A2817217F280C0060F920 /* chat_list_indicator.png in Resources */,
633FEEFF1D3CD55A0014B822 /* options_add_call_disabled@2x.png in Resources */,
633FEF091D3CD55A0014B822 /* options_start_conference_disabled@2x.png in Resources */,
C622E3F326A81290004F5434 /* vr_pause.png in Resources */,
633FEE051D3CD5590014B822 /* cancel_edit_disabled@2x.png in Resources */,
633FEE5F1D3CD5590014B822 /* edit_list_default@2x.png in Resources */,
633FEEB61D3CD55A0014B822 /* numpad_3_over@2x.png in Resources */,
@ -3418,7 +3496,7 @@
633FEED41D3CD55A0014B822 /* numpad_7_default@2x.png in Resources */,
633FEEE01D3CD55A0014B822 /* numpad_8_over~ipad@2x.png in Resources */,
633FEDDC1D3CD5590014B822 /* call_start_body_disabled~ipad.png in Resources */,
63E802DB1C625AEF000D5509 /* (null) in Resources */,
63E802DB1C625AEF000D5509 /* BuildFile in Resources */,
633FEE2E1D3CD5590014B822 /* color_F.png in Resources */,
633FEDC51D3CD5590014B822 /* call_hangup_disabled@2x.png in Resources */,
633FEEDF1D3CD55A0014B822 /* numpad_8_over~ipad.png in Resources */,
@ -3443,6 +3521,7 @@
633FEF331D3CD55A0014B822 /* route_speaker_selected@2x.png in Resources */,
633FEE6C1D3CD5590014B822 /* footer_dialer_disabled.png in Resources */,
633FEF231D3CD55A0014B822 /* route_bluetooth_default@2x.png in Resources */,
C6A1BB4526E890BD00540D50 /* file_voice_default.png in Resources */,
633FED9C1D3CD5590014B822 /* add_field_default.png in Resources */,
633FEE411D3CD5590014B822 /* contacts_all_selected@2x.png in Resources */,
D38187F815FE355D00C3EDCA /* TabBarView.xib in Resources */,
@ -3453,6 +3532,7 @@
633FEDD91D3CD5590014B822 /* call_start_body_default~ipad@2x.png in Resources */,
633FEE401D3CD5590014B822 /* contacts_all_selected.png in Resources */,
633FEE0C1D3CD5590014B822 /* chat_attachment_disabled.png in Resources */,
C622E3EF26A81290004F5434 /* vr_stop.png in Resources */,
633FEF001D3CD55A0014B822 /* options_default.png in Resources */,
CF15F21F20E4F9A3008B1DE6 /* UIImageViewDeletable.xib in Resources */,
633FEE951D3CD55A0014B822 /* micro_default@2x.png in Resources */,
@ -3478,6 +3558,7 @@
633FEE7A1D3CD5590014B822 /* history_missed_default.png in Resources */,
633FEF121D3CD55A0014B822 /* pause_big_over_selected.png in Resources */,
633FED9D1D3CD5590014B822 /* add_field_default@2x.png in Resources */,
C622E3F426A81290004F5434 /* vr_play.png in Resources */,
639E9CB01C0DB83000019A75 /* SideMenuView.xib in Resources */,
633FEDBB1D3CD5590014B822 /* call_audio_start_default@2x.png in Resources */,
633FEF1A1D3CD55A0014B822 /* presence_away.png in Resources */,
@ -3505,6 +3586,7 @@
615A283E2180A2560060F920 /* invite_linphone.png in Resources */,
633FEF281D3CD55A0014B822 /* route_earpiece_default.png in Resources */,
633FEE4F1D3CD5590014B822 /* delete_field_over@2x.png in Resources */,
C622E3F226A81290004F5434 /* vr_off.png in Resources */,
633FEE531D3CD5590014B822 /* dialer_alt_back@2x.png in Resources */,
633FEE3E1D3CD5590014B822 /* contacts_all_disabled.png in Resources */,
633FEEF31D3CD55A0014B822 /* numpad_over_background.png in Resources */,
@ -3514,6 +3596,7 @@
633FEEED1D3CD55A0014B822 /* numpad_hash_over.png in Resources */,
633FEE1F1D3CD5590014B822 /* chat_start_body_disabled@2x.png in Resources */,
633FEEF81D3CD55A0014B822 /* numpad_star_over~ipad.png in Resources */,
C6A1BB3826E8815400540D50 /* menu_reply_default.png in Resources */,
633FEF301D3CD55A0014B822 /* route_speaker_disabled.png in Resources */,
639CEAFD1A1DF4D9004DE38F /* StatusBarView.xib in Resources */,
633FEDE91D3CD5590014B822 /* call_status_missed~ipad@2x.png in Resources */,
@ -3547,6 +3630,7 @@
633FEEC81D3CD55A0014B822 /* numpad_5_over~ipad@2x.png in Resources */,
61586B91217A175D0038AC45 /* menu_recordings.png in Resources */,
633FEF1B1D3CD55A0014B822 /* presence_away@2x.png in Resources */,
C6A1BB3A26E881E100540D50 /* menu_delete.png in Resources */,
633FEE281D3CD5590014B822 /* checkbox_unchecked.png in Resources */,
633FEE9D1D3CD55A0014B822 /* numpad_0_over.png in Resources */,
633FEEC21D3CD55A0014B822 /* numpad_4~ipad@2x.png in Resources */,
@ -3563,6 +3647,7 @@
633FEEC01D3CD55A0014B822 /* numpad_4_over~ipad@2x.png in Resources */,
61586B8B217A17320038AC45 /* menu_link_account@2x.png in Resources */,
63CDC4661C3BDE370085F529 /* shortring.caf in Resources */,
C6A1BB4126E889AD00540D50 /* forward_message_default.png in Resources */,
633FEDD51D3CD5590014B822 /* call_quality_indicator_4@2x.png in Resources */,
633FEDE71D3CD5590014B822 /* call_status_missed@2x.png in Resources */,
615A2821217F6FBF0060F920 /* security_alert_indicator@2x.png in Resources */,
@ -3602,6 +3687,7 @@
633FEDFD1D3CD5590014B822 /* camera_switch_default@2x.png in Resources */,
633FEEC51D3CD55A0014B822 /* numpad_5_over.png in Resources */,
633FEE721D3CD5590014B822 /* history_all_default.png in Resources */,
C6B4444326AAD0980076C517 /* file_default.png in Resources */,
615A283C2180789C0060F920 /* security_toogle_button@2x.png in Resources */,
633FEF0A1D3CD55A0014B822 /* options_transfer_call_default.png in Resources */,
633FEDA51D3CD5590014B822 /* back_default@2x.png in Resources */,
@ -3627,6 +3713,7 @@
63E27A321C4FECD000D332AE /* LaunchScreen.xib in Resources */,
633FEED11D3CD55A0014B822 /* numpad_6~ipad.png in Resources */,
CF7602E82108759A00749F76 /* UIRecordingCell.xib in Resources */,
C6B4444626AAD0980076C517 /* file_pdf_default.png in Resources */,
633FEED21D3CD55A0014B822 /* numpad_6~ipad@2x.png in Resources */,
633FEDCD1D3CD5590014B822 /* call_quality_indicator_0@2x.png in Resources */,
636316D41A1DEC650009B839 /* SettingsView.xib in Resources */,
@ -3691,6 +3778,7 @@
24BFAAA5209B0630004F47A7 /* contacts_sip_default.png in Resources */,
633FEF441D3CD55A0014B822 /* speaker_default.png in Resources */,
639CEB031A1DF4EB004DE38F /* UICompositeView.xib in Resources */,
C6A1BB4326E88F7C00540D50 /* menu_resend_default.png in Resources */,
633FEF3A1D3CD55A0014B822 /* security_ko.png in Resources */,
615A283A2180788E0060F920 /* security_toogle_button.png in Resources */,
633FEDA01D3CD5590014B822 /* avatar.png in Resources */,
@ -3722,6 +3810,7 @@
63CDC45E1C3BDE370085F529 /* msg.caf in Resources */,
633FEE6D1D3CD5590014B822 /* footer_dialer_disabled@2x.png in Resources */,
633FEF171D3CD55A0014B822 /* pause_small_disabled@2x.png in Resources */,
C6A1BB3626E8815400540D50 /* menu_forward_default.png in Resources */,
D38187DD15FE348A00C3EDCA /* AssistantView.xib in Resources */,
633FEDA61D3CD5590014B822 /* back_disabled.png in Resources */,
633FEED61D3CD55A0014B822 /* numpad_7_over@2x.png in Resources */,
@ -3740,7 +3829,9 @@
633FEE191D3CD5590014B822 /* chat_send_over@2x.png in Resources */,
633FEF181D3CD55A0014B822 /* pause_small_over_selected.png in Resources */,
633FEE001D3CD5590014B822 /* camera_switch_over.png in Resources */,
C622E3F126A81290004F5434 /* vr_on.png in Resources */,
633FEF401D3CD55A0014B822 /* select_all_default.png in Resources */,
C6B4444426AAD0980076C517 /* file_picture_default.png in Resources */,
633FEDF01D3CD5590014B822 /* call_transfer_disabled.png in Resources */,
633FEE351D3CD5590014B822 /* conference_exit_default@2x.png in Resources */,
633FEECF1D3CD55A0014B822 /* numpad_6_over~ipad.png in Resources */,
@ -3772,6 +3863,7 @@
633FEEFA1D3CD55A0014B822 /* numpad_star~ipad.png in Resources */,
D38187B915FE342200C3EDCA /* ContactDetailsView.xib in Resources */,
633FEE921D3CD55A0014B822 /* menu.png in Resources */,
C622E3F026A81290004F5434 /* vr_wave.png in Resources */,
633FEDE41D3CD5590014B822 /* call_status_incoming~ipad.png in Resources */,
633FEE4C1D3CD5590014B822 /* delete_field_default.png in Resources */,
633FEE391D3CD5590014B822 /* contact_add_default@2x.png in Resources */,
@ -3831,8 +3923,10 @@
633FEEF71D3CD55A0014B822 /* numpad_star_over@2x.png in Resources */,
633FEEAB1D3CD55A0014B822 /* numpad_2_default.png in Resources */,
633FEE851D3CD5590014B822 /* led_error@2x.png in Resources */,
C6B4444226AAD0980076C517 /* file_video_default.png in Resources */,
633FEDBE1D3CD5590014B822 /* call_back_default.png in Resources */,
633FEF0F1D3CD55A0014B822 /* pause_big_default@2x.png in Resources */,
C66B040E26F095D1009B5EDC /* cancel_forward.png in Resources */,
CF7602F6210898CC00749F76 /* rec_on_default@2x.png in Resources */,
633FEF081D3CD55A0014B822 /* options_start_conference_disabled.png in Resources */,
63F1DF511BCE986A00EDED90 /* UICallConferenceCell.xib in Resources */,
@ -3862,6 +3956,7 @@
633FEE221D3CD5590014B822 /* chat_start_body_over.png in Resources */,
633FEE601D3CD5590014B822 /* edit_list_disabled.png in Resources */,
D38187C115FE345B00C3EDCA /* DialerView.xib in Resources */,
C6A1BB3726E8815400540D50 /* menu_copy_text_default.png in Resources */,
D37EE10D16035793003608A6 /* ImageView.xib in Resources */,
633FEE9F1D3CD55A0014B822 /* numpad_0_over~ipad.png in Resources */,
633FEED51D3CD55A0014B822 /* numpad_7_over.png in Resources */,
@ -3876,6 +3971,8 @@
633FEF3B1D3CD55A0014B822 /* security_ko@2x.png in Resources */,
633FEE4A1D3CD5590014B822 /* delete_disabled.png in Resources */,
614D09CE21E74D5400C43EDF /* GoogleService-Info.plist in Resources */,
C6B4444526AAD0980076C517 /* file_audio_default.png in Resources */,
C6A1BB3526E8815400540D50 /* menu_info.png in Resources */,
C61B1BF72667EC6B001A4E4A /* ephemeral_messages_color_A.png in Resources */,
633FEF151D3CD55A0014B822 /* pause_small_default@2x.png in Resources */,
633FEEF91D3CD55A0014B822 /* numpad_star_over~ipad@2x.png in Resources */,
@ -3950,6 +4047,7 @@
633FEDDD1D3CD5590014B822 /* call_start_body_disabled~ipad@2x.png in Resources */,
633FEEBD1D3CD55A0014B822 /* numpad_4_over.png in Resources */,
8CA70AD41F9E285C00A3D2EB /* chat_group_add@2x.png in Resources */,
C66B040A26EFDA55009B5EDC /* reply_cancel.png in Resources */,
633FEEF11D3CD55A0014B822 /* numpad_hash~ipad.png in Resources */,
633FEE781D3CD5590014B822 /* history_chat_indicator.png in Resources */,
633FEF431D3CD55A0014B822 /* select_all_disabled@2x.png in Resources */,
@ -4195,6 +4293,7 @@
6135761C240E81BB005304D4 /* UIInterfaceStyleButton.m in Sources */,
8CD99A3C2090B9FA008A7CDA /* ChatConversationImdnView.m in Sources */,
1D3623260D0F684500981E51 /* LinphoneAppDelegate.m in Sources */,
C6B4444826AADA530076C517 /* SwiftUtil.swift in Sources */,
614C087A23D1A37400217F80 /* CallManager.swift in Sources */,
CF15F21E20E4F9A3008B1DE6 /* UIImageViewDeletable.m in Sources */,
22F2508E107141E100AC9B3F /* DialerView.m in Sources */,
@ -4227,6 +4326,7 @@
CF7602D7210867E800749F76 /* RecordingsListView.m in Sources */,
63F1DF4B1BCE983200EDED90 /* CallConferenceTableView.m in Sources */,
D3F83F8E15822ABE00336684 /* PhoneMainView.m in Sources */,
C6A1BB3E26E882D000540D50 /* UIChatReplyBubbleView.m in Sources */,
6377AC801BDE4069007F7625 /* UIBackToCallButton.m in Sources */,
6308F9C51BF0DD6600D1234B /* XMLRPCHelper.m in Sources */,
D3ED3E871586291E006C0DE4 /* TabBarView.m in Sources */,
@ -4716,6 +4816,16 @@
name = UIChatCreateCollectionViewCell.xib;
sourceTree = "<group>";
};
C66B03BD26E8EB1A009B5EDC /* UIChatReplyBubbleView.xib */ = {
isa = PBXVariantGroup;
children = (
C66B03BC26E8EB1A009B5EDC /* Base */,
C66B03C126E8EB82009B5EDC /* en */,
C66B03C326E8EB87009B5EDC /* fr */,
);
name = UIChatReplyBubbleView.xib;
sourceTree = "<group>";
};
D37EE11016035793003608A6 /* ImageView.xib */ = {
isa = PBXVariantGroup;
children = (
@ -4949,7 +5059,7 @@
"-DENABLE_QRCODE=TRUE",
"-DENABLE_SMS_INVITE=TRUE",
"$(inherited)",
"-DLINPHONE_SDK_VERSION=\\\"5.0.0-alpha.109+40dd0cf\\\"",
"-DLINPHONE_SDK_VERSION=\\\"5.1.0-alpha.75+d4a0bd2\\\"",
);
OTHER_SWIFT_FLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone;
@ -5072,7 +5182,7 @@
"-DENABLE_QRCODE=TRUE",
"-DENABLE_SMS_INVITE=TRUE",
"$(inherited)",
"-DLINPHONE_SDK_VERSION=\\\"5.0.0-alpha.109+40dd0cf\\\"",
"-DLINPHONE_SDK_VERSION=\\\"5.1.0-alpha.75+d4a0bd2\\\"",
);
OTHER_SWIFT_FLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone;
@ -5194,7 +5304,7 @@
"-DENABLE_QRCODE=TRUE",
"-DENABLE_SMS_INVITE=TRUE",
"$(inherited)",
"-DLINPHONE_SDK_VERSION=\\\"5.0.0-alpha.109+40dd0cf\\\"",
"-DLINPHONE_SDK_VERSION=\\\"5.1.0-alpha.75+d4a0bd2\\\"",
);
OTHER_SWIFT_FLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone;
@ -5315,7 +5425,7 @@
"-DENABLE_QRCODE=TRUE",
"-DENABLE_SMS_INVITE=TRUE",
"$(inherited)",
"-DLINPHONE_SDK_VERSION=\\\"5.0.0-alpha.109+40dd0cf\\\"",
"-DLINPHONE_SDK_VERSION=\\\"5.1.0-alpha.75+d4a0bd2\\\"",
);
OTHER_SWIFT_FLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.phone;