forked from mirrors/linphone-iphone
Compare commits
224 commits
master
...
release/4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29bcbf64c0 | ||
|
|
b99327dbe5 | ||
|
|
952b27c94f | ||
|
|
5407a18b57 | ||
|
|
9e52922fff | ||
|
|
4ade9f2c60 | ||
|
|
abf598b654 | ||
|
|
0a05baea1e | ||
|
|
4cd9da44de | ||
|
|
a341bb6aec | ||
|
|
ff5bafb7c0 | ||
|
|
9ba95b024c | ||
|
|
05b905a3f1 | ||
|
|
e8c2e92fc9 | ||
|
|
82289f4523 | ||
|
|
6365c66d55 | ||
|
|
61e645c238 | ||
|
|
9d5836b991 | ||
|
|
b78b4a1e6b | ||
|
|
6850282208 | ||
|
|
9803678d6a | ||
|
|
f2b36ed7f8 | ||
|
|
d39fb0661b | ||
|
|
b378682d0c | ||
|
|
7da10d500f | ||
|
|
4b5eaa3bc5 | ||
|
|
78c21a5c2b | ||
|
|
fecbb85a81 | ||
|
|
8582d93555 | ||
|
|
a74d042a6a | ||
|
|
ad9163320c | ||
|
|
5ab6a7ce1b | ||
|
|
7ccdcbebcf | ||
|
|
0fe94354d7 | ||
|
|
3dc7d4fb15 | ||
|
|
a98aa42ca4 | ||
|
|
84a817783d | ||
|
|
6e846f092c | ||
|
|
fd9afd66fa | ||
|
|
e5505a836c | ||
|
|
781a9b07d1 | ||
|
|
6a4ef41ab5 | ||
|
|
c09519bcc1 | ||
|
|
9ab5a0f106 | ||
|
|
eff9964b12 | ||
|
|
0202c7aa6b | ||
|
|
4cb99a62a0 | ||
|
|
fc3f48363f | ||
|
|
3800aafd1f | ||
|
|
3a3c04bb23 | ||
|
|
8607469f68 | ||
|
|
987ea21e05 | ||
|
|
b6ff317551 | ||
|
|
9977644872 | ||
|
|
d447158a25 | ||
|
|
c3746801ac | ||
|
|
dbd56b5c38 | ||
|
|
c49013aa2b | ||
|
|
fc9c9b9508 | ||
|
|
6cb4ea55f6 | ||
|
|
54fb56d93c | ||
|
|
ac49ee5d56 | ||
|
|
03af1afac1 | ||
|
|
233865747e | ||
|
|
1291e7dee4 | ||
|
|
61ec8a37dd | ||
|
|
bd42b8855c | ||
|
|
7a78a14bbf | ||
|
|
236a8ee52f | ||
|
|
62f7d8a620 | ||
|
|
8a47583130 | ||
|
|
59098c6db0 | ||
|
|
3043fc5c7a | ||
|
|
3e6bffd723 | ||
|
|
0cd72844b6 | ||
|
|
d5a6a233af | ||
|
|
65573ba1be | ||
|
|
669851065a | ||
|
|
6fa24fff6d | ||
|
|
670dabaf77 | ||
|
|
93eecbc304 | ||
|
|
e02580bade | ||
|
|
581d2dbf50 | ||
|
|
f7ad67390a | ||
|
|
c72d8913b8 | ||
|
|
490f9e96db | ||
|
|
5fb42ce09f | ||
|
|
736059f699 | ||
|
|
b63779b65e | ||
|
|
0fc1f024d3 | ||
|
|
8b5668e8ce | ||
|
|
8909ae7279 | ||
|
|
be5e303b09 | ||
|
|
82704471ac | ||
|
|
988840d9a9 | ||
|
|
a120a067c9 | ||
|
|
555428d62d | ||
|
|
d326b7f56e | ||
|
|
59c90fe65a | ||
|
|
3edcfb4222 | ||
|
|
77c4fb1747 | ||
|
|
50f656d1ee | ||
|
|
06cbe9fa1d | ||
|
|
f3bc7add35 | ||
|
|
9fcfe2b8de | ||
|
|
d04f961559 | ||
|
|
1e1c0fd3d3 | ||
|
|
7ddfff9c32 | ||
|
|
ecdb22dc5d | ||
|
|
d340db5680 | ||
|
|
960046b87e | ||
|
|
79a2235368 | ||
|
|
df53cc73e9 | ||
|
|
44cf121007 | ||
|
|
14ddbaa58a | ||
|
|
0c687d1dce | ||
|
|
f00daf1997 | ||
|
|
c80ad228ef | ||
|
|
70b2671f19 | ||
|
|
3c8af14495 | ||
|
|
51f23e91bb | ||
|
|
cd7951e590 | ||
|
|
a6638d3c9b | ||
|
|
0e947803ce | ||
|
|
666b2c7f48 | ||
|
|
ac32d80b51 | ||
|
|
e2dc5d4ad3 | ||
|
|
eda3fa114a | ||
|
|
fd3afda60c | ||
|
|
670ad21770 | ||
|
|
0353180bd0 | ||
|
|
b402f08006 | ||
|
|
b495e4b8bb | ||
|
|
a0a1e1a417 | ||
|
|
821f2e30b7 | ||
|
|
d0f83d6d1d | ||
|
|
f705e14664 | ||
|
|
35c772db3a | ||
|
|
a57da3d499 | ||
|
|
b9ef7a83b5 | ||
|
|
559a9d8bc3 | ||
|
|
f8d3a196f5 | ||
|
|
298778e20d | ||
|
|
b4103d2f4f | ||
|
|
4c75c4222d | ||
|
|
d8163fb55b | ||
|
|
68597369ed | ||
|
|
388e3482a9 | ||
|
|
811a859430 | ||
|
|
96543cdaca | ||
|
|
23633d1ea4 | ||
|
|
cf78ae8ff9 | ||
|
|
2b252a04ff | ||
|
|
d54c9ef5a9 | ||
|
|
aaea844c4c | ||
|
|
507060fb31 | ||
|
|
863731f775 | ||
|
|
6a8c5a4440 | ||
|
|
360c88b764 | ||
|
|
a4bfa37454 | ||
|
|
68bece526b | ||
|
|
8efce6e446 | ||
|
|
4333e97932 | ||
|
|
77b9287195 | ||
|
|
a4bc64f2b3 | ||
|
|
2a54eae049 | ||
|
|
2279a23db1 | ||
|
|
8743a01b88 | ||
|
|
8ed7ba7bee | ||
|
|
240d28e234 | ||
|
|
d352034e5e | ||
|
|
3c12854dc6 | ||
|
|
47b7820b58 | ||
|
|
ed56de2527 | ||
|
|
57399ec722 | ||
|
|
57b676c775 | ||
|
|
07e0f0ca80 | ||
|
|
981a7c5a60 | ||
|
|
8ba4230c19 | ||
|
|
12f9de3384 | ||
|
|
6af2602639 | ||
|
|
81964daa0c | ||
|
|
7cdcdd4a4d | ||
|
|
be1e726a0c | ||
|
|
8d3fead61d | ||
|
|
5dda082a75 | ||
|
|
a77d6bb1b6 | ||
|
|
dcc832436e | ||
|
|
1559bf46c7 | ||
|
|
4ec4723fbb | ||
|
|
d25cbbf609 | ||
|
|
90c367ccca | ||
|
|
3e22ea3a80 | ||
|
|
49bee7c6a0 | ||
|
|
907cc94fc6 | ||
|
|
b04a306443 | ||
|
|
ffe795bf02 | ||
|
|
5ee6695cdc | ||
|
|
d14a0d3c10 | ||
|
|
9612e21162 | ||
|
|
81688b416b | ||
|
|
da08af7e3f | ||
|
|
9ab70c60fe | ||
|
|
e3ed160c54 | ||
|
|
7d71bd500e | ||
|
|
6ca276b718 | ||
|
|
0d0c0225f1 | ||
|
|
6adeb43fdc | ||
|
|
761a47ad87 | ||
|
|
343a30d93b | ||
|
|
54071f9d15 | ||
|
|
924b499496 | ||
|
|
10b28cd6cf | ||
|
|
33b07703ca | ||
|
|
74c69b3779 | ||
|
|
ef8e1baa92 | ||
|
|
6e93601508 | ||
|
|
0e31b555c1 | ||
|
|
930dd74c89 | ||
|
|
f847d8cfe3 | ||
|
|
263b460372 | ||
|
|
4c690f9274 | ||
|
|
ff14c18f1c | ||
|
|
97708e9096 |
189 changed files with 4379 additions and 2008 deletions
|
|
@ -7,11 +7,12 @@ variables:
|
||||||
job-ios:
|
job-ios:
|
||||||
|
|
||||||
stage: build
|
stage: build
|
||||||
tags: [ "macmini-m1-xcode13" ]
|
tags: [ "macos-xcode13" ]
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- pod install --repo-update
|
- pod install --repo-update
|
||||||
- pwd
|
- pwd
|
||||||
|
- sed 's/fileprivate let tableView =/public let tableView =/g' ./Pods/DropDown/DropDown/src/DropDown.swift > tmp.swift && mv -f tmp.swift ./Pods/DropDown/DropDown/src/DropDown.swift
|
||||||
- xcodebuild archive -scheme $archive_scheme -archivePath ./$archive_path -configuration Release -workspace ./linphone.xcworkspace -UseModernBuildSystem=YES -destination 'generic/platform=iOS'
|
- xcodebuild archive -scheme $archive_scheme -archivePath ./$archive_path -configuration Release -workspace ./linphone.xcworkspace -UseModernBuildSystem=YES -destination 'generic/platform=iOS'
|
||||||
- xcodebuild -exportArchive -archivePath ./$archive_path -exportPath ./$export_path -exportOptionsPlist ./$export_options_plist -allowProvisioningUpdates -UseModernBuildSystem=YES -destination 'generic/platform=iOS'
|
- xcodebuild -exportArchive -archivePath ./$archive_path -exportPath ./$export_path -exportOptionsPlist ./$export_options_plist -allowProvisioningUpdates -UseModernBuildSystem=YES -destination 'generic/platform=iOS'
|
||||||
|
|
||||||
|
|
|
||||||
28
CHANGELOG.md
28
CHANGELOG.md
|
|
@ -9,7 +9,33 @@ Group changes to describe their impact on the project, as follows:
|
||||||
Removed for deprecated features removed in this release.
|
Removed for deprecated features removed in this release.
|
||||||
Fixed for any bug fixes.
|
Fixed for any bug fixes.
|
||||||
Security to invite users to upgrade in case of vulnerabilities.
|
Security to invite users to upgrade in case of vulnerabilities.
|
||||||
|
|
||||||
|
## [5.0.0] - 2021-12-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Post Quantum encryption when using ZRTP
|
||||||
|
- Conference creation with scheduling, video, different layouts, showing who is speaking and who is muted, etc...
|
||||||
|
- Group calls directly from group chat rooms
|
||||||
|
- Chat rooms can be individually muted (no notification when receiving a chat message)
|
||||||
|
- Outgoing call video in early-media if requested by callee
|
||||||
|
- Call recordings can be exported
|
||||||
|
- Setting to prevent international prefix from account to be applied to call & chat
|
||||||
|
- Add a "Never ask again" option to the "Link my account" pop-up when starting the app
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- In-call views have been re-designed
|
||||||
|
- Improved how contact avatars are generated
|
||||||
|
- 3-dots menu even for basic chat rooms with more options
|
||||||
|
- Update linphone SDK to 5.2.0
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Chatroom appearing as empty when being logged on multiple accounts
|
||||||
|
- Chatroom appearing as empty after playing a video file inside it
|
||||||
|
- Fix potential crash when entering a chatroom
|
||||||
|
- Fix potential crash when accessing to the delivery infos of a message in a group chat.
|
||||||
|
- IMDN logo not properly displayed when transfering or replying to a message with media (voice message, photo...)
|
||||||
|
- Clarified view when sending an image from the galery
|
||||||
|
- Various audio route fixes for CallKit and IOS 16
|
||||||
|
|
||||||
## [4.6.4] - 2021-08-06
|
## [4.6.4] - 2021-08-06
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,9 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
if (!mustRestoreView) {
|
if (!mustRestoreView) {
|
||||||
new_account = NULL;
|
new_account = NULL;
|
||||||
number_of_accounts_before = bctbx_list_size(linphone_core_get_account_list(LC));
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
number_of_accounts_before = bctbx_list_size(accounts);
|
||||||
|
bctbx_free(accounts);
|
||||||
[self resetTextFields];
|
[self resetTextFields];
|
||||||
[self changeView:_welcomeView back:FALSE animation:FALSE];
|
[self changeView:_welcomeView back:FALSE animation:FALSE];
|
||||||
}
|
}
|
||||||
|
|
@ -519,6 +521,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
#endif
|
#endif
|
||||||
linphone_push_notification_config_set_provider(pushConfig, PROVIDER_NAME);
|
linphone_push_notification_config_set_provider(pushConfig, PROVIDER_NAME);
|
||||||
|
|
||||||
|
if (strcmp(creatorDomain, "sip.linphone.org")==0) {
|
||||||
|
linphone_core_set_media_encryption(LC, LinphoneMediaEncryptionSRTP);
|
||||||
|
}
|
||||||
|
|
||||||
new_account = linphone_core_create_account(LC, accountParams);
|
new_account = linphone_core_create_account(LC, accountParams);
|
||||||
linphone_account_params_unref(accountParams);
|
linphone_account_params_unref(accountParams);
|
||||||
|
|
||||||
|
|
@ -705,7 +711,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
LinphoneAccount *default_account = linphone_core_create_account(LC, default_account_params);
|
LinphoneAccount *default_account = linphone_core_create_account(LC, default_account_params);
|
||||||
const char *identity = linphone_account_params_get_identity(linphone_account_get_params(default_account));
|
const char *identity = linphone_account_params_get_identity(linphone_account_get_params(default_account));
|
||||||
if (identity) {
|
if (identity) {
|
||||||
LinphoneAddress *default_addr = linphone_core_interpret_url(LC, identity);
|
LinphoneAddress *default_addr = linphone_core_interpret_url_2(LC, identity, false);
|
||||||
if (default_addr) {
|
if (default_addr) {
|
||||||
const char *domain = linphone_address_get_domain(default_addr);
|
const char *domain = linphone_address_get_domain(default_addr);
|
||||||
const char *username = linphone_address_get_username(default_addr);
|
const char *username = linphone_address_get_username(default_addr);
|
||||||
|
|
@ -1011,10 +1017,13 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
[LinphoneManager.instance lpConfigSetInt:[NSDate new].timeIntervalSince1970
|
[LinphoneManager.instance lpConfigSetInt:[NSDate new].timeIntervalSince1970
|
||||||
forKey:@"must_link_account_time"];
|
forKey:@"must_link_account_time"];
|
||||||
[LinphoneManager.instance configurePushProviderForAccounts];
|
[LinphoneManager.instance configurePushProviderForAccounts];
|
||||||
if (number_of_accounts_before < bctbx_list_size(linphone_core_get_account_list(LC))) {
|
|
||||||
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
if (number_of_accounts_before < bctbx_list_size(accounts)) {
|
||||||
LOGI(@"A proxy config was set up with the remote provisioning, skip assistant");
|
LOGI(@"A proxy config was set up with the remote provisioning, skip assistant");
|
||||||
[self onDialerClick:nil];
|
[self onDialerClick:nil];
|
||||||
}
|
}
|
||||||
|
bctbx_free(accounts);
|
||||||
|
|
||||||
_waitView.hidden = true;
|
_waitView.hidden = true;
|
||||||
if (nextView == nil) {
|
if (nextView == nil) {
|
||||||
|
|
@ -1149,7 +1158,11 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
_outgoingView = DialerView.compositeViewDescription;
|
_outgoingView = DialerView.compositeViewDescription;
|
||||||
[self configureAccount];
|
[self configureAccount];
|
||||||
} else if (status == LinphoneAccountCreatorStatusAccountExist) {
|
} else if (status == LinphoneAccountCreatorStatusAccountExist) {
|
||||||
_outgoingView = AssistantLinkView.compositeViewDescription;
|
if([LinphoneManager.instance lpConfigIntForKey:@"hide_link_phone_number"]){
|
||||||
|
_outgoingView = DialerView.compositeViewDescription;
|
||||||
|
}else{
|
||||||
|
_outgoingView = AssistantLinkView.compositeViewDescription;
|
||||||
|
}
|
||||||
[self configureAccount];
|
[self configureAccount];
|
||||||
} else {
|
} else {
|
||||||
if (resp) {
|
if (resp) {
|
||||||
|
|
@ -1584,10 +1597,11 @@ UIColor *previousColor = (UIColor*)[sender backgroundColor]; \
|
||||||
|
|
||||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||||
style:UIAlertActionStyleDefault
|
style:UIAlertActionStyleDefault
|
||||||
handler:^(UIAlertAction * action) {}];
|
handler:^(UIAlertAction * action) {}];
|
||||||
|
|
||||||
[errView addAction:defaultAction];
|
[errView addAction:defaultAction];
|
||||||
[self presentViewController:errView animated:YES completion:nil];
|
[self presentViewController:errView animated:YES completion:nil];
|
||||||
|
_waitView.hidden = TRUE;
|
||||||
} else {
|
} else {
|
||||||
linphone_core_set_provisioning_uri(LC, [self addSchemeToProvisiionninUriIMissing:[self findTextField:ViewElement_URL].text].UTF8String);
|
linphone_core_set_provisioning_uri(LC, [self addSchemeToProvisiionninUriIMissing:[self findTextField:ViewElement_URL].text].UTF8String);
|
||||||
[self resetLiblinphone:TRUE];
|
[self resetLiblinphone:TRUE];
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21207"/>
|
||||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -175,13 +175,13 @@
|
||||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KRQ-Fm-3cQ" userLabel="addedContacts" customClass="UICollectionView">
|
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KRQ-Fm-3cQ" userLabel="addedContacts" customClass="UICollectionView">
|
||||||
<rect key="frame" x="8" y="110" width="398" height="70"/>
|
<rect key="frame" x="8" y="110" width="398" height="50"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="addedContacts"/>
|
<accessibility key="accessibilityConfiguration" label="addedContacts"/>
|
||||||
</view>
|
</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="6">
|
<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="6">
|
||||||
<rect key="frame" x="5" y="178" width="403" height="610"/>
|
<rect key="frame" x="5" y="158" width="403" height="610"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<color key="separatorColor" red="0.67030966281890869" green="0.71867996454238892" blue="0.75078284740447998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="separatorColor" red="0.67030966281890869" green="0.71867996454238892" blue="0.75078284740447998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21207"/>
|
||||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -97,7 +97,7 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="XSI-9T-NtW" userLabel="addButton" customClass="UIInterfaceStyleButton">
|
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="XSI-9T-NtW" userLabel="addButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="382" y="4" width="24" height="21"/>
|
<rect key="frame" x="382" y="2" width="24" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Back"/>
|
<accessibility key="accessibilityConfiguration" label="Back"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -218,7 +218,7 @@
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||||
<subviews>
|
<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">
|
<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">
|
||||||
<rect key="frame" x="0.0" y="1" width="414" height="22"/>
|
<rect key="frame" x="10" y="-5" width="406" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label=""/>
|
<accessibility key="accessibilityConfiguration" label=""/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
|
@ -608,7 +608,6 @@
|
||||||
</state>
|
</state>
|
||||||
<state key="selected" image="vr_on.png"/>
|
<state key="selected" image="vr_on.png"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="onPictureClick:" destination="-1" eventType="touchUpInside" id="qhP-B0-dkG"/>
|
|
||||||
<action selector="onVrStart:" destination="-1" eventType="touchUpInside" id="yWJ-st-yz2"/>
|
<action selector="onVrStart:" destination="-1" eventType="touchUpInside" id="yWJ-st-yz2"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="addButton" destination="6" id="91"/>
|
<outlet property="addButton" destination="6" id="91"/>
|
||||||
<outlet property="allButton" destination="4" id="27"/>
|
<outlet property="allButton" destination="4" id="27"/>
|
||||||
|
<outlet property="ldapMoreResultsLabel" destination="cDH-mL-cHP" id="3d9-gp-Hog"/>
|
||||||
<outlet property="linphoneButton" destination="5" id="31"/>
|
<outlet property="linphoneButton" destination="5" id="31"/>
|
||||||
<outlet property="loadingLabel" destination="qSa-Ba-dq9" id="CPa-pO-OQD"/>
|
<outlet property="loadingLabel" destination="qSa-Ba-dq9" id="CPa-pO-OQD"/>
|
||||||
<outlet property="loadingView" destination="CM2-Aq-Q3g" id="uie-SJ-TKf"/>
|
<outlet property="loadingView" destination="CM2-Aq-Q3g" id="uie-SJ-TKf"/>
|
||||||
|
|
@ -179,6 +180,14 @@
|
||||||
<outlet property="delegate" destination="TJG-JZ-YRR" id="V1N-gI-U4J"/>
|
<outlet property="delegate" destination="TJG-JZ-YRR" id="V1N-gI-U4J"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="More results are available, refine search to see them" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cDH-mL-cHP" userLabel="ldapMoreResultsLabel">
|
||||||
|
<rect key="frame" x="8" y="110" width="359" height="18"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No contact found in your address book" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JR3-k7-gVP" userLabel="emptyTableLabel">
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No contact found in your address book" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JR3-k7-gVP" userLabel="emptyTableLabel">
|
||||||
<rect key="frame" x="0.0" y="110" width="375" height="449"/>
|
<rect key="frame" x="0.0" y="110" width="375" height="449"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
|
|
@ -187,7 +196,7 @@
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view hidden="YES" contentMode="scaleToFill" id="CM2-Aq-Q3g">
|
<view hidden="YES" alpha="0.80000000000000004" contentMode="scaleToFill" id="CM2-Aq-Q3g">
|
||||||
<rect key="frame" x="0.0" y="110" width="375" height="449"/>
|
<rect key="frame" x="0.0" y="110" width="375" height="449"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
|
|
@ -209,7 +218,7 @@
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<point key="canvasLocation" x="6.5217391304347831" y="142.29910714285714"/>
|
<point key="canvasLocation" x="5.7971014492753632" y="141.96428571428569"/>
|
||||||
</view>
|
</view>
|
||||||
<tableViewController id="TJG-JZ-YRR" userLabel="tableController" customClass="ContactsListTableView">
|
<tableViewController id="TJG-JZ-YRR" userLabel="tableController" customClass="ContactsListTableView">
|
||||||
<connections>
|
<connections>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
|
<device id="retina6_0" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21207"/>
|
||||||
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
|
|
@ -11,6 +14,7 @@
|
||||||
<outlet property="addressLabel" destination="EoB-ux-sD7" id="Ajw-2s-M6X"/>
|
<outlet property="addressLabel" destination="EoB-ux-sD7" id="Ajw-2s-M6X"/>
|
||||||
<outlet property="avatarImage" destination="23" id="43"/>
|
<outlet property="avatarImage" destination="23" id="43"/>
|
||||||
<outlet property="backButton" destination="9" id="Pqj-y9-hqc"/>
|
<outlet property="backButton" destination="9" id="Pqj-y9-hqc"/>
|
||||||
|
<outlet property="chatButton" destination="obZ-W7-q8P" id="96n-Oe-Gm0"/>
|
||||||
<outlet property="contactLabel" destination="25" id="rTL-Ut-42o"/>
|
<outlet property="contactLabel" destination="25" id="rTL-Ut-42o"/>
|
||||||
<outlet property="emptyLabel" destination="hvz-CS-NME" id="Qws-r1-XMh"/>
|
<outlet property="emptyLabel" destination="hvz-CS-NME" id="Qws-r1-XMh"/>
|
||||||
<outlet property="encryptedChatView" destination="JU4-bf-tVI" id="j6f-qz-VKd"/>
|
<outlet property="encryptedChatView" destination="JU4-bf-tVI" id="j6f-qz-VKd"/>
|
||||||
|
|
@ -26,19 +30,19 @@
|
||||||
</placeholder>
|
</placeholder>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
<view contentMode="scaleToFill" id="HKr-sq-hGv" userLabel="iphone6MetricsView">
|
<view contentMode="scaleToFill" id="HKr-sq-hGv" userLabel="iphone6MetricsView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
|
<rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view tag="1" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4">
|
<view tag="1" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4">
|
||||||
<rect key="frame" x="0.0" y="42" width="667" height="267"/>
|
<rect key="frame" x="-1" y="41" width="389" height="735"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view alpha="0.90000000000000002" tag="2" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6" userLabel="topBar">
|
<view alpha="0.90000000000000002" tag="2" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6" userLabel="topBar">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="667" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="389" height="66"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9" userLabel="backButton" customClass="UIInterfaceStyleButton">
|
<button opaque="NO" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9" userLabel="backButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="128" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="74" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Back"/>
|
<accessibility key="accessibilityConfiguration" label="Back"/>
|
||||||
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
|
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
|
||||||
|
|
@ -50,7 +54,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="5" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="50" userLabel="addButton" customClass="UIInterfaceStyleButton">
|
<button opaque="NO" tag="5" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="50" userLabel="addButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="539" y="0.0" width="128" height="66"/>
|
<rect key="frame" x="314" y="0.0" width="75" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Add to contact"/>
|
<accessibility key="accessibilityConfiguration" label="Add to contact"/>
|
||||||
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
|
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
|
||||||
|
|
@ -62,14 +66,14 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</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>
|
||||||
<view tag="7" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="33" userLabel="headerView">
|
<view tag="7" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="33" userLabel="headerView">
|
||||||
<rect key="frame" x="0.0" y="66" width="667" height="250"/>
|
<rect key="frame" x="0.0" y="66" width="389" height="250"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" tag="8" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="23" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView userInteractionEnabled="NO" tag="8" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="23" userLabel="avatarImage" customClass="UIRoundedImageView">
|
||||||
<rect key="frame" x="244" y="8" width="178" height="100"/>
|
<rect key="frame" x="141" y="8" width="104" height="100"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
||||||
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
||||||
|
|
@ -77,7 +81,7 @@
|
||||||
</accessibility>
|
</accessibility>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="9" contentMode="left" fixedFrame="YES" text="John Doe" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="25" userLabel="contactLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="9" contentMode="left" fixedFrame="YES" text="John Doe" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="25" userLabel="contactLabel">
|
||||||
<rect key="frame" x="0.0" y="110" width="667" height="40"/>
|
<rect key="frame" x="0.0" y="110" width="389" height="40"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="33"/>
|
<fontDescription key="fontDescription" type="system" pointSize="33"/>
|
||||||
|
|
@ -85,7 +89,7 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<imageView userInteractionEnabled="NO" tag="10" contentMode="scaleAspectFit" fixedFrame="YES" image="linphone_user.png" translatesAutoresizingMaskIntoConstraints="NO" id="mfN-Ai-9RX" userLabel="linphoneImage" customClass="UIRoundedImageView">
|
<imageView userInteractionEnabled="NO" tag="10" contentMode="scaleAspectFit" fixedFrame="YES" image="linphone_user.png" translatesAutoresizingMaskIntoConstraints="NO" id="mfN-Ai-9RX" userLabel="linphoneImage" customClass="UIRoundedImageView">
|
||||||
<rect key="frame" x="642" y="124" width="15" height="15"/>
|
<rect key="frame" x="363" y="124" width="16" height="15"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
||||||
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
||||||
|
|
@ -93,7 +97,7 @@
|
||||||
</accessibility>
|
</accessibility>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="11" contentMode="left" fixedFrame="YES" text="johndoe@sip.linphone.org" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="EoB-ux-sD7" userLabel="addressLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="11" contentMode="left" fixedFrame="YES" text="johndoe@sip.linphone.org" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="EoB-ux-sD7" userLabel="addressLabel">
|
||||||
<rect key="frame" x="0.0" y="158" width="667" height="23"/>
|
<rect key="frame" x="0.0" y="158" width="389" height="23"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="18"/>
|
<fontDescription key="fontDescription" type="system" pointSize="18"/>
|
||||||
|
|
@ -101,11 +105,11 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="k0D-99-OKO" userLabel="optionsView">
|
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="k0D-99-OKO" userLabel="optionsView">
|
||||||
<rect key="frame" x="0.0" y="189" width="667" height="44"/>
|
<rect key="frame" x="0.0" y="189" width="389" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" tag="13" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5eX-W0-T4B" userLabel="callButton">
|
<button opaque="NO" tag="13" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5eX-W0-T4B" userLabel="callButton">
|
||||||
<rect key="frame" x="179" y="0.0" width="51" height="51"/>
|
<rect key="frame" x="98" y="0.0" width="51" height="51"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" image="call_start_body_default.png">
|
<state key="normal" image="call_start_body_default.png">
|
||||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
|
@ -117,7 +121,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="12" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="obZ-W7-q8P" userLabel="chatButton">
|
<button opaque="NO" tag="12" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="obZ-W7-q8P" userLabel="chatButton">
|
||||||
<rect key="frame" x="317" y="0.0" width="50" height="51"/>
|
<rect key="frame" x="174" y="0.0" width="50" height="51"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" image="chat_start_body_default.png">
|
<state key="normal" image="chat_start_body_default.png">
|
||||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
|
@ -129,11 +133,11 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JU4-bf-tVI" userLabel="encryptedChatView">
|
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JU4-bf-tVI" userLabel="encryptedChatView">
|
||||||
<rect key="frame" x="456" y="-1" width="50" height="51"/>
|
<rect key="frame" x="251" y="-2" width="49" height="50"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="E2n-mF-saI" userLabel="encryptedChatButton" customClass="UIIconButton">
|
<button opaque="NO" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="E2n-mF-saI" userLabel="encryptedChatButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="-1" y="0.0" width="51" height="51"/>
|
<rect key="frame" x="0.0" y="-2" width="51" height="53"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Chat"/>
|
<accessibility key="accessibilityConfiguration" label="Chat"/>
|
||||||
<state key="normal" image="chat_start_body_default.png">
|
<state key="normal" image="chat_start_body_default.png">
|
||||||
|
|
@ -154,35 +158,35 @@
|
||||||
</subviews>
|
</subviews>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
<tableView clipsSubviews="YES" tag="6" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="30" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="k6N-Av-eOu">
|
<tableView clipsSubviews="YES" tag="6" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="30" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="k6N-Av-eOu">
|
||||||
<rect key="frame" x="0.0" y="316" width="667" height="0.0"/>
|
<rect key="frame" x="0.0" y="316" width="389" height="419"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<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"/>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="dataSource" destination="baU-d4-eu3" id="p7o-Mx-Kmc"/>
|
<outlet property="dataSource" destination="baU-d4-eu3" id="p7o-Mx-Kmc"/>
|
||||||
<outlet property="delegate" destination="baU-d4-eu3" id="iS5-xg-0C2"/>
|
<outlet property="delegate" destination="baU-d4-eu3" id="iS5-xg-0C2"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="40" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No log selected" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hvz-CS-NME" userLabel="emptyLabel">
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="40" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No log selected" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hvz-CS-NME" userLabel="emptyLabel">
|
||||||
<rect key="frame" x="0.0" y="66" width="667" height="201"/>
|
<rect key="frame" x="0.0" y="65" width="389" height="670"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view hidden="YES" tag="8" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dEJ-xc-518" userLabel="waitView">
|
<view hidden="YES" tag="8" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dEJ-xc-518" userLabel="waitView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="667" height="267"/>
|
<rect key="frame" x="0.0" y="0.0" width="389" height="735"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<activityIndicatorView opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="NK3-ME-9jd" userLabel="activityIndicatorView">
|
<activityIndicatorView opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="NK3-ME-9jd" userLabel="activityIndicatorView">
|
||||||
<rect key="frame" x="326" y="122" width="20" height="20"/>
|
<rect key="frame" x="186" y="352" width="20" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
</activityIndicatorView>
|
</activityIndicatorView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<gestureRecognizers/>
|
<gestureRecognizers/>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|
@ -193,23 +197,23 @@
|
||||||
<point key="canvasLocation" x="-3.2000000000000002" y="22.488755622188908"/>
|
<point key="canvasLocation" x="-3.2000000000000002" y="22.488755622188908"/>
|
||||||
</view>
|
</view>
|
||||||
<view contentMode="scaleToFill" id="LBc-mh-ozk" userLabel="iphone6MetricsView">
|
<view contentMode="scaleToFill" id="LBc-mh-ozk" userLabel="iphone6MetricsView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
|
<rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view tag="1" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NHC-7w-48z">
|
<view tag="1" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NHC-7w-48z">
|
||||||
<rect key="frame" x="0.0" y="42" width="667" height="333"/>
|
<rect key="frame" x="-2" y="42" width="391" height="800"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view tag="2" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Rtv-hu-bCz" userLabel="topBar">
|
<view tag="2" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Rtv-hu-bCz" userLabel="topBar">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="667" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="391" height="66"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" tag="3" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="imageView:JOe-5t-C7f:image" translatesAutoresizingMaskIntoConstraints="NO" id="JOe-5t-C7f" userLabel="backgroundColor">
|
<imageView userInteractionEnabled="NO" tag="3" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="imageView:JOe-5t-C7f:image" translatesAutoresizingMaskIntoConstraints="NO" id="JOe-5t-C7f" userLabel="backgroundColor">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="667" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="391" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<button opaque="NO" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NJl-Lb-CU6" userLabel="backButton" customClass="UIIconButton">
|
<button opaque="NO" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NJl-Lb-CU6" userLabel="backButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="71" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="41" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Back"/>
|
<accessibility key="accessibilityConfiguration" label="Back"/>
|
||||||
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
|
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
|
||||||
|
|
@ -221,7 +225,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="5" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="O7r-6t-b7w" userLabel="addButton" customClass="UIIconButton">
|
<button opaque="NO" tag="5" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="O7r-6t-b7w" userLabel="addButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="594" y="0.0" width="73" height="66"/>
|
<rect key="frame" x="346" y="0.0" width="45" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Add to contact"/>
|
<accessibility key="accessibilityConfiguration" label="Add to contact"/>
|
||||||
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
|
<inset key="titleEdgeInsets" minX="0.0" minY="18" maxX="0.0" maxY="0.0"/>
|
||||||
|
|
@ -235,7 +239,7 @@
|
||||||
</subviews>
|
</subviews>
|
||||||
</view>
|
</view>
|
||||||
<tableView clipsSubviews="YES" tag="6" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="30" sectionHeaderHeight="44" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="2jK-gw-ULv">
|
<tableView clipsSubviews="YES" tag="6" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="30" sectionHeaderHeight="44" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="2jK-gw-ULv">
|
||||||
<rect key="frame" x="0.0" y="168" width="667" height="165"/>
|
<rect key="frame" x="0.0" y="167" width="391" height="633"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
@ -244,11 +248,11 @@
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<view tag="7" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Mwp-y3-g1b" userLabel="headerView">
|
<view tag="7" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Mwp-y3-g1b" userLabel="headerView">
|
||||||
<rect key="frame" x="0.0" y="66" width="667" height="102"/>
|
<rect key="frame" x="0.0" y="66" width="391" height="102"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" tag="8" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="d9m-G0-1u3" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView userInteractionEnabled="NO" tag="8" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="d9m-G0-1u3" userLabel="avatarImage" customClass="UIRoundedImageView">
|
||||||
<rect key="frame" x="28" y="8" width="88" height="86"/>
|
<rect key="frame" x="16" y="8" width="51" height="86"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
||||||
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
||||||
|
|
@ -256,7 +260,7 @@
|
||||||
</accessibility>
|
</accessibility>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="9" contentMode="left" fixedFrame="YES" text="John Doe" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Qbg-hm-bd7" userLabel="contactLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="9" contentMode="left" fixedFrame="YES" text="John Doe" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Qbg-hm-bd7" userLabel="contactLabel">
|
||||||
<rect key="frame" x="160" y="8" width="356" height="50"/>
|
<rect key="frame" x="94" y="8" width="207" height="48"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="33"/>
|
<fontDescription key="fontDescription" type="system" pointSize="33"/>
|
||||||
|
|
@ -264,7 +268,7 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="11" contentMode="left" fixedFrame="YES" text="johndoe@sip.linphone.org" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="XJa-f6-K0y" userLabel="addressLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="11" contentMode="left" fixedFrame="YES" text="johndoe@sip.linphone.org" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="XJa-f6-K0y" userLabel="addressLabel">
|
||||||
<rect key="frame" x="160" y="56" width="356" height="38"/>
|
<rect key="frame" x="94" y="54" width="207" height="39"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="18"/>
|
<fontDescription key="fontDescription" type="system" pointSize="18"/>
|
||||||
|
|
@ -272,11 +276,11 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="teU-AB-8hO" userLabel="optionsView">
|
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="teU-AB-8hO" userLabel="optionsView">
|
||||||
<rect key="frame" x="0.0" y="29" width="667" height="44"/>
|
<rect key="frame" x="0.0" y="29" width="391" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" tag="13" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pBo-Oo-bAW" userLabel="callButton">
|
<button opaque="NO" tag="13" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pBo-Oo-bAW" userLabel="callButton">
|
||||||
<rect key="frame" x="491" y="0.0" width="51" height="51"/>
|
<rect key="frame" x="271" y="0.0" width="51" height="51"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" image="call_start_body_default.png">
|
<state key="normal" image="call_start_body_default.png">
|
||||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
|
@ -288,7 +292,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="12" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iDG-Mn-jm2" userLabel="chatButton">
|
<button opaque="NO" tag="12" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iDG-Mn-jm2" userLabel="chatButton">
|
||||||
<rect key="frame" x="551" y="0.0" width="51" height="51"/>
|
<rect key="frame" x="303" y="0.0" width="51" height="51"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" image="chat_start_body_default.png">
|
<state key="normal" image="chat_start_body_default.png">
|
||||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
|
@ -300,11 +304,11 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="m90-u6-x3J" userLabel="encryptedChatView">
|
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="m90-u6-x3J" userLabel="encryptedChatView">
|
||||||
<rect key="frame" x="611" y="0.0" width="51" height="51"/>
|
<rect key="frame" x="336" y="-1" width="51" height="51"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8fY-hz-ECC" userLabel="encryptedChatButton" customClass="UIIconButton">
|
<button opaque="NO" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8fY-hz-ECC" userLabel="encryptedChatButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="51" height="51"/>
|
<rect key="frame" x="0.0" y="-2" width="51" height="53"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Chat"/>
|
<accessibility key="accessibilityConfiguration" label="Chat"/>
|
||||||
<state key="normal" image="chat_start_body_default.png">
|
<state key="normal" image="chat_start_body_default.png">
|
||||||
|
|
@ -325,7 +329,7 @@
|
||||||
</subviews>
|
</subviews>
|
||||||
</view>
|
</view>
|
||||||
<imageView hidden="YES" userInteractionEnabled="NO" tag="10" contentMode="scaleAspectFit" fixedFrame="YES" image="linphone_user.png" translatesAutoresizingMaskIntoConstraints="NO" id="G2O-Yh-fZA" userLabel="linphoneImage">
|
<imageView hidden="YES" userInteractionEnabled="NO" tag="10" contentMode="scaleAspectFit" fixedFrame="YES" image="linphone_user.png" translatesAutoresizingMaskIntoConstraints="NO" id="G2O-Yh-fZA" userLabel="linphoneImage">
|
||||||
<rect key="frame" x="123" y="8" width="30" height="25"/>
|
<rect key="frame" x="71" y="8" width="19" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
||||||
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
||||||
|
|
@ -336,7 +340,7 @@
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</view>
|
</view>
|
||||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="40" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No log selected" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IHY-Yg-pkN" userLabel="emptyLabel">
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="40" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No log selected" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IHY-Yg-pkN" userLabel="emptyLabel">
|
||||||
<rect key="frame" x="0.0" y="66" width="667" height="267"/>
|
<rect key="frame" x="0.0" y="65" width="391" height="735"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
|
@ -344,11 +348,11 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view hidden="YES" tag="8" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X29-vB-VIz" userLabel="waitView">
|
<view hidden="YES" tag="8" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X29-vB-VIz" userLabel="waitView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="667" height="333"/>
|
<rect key="frame" x="0.0" y="0.0" width="391" height="800"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<activityIndicatorView opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="7l5-ZU-CbW" userLabel="activityIndicatorView">
|
<activityIndicatorView opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="7l5-ZU-CbW" userLabel="activityIndicatorView">
|
||||||
<rect key="frame" x="326" y="155" width="20" height="20"/>
|
<rect key="frame" x="185" y="385" width="21" height="20"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
</activityIndicatorView>
|
</activityIndicatorView>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|
@ -384,106 +388,113 @@
|
||||||
<image name="contact_add_disabled.png" width="55.200000762939453" height="47.200000762939453"/>
|
<image name="contact_add_disabled.png" width="55.200000762939453" height="47.200000762939453"/>
|
||||||
<image name="imageView:JOe-5t-C7f:image" width="2" height="2">
|
<image name="imageView:JOe-5t-C7f:image" width="2" height="2">
|
||||||
<mutableData key="keyedArchiveRepresentation">
|
<mutableData key="keyedArchiveRepresentation">
|
||||||
YnBsaXN0MDDUAQIDBAUGUlNYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3ASAAGGoK8QEQcI
|
YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMSAAGGoF8QD05T
|
||||||
ERYbHCAhKCsuOEBESExPVSRudWxs1AkKCwwNDg8QViRjbGFzc1xOU0ltYWdlRmxhZ3NWTlNSZXBzV05T
|
S2V5ZWRBcmNoaXZlctEICVRyb290gAGvEBALDBccEyEmJy4xND5GR0tOVSRudWxs1Q0ODxAREhMUFRZW
|
||||||
Q29sb3KAEBIAwAAAgAKACtISCRMVWk5TLm9iamVjdHOhFIADgAnSEgkXGqIYGYAEgAWACBAA0h0JHh9f
|
JGNsYXNzXk5TUmVzaXppbmdNb2RlXE5TSW1hZ2VGbGFnc1ZOU1JlcHNXTlNDb2xvcoAPEAASAMAAAIAC
|
||||||
EBROU1RJRkZSZXByZXNlbnRhdGlvboAGgAdPEQI+TU0AKgAAAAzh4eHhAA8BAAADAAAAAQACAAABAQAD
|
gArSGA0ZG1pOUy5vYmplY3RzoRqAA4AJ0hgNHSCiHh+ABIAFgAjTDSIjJCUTXxAUTlNUSUZGUmVwcmVz
|
||||||
AAAAAQACAAABAgADAAAAAQAIAAABAwADAAAAAQABAAABBgADAAAAAQABAAABCgADAAAAAQABAAABEQAE
|
ZW50YXRpb25fEBlOU0ludGVybmFsTGF5b3V0RGlyZWN0aW9ugAeABk8RAj5NTQAqAAAADOHh4eEADwEA
|
||||||
AAAAAQAAAAgBEgADAAAAAQABAAABFQADAAAAAQABAAABFgADAAAAAQACAAABFwAEAAAAAQAAAAQBHAAD
|
AAMAAAABAAIAAAEBAAMAAAABAAIAAAECAAMAAAABAAgAAAEDAAMAAAABAAEAAAEGAAMAAAABAAEAAAEK
|
||||||
AAAAAQABAAABKAADAAAAAQACAAABUwADAAAAAQABAACHcwAHAAABeAAAAMYAAAAAAAABeGFwcGwCEAAA
|
AAMAAAABAAEAAAERAAQAAAABAAAACAESAAMAAAABAAEAAAEVAAMAAAABAAEAAAEWAAMAAAABAAIAAAEX
|
||||||
bW50ckdSQVlYWVogB9UABwABAAAAAAAAYWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPbW
|
AAQAAAABAAAABAEcAAMAAAABAAEAAAEoAAMAAAABAAIAAAFTAAMAAAABAAEAAIdzAAcAAAF4AAAAxgAA
|
||||||
AAEAAAAA0y1hcHBsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE
|
AAAAAAF4YXBwbAIQAABtbnRyR1JBWVhZWiAH1QAHAAEAAAAAAABhY3NwQVBQTAAAAAAAAAAAAAAAAAAA
|
||||||
ZGVzYwAAALQAAAB1Y3BydAAAASwAAAAnd3RwdAAAAVQAAAAUa1RSQwAAAWgAAAAOZGVzYwAAAAAAAAAb
|
AAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
Q2FsaWJyYXRlZCBHcmF5IENvbG9yc3BhY2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAARkZXNjAAAAtAAAAHVjcHJ0AAABLAAAACd3dHB0AAABVAAAABRrVFJDAAABaAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5
|
AA5kZXNjAAAAAAAAABtDYWxpYnJhdGVkIEdyYXkgQ29sb3JzcGFjZQAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
cmlnaHQgQXBwbGUgQ29tcHV0ZXIsIEluYy4AAFhZWiAAAAAAAADzUQABAAAAARbMY3VydgAAAAAAAAAB
|
|
||||||
AjMAANIiIyQlWiRjbGFzc25hbWVYJGNsYXNzZXNfEBBOU0JpdG1hcEltYWdlUmVwoyQmJ1pOU0ltYWdl
|
|
||||||
UmVwWE5TT2JqZWN00iIjKSpXTlNBcnJheaIpJ9IiIywtXk5TTXV0YWJsZUFycmF5oywpJ9UvMDEyCTM0
|
|
||||||
NTY3V05TV2hpdGVcTlNDb21wb25lbnRzXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29sb3JTcGFjZUQw
|
|
||||||
IDAAQzAgMBADgAuAD9Q5OjsJPD0+P1ROU0lEVU5TSUNDV05TTW9kZWwQCYAMEACADtJBCUJDV05TLmRh
|
|
||||||
dGFPERFoAAARaGFwcGwCAAAAbW50ckdSQVlYWVogB9wACAAXAA8ALgAPYWNzcEFQUEwAAAAAbm9uZQAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1hcHBsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAFZGVzYwAAAMAAAAB5ZHNjbQAAATwAAAfoY3BydAAACSQAAAAjd3RwdAAA
|
|
||||||
CUgAAAAUa1RSQwAACVwAAAgMZGVzYwAAAAAAAAAfR2VuZXJpYyBHcmF5IEdhbW1hIDIuMiBQcm9maWxl
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1sdWMAAAAAAAAAHwAAAAxza1NLAAAALgAAAYRkYURLAAAAOAAA
|
AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLgAAWFlaIAAAAAAAAPNRAAEAAAAB
|
||||||
AbJjYUVTAAAAOAAAAep2aVZOAAAAQAAAAiJwdEJSAAAASgAAAmJ1a1VBAAAALAAAAqxmckZVAAAAPgAA
|
FsxjdXJ2AAAAAAAAAAECMwAA0igpKitaJGNsYXNzbmFtZVgkY2xhc3Nlc18QEE5TQml0bWFwSW1hZ2VS
|
||||||
AthodUhVAAAANAAAAxZ6aFRXAAAAHgAAA0puYk5PAAAAOgAAA2hjc0NaAAAAKAAAA6JoZUlMAAAAJAAA
|
ZXCjKiwtWk5TSW1hZ2VSZXBYTlNPYmplY3TSKCkvMFdOU0FycmF5oi8t0igpMjNeTlNNdXRhYmxlQXJy
|
||||||
A8ppdElUAAAATgAAA+5yb1JPAAAAKgAABDxkZURFAAAATgAABGZrb0tSAAAAIgAABLRzdlNFAAAAOAAA
|
YXmjMi8t1TU2NzgNOTo7PD1XTlNXaGl0ZVxOU0NvbXBvbmVudHNcTlNDb2xvclNwYWNlXxASTlNDdXN0
|
||||||
AbJ6aENOAAAAHgAABNZqYUpQAAAAJgAABPRlbEdSAAAAKgAABRpwdFBPAAAAUgAABURubE5MAAAAQAAA
|
b21Db2xvclNwYWNlRDAgMABDMCAwEAOAC4AO1D9AQQ1CQ0RFVE5TSURVTlNJQ0NXTlNNb2RlbBAJgAwQ
|
||||||
BZZlc0VTAAAATAAABdZ0aFRIAAAAMgAABiJ0clRSAAAAJAAABlRmaUZJAAAARgAABnhockhSAAAAPgAA
|
AIANTxERnAAAEZxhcHBsAgAAAG1udHJHUkFZWFlaIAfcAAgAFwAPAC4AD2Fjc3BBUFBMAAAAAG5vbmUA
|
||||||
Br5wbFBMAAAASgAABvxydVJVAAAAOgAAB0ZlblVTAAAAPAAAB4BhckVHAAAALAAAB7wAVgFhAGUAbwBi
|
AAAAAAAAAAAAAAAAAAAAAAD21gABAAAAANMtYXBwbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AGUAYwBuAOEAIABzAGkAdgDhACAAZwBhAG0AYQAgADIALAAyAEcAZQBuAGUAcgBpAHMAawAgAGcAcgDl
|
AAAAAAAAAAAAAAAAAAAAAAAABWRlc2MAAADAAAAAeWRzY20AAAE8AAAIGmNwcnQAAAlYAAAAI3d0cHQA
|
||||||
ACAAMgAsADIAIABnAGEAbQBtAGEAcAByAG8AZgBpAGwARwBhAG0AbQBhACAAZABlACAAZwByAGkAcwBv
|
AAl8AAAAFGtUUkMAAAmQAAAIDGRlc2MAAAAAAAAAH0dlbmVyaWMgR3JheSBHYW1tYSAyLjIgUHJvZmls
|
||||||
AHMAIABnAGUAbgDoAHIAaQBjAGEAIAAyAC4AMgBDHqUAdQAgAGgA7ABuAGgAIABNAOAAdQAgAHgA4QBt
|
ZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
ACAAQwBoAHUAbgBnACAARwBhAG0AbQBhACAAMgAuADIAUABlAHIAZgBpAGwAIABHAGUAbgDpAHIAaQBj
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAB8AAAAMc2tTSwAAAC4AAAGEZGFESwAAADoA
|
||||||
AG8AIABkAGEAIABHAGEAbQBhACAAZABlACAAQwBpAG4AegBhAHMAIAAyACwAMgQXBDAEMwQwBDsETAQ9
|
AAGyY2FFUwAAADgAAAHsdmlWTgAAAEAAAAIkcHRCUgAAAEoAAAJkdWtVQQAAACwAAAKuZnJGVQAAAD4A
|
||||||
BDAAIABHAHIAYQB5AC0EMwQwBDwEMAAgADIALgAyAFAAcgBvAGYAaQBsACAAZwDpAG4A6QByAGkAcQB1
|
AALaaHVIVQAAADQAAAMYemhUVwAAABoAAANMa29LUgAAACIAAANmbmJOTwAAADoAAAOIY3NDWgAAACgA
|
||||||
AGUAIABnAHIAaQBzACAAZwBhAG0AbQBhACAAMgAsADIAwQBsAHQAYQBsAOEAbgBvAHMAIABzAHoA/ABy
|
AAPCaGVJTAAAACQAAAPqcm9STwAAACoAAAQOZGVERQAAAE4AAAQ4aXRJVAAAAE4AAASGc3ZTRQAAADgA
|
||||||
AGsAZQAgAGcAYQBtAG0AYQAgADIALgAykBp1KHBwlo5RSV6mACAAMgAuADIAIIJyX2ljz4/wAEcAZQBu
|
AATUemhDTgAAABoAAAUMamFKUAAAACYAAAUmZWxHUgAAACoAAAVMcHRQTwAAAFIAAAV2bmxOTAAAAEAA
|
||||||
AGUAcgBpAHMAawAgAGcAcgDlACAAZwBhAG0AbQBhACAAMgAsADIALQBwAHIAbwBmAGkAbABPAGIAZQBj
|
AAXIZXNFUwAAAEwAAAYIdGhUSAAAADIAAAZUdHJUUgAAACQAAAaGZmlGSQAAAEYAAAaqaHJIUgAAAD4A
|
||||||
AG4A4QAgAWEAZQBkAOEAIABnAGEAbQBhACAAMgAuADIF0gXQBd4F1AAgBdAF5AXVBegAIAXbBdwF3AXZ
|
AAbwcGxQTAAAAEoAAAcuYXJFRwAAACwAAAd4cnVSVQAAADoAAAekZW5VUwAAADwAAAfeAFYBYQBlAG8A
|
||||||
ACAAMgAuADIAUAByAG8AZgBpAGwAbwAgAGcAcgBpAGcAaQBvACAAZwBlAG4AZQByAGkAYwBvACAAZABl
|
YgBlAGMAbgDhACAAcwBpAHYA4QAgAGcAYQBtAGEAIAAyACwAMgBHAGUAbgBlAHIAaQBzAGsAIABnAHIA
|
||||||
AGwAbABhACAAZwBhAG0AbQBhACAAMgAsADIARwBhAG0AYQAgAGcAcgBpACAAZwBlAG4AZQByAGkAYwED
|
5QAgADIALAAyACAAZwBhAG0AbQBhAC0AcAByAG8AZgBpAGwARwBhAG0AbQBhACAAZABlACAAZwByAGkA
|
||||||
ACAAMgAsADIAQQBsAGwAZwBlAG0AZQBpAG4AZQBzACAARwByAGEAdQBzAHQAdQBmAGUAbgAtAFAAcgBv
|
cwBvAHMAIABnAGUAbgDoAHIAaQBjAGEAIAAyAC4AMgBDHqUAdQAgAGgA7ABuAGgAIABNAOAAdQAgAHgA
|
||||||
AGYAaQBsACAARwBhAG0AbQBhACAAMgAsADLHfLwYACDWjMDJACCsELnIACAAMgAuADIAINUEuFzTDMd8
|
4QBtACAAQwBoAHUAbgBnACAARwBhAG0AbQBhACAAMgAuADIAUABlAHIAZgBpAGwAIABHAGUAbgDpAHIA
|
||||||
Zm6QGnBwXqZ8+2VwACAAMgAuADIAIGPPj/Blh072TgCCLDCwMOwwpDCsMPMw3gAgADIALgAyACAw1zDt
|
aQBjAG8AIABkAGEAIABHAGEAbQBhACAAZABlACAAQwBpAG4AegBhAHMAIAAyACwAMgQXBDAEMwQwBDsE
|
||||||
MNUwoTCkMOsDkwO1A70DuQO6A8wAIAOTA7oDwQO5ACADkwOsA7wDvAOxACAAMgAuADIAUABlAHIAZgBp
|
TAQ9BDAAIABHAHIAYQB5AC0EMwQwBDwEMAAgADIALgAyAFAAcgBvAGYAaQBsACAAZwDpAG4A6QByAGkA
|
||||||
AGwAIABnAGUAbgDpAHIAaQBjAG8AIABkAGUAIABjAGkAbgB6AGUAbgB0AG8AcwAgAGQAYQAgAEcAYQBt
|
cQB1AGUAIABnAHIAaQBzACAAZwBhAG0AbQBhACAAMgAsADIAwQBsAHQAYQBsAOEAbgBvAHMAIABzAHoA
|
||||||
AG0AYQAgADIALAAyAEEAbABnAGUAbQBlAGUAbgAgAGcAcgBpAGoAcwAgAGcAYQBtAG0AYQAgADIALAAy
|
/AByAGsAZQAgAGcAYQBtAG0AYQAgADIALgAykBp1KHBwlo5RSV6mADIALgAygnJfaWPPj/DHfLwYACDW
|
||||||
AC0AcAByAG8AZgBpAGUAbABQAGUAcgBmAGkAbAAgAGcAZQBuAOkAcgBpAGMAbwAgAGQAZQAgAGcAYQBt
|
jMDJACCsELnIACAAMgAuADIAINUEuFzTDMd8AEcAZQBuAGUAcgBpAHMAawAgAGcAcgDlACAAZwBhAG0A
|
||||||
AG0AYQAgAGQAZQAgAGcAcgBpAHMAZQBzACAAMgAsADIOIw4xDgcOKg41DkEOAQ4hDiEOMg5ADgEOIw4i
|
bQBhACAAMgAsADIALQBwAHIAbwBmAGkAbABPAGIAZQBjAG4A4QAgAWEAZQBkAOEAIABnAGEAbQBhACAA
|
||||||
DkwOFw4xDkgOJw5EDhsAIAAyAC4AMgBHAGUAbgBlAGwAIABHAHIAaQAgAEcAYQBtAGEAIAAyACwAMgBZ
|
MgAuADIF0gXQBd4F1AAgBdAF5AXVBegAIAXbBdwF3AXZACAAMgAuADIARwBhAG0AYQAgAGcAcgBpACAA
|
||||||
AGwAZQBpAG4AZQBuACAAaABhAHIAbQBhAGEAbgAgAGcAYQBtAG0AYQAgADIALAAyACAALQBwAHIAbwBm
|
ZwBlAG4AZQByAGkAYwEDACAAMgAsADIAQQBsAGwAZwBlAG0AZQBpAG4AZQBzACAARwByAGEAdQBzAHQA
|
||||||
AGkAaQBsAGkARwBlAG4AZQByAGkBDQBrAGkAIABHAHIAYQB5ACAARwBhAG0AbQBhACAAMgAuADIAIABw
|
dQBmAGUAbgAtAFAAcgBvAGYAaQBsACAARwBhAG0AbQBhACAAMgAsADIAUAByAG8AZgBpAGwAbwAgAGcA
|
||||||
AHIAbwBmAGkAbABVAG4AaQB3AGUAcgBzAGEAbABuAHkAIABwAHIAbwBmAGkAbAAgAHMAegBhAHIAbwFb
|
cgBpAGcAaQBvACAAZwBlAG4AZQByAGkAYwBvACAAZABlAGwAbABhACAAZwBhAG0AbQBhACAAMgAsADIA
|
||||||
AGMAaQAgAGcAYQBtAG0AYQAgADIALAAyBB4EMQRJBDAETwAgBEEENQRABDAETwAgBDMEMAQ8BDwEMAAg
|
RwBlAG4AZQByAGkAcwBrACAAZwByAOUAIAAyACwAMgAgAGcAYQBtAG0AYQBwAHIAbwBmAGkAbGZukBpw
|
||||||
ADIALAAyAC0EPwRABD4ERAQ4BDsETABHAGUAbgBlAHIAaQBjACAARwByAGEAeQAgAEcAYQBtAG0AYQAg
|
cF6mfPtlcAAyAC4AMmPPj/Blh072TgCCLDCwMOwwpDCsMPMw3gAgADIALgAyACAw1zDtMNUwoTCkMOsD
|
||||||
ADIALgAyACAAUAByAG8AZgBpAGwAZQY6BicGRQYnACAAMgAuADIAIAZEBkgGRgAgBjEGRQYnBi8GSgAg
|
kwO1A70DuQO6A8wAIAOTA7oDwQO5ACADkwOsA7wDvAOxACAAMgAuADIAUABlAHIAZgBpAGwAIABnAGUA
|
||||||
BjkGJwZFdGV4dAAAAABDb3B5cmlnaHQgQXBwbGUgSW5jLiwgMjAxMgAAWFlaIAAAAAAAAPNRAAEAAAAB
|
bgDpAHIAaQBjAG8AIABkAGUAIABjAGkAbgB6AGUAbgB0AG8AcwAgAGQAYQAgAEcAYQBtAG0AYQAgADIA
|
||||||
FsxjdXJ2AAAAAAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
|
LAAyAEEAbABnAGUAbQBlAGUAbgAgAGcAcgBpAGoAcwAgAGcAYQBtAG0AYQAgADIALAAyAC0AcAByAG8A
|
||||||
AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA8AD2APsBAQEH
|
ZgBpAGUAbABQAGUAcgBmAGkAbAAgAGcAZQBuAOkAcgBpAGMAbwAgAGQAZQAgAGcAYQBtAG0AYQAgAGQA
|
||||||
AQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGSAZoBoQGpAbEBuQHBAckB0QHZ
|
ZQAgAGcAcgBpAHMAZQBzACAAMgAsADIOIw4xDgcOKg41DkEOAQ4hDiEOMg5ADgEOIw4iDkwOFw4xDkgO
|
||||||
AeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcCcQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1
|
Jw5EDhsAIAAyAC4AMgBHAGUAbgBlAGwAIABHAHIAaQAgAEcAYQBtAGEAIAAyACwAMgBZAGwAZQBpAG4A
|
||||||
AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRj
|
ZQBuACAAaABhAHIAbQBhAGEAbgAgAGcAYQBtAG0AYQAgADIALAAyACAALQBwAHIAbwBmAGkAaQBsAGkA
|
||||||
BHEEfgSMBJoEqAS2BMQE0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYn
|
RwBlAG4AZQByAGkBDQBrAGkAIABHAHIAYQB5ACAARwBhAG0AbQBhACAAMgAuADIAIABwAHIAbwBmAGkA
|
||||||
BjcGSAZZBmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8IMghG
|
bABVAG4AaQB3AGUAcgBzAGEAbABuAHkAIABwAHIAbwBmAGkAbAAgAHMAegBhAHIAbwFbAGMAaQAgAGcA
|
||||||
CFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9ClQKagqBCpgKrgrF
|
YQBtAG0AYQAgADIALAAyBjoGJwZFBicAIAAyAC4AMgAgBkQGSAZGACAGMQZFBicGLwZKACAGOQYnBkUE
|
||||||
CtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4MpwzADNkM8w0NDSYNQA1aDXQNjg2p
|
HgQxBEkEMARPACAEQQQ1BEAEMARPACAEMwQwBDwEPAQwACAAMgAsADIALQQ/BEAEPgREBDgEOwRMAEcA
|
||||||
DcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9BD14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1
|
ZQBuAGUAcgBpAGMAIABHAHIAYQB5ACAARwBhAG0AbQBhACAAMgAuADIAIABQAHIAbwBmAGkAbABlAAB0
|
||||||
ERMRMRFPEW0RjBGqEckR6BIHEiYSRRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixSt
|
ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBJbmMuLCAyMDEyAABYWVogAAAAAAAA81EAAQAAAAEWzGN1cnYA
|
||||||
FM4U8BUSFTQVVhV4FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjV
|
AAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBoAG0AcgB3AHwA
|
||||||
GPoZIBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1HR4dRx1w
|
gQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDgAOUA6wDwAPYA+wEBAQcBDQETARkB
|
||||||
HZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwhSCF1IaEhziH7IiciVSKC
|
HwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwBgwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB
|
||||||
Iq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXHJfcmJyZXJocmtyboJxgnSSd6J6sn3CgN
|
+gIDAgwCFAIdAiYCLwI4AkECSwJUAl0CZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYD
|
||||||
KD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsqzysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4W
|
IQMtAzgDQwNPA1oDZgNyA34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwE
|
||||||
Lkwugi63Lu4vJC9aL5Evxy/+MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSe
|
mgSoBLYExATTBOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZIBlkG
|
||||||
NNg1EzVNNYc1wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
|
agZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsIHwgyCEYIWghuCIII
|
||||||
O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5CMEJyQrVC90M6
|
lgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQonCj0KVApqCoEKmAquCsUK3ArzCwsL
|
||||||
Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjXSR1JY0mpSfBKN0p9SsRLDEtT
|
Igs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUMjgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgO
|
||||||
S5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91QJ1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2
|
Ew4uDkkOZA5/DpsOtg7SDu4PCQ8lD0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8R
|
||||||
VEJUj1TbVShVdVXCVg9WXFapVvdXRFeSV+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0n
|
bRGMEaoRyRHoEgcSJhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIV
|
||||||
XXhdyV4aXmxevV8PX2Ffs2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmbo
|
NBVWFXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihivGNUY+hkgGUUZ
|
||||||
Zz1nk2fpaD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw4HE6
|
axmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzMHPUdHh1HHXAdmR3DHewe
|
||||||
cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnnekZ6pXsEe2N7wnwh
|
Fh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAhHCFIIXUhoSHOIfsiJyJVIoIiryLdIwoj
|
||||||
fIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eDuoQdhICE44VHhauGDoZyhteHO4ef
|
OCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWXJccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo
|
||||||
iASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Yjf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2
|
1CkGKTgpaymdKdAqAio1KmgqmyrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6CLrcu
|
||||||
lCCUipT0lV+VyZY0lp+XCpd1l+CYTJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBp
|
7i8kL1ovkS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01
|
||||||
oNihR6G2oiailqMGo3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24
|
hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87LTtrO6o76DwnPGU8
|
||||||
ri2uoa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7urW7Lrun
|
pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFqQaxB7kIwQnJCtUL3QzpDfUPARANE
|
||||||
vCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbGw8dBx7/IPci8yTrJuco4
|
R0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVIS0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpM
|
||||||
yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls
|
cky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtV
|
||||||
2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4DbgveFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG
|
KFV1VcJWD1ZcVqlW91dEV5JX4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpe
|
||||||
6dDqW+rl63Dr++yG7RHtnO4o7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH
|
bF69Xw9fYV+zYAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeTZ+lo
|
||||||
+lf65/t3/Af8mP0p/br+S/7c/23//4AN0iIjRUZdTlNNdXRhYmxlRGF0YaNFRydWTlNEYXRh0iIjSUpc
|
P2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtwhnDgcTpxlXHwckty
|
||||||
TlNDb2xvclNwYWNloksnXE5TQ29sb3JTcGFjZdIiI01OV05TQ29sb3KiTSfSIiNQUVdOU0ltYWdlolAn
|
pnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJeed6RnqlewR7Y3vCfCF8gXzhfUF9
|
||||||
XxAPTlNLZXllZEFyY2hpdmVy0VRVVHJvb3SAAQAIABEAGgAjAC0AMgA3AEsAUQBaAGEAbgB1AH0AfwCE
|
oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSDV4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6J
|
||||||
AIYAiACNAJgAmgCcAJ4AowCmAKgAqgCsAK4AswDKAMwAzgMQAxUDIAMpAzwDQANLA1QDWQNhA2QDaQN4
|
M4mZif6KZIrKizCLlov8jGOMyo0xjZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSV
|
||||||
A3wDhwOPA5wDqQO+A8MDxwPJA8sDzQPWA9sD4QPpA+sD7QPvA/ED9gP+FWoVbBVxFX8VgxWKFY8VnBWf
|
X5XJljSWn5cKl3WX4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobai
|
||||||
FawVsRW5FbwVwRXJFcwV3hXhFeYAAAAAAAACAQAAAAAAAABWAAAAAAAAAAAAAAAAAAAV6A
|
JqKWowajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1ErbiuLa6hrxav
|
||||||
|
i7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnCuju6tbsuu6e8IbybvRW9
|
||||||
|
j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjGRsbDx0HHv8g9yLzJOsm5yjjKt8s2y7bM
|
||||||
|
Ncy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvb
|
||||||
|
gNwF3IrdEN2W3hzeot8p36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb6uXr
|
||||||
|
cOv77IbtEe2c7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn+3f8
|
||||||
|
B/yY/Sn9uv5L/tz/bf//0igpSElcTlNDb2xvclNwYWNlokotXE5TQ29sb3JTcGFjZdIoKUxNV05TQ29s
|
||||||
|
b3KiTC3SKClPUFdOU0ltYWdlok8tAAgAEQAaACQAKQAyADcASQBMAFEAUwBmAGwAdwB+AI0AmgChAKkA
|
||||||
|
qwCtALIAtAC2ALsAxgDIAMoAzADRANQA1gDYANoA4QD4ARQBFgEYA1oDXwNqA3MDhgOKA5UDngOjA6sD
|
||||||
|
rgOzA8IDxgPRA9kD5gPzBAgEDQQRBBMEFQQXBCAEJQQrBDMENQQ3BDkEOxXbFeAV7RXwFf0WAhYKFg0W
|
||||||
|
EhYaAAAAAAAAAgEAAAAAAAAAUQAAAAAAAAAAAAAAAAAAFh0
|
||||||
</mutableData>
|
</mutableData>
|
||||||
</image>
|
</image>
|
||||||
<image name="linphone_user.png" width="41.599998474121094" height="42.400001525878906"/>
|
<image name="linphone_user.png" width="41.599998474121094" height="42.400001525878906"/>
|
||||||
<image name="security_toogle_icon_green.png" width="33.599998474121094" height="38.400001525878906"/>
|
<image name="security_toogle_icon_green.png" width="33.599998474121094" height="38.400001525878906"/>
|
||||||
|
<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>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,15 @@
|
||||||
@property(nonatomic, strong) NSMutableArray *addresses;
|
@property(nonatomic, strong) NSMutableArray *addresses;
|
||||||
@property(nonatomic, strong) NSMutableArray *phoneOrAddr;
|
@property(nonatomic, strong) NSMutableArray *phoneOrAddr;
|
||||||
@property(nonatomic, strong) NSMutableArray *addressesCached;
|
@property(nonatomic, strong) NSMutableArray *addressesCached;
|
||||||
@property(readonly, nonatomic) NSMutableDictionary *ldapContactAddressBookMap;
|
@property(readonly, nonatomic) NSMutableDictionary *ldapAndProvisioningContactAddressBookMap;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation ChatConversationCreateTableView
|
@implementation ChatConversationCreateTableView
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
if (!_ldapContactAddressBookMap) {
|
if (!_ldapAndProvisioningContactAddressBookMap) {
|
||||||
_ldapContactAddressBookMap = [NSMutableDictionary dictionary];
|
_ldapAndProvisioningContactAddressBookMap = [NSMutableDictionary dictionary];
|
||||||
}
|
}
|
||||||
[super viewWillAppear:animated];
|
[super viewWillAppear:animated];
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
|
|
||||||
_addresses = [[NSMutableArray alloc] initWithCapacity:LinphoneManager.instance.fastAddressBook.addressBookMap.allKeys.count];
|
_addresses = [[NSMutableArray alloc] initWithCapacity:LinphoneManager.instance.fastAddressBook.addressBookMap.allKeys.count];
|
||||||
_phoneOrAddr = [[NSMutableArray alloc] initWithCapacity:LinphoneManager.instance.fastAddressBook.addressBookMap.allKeys.count];
|
_phoneOrAddr = [[NSMutableArray alloc] initWithCapacity:LinphoneManager.instance.fastAddressBook.addressBookMap.allKeys.count];
|
||||||
_addressesCached = [[NSMutableArray alloc] initWithCapacity:LinphoneManager.instance.fastAddressBook.addressBookMap.allKeys.count];
|
_addressesCached = [[NSMutableArray alloc] initWithCapacity:LinphoneManager.instance.fastAddressBook.addressBookMap.allKeys.count];
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
addObserver:self
|
addObserver:self
|
||||||
|
|
@ -104,25 +104,27 @@
|
||||||
|
|
||||||
LinphoneSearchResult *result = results->data;
|
LinphoneSearchResult *result = results->data;
|
||||||
const LinphoneAddress *addr = linphone_search_result_get_address(result);
|
const LinphoneAddress *addr = linphone_search_result_get_address(result);
|
||||||
|
const LinphoneFriend* friend = linphone_search_result_get_friend(result);
|
||||||
|
const char *phoneNumber = linphone_search_result_get_phone_number(result);
|
||||||
|
|
||||||
const char *phoneNumber = NULL;
|
|
||||||
Contact *contact = nil;
|
Contact *contact = nil;
|
||||||
char *uri = nil;
|
char *uri = nil;
|
||||||
NSString *address = nil;
|
NSString *address = nil;
|
||||||
if (addr) {
|
if (addr) {
|
||||||
uri = linphone_address_as_string_uri_only(addr);
|
uri = linphone_address_as_string_uri_only(addr);
|
||||||
address = [NSString stringWithUTF8String:uri];
|
address = [NSString stringWithUTF8String:uri];
|
||||||
contact = [LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:[FastAddressBook normalizeSipURI:address]];
|
contact = [LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:[FastAddressBook normalizeSipURI:address use_prefix:[CallManager.instance applyInternationalPrefix]]];
|
||||||
}
|
|
||||||
|
if (!contact && friend) {
|
||||||
const LinphoneFriend* friend = linphone_search_result_get_friend(result);
|
contact = [[Contact alloc] initWithFriend:friend];
|
||||||
if (!addr || (!contact && friend)) {
|
[contact setCreatedFromLdapOrProvisioning:TRUE];
|
||||||
phoneNumber = linphone_search_result_get_phone_number(result);
|
[_ldapAndProvisioningContactAddressBookMap setObject:contact forKey:address];
|
||||||
|
}
|
||||||
|
} else if (friend){
|
||||||
if (!phoneNumber) {
|
if (!phoneNumber) {
|
||||||
results = results->next;
|
results = results->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinphoneAccount *account = linphone_core_get_default_account(LC);
|
LinphoneAccount *account = linphone_core_get_default_account(LC);
|
||||||
if (account) {
|
if (account) {
|
||||||
const char *normalizedPhoneNumber = linphone_account_normalize_phone_number(account, phoneNumber);
|
const char *normalizedPhoneNumber = linphone_account_normalize_phone_number(account, phoneNumber);
|
||||||
|
|
@ -136,10 +138,9 @@
|
||||||
address = [NSString stringWithUTF8String:uri];
|
address = [NSString stringWithUTF8String:uri];
|
||||||
|
|
||||||
contact = [[Contact alloc] initWithFriend:friend];
|
contact = [[Contact alloc] initWithFriend:friend];
|
||||||
[contact setCreatedFromLdap:TRUE];
|
[contact setCreatedFromLdapOrProvisioning:TRUE];
|
||||||
[_ldapContactAddressBookMap setObject:contact forKey:address];
|
[_ldapAndProvisioningContactAddressBookMap setObject:contact forKey:address];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
|
|
@ -168,7 +169,7 @@
|
||||||
[_addresses removeAllObjects];
|
[_addresses removeAllObjects];
|
||||||
[_phoneOrAddr removeAllObjects];
|
[_phoneOrAddr removeAllObjects];
|
||||||
[_addressesCached removeAllObjects];
|
[_addressesCached removeAllObjects];
|
||||||
[_ldapContactAddressBookMap removeAllObjects];
|
[_ldapAndProvisioningContactAddressBookMap removeAllObjects];
|
||||||
[self.tableView reloadData];
|
[self.tableView reloadData];
|
||||||
|
|
||||||
_reloadMagicSearch = _reloadMagicSearch || [filter length]==0 || ![[MagicSearchSingleton.instance currentFilter] isEqualToString:filter];
|
_reloadMagicSearch = _reloadMagicSearch || [filter length]==0 || ![[MagicSearchSingleton.instance currentFilter] isEqualToString:filter];
|
||||||
|
|
@ -192,7 +193,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
|
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
|
||||||
return 60.0;
|
return 60.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
|
|
@ -203,12 +204,12 @@
|
||||||
|
|
||||||
NSString *key = [_addresses objectAtIndex:indexPath.row];
|
NSString *key = [_addresses objectAtIndex:indexPath.row];
|
||||||
NSString *phoneOrAddr = [_phoneOrAddr objectAtIndex:indexPath.row];
|
NSString *phoneOrAddr = [_phoneOrAddr objectAtIndex:indexPath.row];
|
||||||
Contact *contact = [LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:[FastAddressBook normalizeSipURI:key]];
|
Contact *contact = [LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:[FastAddressBook normalizeSipURI:key use_prefix:[CallManager.instance applyInternationalPrefix]]];
|
||||||
if (!contact) {
|
if (!contact) {
|
||||||
contact = [_ldapContactAddressBookMap objectForKey:key];
|
contact = [_ldapAndProvisioningContactAddressBookMap objectForKey:key];
|
||||||
}
|
}
|
||||||
|
|
||||||
const LinphonePresenceModel *model = contact.friend ? linphone_friend_get_presence_model(contact.friend) : NULL;
|
const LinphonePresenceModel *model = contact.friend ? linphone_friend_get_presence_model(contact.friend) : NULL;
|
||||||
Boolean linphoneContact = [FastAddressBook contactHasValidSipDomain:contact]
|
Boolean linphoneContact = [FastAddressBook contactHasValidSipDomain:contact]
|
||||||
|| (model && linphone_presence_model_get_basic_status(model) == LinphonePresenceBasicStatusOpen);
|
|| (model && linphone_presence_model_get_basic_status(model) == LinphonePresenceBasicStatusOpen);
|
||||||
LinphoneAddress *addr = [LinphoneUtils normalizeSipOrPhoneAddress:key];
|
LinphoneAddress *addr = [LinphoneUtils normalizeSipOrPhoneAddress:key];
|
||||||
|
|
@ -216,30 +217,32 @@
|
||||||
return cell;
|
return cell;
|
||||||
|
|
||||||
cell.linphoneImage.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"] || !linphoneContact;
|
cell.linphoneImage.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"] || !linphoneContact;
|
||||||
cell.securityImage.hidden = !(model && linphone_presence_model_has_capability(model, LinphoneFriendCapabilityLimeX3dh));
|
cell.securityImage.hidden = !(model && linphone_presence_model_has_capability(model, LinphoneFriendCapabilityLimeX3dh));
|
||||||
int capabilities = [[_addressesCached objectAtIndex:indexPath.row] intValue];
|
int capabilities = [[_addressesCached objectAtIndex:indexPath.row] intValue];
|
||||||
BOOL greyCellForEncryptedChat = _isEncrypted ? capabilities > 1 : TRUE;
|
BOOL greyCellForEncryptedChat = _isEncrypted ? capabilities > 1 : TRUE;
|
||||||
BOOL greyCellForGroupChat = _isGroupChat ? capabilities > 0 : TRUE;
|
BOOL greyCellForGroupChat = _isGroupChat ? capabilities > 0 : TRUE;
|
||||||
cell.userInteractionEnabled = cell.greyView.hidden = greyCellForEncryptedChat && greyCellForGroupChat;
|
cell.userInteractionEnabled = cell.greyView.hidden = greyCellForEncryptedChat && greyCellForGroupChat;
|
||||||
cell.displayNameLabel.text = [contact createdFromLdap] ? [contact displayName] : [FastAddressBook displayNameForAddress:addr];
|
cell.displayNameLabel.text = [contact createdFromLdapOrProvisioning] ? [contact displayName] : [FastAddressBook displayNameForAddress:addr];
|
||||||
char *str = linphone_address_as_string(addr);
|
char *str = linphone_address_as_string(addr);
|
||||||
cell.addressLabel.text = linphoneContact ? [NSString stringWithUTF8String:str] : phoneOrAddr;
|
cell.addressLabel.text = linphoneContact ? [NSString stringWithUTF8String:str] : phoneOrAddr;
|
||||||
ms_free(str);
|
ms_free(str);
|
||||||
cell.selectedImage.hidden = ![_contactsGroup containsObject:cell.addressLabel.text];
|
cell.selectedImage.hidden = ![_contactsGroup containsObject:cell.addressLabel.text];
|
||||||
[cell.avatarImage setImage:[FastAddressBook imageForAddress:addr] bordered:NO withRoundedRadius:YES];
|
[cell.avatarImage setImage:[FastAddressBook imageForAddress:addr] bordered:NO withRoundedRadius:YES];
|
||||||
cell.contentView.userInteractionEnabled = false;
|
cell.contentView.userInteractionEnabled = false;
|
||||||
|
cell.contentView.backgroundColor = UIColor.clearColor;
|
||||||
|
cell.backgroundColor = UIColor.clearColor;
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
UIChatCreateCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
UIChatCreateCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
||||||
if (!cell.userInteractionEnabled)
|
if (!cell.userInteractionEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC);
|
LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC);
|
||||||
if (!(defaultAccount && linphone_account_params_get_conference_factory_uri(linphone_account_get_params(defaultAccount))) || !_isGroupChat) {
|
if (!(defaultAccount && linphone_account_params_get_conference_factory_uri(linphone_account_get_params(defaultAccount))) || !_isGroupChat) {
|
||||||
LinphoneAddress *addr = linphone_address_new(cell.addressLabel.text.UTF8String);
|
LinphoneAddress *addr = linphone_address_new(cell.addressLabel.text.UTF8String);
|
||||||
[PhoneMainView.instance getOrCreateOneToOneChatRoom:addr waitView:_waitView isEncrypted:_isEncrypted];
|
[PhoneMainView.instance getOrCreateOneToOneChatRoom:addr waitView:_waitView isEncrypted:_isEncrypted];
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
LOGE(@"Chat room could not be created on server, because null address.");
|
LOGE(@"Chat room could not be created on server, because null address.");
|
||||||
[ChatConversationInfoView displayCreationError];
|
[ChatConversationInfoView displayCreationError];
|
||||||
|
|
@ -251,8 +254,6 @@
|
||||||
|
|
||||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||||
NSInteger index = 0;
|
NSInteger index = 0;
|
||||||
_searchBar.text = @"";
|
|
||||||
[self searchBar:_searchBar textDidChange:@""];
|
|
||||||
if(cell.selectedImage.hidden) {
|
if(cell.selectedImage.hidden) {
|
||||||
if(![_contactsGroup containsObject:cell.addressLabel.text]) {
|
if(![_contactsGroup containsObject:cell.addressLabel.text]) {
|
||||||
[_contactsGroup addObject:cell.addressLabel.text];
|
[_contactsGroup addObject:cell.addressLabel.text];
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,9 @@
|
||||||
- (IBAction)onNextClick:(id)sender;
|
- (IBAction)onNextClick:(id)sender;
|
||||||
- (IBAction)onChiffreClick:(id)sender;
|
- (IBAction)onChiffreClick:(id)sender;
|
||||||
|
|
||||||
|
-(void) unfragmentCompositeDescription;
|
||||||
|
-(void) fragmentCompositeDescription;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* ChatConversationCreateView_h */
|
#endif /* ChatConversationCreateView_h */
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,21 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
return self.class.compositeViewDescription;
|
return self.class.compositeViewDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(void) unfragmentCompositeDescription {
|
||||||
|
if (!IPAD)
|
||||||
|
return;
|
||||||
|
compositeDescription.isLeftFragment = true;
|
||||||
|
compositeDescription.otherFragment = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) fragmentCompositeDescription {
|
||||||
|
if (!IPAD)
|
||||||
|
return;
|
||||||
|
compositeDescription.otherFragment = IPAD ? NSStringFromClass(ChatsListView.class) : nil;
|
||||||
|
compositeDescription.isLeftFragment = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)viewDidLoad {
|
- (void)viewDidLoad {
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
|
||||||
|
|
@ -54,7 +69,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
[self.view addGestureRecognizer:tap];
|
[self.view addGestureRecognizer:tap];
|
||||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||||
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
|
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
|
||||||
layout.itemSize = CGSizeMake(100.0 , 50.0);
|
layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize;
|
||||||
_collectionController.collectionView = _collectionView;
|
_collectionController.collectionView = _collectionView;
|
||||||
_collectionController = (ChatConversationCreateCollectionViewController *)[[UICollectionViewController alloc] initWithCollectionViewLayout:layout];
|
_collectionController = (ChatConversationCreateCollectionViewController *)[[UICollectionViewController alloc] initWithCollectionViewLayout:layout];
|
||||||
_collectionView.dataSource = self;
|
_collectionView.dataSource = self;
|
||||||
|
|
@ -75,6 +90,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
selector:@selector(viewUpdateEvent:)
|
selector:@selector(viewUpdateEvent:)
|
||||||
name:kLinphoneChatCreateViewChange
|
name:kLinphoneChatCreateViewChange
|
||||||
object:nil];
|
object:nil];
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector:@selector(displayModeChanged)
|
||||||
|
name:kDisplayModeChanged
|
||||||
|
object:nil];
|
||||||
LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC);
|
LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC);
|
||||||
_chiffreOptionView.hidden = !(defaultAccount && linphone_account_params_get_conference_factory_uri(linphone_account_get_params(defaultAccount)));
|
_chiffreOptionView.hidden = !(defaultAccount && linphone_account_params_get_conference_factory_uri(linphone_account_get_params(defaultAccount)));
|
||||||
if ([LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"]) {
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"]) {
|
||||||
|
|
@ -83,8 +102,15 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
CGRect frame = _allButton.frame;
|
CGRect frame = _allButton.frame;
|
||||||
frame.origin.x = _linphoneButton.frame.origin.x;
|
frame.origin.x = _linphoneButton.frame.origin.x;
|
||||||
_allButton.frame = frame;
|
_allButton.frame = frame;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"force_lime_chat_rooms"]) {
|
||||||
|
_chiffreOptionView.hidden = true;
|
||||||
|
_isEncrypted = true;
|
||||||
|
_tableController.isEncrypted = true;
|
||||||
|
_allButton.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_isForVoipConference) {
|
if (_isForVoipConference) {
|
||||||
_switchView.hidden = true;
|
_switchView.hidden = true;
|
||||||
|
|
@ -95,13 +121,28 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
} else {
|
} else {
|
||||||
[_nextButton setImage:[UIImage imageNamed:@"next_default"] forState:UIControlStateNormal];
|
[_nextButton setImage:[UIImage imageNamed:@"next_default"] forState:UIControlStateNormal];
|
||||||
}
|
}
|
||||||
_topBar.backgroundColor = VoipTheme.toolbar_color;
|
|
||||||
} else {
|
} else {
|
||||||
_voipTitle.hidden = true;
|
_voipTitle.hidden = true;
|
||||||
[_nextButton setImage:[UIImage imageNamed:@"next_default"] forState:UIControlStateNormal];
|
[_nextButton setImage:[UIImage imageNamed:@"next_default"] forState:UIControlStateNormal];
|
||||||
_topBar.backgroundColor = UIColor.secondarySystemBackgroundColor;
|
|
||||||
}
|
}
|
||||||
|
[self displayModeChanged];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)displayModeChanged{
|
||||||
|
[self.tableController.tableView reloadData];
|
||||||
|
if (_isForVoipConference) {
|
||||||
|
_topBar.backgroundColor = [VoipTheme.voipToolbarBackgroundColor get];
|
||||||
|
self.view.backgroundColor = [VoipTheme.voipBackgroundBWColor get];
|
||||||
|
_tableController.tableView.backgroundColor = [VoipTheme.voipBackgroundBWColor get];
|
||||||
|
_tableController.searchBar.backgroundColor = [VoipTheme.voipBackgroundBWColor get];
|
||||||
|
_tableController.collectionView.backgroundColor = [VoipTheme.voipBackgroundBWColor get];
|
||||||
|
} else {
|
||||||
|
_topBar.backgroundColor = UIColor.secondarySystemBackgroundColor;
|
||||||
|
self.view.backgroundColor = [VoipTheme.backgroundWhiteBlack get];
|
||||||
|
_tableController.tableView.backgroundColor = [VoipTheme.backgroundWhiteBlack get];
|
||||||
|
_tableController.searchBar.backgroundColor = [VoipTheme.backgroundWhiteBlack get];
|
||||||
|
_tableController.collectionView.backgroundColor = [VoipTheme.backgroundWhiteBlack get];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewUpdateEvent:(NSNotification *)notif {
|
- (void)viewUpdateEvent:(NSNotification *)notif {
|
||||||
|
|
@ -116,17 +157,17 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
frame.origin.x = self.view.frame.size.width * 0.192;
|
frame.origin.x = self.view.frame.size.width * 0.192;
|
||||||
}
|
}
|
||||||
_chiffreOptionView.frame = frame;
|
_chiffreOptionView.frame = frame;
|
||||||
_isEncrypted = FALSE;
|
_isEncrypted = [LinphoneManager.instance lpConfigBoolForKey:@"force_lime_chat_rooms"]; // false by default
|
||||||
CGRect buttonFrame = _chiffreButton.frame;
|
CGRect buttonFrame = _chiffreButton.frame;
|
||||||
_tableController.isEncrypted = _isEncrypted;
|
|
||||||
|
|
||||||
// no encrypted by default
|
if (!_isEncrypted) {
|
||||||
buttonFrame.origin.x = 2;
|
buttonFrame.origin.x = 2;
|
||||||
[_chiffreImage setImage:[UIImage imageNamed:@"security_toogle_background_grey.png"]];
|
[_chiffreImage setImage:[UIImage imageNamed:@"security_toogle_background_grey.png"]];
|
||||||
_chiffreButton.frame = buttonFrame;
|
_chiffreButton.frame = buttonFrame;
|
||||||
|
}
|
||||||
|
|
||||||
_waitView.hidden = YES;
|
_waitView.hidden = YES;
|
||||||
_backButton.hidden = IPAD;
|
_backButton.hidden = IPAD && !(_isForVoipConference||_isForOngoingVoipConference);
|
||||||
if(_tableController.contactsGroup.count == 0) {
|
if(_tableController.contactsGroup.count == 0) {
|
||||||
if (!_isForEditing)
|
if (!_isForEditing)
|
||||||
_nextButton.enabled = FALSE;
|
_nextButton.enabled = FALSE;
|
||||||
|
|
@ -149,9 +190,8 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
[super viewWillDisappear:animated];
|
[super viewWillDisappear:animated];
|
||||||
if (IPAD)
|
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Chat room functions
|
#pragma mark - Chat room functions
|
||||||
|
|
@ -168,7 +208,12 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
- (IBAction)onBackClick:(id)sender {
|
- (IBAction)onBackClick:(id)sender {
|
||||||
[_tableController.contactsGroup removeAllObjects];
|
[_tableController.contactsGroup removeAllObjects];
|
||||||
if (_isForVoipConference) {
|
if (_isForVoipConference) {
|
||||||
[PhoneMainView.instance popToView:ConferenceSchedulingView.compositeViewDescription];
|
if (_isForOngoingVoipConference) {
|
||||||
|
[PhoneMainView.instance popToView:VIEW(ConferenceCallView).compositeViewDescription];
|
||||||
|
[ControlsViewModelBridge showParticipants];
|
||||||
|
} else {
|
||||||
|
[PhoneMainView.instance popToView:ConferenceSchedulingView.compositeViewDescription];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_tableController.isForEditing)
|
if (_tableController.isForEditing)
|
||||||
[PhoneMainView.instance popToView:ChatConversationInfoView.compositeViewDescription];
|
[PhoneMainView.instance popToView:ChatConversationInfoView.compositeViewDescription];
|
||||||
|
|
@ -180,7 +225,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
- (IBAction)onNextClick:(id)sender {
|
- (IBAction)onNextClick:(id)sender {
|
||||||
if (_isForVoipConference) {
|
if (_isForVoipConference) {
|
||||||
if (_isForOngoingVoipConference) {
|
if (_isForOngoingVoipConference) {
|
||||||
[PhoneMainView.instance changeCurrentView:VIEW(ActiveCallOrConferenceView).compositeViewDescription];
|
[PhoneMainView.instance popToView:VIEW(ConferenceCallView).compositeViewDescription];
|
||||||
[ConferenceViewModelBridge updateParticipantsListWithAddresses:_tableController.contactsGroup];
|
[ConferenceViewModelBridge updateParticipantsListWithAddresses:_tableController.contactsGroup];
|
||||||
} else {
|
} else {
|
||||||
[PhoneMainView.instance changeCurrentView:VIEW(ConferenceSchedulingSummaryView).compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:VIEW(ConferenceSchedulingSummaryView).compositeViewDescription];
|
||||||
|
|
@ -260,7 +305,7 @@ typedef enum { ContactsAll, ContactsLinphone, ContactsMAX } ContactsCategory;
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - UICollectionViewDataSource
|
#pragma mark - UICollectionViewDataSource & Delegate
|
||||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
||||||
return _tableController.contactsGroup.count;
|
return _tableController.contactsGroup.count;
|
||||||
}
|
}
|
||||||
|
|
@ -282,9 +327,10 @@ typedef enum { ContactsAll, ContactsLinphone, ContactsMAX } ContactsCategory;
|
||||||
ms_free(phone);
|
ms_free(phone);
|
||||||
} else
|
} else
|
||||||
addr = linphone_address_new(uri.UTF8String);
|
addr = linphone_address_new(uri.UTF8String);
|
||||||
cell = [cell initWithName:[FastAddressBook displayNameForAddress:addr]];
|
[cell.nameLabel setText:[FastAddressBook displayNameForAddress:addr]];
|
||||||
linphone_address_unref(addr);
|
linphone_address_unref(addr);
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
NSString *messageText;
|
NSString *messageText;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property(nonatomic) LinphoneChatMessage *msg;
|
@property(nonatomic) LinphoneEventLog *event;
|
||||||
@property(nonatomic) bctbx_list_t *displayedList;
|
@property(nonatomic) bctbx_list_t *displayedList;
|
||||||
@property(nonatomic) bctbx_list_t *receivedList;
|
@property(nonatomic) bctbx_list_t *receivedList;
|
||||||
@property(nonatomic) bctbx_list_t *notReceivedList;
|
@property(nonatomic) bctbx_list_t *notReceivedList;
|
||||||
|
|
|
||||||
|
|
@ -48,17 +48,12 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
- (void)viewDidLoad {
|
- (void)viewDidLoad {
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
_msg = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
[super viewWillAppear:animated];
|
[super viewWillAppear:animated];
|
||||||
|
|
||||||
int index = [VIEW(ChatConversationView).tableController indexOfMesssage:_msg];
|
_cell = [VIEW(ChatConversationView).tableController buildMessageCell:_event];
|
||||||
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.frame = CGRectMake(-10,0,_msgView.frame.size.width,_msgView.frame.size.height);
|
||||||
_cell.isFirst = true;
|
_cell.isFirst = true;
|
||||||
_cell.isLast = true;
|
_cell.isLast = true;
|
||||||
|
|
@ -90,18 +85,21 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateImdnList {
|
- (void)updateImdnList {
|
||||||
if (_msg && linphone_chat_message_get_chat_room(_msg)) {
|
if (_event) {
|
||||||
_displayedList = linphone_chat_message_get_participants_by_imdn_state(_msg, LinphoneChatMessageStateDisplayed);
|
LinphoneChatMessage *_msg = linphone_event_log_get_chat_message(_event);
|
||||||
_receivedList = linphone_chat_message_get_participants_by_imdn_state(_msg, LinphoneChatMessageStateDeliveredToUser);
|
if (_msg) {
|
||||||
_notReceivedList = linphone_chat_message_get_participants_by_imdn_state(_msg, LinphoneChatMessageStateDelivered);
|
_displayedList = linphone_chat_message_get_participants_by_imdn_state(_msg, LinphoneChatMessageStateDisplayed);
|
||||||
_errorList = linphone_chat_message_get_participants_by_imdn_state(_msg, LinphoneChatMessageStateNotDelivered);
|
_receivedList = linphone_chat_message_get_participants_by_imdn_state(_msg, LinphoneChatMessageStateDeliveredToUser);
|
||||||
|
_notReceivedList = linphone_chat_message_get_participants_by_imdn_state(_msg, LinphoneChatMessageStateDelivered);
|
||||||
[_tableView reloadData];
|
_errorList = linphone_chat_message_get_participants_by_imdn_state(_msg, LinphoneChatMessageStateNotDelivered);
|
||||||
|
|
||||||
|
[_tableView reloadData];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)fitContent {
|
- (void)fitContent {
|
||||||
|
LinphoneChatMessage *_msg = linphone_event_log_get_chat_message(_event);
|
||||||
CGSize messageSize = [UIChatBubbleTextCell ViewHeightForMessage:_msg withWidth:self.view.frame.size.width];
|
CGSize messageSize = [UIChatBubbleTextCell ViewHeightForMessage:_msg withWidth:self.view.frame.size.width];
|
||||||
[_msgView setFrame:CGRectMake(_msgView.frame.origin.x,
|
[_msgView setFrame:CGRectMake(_msgView.frame.origin.x,
|
||||||
_msgView.frame.origin.y,
|
_msgView.frame.origin.y,
|
||||||
|
|
@ -299,7 +297,8 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
f.unitsStyle = NSDateComponentsFormatterUnitsStylePositional;
|
f.unitsStyle = NSDateComponentsFormatterUnitsStylePositional;
|
||||||
f.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
|
f.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
|
||||||
|
|
||||||
if (linphone_chat_message_is_ephemeral(_msg)) {
|
LinphoneChatMessage *_msg = _event ? linphone_event_log_get_chat_message(_event) : nil;
|
||||||
|
if (_msg && linphone_chat_message_is_ephemeral(_msg)) {
|
||||||
long duration = linphone_chat_message_get_ephemeral_expire_time(_msg) == 0 ?
|
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_room_get_ephemeral_lifetime(linphone_chat_message_get_chat_room(_msg)) :
|
||||||
linphone_chat_message_get_ephemeral_expire_time(_msg)-[NSDate date].timeIntervalSince1970;
|
linphone_chat_message_get_ephemeral_expire_time(_msg)-[NSDate date].timeIntervalSince1970;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
@property(nonatomic) LinphoneChatRoom *room;
|
@property(nonatomic) LinphoneChatRoom *room;
|
||||||
@property(nonatomic) LinphoneChatRoomCbs *chatRoomCbs;
|
@property(nonatomic) LinphoneChatRoomCbs *chatRoomCbs;
|
||||||
@property(nonatomic) const char *peerAddress;
|
@property(nonatomic) const char *peerAddress;
|
||||||
|
@property(nonatomic) const char *localAddress;
|
||||||
|
|
||||||
@property (weak, nonatomic) IBOutlet UIIconButton *nextButton;
|
@property (weak, nonatomic) IBOutlet UIIconButton *nextButton;
|
||||||
@property (weak, nonatomic) IBOutlet UIRoundBorderedButton *quitButton;
|
@property (weak, nonatomic) IBOutlet UIRoundBorderedButton *quitButton;
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
_room = NULL;
|
_room = NULL;
|
||||||
_chatRoomCbs = NULL;
|
_chatRoomCbs = NULL;
|
||||||
_peerAddress = NULL;
|
_peerAddress = NULL;
|
||||||
|
_localAddress = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
|
@ -153,10 +154,11 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
- (void)onLinphoneCoreReady:(NSNotification *)notif {
|
- (void)onLinphoneCoreReady:(NSNotification *)notif {
|
||||||
if ((LinphoneGlobalState)[[[notif userInfo] valueForKey:@"state"] integerValue] == LinphoneGlobalOn) {
|
if ((LinphoneGlobalState)[[[notif userInfo] valueForKey:@"state"] integerValue] == LinphoneGlobalOn) {
|
||||||
if (!_create && _peerAddress) {
|
if (!_create && _peerAddress && _localAddress) {
|
||||||
LinphoneAddress *peerAddr = linphone_core_create_address([LinphoneManager getLc], _peerAddress);
|
LinphoneAddress *peerAddr = linphone_core_create_address([LinphoneManager getLc], _peerAddress);
|
||||||
if (peerAddr) {
|
LinphoneAddress *localAddr = linphone_core_create_address([LinphoneManager getLc], _localAddress);
|
||||||
_room = linphone_core_get_chat_room([LinphoneManager getLc], peerAddr);
|
if (peerAddr && localAddr) {
|
||||||
|
_room = linphone_core_search_chat_room([LinphoneManager getLc], NULL, localAddr, peerAddr, NULL);
|
||||||
}
|
}
|
||||||
[self configure];
|
[self configure];
|
||||||
}
|
}
|
||||||
|
|
@ -270,6 +272,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
- (IBAction)onBackClick:(id)sender {
|
- (IBAction)onBackClick:(id)sender {
|
||||||
if(_create) {
|
if(_create) {
|
||||||
ChatConversationCreateView *view = VIEW(ChatConversationCreateView);
|
ChatConversationCreateView *view = VIEW(ChatConversationCreateView);
|
||||||
|
[view fragmentCompositeDescription];
|
||||||
view.tableController.contactsGroup = [_contacts mutableCopy];
|
view.tableController.contactsGroup = [_contacts mutableCopy];
|
||||||
view.tableController.notFirstTime = TRUE;
|
view.tableController.notFirstTime = TRUE;
|
||||||
view.isForEditing = FALSE;
|
view.isForEditing = FALSE;
|
||||||
|
|
@ -296,6 +299,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
- (IBAction)onAddClick:(id)sender {
|
- (IBAction)onAddClick:(id)sender {
|
||||||
if (_create || _imAdmin) {
|
if (_create || _imAdmin) {
|
||||||
ChatConversationCreateView *view = VIEW(ChatConversationCreateView);
|
ChatConversationCreateView *view = VIEW(ChatConversationCreateView);
|
||||||
|
[view fragmentCompositeDescription];
|
||||||
view.tableController.notFirstTime = TRUE;
|
view.tableController.notFirstTime = TRUE;
|
||||||
view.isForEditing = !_create;
|
view.isForEditing = !_create;
|
||||||
view.isGroupChat = TRUE;
|
view.isGroupChat = TRUE;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#import "UICheckBoxTableView.h"
|
#import "UICheckBoxTableView.h"
|
||||||
|
|
||||||
|
|
||||||
@interface FileContext : NSObject
|
@interface FileContext : NSObject
|
||||||
@property NSMutableArray <NSString *> *typesArray;
|
@property NSMutableArray <NSString *> *typesArray;
|
||||||
@property NSMutableArray <NSData *> *datasArray;
|
@property NSMutableArray <NSData *> *datasArray;
|
||||||
|
|
@ -70,5 +71,6 @@
|
||||||
- (void) dismissMessagesPopups;
|
- (void) dismissMessagesPopups;
|
||||||
- (void) scrollToMessage:(LinphoneChatMessage *)message;
|
- (void) scrollToMessage:(LinphoneChatMessage *)message;
|
||||||
- (int) indexOfMesssage:(LinphoneChatMessage *)message;
|
- (int) indexOfMesssage:(LinphoneChatMessage *)message;
|
||||||
|
- (void *)buildMessageCell:(LinphoneEventLog *) event;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@
|
||||||
#import "LinphoneManager.h"
|
#import "LinphoneManager.h"
|
||||||
#import "ChatConversationTableView.h"
|
#import "ChatConversationTableView.h"
|
||||||
#import "ChatConversationImdnView.h"
|
#import "ChatConversationImdnView.h"
|
||||||
#import "UIChatBubbleTextCell.h"
|
|
||||||
#import "UIChatBubblePhotoCell.h"
|
#import "UIChatBubblePhotoCell.h"
|
||||||
#import "UIChatNotifiedEventCell.h"
|
#import "UIChatNotifiedEventCell.h"
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
|
|
@ -84,7 +83,6 @@
|
||||||
LinphoneChatRoomCapabilitiesMask capabilities = linphone_chat_room_get_capabilities(_chatRoom);
|
LinphoneChatRoomCapabilitiesMask capabilities = linphone_chat_room_get_capabilities(_chatRoom);
|
||||||
bool oneToOne = capabilities & LinphoneChatRoomCapabilitiesOneToOne;
|
bool oneToOne = capabilities & LinphoneChatRoomCapabilitiesOneToOne;
|
||||||
bctbx_list_t *chatRoomEvents = linphone_chat_room_get_history_events(_chatRoom, 0);
|
bctbx_list_t *chatRoomEvents = linphone_chat_room_get_history_events(_chatRoom, 0);
|
||||||
|
|
||||||
int unread_count = 0;
|
int unread_count = 0;
|
||||||
|
|
||||||
bctbx_list_t *head = chatRoomEvents;
|
bctbx_list_t *head = chatRoomEvents;
|
||||||
|
|
@ -142,12 +140,11 @@
|
||||||
|
|
||||||
- (void)addEventEntry:(LinphoneEventLog *)event {
|
- (void)addEventEntry:(LinphoneEventLog *)event {
|
||||||
[eventList addObject:[NSValue valueWithPointer:linphone_event_log_ref(event)]];
|
[eventList addObject:[NSValue valueWithPointer:linphone_event_log_ref(event)]];
|
||||||
[totalEventList addObject:[NSValue valueWithPointer:linphone_event_log_ref(event)]];
|
[totalEventList addObject:[NSValue valueWithPointer:linphone_event_log_ref(event)]];
|
||||||
int pos = (int)eventList.count - 1;
|
int pos = (int)eventList.count - 1;
|
||||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:pos inSection:0];
|
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:pos inSection:0];
|
||||||
[self.tableView beginUpdates];
|
[self.tableView beginUpdates];
|
||||||
[self.tableView insertRowsAtIndexPaths:@[ indexPath ] withRowAnimation:UITableViewRowAnimationFade];
|
[self.tableView insertRowsAtIndexPaths:@[ indexPath ] withRowAnimation:UITableViewRowAnimationFade];
|
||||||
[self.tableView reloadData];
|
|
||||||
[self.tableView endUpdates];
|
[self.tableView endUpdates];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,28 +328,32 @@ static const int BASIC_EVENT_LIST=15;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(UIChatBubbleTextCell *)buildMessageCell:(LinphoneEventLog *) event {
|
||||||
|
NSString *kCellId = nil;
|
||||||
|
LinphoneChatMessage *chat = linphone_event_log_get_chat_message(event);
|
||||||
|
BOOL isConferenceIcs = [ICSBubbleView isConferenceInvitationMessageWithCmessage:chat];
|
||||||
|
if (!isConferenceIcs && (linphone_chat_message_get_file_transfer_information(chat) || linphone_chat_message_get_external_body_url(chat)))
|
||||||
|
kCellId = NSStringFromClass(UIChatBubblePhotoCell.class);
|
||||||
|
else
|
||||||
|
kCellId = NSStringFromClass(UIChatBubbleTextCell.class);
|
||||||
|
// To use less memory and to avoid overlapping. To be improved.
|
||||||
|
UIChatBubbleTextCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCellId];
|
||||||
|
cell = [[NSClassFromString(kCellId) alloc] initWithIdentifier:kCellId];
|
||||||
|
[cell setEvent:event];
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
NSString *kCellId = nil;
|
NSString *kCellId = nil;
|
||||||
LinphoneEventLog *event = [[eventList objectAtIndex:indexPath.row] pointerValue];
|
LinphoneEventLog *event = [[eventList objectAtIndex:indexPath.row] pointerValue];
|
||||||
if (linphone_event_log_get_type(event) == LinphoneEventLogTypeConferenceChatMessage) {
|
if (linphone_event_log_get_type(event) == LinphoneEventLogTypeConferenceChatMessage) {
|
||||||
|
UIChatBubbleTextCell *cell = [self buildMessageCell:event];
|
||||||
LinphoneChatMessage *chat = linphone_event_log_get_chat_message(event);
|
LinphoneChatMessage *chat = linphone_event_log_get_chat_message(event);
|
||||||
BOOL isConferenceIcs = [ICSBubbleView isConferenceInvitationMessageWithCmessage:chat];
|
if (chat) {
|
||||||
if (!isConferenceIcs && (linphone_chat_message_get_file_transfer_information(chat) || linphone_chat_message_get_external_body_url(chat)))
|
cell.isFirst = [self isFirstIndexInTableView:indexPath chat:chat];
|
||||||
kCellId = NSStringFromClass(UIChatBubblePhotoCell.class);
|
cell.isLast = [self isLastIndexInTableView:indexPath chat:chat];
|
||||||
else
|
[cell update];
|
||||||
kCellId = NSStringFromClass(UIChatBubbleTextCell.class);
|
}
|
||||||
|
|
||||||
// To use less memory and to avoid overlapping. To be improved.
|
|
||||||
UIChatBubbleTextCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId];
|
|
||||||
cell = [[NSClassFromString(kCellId) alloc] initWithIdentifier:kCellId];
|
|
||||||
|
|
||||||
[cell setEvent:event];
|
|
||||||
if (chat) {
|
|
||||||
cell.isFirst = [self isFirstIndexInTableView:indexPath chat:chat];
|
|
||||||
cell.isLast = [self isLastIndexInTableView:indexPath chat:chat];
|
|
||||||
[cell update];
|
|
||||||
}
|
|
||||||
|
|
||||||
[cell setChatRoomDelegate:_chatRoomDelegate];
|
[cell setChatRoomDelegate:_chatRoomDelegate];
|
||||||
[super accessoryForCell:cell atPath:indexPath];
|
[super accessoryForCell:cell atPath:indexPath];
|
||||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||||
|
|
@ -378,6 +379,13 @@ static const int BASIC_EVENT_LIST=15;
|
||||||
[_chatRoomDelegate tableViewIsScrolling];
|
[_chatRoomDelegate tableViewIsScrolling];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
|
||||||
|
if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
|
||||||
|
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
|
||||||
|
[ChatConversationView markAsRead:_chatRoom];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const CGFloat MESSAGE_SPACING_PERCENTAGE = 1.f;
|
static const CGFloat MESSAGE_SPACING_PERCENTAGE = 1.f;
|
||||||
|
|
||||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
|
|
@ -443,12 +451,11 @@ static const CGFloat MESSAGE_SPACING_PERCENTAGE = 1.f;
|
||||||
|
|
||||||
LinphoneEventLog *event = [[eventList objectAtIndex:indexPath.row] pointerValue];
|
LinphoneEventLog *event = [[eventList objectAtIndex:indexPath.row] pointerValue];
|
||||||
UIContextualAction *imdnAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal
|
UIContextualAction *imdnAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal
|
||||||
title:NSLocalizedString(@"Info", nil)
|
title:NSLocalizedString(@"Info", nil)
|
||||||
handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
|
handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
|
||||||
LinphoneChatMessage *msg = linphone_event_log_get_chat_message(event);
|
ChatConversationImdnView *view = VIEW(ChatConversationImdnView);
|
||||||
ChatConversationImdnView *view = VIEW(ChatConversationImdnView);
|
view.event = event;
|
||||||
view.msg = msg;
|
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
||||||
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
UISwipeActionsConfiguration *swipeActionConfig;
|
UISwipeActionsConfiguration *swipeActionConfig;
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@
|
||||||
@property(nonatomic) LinphoneChatRoomCbs *chatRoomCbs;
|
@property(nonatomic) LinphoneChatRoomCbs *chatRoomCbs;
|
||||||
@property(nonatomic) Boolean markAsRead;
|
@property(nonatomic) Boolean markAsRead;
|
||||||
@property(nonatomic) const char *peerAddress;
|
@property(nonatomic) const char *peerAddress;
|
||||||
|
@property(nonatomic) const char *localAddress;
|
||||||
|
|
||||||
@property (strong, nonatomic) FileDataSource *FileDataSource;
|
@property (strong, nonatomic) FileDataSource *FileDataSource;
|
||||||
|
|
||||||
|
|
@ -112,6 +113,7 @@
|
||||||
@property LinphonePlayer *sharedVoicePlayer;
|
@property LinphonePlayer *sharedVoicePlayer;
|
||||||
@property BOOL showVoiceRecorderView;
|
@property BOOL showVoiceRecorderView;
|
||||||
@property BOOL preservePendingActions;
|
@property BOOL preservePendingActions;
|
||||||
|
@property BOOL *sharingMedia;
|
||||||
|
|
||||||
// Reply
|
// Reply
|
||||||
@property (weak, nonatomic) IBOutlet UIView *replyView;
|
@property (weak, nonatomic) IBOutlet UIView *replyView;
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
if (compositeDescription == nil) {
|
if (compositeDescription == nil) {
|
||||||
compositeDescription = [[UICompositeViewDescription alloc] init:self.class
|
compositeDescription = [[UICompositeViewDescription alloc] init:self.class
|
||||||
statusBar:StatusBarView.class
|
statusBar:StatusBarView.class
|
||||||
tabBar:nil
|
tabBar:IPAD ? TabBarView.class :nil
|
||||||
sideMenu:SideMenuView.class
|
sideMenu:SideMenuView.class
|
||||||
fullscreen:false
|
fullscreen:false
|
||||||
isLeftFragment:NO
|
isLeftFragment:NO
|
||||||
|
|
@ -196,7 +196,8 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
_vrInnerView.layer.masksToBounds = YES;
|
_vrInnerView.layer.masksToBounds = YES;
|
||||||
_vrWaveMaskPlayer.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"color_L"]]; // rgba(1,88,7,0.2);
|
_vrWaveMaskPlayer.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"color_L"]]; // rgba(1,88,7,0.2);
|
||||||
_showVoiceRecorderView = false;
|
_showVoiceRecorderView = false;
|
||||||
|
_toggleMenuButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
|
_toggleRecord.imageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)refreshData {
|
- (void)refreshData {
|
||||||
|
|
@ -212,10 +213,17 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
[super viewWillAppear:animated];
|
[super viewWillAppear:animated];
|
||||||
|
if (!_chatRoom)
|
||||||
|
[self onLinphoneCoreReady:nil];
|
||||||
|
|
||||||
[NSNotificationCenter.defaultCenter addObserver:self
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
selector:@selector(applicationWillEnterBackground)
|
selector:@selector(applicationDidEnterBackground)
|
||||||
name:UIApplicationDidEnterBackgroundNotification
|
name:UIApplicationDidEnterBackgroundNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector:@selector(applicationWillEnterForeground)
|
||||||
|
name:UIApplicationWillEnterForegroundNotification
|
||||||
|
object:nil];
|
||||||
[NSNotificationCenter.defaultCenter addObserver:self
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
selector:@selector(keyboardWillShow:)
|
selector:@selector(keyboardWillShow:)
|
||||||
name:UIKeyboardWillShowNotification
|
name:UIKeyboardWillShowNotification
|
||||||
|
|
@ -232,10 +240,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
selector:@selector(callUpdateEvent:)
|
selector:@selector(callUpdateEvent:)
|
||||||
name:kLinphoneCallUpdate
|
name:kLinphoneCallUpdate
|
||||||
object:nil];
|
object:nil];
|
||||||
[NSNotificationCenter.defaultCenter addObserver:self
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
selector:@selector(onLinphoneCoreReady:)
|
selector:@selector(onLinphoneCoreReady:)
|
||||||
name:kLinphoneGlobalStateUpdate
|
name:kLinphoneGlobalStateUpdate
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
[NSNotificationCenter.defaultCenter addObserver:self
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
selector:@selector(endVoicePlayingIfDoingSO:)
|
selector:@selector(endVoicePlayingIfDoingSO:)
|
||||||
|
|
@ -246,24 +254,23 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
selector:@selector(endVoicePlayingIfDoingSO:)
|
selector:@selector(endVoicePlayingIfDoingSO:)
|
||||||
name:kLinphoneVoiceMessagePlayerEOF
|
name:kLinphoneVoiceMessagePlayerEOF
|
||||||
object:nil];
|
object:nil];
|
||||||
if ([_fileContext count] > 0) {
|
if ([_fileContext count] > 0) {
|
||||||
[UIView animateWithDuration:0
|
[UIView animateWithDuration:0
|
||||||
delay:0
|
delay:0
|
||||||
options:UIViewAnimationOptionBeginFromCurrentState
|
options:UIViewAnimationOptionBeginFromCurrentState
|
||||||
animations:^{
|
animations:^{
|
||||||
// resizing imagesView
|
// resizing imagesView
|
||||||
CGRect imagesFrame = [_imagesView frame];
|
CGRect imagesFrame = [_imagesView frame];
|
||||||
imagesFrame.origin.y = [_messageView frame].origin.y - 120;
|
imagesFrame.origin.y = [_messageView frame].origin.y - 120;
|
||||||
imagesFrame.size.height = 120;
|
imagesFrame.size.height = 120;
|
||||||
[_imagesView setFrame:imagesFrame];
|
[_imagesView setFrame:imagesFrame];
|
||||||
// resizing chatTable
|
// resizing chatTable
|
||||||
CGRect tableViewFrame = [_tableController.tableView frame];
|
CGRect tableViewFrame = [_tableController.tableView frame];
|
||||||
tableViewFrame.size.height -= 120;
|
tableViewFrame.size.height -= 120;
|
||||||
[_tableController.tableView setFrame:tableViewFrame];
|
[_tableController.tableView setFrame:tableViewFrame];
|
||||||
[self updateFramesInclRecordingAndReplyView];
|
[self updateFramesInclRecordingAndReplyView];
|
||||||
}
|
} completion:nil];
|
||||||
completion:nil];
|
}
|
||||||
}
|
|
||||||
[self configureForRoom:self.editing];
|
[self configureForRoom:self.editing];
|
||||||
|
|
||||||
// Resize the popup table depending on wether ephemeral messages are enabled or not.
|
// Resize the popup table depending on wether ephemeral messages are enabled or not.
|
||||||
|
|
@ -273,12 +280,13 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
// Voice recording & Replies
|
// Voice recording & Replies
|
||||||
_vrView.hidden = true;
|
_vrView.hidden = true;
|
||||||
_toggleRecord.enabled = linphone_core_get_calls_nb(LC) == 0;
|
_toggleRecord.enabled = linphone_core_get_calls_nb(LC) == 0;
|
||||||
_replyView.hidden = true;
|
_replyView.hidden = true;
|
||||||
_preservePendingActions = false;
|
_preservePendingActions = false;
|
||||||
|
|
||||||
_toggleRecord.enabled = linphone_core_get_calls_nb(LC) == 0;
|
_toggleRecord.enabled = linphone_core_get_calls_nb(LC) == 0;
|
||||||
|
|
||||||
|
[PhoneMainView.instance hideTabBar:!IPAD];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
|
@ -307,6 +315,8 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||||
PhoneMainView.instance.currentRoom = NULL;
|
PhoneMainView.instance.currentRoom = NULL;
|
||||||
[[UIApplication sharedApplication] setIdleTimerDisabled:false];
|
[[UIApplication sharedApplication] setIdleTimerDisabled:false];
|
||||||
|
_chatRoom = NULL;
|
||||||
|
_tableController.chatRoom = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)removeCallBacks {
|
- (void)removeCallBacks {
|
||||||
|
|
@ -323,27 +333,31 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
composingVisible = !composingVisible;
|
composingVisible = !composingVisible;
|
||||||
[self setComposingVisible:!composingVisible withDelay:0];
|
|
||||||
|
|
||||||
// force offset recomputing
|
// force offset recomputing
|
||||||
[_messageField refreshHeight];
|
[_messageField refreshHeight];
|
||||||
LinphoneAddress *peerAddr = linphone_core_create_address([LinphoneManager getLc], _peerAddress);
|
LinphoneAddress *peerAddr = linphone_core_create_address([LinphoneManager getLc], _peerAddress);
|
||||||
if (peerAddr) {
|
LinphoneAddress *localAddr = linphone_core_create_address([LinphoneManager getLc], _localAddress);
|
||||||
_chatRoom = linphone_core_get_chat_room([LinphoneManager getLc], peerAddr);
|
if (peerAddr && localAddr) {
|
||||||
isOneToOne = linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesOneToOne;
|
_chatRoom = linphone_core_search_chat_room([LinphoneManager getLc], NULL, localAddr, peerAddr, NULL);
|
||||||
isEncrypted = linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesEncrypted;
|
if (_chatRoom) {
|
||||||
|
isOneToOne = linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesOneToOne;
|
||||||
|
isEncrypted = linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesEncrypted;
|
||||||
|
[self setComposingVisible:!composingVisible withDelay:0];
|
||||||
|
[self configureForRoom:true];
|
||||||
|
[_tableController scrollToBottom:true];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
[self configureForRoom:true];
|
|
||||||
_backButton.hidden = _tableController.isEditing;
|
|
||||||
[_tableController scrollToBottom:true];
|
|
||||||
[self refreshImageDrawer];
|
|
||||||
[self stopAllPlays];
|
|
||||||
|
|
||||||
|
_backButton.hidden = _tableController.isEditing;
|
||||||
|
[self refreshImageDrawer];
|
||||||
|
[self stopAllPlays];
|
||||||
|
[self keyboardWillHide:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
- (void)applicationWillEnterBackground{
|
- (void)applicationDidEnterBackground{
|
||||||
if (!_preservePendingActions)
|
if (!_preservePendingActions)
|
||||||
[self cancelVoiceRecording];
|
[self cancelVoiceRecording];
|
||||||
else if (_isVoiceRecording)
|
else if (_isVoiceRecording)
|
||||||
|
|
@ -351,9 +365,18 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
if (!_preservePendingActions)
|
if (!_preservePendingActions)
|
||||||
[self closePendingReply];
|
[self closePendingReply];
|
||||||
[self stopAllPlays];
|
[self stopAllPlays];
|
||||||
|
_chatRoom = nil;
|
||||||
|
[_messageField resignFirstResponder];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillEnterForeground{
|
||||||
|
if (_chatRoom == nil) {
|
||||||
|
if (linphone_core_get_calls_nb(LC) == 0)
|
||||||
|
[SVProgressHUD show];
|
||||||
|
else
|
||||||
|
[self onLinphoneCoreReady:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)configureForRoom:(BOOL)editing {
|
- (void)configureForRoom:(BOOL)editing {
|
||||||
if (!_chatRoom) {
|
if (!_chatRoom) {
|
||||||
|
|
@ -426,7 +449,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
if (!room)
|
if (!room)
|
||||||
return true;
|
return true;
|
||||||
LinphoneChatRoomCapabilitiesMask capabilities = linphone_chat_room_get_capabilities(room);
|
LinphoneChatRoomCapabilitiesMask capabilities = linphone_chat_room_get_capabilities(room);
|
||||||
return capabilities & LinphoneChatRoomCapabilitiesBasic;
|
return capabilities & LinphoneChatRoomCapabilitiesEncrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -466,7 +489,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
//file shared from photo lib
|
//file shared from photo lib
|
||||||
NSString *fileName = dict[@"url"];
|
NSString *fileName = dict[@"url"];
|
||||||
[_messageField setText:dict[@"message"]];
|
[_messageField setText:dict[@"message"]];
|
||||||
[self confirmShare:[self nsDataRead] url:nil fileName:fileName];
|
[self confirmShare:[self nsDataRead] url:nil fileName:fileName];
|
||||||
[defaults removeObjectForKey:@"photoData"];
|
[defaults removeObjectForKey:@"photoData"];
|
||||||
} else if (dictFile) {
|
} else if (dictFile) {
|
||||||
NSString *fileName = dictFile[@"url"];
|
NSString *fileName = dictFile[@"url"];
|
||||||
|
|
@ -483,23 +506,26 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
// reload the chatroom after the core starts
|
// reload the chatroom after the core starts
|
||||||
- (void)onLinphoneCoreReady:(NSNotification *)notif {
|
- (void)onLinphoneCoreReady:(NSNotification *)notif {
|
||||||
if ((LinphoneGlobalState)[[[notif userInfo] valueForKey:@"state"] integerValue] == LinphoneGlobalOn) {
|
if (linphone_core_get_global_state(LC) == LinphoneGlobalOn) {
|
||||||
LinphoneAddress *peerAddr = linphone_core_create_address([LinphoneManager getLc], _peerAddress);
|
LinphoneAddress *peerAddr = linphone_core_create_address([LinphoneManager getLc], _peerAddress);
|
||||||
if (peerAddr) {
|
LinphoneAddress *localAddr = linphone_core_create_address([LinphoneManager getLc], _localAddress);
|
||||||
_chatRoom = linphone_core_get_chat_room([LinphoneManager getLc], peerAddr);
|
if (peerAddr && localAddr) {
|
||||||
isOneToOne = linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesOneToOne;
|
_chatRoom = linphone_core_search_chat_room([LinphoneManager getLc], NULL, localAddr, peerAddr, NULL);
|
||||||
isEncrypted = linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesEncrypted;
|
if (_chatRoom) {
|
||||||
}
|
isOneToOne = linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesOneToOne;
|
||||||
[self configureForRoom:self.editing];
|
isEncrypted = linphone_chat_room_get_capabilities(_chatRoom) & LinphoneChatRoomCapabilitiesEncrypted;
|
||||||
if (_chatRoom && _markAsRead) {
|
[self configureForRoom:self.editing];
|
||||||
if (IPAD) {
|
if (_chatRoom && _markAsRead) {
|
||||||
[VIEW(ChatsListView).tableController loadData];
|
if (IPAD) {
|
||||||
|
[VIEW(ChatsListView).tableController loadData];
|
||||||
|
}
|
||||||
|
[ChatConversationView markAsRead:_chatRoom];
|
||||||
|
}
|
||||||
|
_markAsRead = TRUE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
[ChatConversationView markAsRead:_chatRoom];
|
[SVProgressHUD dismiss];
|
||||||
}
|
}
|
||||||
_markAsRead = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)callUpdateEvent:(NSNotification *)notif {
|
- (void)callUpdateEvent:(NSNotification *)notif {
|
||||||
|
|
@ -598,9 +624,9 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)confirmShare:(NSData *)data url:(NSString *)url fileName:(NSString *)fileName {
|
- (void)confirmShare:(NSData *)data url:(NSString *)url fileName:(NSString *)fileName {
|
||||||
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:@""];
|
DTActionSheet *sheet = [[DTActionSheet alloc] initWithTitle:NSLocalizedString(@"Select or create a conversation to share the file(s)", nil)];
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[sheet addButtonWithTitle:NSLocalizedString(@"send to this conversation", nil)
|
[sheet addButtonWithTitle:NSLocalizedString(@"Send to this conversation", nil)
|
||||||
block:^() {
|
block:^() {
|
||||||
if (![[self.messageField text] isEqualToString:@""]) {
|
if (![[self.messageField text] isEqualToString:@""]) {
|
||||||
[self sendMessageInMessageField:linphone_chat_room_create_empty_message(_chatRoom)];
|
[self sendMessageInMessageField:linphone_chat_room_create_empty_message(_chatRoom)];
|
||||||
|
|
@ -657,6 +683,11 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
completion:^(BOOL finished) {
|
completion:^(BOOL finished) {
|
||||||
_composeIndicatorView.hidden = !visible;
|
_composeIndicatorView.hidden = !visible;
|
||||||
}];
|
}];
|
||||||
|
if (visible) {
|
||||||
|
if (_tableController.tableView.contentOffset.y + newComposingFrame.size.height >= (_tableController.tableView.contentSize.height - _tableController.tableView.frame.size.height - 1)) {
|
||||||
|
[_tableController scrollToBottom:TRUE];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) groupCallAvailable {
|
- (BOOL) groupCallAvailable {
|
||||||
|
|
@ -771,9 +802,9 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
// if we're showing the compose message, update it position
|
// if we're showing the compose message, update it position
|
||||||
if (![_composeLabel isHidden]) {
|
if (![_composeLabel isHidden]) {
|
||||||
CGRect frame = [_composeLabel frame];
|
CGRect frame = [_composeIndicatorView frame];
|
||||||
frame.origin.y -= diff;
|
frame.origin.y -= diff;
|
||||||
[_composeLabel setFrame:frame];
|
[_composeIndicatorView setFrame:frame];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -781,7 +812,15 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
#pragma mark - Action Functions
|
#pragma mark - Action Functions
|
||||||
|
|
||||||
- (IBAction)onBackClick:(id)event {
|
- (IBAction)onBackClick:(id)event {
|
||||||
[PhoneMainView.instance popCurrentView];
|
NSString *previousViewName = [PhoneMainView.instance getPreviousViewName];
|
||||||
|
_sharingMedia = nil;
|
||||||
|
if ([previousViewName isEqualToString:@"ContactDetailsView"]) {
|
||||||
|
ContactDetailsView *view = VIEW(ContactDetailsView);
|
||||||
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
|
} else {
|
||||||
|
ChatsListView *view = VIEW(ChatsListView);
|
||||||
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onEditClick:(id)event {
|
- (IBAction)onEditClick:(id)event {
|
||||||
|
|
@ -937,6 +976,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
view.oldSubject = [NSString stringWithUTF8String:linphone_chat_room_get_subject(_chatRoom) ?: LINPHONE_DUMMY_SUBJECT];
|
view.oldSubject = [NSString stringWithUTF8String:linphone_chat_room_get_subject(_chatRoom) ?: LINPHONE_DUMMY_SUBJECT];
|
||||||
view.room = _chatRoom;
|
view.room = _chatRoom;
|
||||||
view.peerAddress = _peerAddress;
|
view.peerAddress = _peerAddress;
|
||||||
|
view.localAddress = _localAddress;
|
||||||
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1415,12 +1455,11 @@ void on_chat_room_chat_message_received(LinphoneChatRoom *cr, const LinphoneEven
|
||||||
|
|
||||||
bool isDisplayingBottomOfTable = [view.tableController.tableView indexPathsForVisibleRows].lastObject.row == [view.tableController totalNumberOfItems] - 1;
|
bool isDisplayingBottomOfTable = [view.tableController.tableView indexPathsForVisibleRows].lastObject.row == [view.tableController totalNumberOfItems] - 1;
|
||||||
[view.tableController addEventEntry:(LinphoneEventLog *)event_log];
|
[view.tableController addEventEntry:(LinphoneEventLog *)event_log];
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];
|
|
||||||
|
|
||||||
|
|
||||||
if (isDisplayingBottomOfTable) {
|
if (isDisplayingBottomOfTable) {
|
||||||
[view.tableController scrollToBottom:TRUE];
|
[view.tableController scrollToBottom:TRUE];
|
||||||
} else {
|
} else {
|
||||||
|
[[view.tableController scrollBadge] setHidden:FALSE];
|
||||||
int unread_msg = linphone_chat_room_get_unread_messages_count(cr);
|
int unread_msg = linphone_chat_room_get_unread_messages_count(cr);
|
||||||
[[view.tableController scrollBadge] setText:[NSString stringWithFormat:@"%d", unread_msg]];
|
[[view.tableController scrollBadge] setText:[NSString stringWithFormat:@"%d", unread_msg]];
|
||||||
}
|
}
|
||||||
|
|
@ -1721,13 +1760,6 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL) isConversationMuted {
|
|
||||||
return FALSE; // TODO
|
|
||||||
}
|
|
||||||
-(void) toggleMuteConversation {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void) showAddressAndIdentityPopup {
|
-(void) showAddressAndIdentityPopup {
|
||||||
|
|
||||||
char *localAddress = linphone_address_as_string(linphone_chat_room_get_local_address(_chatRoom));
|
char *localAddress = linphone_address_as_string(linphone_chat_room_get_local_address(_chatRoom));
|
||||||
|
|
@ -1754,8 +1786,7 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL) canAdminEphemeral:(const LinphoneChatRoom *)cr {
|
-(BOOL) canAdminEphemeral:(const LinphoneChatRoom *)cr {
|
||||||
if (!cr) return FALSE;
|
if (!cr || !isEncrypted) return FALSE;
|
||||||
if ([ChatConversationView isBasicChatRoom:_chatRoom]) return FALSE;
|
|
||||||
|
|
||||||
// If ephemeral mode is DeviceManaged, then we don't need to check anything else
|
// If ephemeral mode is DeviceManaged, then we don't need to check anything else
|
||||||
return (linphone_chat_room_params_get_ephemeral_mode(linphone_chat_room_get_current_params(cr)) == LinphoneChatRoomEphemeralModeDeviceManaged)
|
return (linphone_chat_room_params_get_ephemeral_mode(linphone_chat_room_get_current_params(cr)) == LinphoneChatRoomEphemeralModeDeviceManaged)
|
||||||
|
|
@ -1773,42 +1804,57 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
||||||
_popupMenu.layer.masksToBounds = false;
|
_popupMenu.layer.masksToBounds = false;
|
||||||
_toggleMenuButton.hidden = false;
|
_toggleMenuButton.hidden = false;
|
||||||
_popupMenu.tableFooterView = [UIView new];
|
_popupMenu.tableFooterView = [UIView new];
|
||||||
|
_popupMenu.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||||
[_popupMenu reloadData];
|
[_popupMenu reloadData];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
[self onToggleMenu:nil];
|
[self onToggleMenu:nil];
|
||||||
BOOL isEncrypted = ![ChatConversationView isBasicChatRoom:_chatRoom];
|
|
||||||
|
|
||||||
if (indexPath.row == 0) {
|
int firstIndex = isOneToOne ? 0 : 1;
|
||||||
|
|
||||||
|
if (!isOneToOne && indexPath.row == 0) { //Schedule meeting
|
||||||
|
[ConferenceViewModelBridge scheduleFromGroupChatWithCChatRoom:_chatRoom];
|
||||||
|
[PhoneMainView.instance popToView:ConferenceSchedulingView.compositeViewDescription];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexPath.row == firstIndex) {
|
||||||
if (isOneToOne) {
|
if (isOneToOne) {
|
||||||
[self addOrGoToContact:linphone_chat_room_get_peer_address(_chatRoom)];
|
if (isEncrypted) {
|
||||||
|
LinphoneAddress* contactAddress = linphone_address_clone(linphone_participant_get_address(bctbx_list_nth_data(linphone_chat_room_get_participants(_chatRoom), 0)));
|
||||||
|
linphone_address_clean(contactAddress);
|
||||||
|
[self addOrGoToContact:contactAddress];
|
||||||
|
linphone_address_unref(contactAddress);
|
||||||
|
} else {
|
||||||
|
[self addOrGoToContact:linphone_chat_room_get_peer_address(_chatRoom)];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
[self displayGroupInfo];
|
[self displayGroupInfo];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEncrypted && indexPath.row == 1) {
|
if (isEncrypted && indexPath.row == 1+firstIndex) {
|
||||||
[self goToDeviceListView];
|
[self goToDeviceListView];
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL canEphemeral = [self canAdminEphemeral:_chatRoom];
|
BOOL canEphemeral = [self canAdminEphemeral:_chatRoom];
|
||||||
if (canEphemeral && indexPath.row == 2) {
|
if (canEphemeral && indexPath.row == 2+firstIndex) {
|
||||||
EphemeralSettingsView *view = VIEW(EphemeralSettingsView);
|
EphemeralSettingsView *view = VIEW(EphemeralSettingsView);
|
||||||
view.room = _chatRoom;
|
view.room = _chatRoom;
|
||||||
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
if ((!isEncrypted && indexPath.row == 1) || (isEncrypted && indexPath.row == 3)) {
|
if ((!isEncrypted && indexPath.row == 1+firstIndex) || (isEncrypted && indexPath.row == 3+firstIndex)) {
|
||||||
[self toggleMuteConversation];
|
[LinphoneManager setChatroomPushEnabled:_chatRoom withPushEnabled:![LinphoneManager getChatroomPushEnabled:_chatRoom]];
|
||||||
|
[_popupMenu reloadData];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!isEncrypted && indexPath.row == 2) || (isEncrypted && indexPath.row == 4)) {
|
if ((!isEncrypted && indexPath.row == 2+firstIndex) || (isEncrypted && indexPath.row == 4+firstIndex)) {
|
||||||
[_tableController onEditClick:nil];
|
[_tableController onEditClick:nil];
|
||||||
[self onEditionChangeClick:nil];
|
[self onEditionChangeClick:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isEncrypted && ((!canEphemeral && indexPath.row == 4)||(canEphemeral && indexPath.row == 5)))
|
if ((isEncrypted && ((!canEphemeral && indexPath.row == 4+firstIndex)||(canEphemeral && indexPath.row == 5+firstIndex)))
|
||||||
|| (!isEncrypted && indexPath.row == 3)) {
|
|| (!isEncrypted && indexPath.row == 3+firstIndex)) {
|
||||||
[self showAddressAndIdentityPopup];
|
[self showAddressAndIdentityPopup];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1831,61 +1877,89 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
||||||
if ([self canAdminEphemeral:_chatRoom])
|
if ([self canAdminEphemeral:_chatRoom])
|
||||||
++nbRows;
|
++nbRows;
|
||||||
|
|
||||||
|
if (!isOneToOne) // schedule meeting
|
||||||
|
++nbRows;
|
||||||
|
|
||||||
return nbRows;
|
return nbRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
UITableViewCell *cell = [[UITableViewCell alloc] init];
|
UITableViewCell *cell = [[UITableViewCell alloc] init];
|
||||||
|
|
||||||
if (indexPath.row == 0) {
|
if (!_chatRoom) {
|
||||||
|
// Workaround to avoid crash in background for release 4.7. This shouldn't happen though, so there may be a deeper issue not found yet
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
int firstIndex = isOneToOne ? 0 : 1;
|
||||||
|
|
||||||
|
if (!isOneToOne && indexPath.row == 0) {
|
||||||
|
cell.imageView.image = [UIImage imageNamed:@"menu_voip_meeting_schedule"];
|
||||||
|
cell.textLabel.text = NSLocalizedString(@"Schedule a meeting",nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexPath.row == firstIndex) {
|
||||||
if (isOneToOne) {
|
if (isOneToOne) {
|
||||||
Contact *contact = [FastAddressBook getContactWithAddress:linphone_chat_room_get_peer_address(_chatRoom)];
|
Contact *contact;
|
||||||
|
if (isEncrypted) {
|
||||||
|
LinphoneAddress * contactAddress = linphone_address_clone(linphone_participant_get_address(bctbx_list_nth_data(linphone_chat_room_get_participants(_chatRoom), 0)));
|
||||||
|
linphone_address_clean(contactAddress);
|
||||||
|
contact = [FastAddressBook getContactWithAddress:contactAddress];
|
||||||
|
linphone_address_unref(contactAddress);
|
||||||
|
} else {
|
||||||
|
contact = [FastAddressBook getContactWithAddress:linphone_chat_room_get_peer_address(_chatRoom)];
|
||||||
|
}
|
||||||
if (contact == nil) {
|
if (contact == nil) {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"contact_add_default.png"] newSize:CGSizeMake(20, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"contact_add_default.png"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"Add to contacts",nil);
|
cell.textLabel.text = NSLocalizedString(@"Add to contacts",nil);
|
||||||
} else {
|
} else {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"contacts_all_default.png"] newSize:CGSizeMake(20, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"contacts_all_default.png"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"Go to contact",nil);
|
cell.textLabel.text = NSLocalizedString(@"Go to contact",nil);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"chat_group_informations.png"] newSize:CGSizeMake(25, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"chat_group_informations.png"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"Group infos",nil);
|
cell.textLabel.text = NSLocalizedString(@"Group infos",nil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEncrypted && indexPath.row == 1) {
|
if (isEncrypted && indexPath.row == 1+firstIndex) {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"menu_security_default.png"] newSize:CGSizeMake(20, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"menu_security_default.png"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"Conversation's devices",nil);
|
cell.textLabel.text = NSLocalizedString(@"Conversation's devices",nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canEphemeral = [self canAdminEphemeral:_chatRoom];
|
bool canEphemeral = [self canAdminEphemeral:_chatRoom];
|
||||||
if (canEphemeral && indexPath.row == 2) {
|
if (canEphemeral && indexPath.row == 2+firstIndex) {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"ephemeral_messages_default.png"] newSize:CGSizeMake(20, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"ephemeral_messages_default.png"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"Ephemeral messages",nil);
|
cell.textLabel.text = NSLocalizedString(@"Ephemeral messages",nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isEncrypted && indexPath.row == 3) || (!isEncrypted && indexPath.row == 1)) {
|
if ((isEncrypted && indexPath.row == 3+firstIndex) || (!isEncrypted && indexPath.row == 1+firstIndex)) {
|
||||||
if ([self isConversationMuted]) {
|
if ([LinphoneManager getChatroomPushEnabled:_chatRoom]) {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"menu_notifications_off.png"] newSize:CGSizeMake(20, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"menu_notifications_off.png"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"NOT IMPLEMENTED",nil);
|
cell.textLabel.text = NSLocalizedString(@"Mute notifications",nil);
|
||||||
} else {
|
} else {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"menu_notifications_on.png"] newSize:CGSizeMake(20, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"menu_notifications_on.png"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"NOT IMPLEMENTED",nil);
|
cell.textLabel.text = NSLocalizedString(@"Un-mute notifications",nil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isEncrypted && indexPath.row == 4) || (!isEncrypted && indexPath.row == 2)) {
|
if ((isEncrypted && indexPath.row == 4+firstIndex) || (!isEncrypted && indexPath.row == 2+firstIndex)) {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"delete_default.png"] newSize:CGSizeMake(20, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"delete_default.png"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"Delete messages",nil);
|
cell.textLabel.text = NSLocalizedString(@"Delete messages",nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isEncrypted && ((!canEphemeral && indexPath.row == 4)||(canEphemeral && indexPath.row == 5)))
|
if ((isEncrypted && ((!canEphemeral && indexPath.row == 4+firstIndex)||(canEphemeral && indexPath.row == 5+firstIndex)))
|
||||||
|| (!isEncrypted && indexPath.row == 3)) {
|
|| (!isEncrypted && indexPath.row == 3+firstIndex)) {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"chat_group_informations.png"] newSize:CGSizeMake(25, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"chat_group_informations.png"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"Show address and identity",nil);
|
cell.textLabel.text = NSLocalizedString(@"Debug infos",nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
|
UIImageView * icon = [[UIImageView alloc] initWithFrame:CGRectMake(tableView.frame.size.width-37, 7, 30, 30)];
|
||||||
|
icon.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
|
icon.image = cell.imageView.image;
|
||||||
|
[cell.contentView addSubview:icon];
|
||||||
|
cell.imageView.image = nil;
|
||||||
|
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
- (IBAction)onToggleMenu:(id)sender {
|
- (IBAction)onToggleMenu:(id)sender {
|
||||||
|
|
@ -2194,6 +2268,7 @@ void on_shared_player_eof_reached(LinphonePlayer *p) {
|
||||||
_showReplyView = true;
|
_showReplyView = true;
|
||||||
[self updateFramesInclRecordingAndReplyView];
|
[self updateFramesInclRecordingAndReplyView];
|
||||||
[self.tableController scrollToMessage:message];
|
[self.tableController scrollToMessage:message];
|
||||||
|
[self.messageField becomeFirstResponder];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) handlePendingTransferIfAny {
|
-(void) handlePendingTransferIfAny {
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
|
||||||
[LinphoneManager.instance lpConfigSetBool:FALSE forKey:@"create_chat"];
|
[LinphoneManager.instance lpConfigSetBool:FALSE forKey:@"create_chat"];
|
||||||
} else if (![self selectFirstRow]) {
|
} else if (![self selectFirstRow]) {
|
||||||
ChatConversationCreateView *view = VIEW(ChatConversationCreateView);
|
ChatConversationCreateView *view = VIEW(ChatConversationCreateView);
|
||||||
|
[view fragmentCompositeDescription];
|
||||||
view.tableController.notFirstTime = FALSE;
|
view.tableController.notFirstTime = FALSE;
|
||||||
view.isForVoipConference = FALSE;
|
view.isForVoipConference = FALSE;
|
||||||
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
||||||
|
|
@ -190,7 +191,7 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
|
||||||
|
|
||||||
void deletion_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomState newState) {
|
void deletion_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomState newState) {
|
||||||
LinphoneChatRoomCbs *cbs = linphone_chat_room_get_current_callbacks(cr);
|
LinphoneChatRoomCbs *cbs = linphone_chat_room_get_current_callbacks(cr);
|
||||||
ChatsListTableView *view = (__bridge ChatsListTableView *)linphone_chat_room_cbs_get_user_data(cbs) ?: NULL;
|
ChatsListTableView *view =cbs ? ((__bridge ChatsListTableView *)linphone_chat_room_cbs_get_user_data(cbs) ?: NULL) : NULL;
|
||||||
if (!view)
|
if (!view)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -231,7 +232,9 @@ void deletion_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomStat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[ftdToDelete cancel];
|
[ftdToDelete cancel];
|
||||||
|
|
||||||
|
// Re-enable push notification after deleting the chatroom, in order to get the notification if we are re-invited, or for secure 1-to-1 chatrooms.
|
||||||
|
[LinphoneManager setChatroomPushEnabled:chatRoom withPushEnabled:TRUE];
|
||||||
linphone_core_delete_chat_room(LC, chatRoom);
|
linphone_core_delete_chat_room(LC, chatRoom);
|
||||||
chatRooms = chatRooms->next;
|
chatRooms = chatRooms->next;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,4 +43,6 @@
|
||||||
- (IBAction)onEditionChangeClick:(id)sender;
|
- (IBAction)onEditionChangeClick:(id)sender;
|
||||||
- (IBAction)onDeleteClick:(id)sender;
|
- (IBAction)onDeleteClick:(id)sender;
|
||||||
|
|
||||||
|
-(void) mediaSharing;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,10 @@
|
||||||
selector:@selector(ephemeralDeleted:)
|
selector:@selector(ephemeralDeleted:)
|
||||||
name:kLinphoneEphemeralMessageDeletedInRoom
|
name:kLinphoneEphemeralMessageDeletedInRoom
|
||||||
object:nil];
|
object:nil];
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector:@selector(displayModeChanged)
|
||||||
|
name:kDisplayModeChanged
|
||||||
|
object:nil];
|
||||||
[_backToCallButton update];
|
[_backToCallButton update];
|
||||||
self.tableController.waitView = _waitView;
|
self.tableController.waitView = _waitView;
|
||||||
[self setEditing:NO];
|
[self setEditing:NO];
|
||||||
|
|
@ -54,20 +58,43 @@
|
||||||
forControlEvents:UIControlEventTouchUpInside];
|
forControlEvents:UIControlEventTouchUpInside];
|
||||||
[self.view addSubview:button];*/
|
[self.view addSubview:button];*/
|
||||||
|
|
||||||
BOOL forwardMode = VIEW(ChatConversationView).pendingForwardMessage != nil;
|
[self mediaSharing];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mediaSharing{
|
||||||
|
BOOL forwardMode;
|
||||||
|
|
||||||
|
NSString* groupName = [NSString stringWithFormat:@"group.%@.linphoneExtension",[[NSBundle mainBundle] bundleIdentifier]];
|
||||||
|
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:groupName];
|
||||||
|
NSDictionary *dict = [defaults valueForKey:@"photoData"];
|
||||||
|
NSDictionary *dictFile = [defaults valueForKey:@"icloudData"];
|
||||||
|
NSDictionary *dictUrl = [defaults valueForKey:@"url"];
|
||||||
|
if(dict||dictFile||dictUrl) VIEW(ChatConversationView).sharingMedia = TRUE;
|
||||||
|
|
||||||
|
if(VIEW(ChatConversationView).sharingMedia == nil){
|
||||||
|
forwardMode = VIEW(ChatConversationView).pendingForwardMessage != nil;
|
||||||
|
}else{
|
||||||
|
forwardMode = VIEW(ChatConversationView).sharingMedia != nil;
|
||||||
|
}
|
||||||
_tableController.editButton.hidden = forwardMode;
|
_tableController.editButton.hidden = forwardMode;
|
||||||
_forwardTitle.text = NSLocalizedString(@"Select a discussion or create a new one",nil);
|
if(VIEW(ChatConversationView).sharingMedia == nil){
|
||||||
|
_forwardTitle.text = NSLocalizedString(@"Select a discussion or create a new one",nil);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
_forwardTitle.text = NSLocalizedString(@"Select or create a conversation to share the file(s)",nil);
|
||||||
|
}
|
||||||
_forwardTitle.hidden = !forwardMode;
|
_forwardTitle.hidden = !forwardMode;
|
||||||
_cancelForwardButton.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 ));
|
_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);
|
_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);
|
_addGroupChatButton.frame = CGRectMake(forwardMode ? 164 : 82 , _addGroupChatButton.frame.origin.y, _addGroupChatButton.frame.size.width, _addGroupChatButton.frame.size.height);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)displayModeChanged{
|
||||||
|
[self.tableController.tableView reloadData];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)ephemeralDeleted:(NSNotification *)notif {
|
- (void)ephemeralDeleted:(NSNotification *)notif {
|
||||||
//LinphoneChatRoom *r =[[notif.userInfo objectForKey:@"room"] intValue];
|
//LinphoneChatRoom *r =[[notif.userInfo objectForKey:@"room"] intValue];
|
||||||
|
|
@ -117,6 +144,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
- (void)newChatCreate:(BOOL)isGroup {
|
- (void)newChatCreate:(BOOL)isGroup {
|
||||||
ChatConversationCreateView *view = VIEW(ChatConversationCreateView);
|
ChatConversationCreateView *view = VIEW(ChatConversationCreateView);
|
||||||
|
[view fragmentCompositeDescription];
|
||||||
view.isForEditing = false;
|
view.isForEditing = false;
|
||||||
view.isGroupChat = isGroup;
|
view.isGroupChat = isGroup;
|
||||||
view.tableController.notFirstTime = FALSE;
|
view.tableController.notFirstTime = FALSE;
|
||||||
|
|
@ -172,8 +200,16 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onCancelForwardClicked:(id)sender {
|
- (IBAction)onCancelForwardClicked:(id)sender {
|
||||||
|
VIEW(ChatConversationView).sharingMedia = nil;
|
||||||
VIEW(ChatConversationView).pendingForwardMessage = nil;
|
VIEW(ChatConversationView).pendingForwardMessage = nil;
|
||||||
|
NSString* groupName = [NSString stringWithFormat:@"group.%@.linphoneExtension",[[NSBundle mainBundle] bundleIdentifier]];
|
||||||
|
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:groupName];
|
||||||
|
[defaults removeObjectForKey:@"photoData"];
|
||||||
|
[defaults removeObjectForKey:@"icloudData"];
|
||||||
|
[defaults removeObjectForKey:@"url"];
|
||||||
[PhoneMainView.instance popCurrentView];
|
[PhoneMainView.instance popCurrentView];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
@property(nonatomic, strong) NSMutableArray *sipAddresses;
|
@property(nonatomic, strong) NSMutableArray *sipAddresses;
|
||||||
@property(nonatomic, strong) NSMutableArray *emails;
|
@property(nonatomic, strong) NSMutableArray *emails;
|
||||||
@property(nonatomic, strong) NSMutableArray *phones;
|
@property(nonatomic, strong) NSMutableArray *phones;
|
||||||
@property BOOL createdFromLdap;
|
@property BOOL createdFromLdapOrProvisioning;
|
||||||
@property BOOL added;
|
@property BOOL added;
|
||||||
|
|
||||||
- (void)setAvatar:(UIImage *)avatar;
|
- (void)setAvatar:(UIImage *)avatar;
|
||||||
|
|
@ -58,4 +58,6 @@
|
||||||
- (BOOL)removeSipAddressAtIndex:(NSInteger)index;
|
- (BOOL)removeSipAddressAtIndex:(NSInteger)index;
|
||||||
- (BOOL)removePhoneNumberAtIndex:(NSInteger)index;
|
- (BOOL)removePhoneNumberAtIndex:(NSInteger)index;
|
||||||
- (BOOL)removeEmailAtIndex:(NSInteger)index;
|
- (BOOL)removeEmailAtIndex:(NSInteger)index;
|
||||||
|
|
||||||
|
- (NSMutableArray*)getSipAddressesWithoutDuplicatePhoneNumbers;
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
_person = acncontact;
|
_person = acncontact;
|
||||||
_friend = afriend ? linphone_friend_ref(afriend) : NULL;
|
_friend = afriend ? linphone_friend_ref(afriend) : NULL;
|
||||||
_added = FALSE;
|
_added = FALSE;
|
||||||
_createdFromLdap = FALSE;
|
_createdFromLdapOrProvisioning = FALSE;
|
||||||
_phones = [[NSMutableArray alloc] init];
|
_phones = [[NSMutableArray alloc] init];
|
||||||
_sipAddresses = [[NSMutableArray alloc] init];
|
_sipAddresses = [[NSMutableArray alloc] init];
|
||||||
_emails = [[NSMutableArray alloc] init];
|
_emails = [[NSMutableArray alloc] init];
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
linphone_friend_set_ref_key(_friend, key);
|
linphone_friend_set_ref_key(_friend, key);
|
||||||
linphone_friend_set_name(_friend, [NSString stringWithFormat:@"%@%@", _firstName ? _firstName : @"", _lastName ? [_firstName ? @" " : @"" stringByAppendingString:_lastName] : @""] .UTF8String);
|
linphone_friend_set_name(_friend, [NSString stringWithFormat:@"%@%@", _firstName ? _firstName : @"", _lastName ? [_firstName ? @" " : @"" stringByAppendingString:_lastName] : @""] .UTF8String);
|
||||||
for (NSString *sipAddr in _sipAddresses) {
|
for (NSString *sipAddr in _sipAddresses) {
|
||||||
LinphoneAddress *addr = linphone_core_interpret_url(LC, sipAddr.UTF8String);
|
LinphoneAddress *addr = linphone_core_interpret_url_2(LC, sipAddr.UTF8String, true);
|
||||||
if (addr) {
|
if (addr) {
|
||||||
linphone_address_set_display_name(addr, [self displayName].UTF8String);
|
linphone_address_set_display_name(addr, [self displayName].UTF8String);
|
||||||
linphone_friend_add_address(_friend, addr);
|
linphone_friend_add_address(_friend, addr);
|
||||||
|
|
@ -287,7 +287,7 @@
|
||||||
[_person setValue:tmpSipAddresses forKey:CNContactInstantMessageAddressesKey];
|
[_person setValue:tmpSipAddresses forKey:CNContactInstantMessageAddressesKey];
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
} else {
|
} else {
|
||||||
LinphoneAddress *addr = linphone_core_interpret_url(LC, sip.UTF8String) ?: linphone_address_new(sip.UTF8String);
|
LinphoneAddress *addr = linphone_core_interpret_url_2(LC, sip.UTF8String, true) ?: linphone_address_new(sip.UTF8String);
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
@ -370,7 +370,7 @@
|
||||||
}
|
}
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
} else {
|
} else {
|
||||||
LinphoneAddress *addr = linphone_core_interpret_url(LC, ((NSString *)_sipAddresses[index]).UTF8String);
|
LinphoneAddress *addr = linphone_core_interpret_url_2(LC, ((NSString *)_sipAddresses[index]).UTF8String, true);
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
@ -465,7 +465,7 @@
|
||||||
linphone_friend_set_ref_key(_friend, key);
|
linphone_friend_set_ref_key(_friend, key);
|
||||||
linphone_friend_set_name(_friend, [NSString stringWithFormat:@"%@%@", _firstName ? _firstName : @"", _lastName ? [_firstName ? @" " : @"" stringByAppendingString:_lastName] : @""] .UTF8String);
|
linphone_friend_set_name(_friend, [NSString stringWithFormat:@"%@%@", _firstName ? _firstName : @"", _lastName ? [_firstName ? @" " : @"" stringByAppendingString:_lastName] : @""] .UTF8String);
|
||||||
for (NSString *sipAddr in _sipAddresses) {
|
for (NSString *sipAddr in _sipAddresses) {
|
||||||
LinphoneAddress *addr = linphone_core_interpret_url(LC, sipAddr.UTF8String);
|
LinphoneAddress *addr = linphone_core_interpret_url_2(LC, sipAddr.UTF8String, true);
|
||||||
if (addr) {
|
if (addr) {
|
||||||
linphone_address_set_display_name(addr, [self displayName].UTF8String);
|
linphone_address_set_display_name(addr, [self displayName].UTF8String);
|
||||||
linphone_friend_add_address(_friend, addr);
|
linphone_friend_add_address(_friend, addr);
|
||||||
|
|
@ -488,4 +488,23 @@
|
||||||
_friend = NULL;
|
_friend = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSMutableArray*)getSipAddressesWithoutDuplicatePhoneNumbers {
|
||||||
|
NSMutableArray* resAdresses = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
for (NSString *address in _sipAddresses) {
|
||||||
|
LinphoneAddress *addr = linphone_core_interpret_url_2(LC, [address UTF8String], YES);
|
||||||
|
bool isFoundInPhones = false;
|
||||||
|
if (addr && linphone_address_get_username(addr)) {
|
||||||
|
for (NSString *phoneNb in _phones) {
|
||||||
|
if ([phoneNb isEqualToString:[NSString stringWithUTF8String:linphone_address_get_username(addr)]]) {
|
||||||
|
isFoundInPhones = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isFoundInPhones) [resAdresses addObject:address];
|
||||||
|
}
|
||||||
|
|
||||||
|
return resAdresses;
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -160,15 +160,15 @@
|
||||||
/*first and last name only when editting */
|
/*first and last name only when editting */
|
||||||
return (self.tableView.isEditing) ? 1 : 0;
|
return (self.tableView.isEditing) ? 1 : 0;
|
||||||
} else if (section == ContactSections_Sip) {
|
} else if (section == ContactSections_Sip) {
|
||||||
return _contact.createdFromLdap ? 0 : _contact.sipAddresses.count;
|
return [_contact getSipAddressesWithoutDuplicatePhoneNumbers].count;
|
||||||
} else if (section == ContactSections_Number) {
|
} else if (section == ContactSections_Number) {
|
||||||
return _contact.phones.count;
|
return _contact.phones.count;
|
||||||
} else if (section == ContactSections_Email) {
|
} else if (section == ContactSections_Email) {
|
||||||
BOOL showEmails = [LinphoneManager.instance
|
BOOL showEmails = [LinphoneManager.instance
|
||||||
lpConfigBoolForKey:@"show_contacts_emails_preference"];
|
lpConfigBoolForKey:@"show_contacts_emails_preference"];
|
||||||
return showEmails ? _contact.emails.count : 0;
|
return showEmails ? _contact.emails.count : 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
|
|
@ -200,7 +200,7 @@
|
||||||
LinphoneAddress *addr = NULL;
|
LinphoneAddress *addr = NULL;
|
||||||
if ([LinphoneManager.instance
|
if ([LinphoneManager.instance
|
||||||
lpConfigBoolForKey:@"contact_display_username_only"] &&
|
lpConfigBoolForKey:@"contact_display_username_only"] &&
|
||||||
(addr = linphone_core_interpret_url(LC, [value UTF8String]))) {
|
(addr = linphone_core_interpret_url_2(LC, [value UTF8String], YES))) {
|
||||||
value =
|
value =
|
||||||
[NSString stringWithCString:linphone_address_get_username(addr)
|
[NSString stringWithCString:linphone_address_get_username(addr)
|
||||||
encoding:[NSString defaultCStringEncoding]];
|
encoding:[NSString defaultCStringEncoding]];
|
||||||
|
|
@ -283,7 +283,7 @@
|
||||||
if (section == ContactSections_Number) {
|
if (section == ContactSections_Number) {
|
||||||
text = NSLocalizedString(@"Phone numbers", nil);
|
text = NSLocalizedString(@"Phone numbers", nil);
|
||||||
addEntryName = NSLocalizedString(@"Add new phone number", nil);
|
addEntryName = NSLocalizedString(@"Add new phone number", nil);
|
||||||
} else if (section == ContactSections_Sip && !_contact.createdFromLdap) {
|
} else if (section == ContactSections_Sip && !_contact.createdFromLdapOrProvisioning) {
|
||||||
text = NSLocalizedString(@"SIP addresses", nil);
|
text = NSLocalizedString(@"SIP addresses", nil);
|
||||||
addEntryName = NSLocalizedString(@"Add new SIP address", nil);
|
addEntryName = NSLocalizedString(@"Add new SIP address", nil);
|
||||||
} else if (section == ContactSections_Email &&
|
} else if (section == ContactSections_Email &&
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
for (NSString *sipAddr in _contact.sipAddresses) {
|
for (NSString *sipAddr in _contact.sipAddresses) {
|
||||||
LinphoneAddress *addr = linphone_core_interpret_url(LC, sipAddr.UTF8String);
|
LinphoneAddress *addr = linphone_core_interpret_url_2(LC, sipAddr.UTF8String, true);
|
||||||
if (addr) {
|
if (addr) {
|
||||||
linphone_friend_add_address(_contact.friend, addr);
|
linphone_friend_add_address(_contact.friend, addr);
|
||||||
linphone_address_destroy(addr);
|
linphone_address_destroy(addr);
|
||||||
|
|
@ -119,8 +119,8 @@
|
||||||
_contact = acontact;
|
_contact = acontact;
|
||||||
_emptyLabel.hidden = (_contact != NULL);
|
_emptyLabel.hidden = (_contact != NULL);
|
||||||
_avatarImage.hidden = !_emptyLabel.hidden;
|
_avatarImage.hidden = !_emptyLabel.hidden;
|
||||||
_deleteButton.hidden = !_emptyLabel.hidden || [_contact createdFromLdap];
|
_deleteButton.hidden = !_emptyLabel.hidden || [_contact createdFromLdapOrProvisioning];
|
||||||
_editButton.hidden = !_emptyLabel.hidden || [_contact createdFromLdap];
|
_editButton.hidden = !_emptyLabel.hidden || [_contact createdFromLdapOrProvisioning];
|
||||||
|
|
||||||
[_avatarImage setImage:[FastAddressBook imageForContact:_contact] bordered:NO withRoundedRadius:YES];
|
[_avatarImage setImage:[FastAddressBook imageForContact:_contact] bordered:NO withRoundedRadius:YES];
|
||||||
[ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
|
[ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
|
||||||
|
|
@ -146,7 +146,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addCurrentContactContactField:(NSString *)address {
|
- (void)addCurrentContactContactField:(NSString *)address {
|
||||||
LinphoneAddress *linphoneAddress = linphone_core_interpret_url(LC, address.UTF8String);
|
LinphoneAddress *linphoneAddress = linphone_core_interpret_url_2(LC, address.UTF8String, true);
|
||||||
NSString *username =
|
NSString *username =
|
||||||
linphoneAddress ? [NSString stringWithUTF8String:linphone_address_get_username(linphoneAddress)] : address;
|
linphoneAddress ? [NSString stringWithUTF8String:linphone_address_get_username(linphoneAddress)] : address;
|
||||||
|
|
||||||
|
|
@ -284,6 +284,9 @@
|
||||||
if (IPAD && self.contact == NULL) {
|
if (IPAD && self.contact == NULL) {
|
||||||
_editButton.hidden = TRUE;
|
_editButton.hidden = TRUE;
|
||||||
_deleteButton.hidden = TRUE;
|
_deleteButton.hidden = TRUE;
|
||||||
|
} else if (self.contact != NULL && self.contact.createdFromLdapOrProvisioning) {
|
||||||
|
_editButton.hidden = TRUE;
|
||||||
|
_deleteButton.hidden = TRUE;
|
||||||
}
|
}
|
||||||
PhoneMainView.instance.currentName = _nameLabel.text;
|
PhoneMainView.instance.currentName = _nameLabel.text;
|
||||||
// Update presence for contact
|
// Update presence for contact
|
||||||
|
|
@ -296,6 +299,7 @@
|
||||||
[_editButton setImage:[UIImage imageNamed:@"valid_default.png"] forState:UIControlStateSelected];
|
[_editButton setImage:[UIImage imageNamed:@"valid_default.png"] forState:UIControlStateSelected];
|
||||||
|
|
||||||
[self updateBackOrCancelButton];
|
[self updateBackOrCancelButton];
|
||||||
|
[self recomputeTableViewSize:FALSE];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)deviceOrientationDidChange:(NSNotification*)notif {
|
- (void)deviceOrientationDidChange:(NSNotification*)notif {
|
||||||
|
|
@ -310,9 +314,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self.contact != NULL && self.contact.createdFromLdapOrProvisioning) {
|
||||||
|
_editButton.hidden = TRUE;
|
||||||
|
_deleteButton.hidden = TRUE;
|
||||||
|
}
|
||||||
|
_nameLabel.hidden = self.tableController.isEditing;
|
||||||
[self updateBackOrCancelButton];
|
[self updateBackOrCancelButton];
|
||||||
|
[self recomputeTableViewSize:self.tableController.isEditing];
|
||||||
[self recomputeTableViewSize:_editButton.hidden];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
|
@ -408,10 +416,11 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
- (void)recomputeTableViewSize:(BOOL)editing {
|
- (void)recomputeTableViewSize:(BOOL)editing {
|
||||||
CGRect frame = _tableController.tableView.frame;
|
CGRect frame = _tableController.tableView.frame;
|
||||||
frame.origin.y = _avatarImage.frame.size.height + _avatarImage.frame.origin.y;
|
|
||||||
if ([self viewIsCurrentlyPortrait] && !editing) {
|
if ([self viewIsCurrentlyPortrait] && !editing) {
|
||||||
frame.origin.y += _nameLabel.frame.size.height;
|
frame.origin.y = _nameLabel.frame.origin.y + _nameLabel.frame.size.height;
|
||||||
}
|
} else {
|
||||||
|
frame.origin.y = _avatarImage.frame.size.height + _avatarImage.frame.origin.y;
|
||||||
|
}
|
||||||
|
|
||||||
frame.size.height = _tableController.tableView.contentSize.height;
|
frame.size.height = _tableController.tableView.contentSize.height;
|
||||||
_tableController.tableView.frame = frame;
|
_tableController.tableView.frame = frame;
|
||||||
|
|
@ -514,11 +523,11 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* previous = [PhoneMainView.instance getPreviousViewName];
|
NSString* previous = [PhoneMainView.instance getPreviousViewName];
|
||||||
if ([previous isEqualToString:@"ContactsListView"] || [previous isEqualToString:@"ImagePickerView"]) {
|
if ([previous isEqualToString:@"HistoryDetailsView"]) {
|
||||||
ContactsListView *view = VIEW(ContactsListView);
|
HistoryDetailsView *view = VIEW(HistoryDetailsView);
|
||||||
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
} else {
|
} else {
|
||||||
HistoryDetailsView *view = VIEW(HistoryDetailsView);
|
ContactsListView *view = VIEW(ContactsListView);
|
||||||
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -588,7 +597,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
[[store unifiedContactWithIdentifier:contactToCheck.identifier keysToFetch:keysToFetch error:nil] mutableCopy];
|
[[store unifiedContactWithIdentifier:contactToCheck.identifier keysToFetch:keysToFetch error:nil] mutableCopy];
|
||||||
if(mCNContact == NULL){
|
if(mCNContact == NULL){
|
||||||
for(NSString *address in contactToCheck.sipAddresses){
|
for(NSString *address in contactToCheck.sipAddresses){
|
||||||
NSString *name = [FastAddressBook normalizeSipURI:address];
|
NSString *name = [FastAddressBook normalizeSipURI:address use_prefix:TRUE];
|
||||||
if([LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:name]){
|
if([LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:name]){
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ typedef enum _ContactSelectionMode { ContactSelectionModeNone, ContactSelectionM
|
||||||
@property (weak, nonatomic) IBOutlet UIInterfaceStyleButton *toggleSelectionButton;
|
@property (weak, nonatomic) IBOutlet UIInterfaceStyleButton *toggleSelectionButton;
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *loadingLabel;
|
@property (weak, nonatomic) IBOutlet UILabel *loadingLabel;
|
||||||
@property (weak, nonatomic) IBOutlet UIView *loadingView;
|
@property (weak, nonatomic) IBOutlet UIView *loadingView;
|
||||||
|
@property (weak, nonatomic) IBOutlet UILabel *ldapMoreResultsLabel;
|
||||||
|
|
||||||
- (IBAction)onAllClick:(id)event;
|
- (IBAction)onAllClick:(id)event;
|
||||||
- (IBAction)onLinphoneClick:(id)event;
|
- (IBAction)onLinphoneClick:(id)event;
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,15 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
selector:@selector(onMagicSearchFinished:)
|
selector:@selector(onMagicSearchFinished:)
|
||||||
name:kLinphoneMagicSearchFinished
|
name:kLinphoneMagicSearchFinished
|
||||||
object:nil];
|
object:nil];
|
||||||
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
addObserver:self
|
||||||
|
selector:@selector(onMagicSearchMoreAvailable:)
|
||||||
|
name:kLinphoneMagicSearchMoreAvailable
|
||||||
|
object:nil];
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector:@selector(displayModeChanged)
|
||||||
|
name:kDisplayModeChanged
|
||||||
|
object:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onMagicSearchStarted:(NSNotification *)k {
|
- (void)onMagicSearchStarted:(NSNotification *)k {
|
||||||
|
|
@ -150,6 +159,9 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
- (void)onMagicSearchFinished:(NSNotification *)k {
|
- (void)onMagicSearchFinished:(NSNotification *)k {
|
||||||
_loadingView.hidden = TRUE;
|
_loadingView.hidden = TRUE;
|
||||||
}
|
}
|
||||||
|
- (void)onMagicSearchMoreAvailable:(NSNotification *)k {
|
||||||
|
_ldapMoreResultsLabel.hidden = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewDidAppear:(BOOL)animated {
|
- (void)viewDidAppear:(BOOL)animated {
|
||||||
NSLog(@"Debuglog viewDidAppear");
|
NSLog(@"Debuglog viewDidAppear");
|
||||||
|
|
@ -225,7 +237,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)refreshButtons {
|
- (void)refreshButtons {
|
||||||
[addButton setHidden:FALSE];
|
[addButton setHidden:![LinphoneManager.instance lpConfigBoolForKey:@"enable_native_address_book"]];
|
||||||
[self changeView:[ContactSelection getSipFilterEnabled] ? ContactsLinphone : ContactsAll];
|
[self changeView:[ContactSelection getSipFilterEnabled] ? ContactsLinphone : ContactsAll];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,6 +262,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)displayModeChanged{
|
||||||
|
[self.tableController.tableView reloadData];
|
||||||
|
}
|
||||||
|
|
||||||
- (IBAction)onDeleteClick:(id)sender {
|
- (IBAction)onDeleteClick:(id)sender {
|
||||||
NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"Do you want to delete selected contacts?\nThey will also be deleted from your phone's address book.", nil)];
|
NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"Do you want to delete selected contacts?\nThey will also be deleted from your phone's address book.", nil)];
|
||||||
[LinphoneManager.instance setContactsUpdated:TRUE];
|
[LinphoneManager.instance setContactsUpdated:TRUE];
|
||||||
|
|
@ -268,6 +284,9 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
- (IBAction)onEditionChangeClick:(id)sender {
|
- (IBAction)onEditionChangeClick:(id)sender {
|
||||||
allButton.hidden = linphoneButton.hidden = _selectedButtonImage.hidden = addButton.hidden = self.tableController.isEditing;
|
allButton.hidden = linphoneButton.hidden = _selectedButtonImage.hidden = addButton.hidden = self.tableController.isEditing;
|
||||||
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"enable_native_address_book"]) {
|
||||||
|
addButton.hidden = self.tableController.isEditing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
|
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
|
||||||
|
|
@ -292,6 +311,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
if (searchText.length == 0) {
|
if (searchText.length == 0) {
|
||||||
[LinphoneManager.instance setContactsUpdated:TRUE];
|
[LinphoneManager.instance setContactsUpdated:TRUE];
|
||||||
}
|
}
|
||||||
|
_ldapMoreResultsLabel.hidden = TRUE;
|
||||||
[tableController loadDataWithFilter:searchText];
|
[tableController loadDataWithFilter:searchText];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,9 +145,17 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
[_videoCameraSwitch setHidden:FALSE];
|
[_videoCameraSwitch setHidden:FALSE];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[_addContactButton setImage:[UIImage imageNamed:@"voip_conference_new"] forState:UIControlStateNormal];
|
|
||||||
_addContactButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
|
LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC);
|
||||||
_addContactButton.enabled = true;
|
if (!(defaultAccount && linphone_account_params_get_conference_factory_uri(linphone_account_get_params(defaultAccount)))){
|
||||||
|
[_addContactButton setImage:[UIImage imageNamed:@"contact_add_default"] forState:UIControlStateNormal];
|
||||||
|
_addContactButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
|
_addContactButton.enabled = true;
|
||||||
|
}else{
|
||||||
|
[_addContactButton setImage:[UIImage imageNamed:@"voip_conference_new"] forState:UIControlStateNormal];
|
||||||
|
_addContactButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
|
_addContactButton.enabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
|
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
|
||||||
|
|
@ -175,10 +183,11 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
_padView.hidden = !IPAD && UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
|
_padView.hidden = !IPAD && UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
|
||||||
if (linphone_core_get_calls_nb(LC)) {
|
if (linphone_core_get_calls_nb(LC)) {
|
||||||
_backButton.hidden = FALSE;
|
_backButton.hidden = FALSE;
|
||||||
|
_addContactButton.hidden = TRUE;
|
||||||
} else {
|
} else {
|
||||||
_backButton.hidden = TRUE;
|
_backButton.hidden = TRUE;
|
||||||
|
_addContactButton.hidden = FALSE;
|
||||||
}
|
}
|
||||||
_addContactButton.hidden = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidAppear:(BOOL)animated {
|
- (void)viewDidAppear:(BOOL)animated {
|
||||||
|
|
@ -392,19 +401,38 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
#pragma mark - Action Functions
|
#pragma mark - Action Functions
|
||||||
|
|
||||||
- (IBAction)onAddContactClick:(id)event {
|
- (IBAction)onAddContactClick:(id)event {
|
||||||
ConferenceSchedulingView *view = VIEW(ConferenceSchedulingView);
|
LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC);
|
||||||
[view resetViewModel];
|
if (!(defaultAccount && linphone_account_params_get_conference_factory_uri(linphone_account_get_params(defaultAccount)))){
|
||||||
[PhoneMainView.instance changeCurrentView:ConferenceSchedulingView.compositeViewDescription];
|
[ContactSelection setSelectionMode:ContactSelectionModeEdit];
|
||||||
|
[ContactSelection setAddAddress:[_addressField text]];
|
||||||
|
[ContactSelection enableSipFilter:FALSE];
|
||||||
|
[PhoneMainView.instance changeCurrentView:ContactsListView.compositeViewDescription];
|
||||||
|
}else{
|
||||||
|
ConferenceSchedulingView *view = VIEW(ConferenceSchedulingView);
|
||||||
|
[view resetViewModel];
|
||||||
|
[PhoneMainView.instance changeCurrentView:ConferenceSchedulingView.compositeViewDescription];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onBackClick:(id)event {
|
- (IBAction)onBackClick:(id)event {
|
||||||
[PhoneMainView.instance popToView:ActiveCallOrConferenceView.compositeViewDescription];
|
[PhoneMainView.instance popToView:[CallsViewModelBridge callViewToDisplay]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onAddressChange:(id)sender {
|
- (IBAction)onAddressChange:(id)sender {
|
||||||
if ([self displayDebugPopup:_addressField.text]) {
|
if ([self displayDebugPopup:_addressField.text]) {
|
||||||
_addressField.text = @"";
|
_addressField.text = @"";
|
||||||
}
|
}
|
||||||
|
LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC);
|
||||||
|
if (!(defaultAccount && linphone_account_params_get_conference_factory_uri(linphone_account_get_params(defaultAccount)))){
|
||||||
|
[_addContactButton setImage:[UIImage imageNamed:@"contact_add_default"] forState:UIControlStateNormal];
|
||||||
|
_addContactButton.enabled = ([[_addressField text] length] > 0);
|
||||||
|
if ([_addressField.text length] == 0) {
|
||||||
|
[self.view endEditing:YES];
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
[_addContactButton setImage:[UIImage imageNamed:@"voip_conference_new"] forState:UIControlStateNormal];
|
||||||
|
_addContactButton.enabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onBackspaceClick:(id)sender {
|
- (IBAction)onBackspaceClick:(id)sender {
|
||||||
|
|
|
||||||
|
|
@ -69,14 +69,15 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
// Update on show
|
// Update on show
|
||||||
const MSList *list = linphone_core_get_account_list([LinphoneManager getLc]);
|
MSList *list = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
if (list != NULL) {
|
if (list != NULL) {
|
||||||
LinphoneAccount *account = (LinphoneAccount *)list->data;
|
LinphoneAccount *account = (LinphoneAccount *)list->data;
|
||||||
if (account) {
|
if (account) {
|
||||||
[self registrationUpdate:linphone_account_get_state(account)];
|
[self registrationUpdate:linphone_account_get_state(account)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bctbx_list_free(list);
|
||||||
|
|
||||||
if (account_creator) {
|
if (account_creator) {
|
||||||
linphone_account_creator_unref(account_creator);
|
linphone_account_creator_unref(account_creator);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
@property (weak, nonatomic) IBOutlet UIView *waitView;
|
@property (weak, nonatomic) IBOutlet UIView *waitView;
|
||||||
@property (weak, nonatomic) IBOutlet UIRoundedImageView *linphoneImage;
|
@property (weak, nonatomic) IBOutlet UIRoundedImageView *linphoneImage;
|
||||||
@property (weak, nonatomic) IBOutlet UIView *optionsView;
|
@property (weak, nonatomic) IBOutlet UIView *optionsView;
|
||||||
|
@property(weak, nonatomic) IBOutlet UIButton *chatButton;
|
||||||
@property (weak, nonatomic) IBOutlet UIView *encryptedChatView;
|
@property (weak, nonatomic) IBOutlet UIView *encryptedChatView;
|
||||||
|
|
||||||
- (IBAction)onBackClick:(id)event;
|
- (IBAction)onBackClick:(id)event;
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,12 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
[_headerView addGestureRecognizer:headerTapGesture];
|
[_headerView addGestureRecognizer:headerTapGesture];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
|
||||||
|
_chatButton.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"force_lime_chat_rooms"];
|
||||||
|
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
|
||||||
|
[self update];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
[super viewWillAppear:animated];
|
[super viewWillAppear:animated];
|
||||||
_waitView.hidden = YES;
|
_waitView.hidden = YES;
|
||||||
|
|
|
||||||
|
|
@ -268,9 +268,13 @@
|
||||||
} else {
|
} else {
|
||||||
if (linphone_call_log_was_conference(callLog)) {
|
if (linphone_call_log_was_conference(callLog)) {
|
||||||
LinphoneConferenceInfo *confInfo = linphone_call_log_get_conference_info(callLog);
|
LinphoneConferenceInfo *confInfo = linphone_call_log_get_conference_info(callLog);
|
||||||
ConferenceWaitingRoomFragment *view = VIEW(ConferenceWaitingRoomFragment);
|
if (linphone_conference_info_get_state(confInfo) == LinphoneConferenceInfoStateCancelled) {
|
||||||
|
[ConferenceViewModelBridge showCancelledMeetingWithCConferenceInfo:confInfo];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ConferenceWaitingRoomView *view = VIEW(ConferenceWaitingRoomView);
|
||||||
[view setDetailsWithSubject:[NSString stringWithUTF8String:linphone_conference_info_get_subject(confInfo)] url:[NSString stringWithUTF8String:linphone_address_as_string(linphone_conference_info_get_uri(confInfo))]];
|
[view setDetailsWithSubject:[NSString stringWithUTF8String:linphone_conference_info_get_subject(confInfo)] url:[NSString stringWithUTF8String:linphone_address_as_string(linphone_conference_info_get_uri(confInfo))]];
|
||||||
[PhoneMainView.instance changeCurrentView:ConferenceWaitingRoomFragment.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:ConferenceWaitingRoomView.compositeViewDescription];
|
||||||
} else {
|
} else {
|
||||||
const LinphoneAddress *addr = linphone_call_log_get_remote_address(callLog);
|
const LinphoneAddress *addr = linphone_call_log_get_remote_address(callLog);
|
||||||
[LinphoneManager.instance call:addr];
|
[LinphoneManager.instance call:addr];
|
||||||
|
|
|
||||||
|
|
@ -67,10 +67,15 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
// Fake event
|
// Fake event
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
|
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneCallUpdate object:self];
|
||||||
[_toggleSelectionButton setImage:[UIImage imageNamed:@"select_all_default.png"] forState:UIControlStateSelected];
|
[_toggleSelectionButton setImage:[UIImage imageNamed:@"select_all_default.png"] forState:UIControlStateSelected];
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector:@selector(displayModeChanged)
|
||||||
|
name:kDisplayModeChanged
|
||||||
|
object:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) viewWillDisappear:(BOOL)animated {
|
- (void) viewWillDisappear:(BOOL)animated {
|
||||||
self.view = NULL;
|
self.view = NULL;
|
||||||
|
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
@ -100,6 +105,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
_selectedButtonImage.frame = frame;
|
_selectedButtonImage.frame = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)displayModeChanged{
|
||||||
|
[self.tableController.tableView reloadData];
|
||||||
|
}
|
||||||
|
|
||||||
#pragma m ~ark - Action Functions
|
#pragma m ~ark - Action Functions
|
||||||
|
|
||||||
- (IBAction)onAllClick:(id)event {
|
- (IBAction)onAllClick:(id)event {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@
|
||||||
#import <IntentsUI/IntentsUI.h>
|
#import <IntentsUI/IntentsUI.h>
|
||||||
#import "linphoneapp-Swift.h"
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
|
#import "SVProgressHUD.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_CRASHLYTICS
|
#ifdef USE_CRASHLYTICS
|
||||||
#include "FIRApp.h"
|
#include "FIRApp.h"
|
||||||
|
|
@ -85,6 +87,7 @@
|
||||||
[LinphoneManager.instance.fastAddressBook reloadFriends];
|
[LinphoneManager.instance.fastAddressBook reloadFriends];
|
||||||
|
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:nil];
|
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:nil];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||||
|
|
@ -137,7 +140,6 @@
|
||||||
if ((floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max)) {
|
if ((floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max)) {
|
||||||
if ([LinphoneManager.instance lpConfigBoolForKey:@"autoanswer_notif_preference"]) {
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"autoanswer_notif_preference"]) {
|
||||||
linphone_call_accept(call);
|
linphone_call_accept(call);
|
||||||
[PhoneMainView.instance changeCurrentView:ActiveCallOrConferenceView.compositeViewDescription];
|
|
||||||
} else {
|
} else {
|
||||||
[PhoneMainView.instance displayIncomingCall:call];
|
[PhoneMainView.instance displayIncomingCall:call];
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +158,9 @@
|
||||||
[self handleShortcut:_shortcutItem];
|
[self handleShortcut:_shortcutItem];
|
||||||
_shortcutItem = nil;
|
_shortcutItem = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_IPHONE_SIMULATOR
|
||||||
|
#else
|
||||||
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge)
|
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge)
|
||||||
completionHandler:^(BOOL granted, NSError *_Nullable error) {
|
completionHandler:^(BOOL granted, NSError *_Nullable error) {
|
||||||
if (error)
|
if (error)
|
||||||
|
|
@ -182,6 +186,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
if ([UIDeviceBridge switchedDisplayMode]) {
|
||||||
|
[AvatarBridge prepareIt];
|
||||||
|
[NSNotificationCenter.defaultCenter postNotificationName:kDisplayModeChanged object:nil];
|
||||||
|
[PhoneMainView.instance.mainViewController removeEntryFromCache:ChatConversationCreateView.compositeViewDescription.name];
|
||||||
|
[PhoneMainView.instance.mainViewController changeView:PhoneMainView.instance.currentView];
|
||||||
|
[UIDeviceBridge notifyDisplayModeSwitch];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,8 +345,9 @@
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
[PhoneMainView.instance.mainViewController getCachedController:ActiveCallOrConferenceView.compositeViewDescription.name]; // This will create the single instance of the ActiveCallOrConferenceView including listeneres
|
[PhoneMainView.instance.mainViewController getCachedController:SingleCallView.compositeViewDescription.name]; // This will create the single instance of the SingleCallView including listeneres
|
||||||
|
[PhoneMainView.instance.mainViewController getCachedController:ConferenceCallView.compositeViewDescription.name]; // This will create the single instance of the ConferenceCallView including listeneres
|
||||||
|
[CallsViewModelBridge setupCallsViewNavigation];
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,6 +367,7 @@
|
||||||
- (BOOL)handleShortcut:(UIApplicationShortcutItem *)shortcutItem {
|
- (BOOL)handleShortcut:(UIApplicationShortcutItem *)shortcutItem {
|
||||||
BOOL success = NO;
|
BOOL success = NO;
|
||||||
if ([shortcutItem.type isEqualToString:@"linphone.phone.action.newMessage"]) {
|
if ([shortcutItem.type isEqualToString:@"linphone.phone.action.newMessage"]) {
|
||||||
|
[VIEW(ChatConversationCreateView) fragmentCompositeDescription];
|
||||||
[PhoneMainView.instance changeCurrentView:ChatConversationCreateView.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:ChatConversationCreateView.compositeViewDescription];
|
||||||
success = YES;
|
success = YES;
|
||||||
}
|
}
|
||||||
|
|
@ -388,7 +404,15 @@
|
||||||
|
|
||||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||||
} else if([[url scheme] isEqualToString:@"message-linphone"]) {
|
} else if([[url scheme] isEqualToString:@"message-linphone"]) {
|
||||||
[PhoneMainView.instance popToView:ChatsListView.compositeViewDescription];
|
if ([[PhoneMainView.instance currentView] equal:ChatsListView.compositeViewDescription]) {
|
||||||
|
VIEW(ChatConversationView).sharingMedia = TRUE;
|
||||||
|
ChatsListView *view = VIEW(ChatsListView);
|
||||||
|
[view mediaSharing];
|
||||||
|
}else{
|
||||||
|
[SVProgressHUD dismiss];
|
||||||
|
VIEW(ChatConversationView).sharingMedia = TRUE;
|
||||||
|
[PhoneMainView.instance popToView:ChatsListView.compositeViewDescription];
|
||||||
|
}
|
||||||
} else if ([scheme isEqualToString:@"sip"]||[scheme isEqualToString:@"sips"]) {
|
} else if ([scheme isEqualToString:@"sip"]||[scheme isEqualToString:@"sips"]) {
|
||||||
// remove "sip://" from the URI, and do it correctly by taking resourceSpecifier and removing leading and
|
// remove "sip://" from the URI, and do it correctly by taking resourceSpecifier and removing leading and
|
||||||
// trailing "/"
|
// trailing "/"
|
||||||
|
|
@ -503,15 +527,15 @@
|
||||||
|
|
||||||
- (void) userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
|
- (void) userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
|
||||||
// If an app extension launch a user notif while app is in fg, it is catch by the app
|
// If an app extension launch a user notif while app is in fg, it is catch by the app
|
||||||
NSString *category = [[[notification request] content] categoryIdentifier];
|
NSString *category = [[[notification request] content] categoryIdentifier];
|
||||||
if (category && [category isEqualToString:@"app_active"]) {
|
if (category && [category isEqualToString:@"app_active"]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (category && [category isEqualToString:@"msg_cat"] && [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
|
if (category && [category isEqualToString:@"msg_cat"] && [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
|
||||||
if ((PhoneMainView.instance.currentView == ChatsListView.compositeViewDescription))
|
if ((PhoneMainView.instance.currentView == ChatsListView.compositeViewDescription))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PhoneMainView.instance.currentView == ChatConversationView.compositeViewDescription) {
|
if (PhoneMainView.instance.currentView == ChatConversationView.compositeViewDescription) {
|
||||||
NSDictionary *userInfo = [[[notification request] content] userInfo];
|
NSDictionary *userInfo = [[[notification request] content] userInfo];
|
||||||
NSString *peerAddress = userInfo[@"peer_addr"];
|
NSString *peerAddress = userInfo[@"peer_addr"];
|
||||||
|
|
@ -519,12 +543,12 @@
|
||||||
if (peerAddress && localAddress) {
|
if (peerAddress && localAddress) {
|
||||||
LinphoneAddress *peer = linphone_core_create_address([LinphoneManager getLc], peerAddress.UTF8String);
|
LinphoneAddress *peer = linphone_core_create_address([LinphoneManager getLc], peerAddress.UTF8String);
|
||||||
LinphoneAddress *local = linphone_core_create_address([LinphoneManager getLc], localAddress.UTF8String);
|
LinphoneAddress *local = linphone_core_create_address([LinphoneManager getLc], localAddress.UTF8String);
|
||||||
LinphoneChatRoom *room = linphone_core_find_chat_room([LinphoneManager getLc], peer, local);
|
LinphoneChatRoom *room = linphone_core_search_chat_room([LinphoneManager getLc], NULL, local, peer, NULL);
|
||||||
if (room == PhoneMainView.instance.currentRoom) return;
|
if (room == PhoneMainView.instance.currentRoom) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
completionHandler(UNNotificationPresentationOptionAlert);
|
completionHandler(UNNotificationPresentationOptionAlert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -616,7 +640,6 @@
|
||||||
}
|
}
|
||||||
} else if ([response.notification.request.content.categoryIdentifier isEqual:@"video_request"]) {
|
} else if ([response.notification.request.content.categoryIdentifier isEqual:@"video_request"]) {
|
||||||
if (!call) return;
|
if (!call) return;
|
||||||
[PhoneMainView.instance changeCurrentView:ActiveCallOrConferenceView.compositeViewDescription];
|
|
||||||
NSTimer *videoDismissTimer = nil;
|
NSTimer *videoDismissTimer = nil;
|
||||||
UIConfirmationDialog *sheet = [UIConfirmationDialog ShowWithMessage:response.notification.request.content.body
|
UIConfirmationDialog *sheet = [UIConfirmationDialog ShowWithMessage:response.notification.request.content.body
|
||||||
cancelMessage:nil
|
cancelMessage:nil
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
@implementation LinphoneCoreSettingsStore
|
@implementation LinphoneCoreSettingsStore
|
||||||
|
|
||||||
- (id)init {
|
- (id)init {
|
||||||
|
|
@ -141,7 +142,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)transformAccountToKeys:(NSString *)username {
|
- (void)transformAccountToKeys:(NSString *)username {
|
||||||
const MSList *accountList = linphone_core_get_account_list(LC);
|
//const MSList *accountList = linphone_core_get_account_list(LC);
|
||||||
|
MSList *accountListToBeFreed = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
MSList *accountList = accountListToBeFreed;
|
||||||
while (username && accountList &&
|
while (username && accountList &&
|
||||||
strcmp(username.UTF8String,
|
strcmp(username.UTF8String,
|
||||||
linphone_address_get_username(linphone_account_params_get_identity_address(linphone_account_get_params(accountList->data)))) != 0) {
|
linphone_address_get_username(linphone_account_params_get_identity_address(linphone_account_get_params(accountList->data)))) != 0) {
|
||||||
|
|
@ -168,6 +171,7 @@
|
||||||
[self setInteger:-1 forKey:@"account_expire_preference"];
|
[self setInteger:-1 forKey:@"account_expire_preference"];
|
||||||
[self setInteger:-1 forKey:@"current_proxy_config_preference"];
|
[self setInteger:-1 forKey:@"current_proxy_config_preference"];
|
||||||
[self setCString:"" forKey:@"account_prefix_preference"];
|
[self setCString:"" forKey:@"account_prefix_preference"];
|
||||||
|
[self setBool:YES forKey:@"apply_international_prefix_for_calls_and_chats"];
|
||||||
[self setBool:NO forKey:@"account_substitute_+_by_00_preference"];
|
[self setBool:NO forKey:@"account_substitute_+_by_00_preference"];
|
||||||
[self setBool:NO forKey:@"account_ice_preference"];
|
[self setBool:NO forKey:@"account_ice_preference"];
|
||||||
[self setCString:"" forKey:@"account_stun_preference"];
|
[self setCString:"" forKey:@"account_stun_preference"];
|
||||||
|
|
@ -183,7 +187,7 @@
|
||||||
|
|
||||||
const LinphoneAddress *identity_addr = linphone_account_params_get_identity_address(accountParams);
|
const LinphoneAddress *identity_addr = linphone_account_params_get_identity_address(accountParams);
|
||||||
const char *server_addr = linphone_account_params_get_server_addr(accountParams);
|
const char *server_addr = linphone_account_params_get_server_addr(accountParams);
|
||||||
LinphoneAddress *proxy_addr = linphone_core_interpret_url(LC, server_addr);
|
LinphoneAddress *proxy_addr = linphone_core_interpret_url_2(LC, server_addr, false);
|
||||||
if (identity_addr && proxy_addr) {
|
if (identity_addr && proxy_addr) {
|
||||||
int port = linphone_address_get_port(proxy_addr);
|
int port = linphone_address_get_port(proxy_addr);
|
||||||
|
|
||||||
|
|
@ -234,9 +238,11 @@
|
||||||
[self setCString:linphone_auth_info_get_algorithm(ai) forKey:@"ha1_algo_preference"];
|
[self setCString:linphone_auth_info_get_algorithm(ai) forKey:@"ha1_algo_preference"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MSList *accountsList = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
int idx = (int)bctbx_list_index(linphone_core_get_account_list(LC), account);
|
int idx = (int)bctbx_list_index(linphone_core_get_account_list(LC), account);
|
||||||
[self setInteger:idx forKey:@"current_proxy_config_preference"];
|
[self setInteger:idx forKey:@"current_proxy_config_preference"];
|
||||||
|
bctbx_list_free(accountsList);
|
||||||
|
|
||||||
int expires = linphone_account_params_get_expires(accountParams);
|
int expires = linphone_account_params_get_expires(accountParams);
|
||||||
[self setInteger:expires forKey:@"account_expire_preference"];
|
[self setInteger:expires forKey:@"account_expire_preference"];
|
||||||
|
|
||||||
|
|
@ -251,10 +257,13 @@
|
||||||
{
|
{
|
||||||
const char *dial_prefix = linphone_account_params_get_international_prefix(accountParams);
|
const char *dial_prefix = linphone_account_params_get_international_prefix(accountParams);
|
||||||
[self setCString:dial_prefix forKey:@"account_prefix_preference"];
|
[self setCString:dial_prefix forKey:@"account_prefix_preference"];
|
||||||
|
BOOL apply_prefix = linphone_account_params_get_use_international_prefix_for_calls_and_chats(accountParams);
|
||||||
|
[self setBool:apply_prefix forKey:@"apply_international_prefix_for_calls_and_chats"];
|
||||||
BOOL dial_escape_plus = linphone_account_params_get_dial_escape_plus_enabled(accountParams);
|
BOOL dial_escape_plus = linphone_account_params_get_dial_escape_plus_enabled(accountParams);
|
||||||
[self setBool:dial_escape_plus forKey:@"account_substitute_+_by_00_preference"];
|
[self setBool:dial_escape_plus forKey:@"account_substitute_+_by_00_preference"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bctbx_list_free(accountListToBeFreed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -343,15 +352,17 @@
|
||||||
|
|
||||||
// root section
|
// root section
|
||||||
{
|
{
|
||||||
const bctbx_list_t *accounts = linphone_core_get_account_list(LC);
|
MSList *accountsListToBeFreed = [lm createAccountsNotHiddenList];
|
||||||
size_t count = bctbx_list_size(accounts);
|
MSList *accountsList = accountsListToBeFreed;
|
||||||
for (size_t i = 1; i <= count; i++, accounts = accounts->next) {
|
size_t count = bctbx_list_size(accountsList);
|
||||||
|
for (size_t i = 1; i <= count; i++, accountsList = accountsList->next) {
|
||||||
NSString *key = [NSString stringWithFormat:@"menu_account_%lu", i];
|
NSString *key = [NSString stringWithFormat:@"menu_account_%lu", i];
|
||||||
LinphoneAccount *account = (LinphoneAccount *)accounts->data;
|
LinphoneAccount *account = (LinphoneAccount *)accountsList->data;
|
||||||
[self setCString:linphone_address_get_username(linphone_account_params_get_identity_address(linphone_account_get_params(account)))
|
[self setCString:linphone_address_get_username(linphone_account_params_get_identity_address(linphone_account_get_params(account)))
|
||||||
forKey:key];
|
forKey:key];
|
||||||
}
|
}
|
||||||
|
bctbx_free(accountsListToBeFreed);
|
||||||
|
|
||||||
[self setBool:linphone_core_video_display_enabled(LC) forKey:@"enable_video_preference"];
|
[self setBool:linphone_core_video_display_enabled(LC) forKey:@"enable_video_preference"];
|
||||||
[self setBool:[LinphoneManager.instance lpConfigBoolForKey:@"auto_answer"]
|
[self setBool:[LinphoneManager.instance lpConfigBoolForKey:@"auto_answer"]
|
||||||
forKey:@"enable_auto_answer_preference"];
|
forKey:@"enable_auto_answer_preference"];
|
||||||
|
|
@ -431,10 +442,10 @@
|
||||||
{
|
{
|
||||||
[self setCString:linphone_core_get_file_transfer_server(LC) forKey:@"file_transfer_server_url_preference"];
|
[self setCString:linphone_core_get_file_transfer_server(LC) forKey:@"file_transfer_server_url_preference"];
|
||||||
int maxSize = linphone_core_get_max_size_for_auto_download_incoming_files(LC);
|
int maxSize = linphone_core_get_max_size_for_auto_download_incoming_files(LC);
|
||||||
[self setObject:maxSize==0 ? @"Always" : (maxSize==-1 ? @"Nerver" : @"Customize") forKey:@"auto_download_mode"];
|
[self setObject:maxSize==0 ? @"Always" : (maxSize==-1 ? @"Never" : @"Customize") forKey:@"auto_download_mode"];
|
||||||
[self setInteger:maxSize forKey:@"auto_download_incoming_files_max_size"];
|
[self setInteger:maxSize forKey:@"auto_download_incoming_files_max_size"];
|
||||||
[self setBool:[VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId] forKey:@"vfs_enabled_mode"];
|
[self setBool:[VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId] forKey:@"vfs_enabled_mode"];
|
||||||
[self setBool:[lm lpConfigBoolForKey:@"auto_write_to_gallery_preference" withDefault:YES] forKey:@"auto_write_to_gallery_mode"];
|
[self setBool:[lm lpConfigBoolForKey:@"auto_write_to_gallery_preference" withDefault:NO] forKey:@"auto_write_to_gallery_mode"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// network section
|
// network section
|
||||||
|
|
@ -486,7 +497,7 @@
|
||||||
val = "None";
|
val = "None";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
[self setCString:val forKey:@"media_encryption_preference"];
|
[self setCString:val forKey:linphone_core_get_post_quantum_available() ? @"media_encryption_preference_pq_enabled" : @"media_encryption_preference"];
|
||||||
[self setInteger:linphone_core_get_upload_bandwidth(LC) forKey:@"upload_bandwidth_preference"];
|
[self setInteger:linphone_core_get_upload_bandwidth(LC) forKey:@"upload_bandwidth_preference"];
|
||||||
[self setInteger:linphone_core_get_download_bandwidth(LC) forKey:@"download_bandwidth_preference"];
|
[self setInteger:linphone_core_get_download_bandwidth(LC) forKey:@"download_bandwidth_preference"];
|
||||||
[self setBool:linphone_core_adaptive_rate_control_enabled(LC) forKey:@"adaptive_rate_control_preference"];
|
[self setBool:linphone_core_adaptive_rate_control_enabled(LC) forKey:@"adaptive_rate_control_preference"];
|
||||||
|
|
@ -604,6 +615,7 @@
|
||||||
int expire = [self integerForKey:@"account_expire_preference"];
|
int expire = [self integerForKey:@"account_expire_preference"];
|
||||||
BOOL pushnotification = [self boolForKey:@"account_pushnotification_preference"];
|
BOOL pushnotification = [self boolForKey:@"account_pushnotification_preference"];
|
||||||
NSString *prefix = [self stringForKey:@"account_prefix_preference"];
|
NSString *prefix = [self stringForKey:@"account_prefix_preference"];
|
||||||
|
BOOL use_prefix = [self boolForKey:@"apply_international_prefix_for_calls_and_chats"];
|
||||||
NSString *proxyAddress = [self stringForKey:@"account_proxy_preference"];
|
NSString *proxyAddress = [self stringForKey:@"account_proxy_preference"];
|
||||||
|
|
||||||
if ((!proxyAddress || [proxyAddress length] < 1) && domain) {
|
if ((!proxyAddress || [proxyAddress length] < 1) && domain) {
|
||||||
|
|
@ -614,7 +626,7 @@
|
||||||
proxyAddress = [NSString stringWithFormat:@"sip:%@", proxyAddress];
|
proxyAddress = [NSString stringWithFormat:@"sip:%@", proxyAddress];
|
||||||
}
|
}
|
||||||
|
|
||||||
LinphoneAddress *proxy_addr = linphone_core_interpret_url(LC, proxyAddress.UTF8String);
|
LinphoneAddress *proxy_addr = linphone_core_interpret_url_2(LC, proxyAddress.UTF8String, false);
|
||||||
|
|
||||||
if (proxy_addr) {
|
if (proxy_addr) {
|
||||||
LinphoneTransportType type = LinphoneTransportUdp;
|
LinphoneTransportType type = LinphoneTransportUdp;
|
||||||
|
|
@ -625,9 +637,11 @@
|
||||||
|
|
||||||
linphone_address_set_transport(proxy_addr, type);
|
linphone_address_set_transport(proxy_addr, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
account = bctbx_list_nth_data(linphone_core_get_account_list(LC),
|
MSList *accountList= [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
account = bctbx_list_nth_data(accountList,
|
||||||
[self integerForKey:@"current_proxy_config_preference"]);
|
[self integerForKey:@"current_proxy_config_preference"]);
|
||||||
|
bctbx_free(accountList);
|
||||||
|
|
||||||
// if account was deleted, it is not present anymore
|
// if account was deleted, it is not present anymore
|
||||||
if (account == NULL)
|
if (account == NULL)
|
||||||
|
|
@ -670,10 +684,8 @@
|
||||||
linphone_nat_policy_set_stun_server(policy, stun_preference.UTF8String);
|
linphone_nat_policy_set_stun_server(policy, stun_preference.UTF8String);
|
||||||
linphone_account_params_set_nat_policy(newAccountParams, policy);
|
linphone_account_params_set_nat_policy(newAccountParams, policy);
|
||||||
|
|
||||||
if ([prefix length] > 0) {
|
linphone_account_params_set_international_prefix(newAccountParams, [prefix UTF8String]);
|
||||||
linphone_account_params_set_international_prefix(newAccountParams, [prefix UTF8String]);
|
linphone_account_params_set_use_international_prefix_for_calls_and_chats(newAccountParams, use_prefix);
|
||||||
}
|
|
||||||
|
|
||||||
if ([self objectForKey:@"account_substitute_+_by_00_preference"]) {
|
if ([self objectForKey:@"account_substitute_+_by_00_preference"]) {
|
||||||
bool substitute_plus_by_00 = [self boolForKey:@"account_substitute_+_by_00_preference"];
|
bool substitute_plus_by_00 = [self boolForKey:@"account_substitute_+_by_00_preference"];
|
||||||
linphone_account_params_set_dial_escape_plus_enabled(newAccountParams, substitute_plus_by_00);
|
linphone_account_params_set_dial_escape_plus_enabled(newAccountParams, substitute_plus_by_00);
|
||||||
|
|
@ -713,7 +725,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
char *identity = linphone_address_as_string(linphoneAddress);
|
char *identity = linphone_address_as_string(linphoneAddress);
|
||||||
LinphoneAddress *from = linphone_core_interpret_url(LC, identity);
|
LinphoneAddress *from = linphone_core_interpret_url_2(LC, identity, false);
|
||||||
ms_free(identity);
|
ms_free(identity);
|
||||||
if (from) {
|
if (from) {
|
||||||
const char *userid_str = (userID != nil) ? [userID UTF8String] : NULL;
|
const char *userid_str = (userID != nil) ? [userID UTF8String] : NULL;
|
||||||
|
|
@ -805,7 +817,7 @@
|
||||||
linphone_ldap_params_set_bind_dn(newLdapParams, [self stringForKey:@"ldap_bind_dn"].UTF8String);
|
linphone_ldap_params_set_bind_dn(newLdapParams, [self stringForKey:@"ldap_bind_dn"].UTF8String);
|
||||||
linphone_ldap_params_set_password(newLdapParams, [self stringForKey:@"ldap_password"].UTF8String);
|
linphone_ldap_params_set_password(newLdapParams, [self stringForKey:@"ldap_password"].UTF8String);
|
||||||
|
|
||||||
LinphoneLdapAuthMethod authMethod = [[self stringForKey:@"ldap_verification_method"] isEqualToString:@"simple"] ? LinphoneLdapAuthMethodSimple : LinphoneLdapAuthMethodAnonymous;
|
LinphoneLdapAuthMethod authMethod = [[self stringForKey:@"ldap_auth_method"] isEqualToString:@"simple"] ? LinphoneLdapAuthMethodSimple : LinphoneLdapAuthMethodAnonymous;
|
||||||
linphone_ldap_params_set_auth_method(newLdapParams, authMethod);
|
linphone_ldap_params_set_auth_method(newLdapParams, authMethod);
|
||||||
linphone_ldap_params_enable_tls(newLdapParams, [self boolForKey:@"ldap_tls_enabled"]);
|
linphone_ldap_params_enable_tls(newLdapParams, [self boolForKey:@"ldap_tls_enabled"]);
|
||||||
|
|
||||||
|
|
@ -829,8 +841,8 @@
|
||||||
|
|
||||||
|
|
||||||
// Analysis parameters
|
// Analysis parameters
|
||||||
linphone_ldap_params_set_name_attribute(newLdapParams, [self stringForKey:@"ldap_name_attributes"].UTF8String);
|
linphone_ldap_params_set_name_attribute(newLdapParams, [self stringForKey:@"ldap_name_attribute"].UTF8String);
|
||||||
linphone_ldap_params_set_sip_attribute(newLdapParams, [self stringForKey:@"ldap_sip_attributes"].UTF8String);
|
linphone_ldap_params_set_sip_attribute(newLdapParams, [self stringForKey:@"ldap_sip_attribute"].UTF8String);
|
||||||
linphone_ldap_params_set_sip_domain(newLdapParams, [self stringForKey:@"ldap_sip_domain"].UTF8String);
|
linphone_ldap_params_set_sip_domain(newLdapParams, [self stringForKey:@"ldap_sip_domain"].UTF8String);
|
||||||
|
|
||||||
// Miscellaneous parameters
|
// Miscellaneous parameters
|
||||||
|
|
@ -1020,7 +1032,7 @@
|
||||||
[LinphoneCoreSettingsStore parsePortRange:video_port_preference minPort:&videoMinPort maxPort:&videoMaxPort];
|
[LinphoneCoreSettingsStore parsePortRange:video_port_preference minPort:&videoMinPort maxPort:&videoMaxPort];
|
||||||
linphone_core_set_video_port_range(LC, videoMinPort, videoMaxPort);
|
linphone_core_set_video_port_range(LC, videoMinPort, videoMaxPort);
|
||||||
|
|
||||||
NSString *menc = [self stringForKey:@"media_encryption_preference"];
|
NSString *menc = [self stringForKey:linphone_core_get_post_quantum_available() ? @"media_encryption_preference_pq_enabled" : @"media_encryption_preference"];
|
||||||
if (menc && [menc compare:@"SRTP"] == NSOrderedSame)
|
if (menc && [menc compare:@"SRTP"] == NSOrderedSame)
|
||||||
linphone_core_set_media_encryption(LC, LinphoneMediaEncryptionSRTP);
|
linphone_core_set_media_encryption(LC, LinphoneMediaEncryptionSRTP);
|
||||||
else if (menc && [menc compare:@"ZRTP"] == NSOrderedSame)
|
else if (menc && [menc compare:@"ZRTP"] == NSOrderedSame)
|
||||||
|
|
@ -1096,7 +1108,9 @@
|
||||||
NSString *rls_uri = [lm lpConfigStringForKey:@"rls_uri" inSection:@"sip" withDefault:@"sips:rls@sip.linphone.org"];
|
NSString *rls_uri = [lm lpConfigStringForKey:@"rls_uri" inSection:@"sip" withDefault:@"sips:rls@sip.linphone.org"];
|
||||||
LinphoneAddress *rls_addr = linphone_address_new(rls_uri.UTF8String);
|
LinphoneAddress *rls_addr = linphone_address_new(rls_uri.UTF8String);
|
||||||
const char *rls_domain = linphone_address_get_domain(rls_addr);
|
const char *rls_domain = linphone_address_get_domain(rls_addr);
|
||||||
const MSList *accounts = linphone_core_get_account_list(LC);
|
|
||||||
|
MSList *accountListToBeFreed = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
const MSList *accounts = accountListToBeFreed;
|
||||||
if (!accounts) // Enable it if no proxy config for first launch of app
|
if (!accounts) // Enable it if no proxy config for first launch of app
|
||||||
[self setInteger:1 forKey:@"use_rls_presence"];
|
[self setInteger:1 forKey:@"use_rls_presence"];
|
||||||
else {
|
else {
|
||||||
|
|
@ -1110,6 +1124,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
linphone_address_unref(rls_addr);
|
linphone_address_unref(rls_addr);
|
||||||
|
bctbx_free(accountListToBeFreed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[lm lpConfigSetInt:[self integerForKey:@"use_rls_presence"] forKey:@"use_rls_presence"];
|
[lm lpConfigSetInt:[self integerForKey:@"use_rls_presence"] forKey:@"use_rls_presence"];
|
||||||
|
|
@ -1151,9 +1166,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)removeAccount {
|
- (void)removeAccount {
|
||||||
LinphoneAccount *account = bctbx_list_nth_data(linphone_core_get_account_list(LC),
|
|
||||||
|
MSList *accountList = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
LinphoneAccount *account = bctbx_list_nth_data(accountList,
|
||||||
[self integerForKey:@"current_proxy_config_preference"]);
|
[self integerForKey:@"current_proxy_config_preference"]);
|
||||||
|
|
||||||
|
|
||||||
const MSList *lists = linphone_core_get_friends_lists(LC);
|
const MSList *lists = linphone_core_get_friends_lists(LC);
|
||||||
while (lists) {
|
while (lists) {
|
||||||
linphone_friend_list_enable_subscriptions(lists->data, FALSE);
|
linphone_friend_list_enable_subscriptions(lists->data, FALSE);
|
||||||
|
|
@ -1174,11 +1192,12 @@
|
||||||
|
|
||||||
if (isDefault) {
|
if (isDefault) {
|
||||||
// if we removed the default proxy config, set another one instead
|
// if we removed the default proxy config, set another one instead
|
||||||
if (linphone_core_get_account_list(LC) != NULL) {
|
if (accountList != NULL) {
|
||||||
linphone_core_set_default_account(LC, (LinphoneAccount *)(linphone_core_get_account_list(LC)->data));
|
linphone_core_set_default_account(LC, (LinphoneAccount *)(accountList->data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[self transformLinphoneCoreToKeys];
|
[self transformLinphoneCoreToKeys];
|
||||||
|
bctbx_free(accountList);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)removeLdap {
|
- (void)removeLdap {
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ extern NSString *const kLinphoneConfStateParticipantListChanged;
|
||||||
extern NSString *const kLinphoneConfStateChanged;
|
extern NSString *const kLinphoneConfStateChanged;
|
||||||
extern NSString *const kLinphoneMagicSearchStarted;
|
extern NSString *const kLinphoneMagicSearchStarted;
|
||||||
extern NSString *const kLinphoneMagicSearchFinished;
|
extern NSString *const kLinphoneMagicSearchFinished;
|
||||||
|
extern NSString *const kLinphoneMagicSearchMoreAvailable;
|
||||||
|
extern NSString *const kDisplayModeChanged;
|
||||||
|
|
||||||
|
|
||||||
extern NSString *const kLinphoneMsgNotificationAppGroupId;
|
extern NSString *const kLinphoneMsgNotificationAppGroupId;
|
||||||
|
|
@ -174,6 +176,7 @@ typedef struct _LinphoneManagerSounds {
|
||||||
|
|
||||||
- (void)silentPushFailed:(NSTimer*)timer;
|
- (void)silentPushFailed:(NSTimer*)timer;
|
||||||
|
|
||||||
|
- (MSList *) createAccountsNotHiddenList; // needs to be unref
|
||||||
- (void)removeAllAccounts;
|
- (void)removeAllAccounts;
|
||||||
|
|
||||||
+ (BOOL)isMyself:(const LinphoneAddress *)addr;
|
+ (BOOL)isMyself:(const LinphoneAddress *)addr;
|
||||||
|
|
@ -192,6 +195,8 @@ typedef struct _LinphoneManagerSounds {
|
||||||
- (BOOL)isCTCallCenterExist;
|
- (BOOL)isCTCallCenterExist;
|
||||||
- (void) checkLocalNetworkPermission;
|
- (void) checkLocalNetworkPermission;
|
||||||
|
|
||||||
|
+ (BOOL) getChatroomPushEnabled:(LinphoneChatRoom *)chatroom;
|
||||||
|
+ (void) setChatroomPushEnabled:(LinphoneChatRoom *)chatroom withPushEnabled:(BOOL)enabled;
|
||||||
|
|
||||||
@property (readonly) BOOL isTesting;
|
@property (readonly) BOOL isTesting;
|
||||||
@property(readonly, strong) FastAddressBook *fastAddressBook;
|
@property(readonly, strong) FastAddressBook *fastAddressBook;
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@ NSString *const kLinphoneConfStateChanged = @"kLinphoneConfStateChanged";
|
||||||
NSString *const kLinphoneConfStateParticipantListChanged = @"kLinphoneConfStateParticipantListChanged";
|
NSString *const kLinphoneConfStateParticipantListChanged = @"kLinphoneConfStateParticipantListChanged";
|
||||||
NSString *const kLinphoneMagicSearchStarted = @"LinphoneMagicSearchStarted";
|
NSString *const kLinphoneMagicSearchStarted = @"LinphoneMagicSearchStarted";
|
||||||
NSString *const kLinphoneMagicSearchFinished = @"LinphoneMagicSearchFinished";
|
NSString *const kLinphoneMagicSearchFinished = @"LinphoneMagicSearchFinished";
|
||||||
|
NSString *const kLinphoneMagicSearchMoreAvailable = @"LinphoneMagicSearchMoreAvailable";
|
||||||
|
NSString *const kDisplayModeChanged = @"DisplayModeChanged";
|
||||||
|
|
||||||
NSString *const kLinphoneMsgNotificationAppGroupId = @"group.org.linphone.phone.msgNotification";
|
NSString *const kLinphoneMsgNotificationAppGroupId = @"group.org.linphone.phone.msgNotification";
|
||||||
|
|
||||||
|
|
@ -276,6 +278,14 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre
|
||||||
[self lpConfigSetString:@"conflate" forKey:@"handle_content_encoding" inSection:@"misc"];
|
[self lpConfigSetString:@"conflate" forKey:@"handle_content_encoding" inSection:@"misc"];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ([self lpConfigStringForKey:@"display_link_account_popup"] == nil) {
|
||||||
|
[self lpConfigSetBool:true forKey:@"display_link_account_popup"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([self lpConfigStringForKey:@"hide_link_phone_number"] == nil) {
|
||||||
|
[self lpConfigSetInt:1 forKey:@"hide_link_phone_number"];
|
||||||
|
}
|
||||||
|
|
||||||
[self migrateFromUserPrefs];
|
[self migrateFromUserPrefs];
|
||||||
[self loadAvatar];
|
[self loadAvatar];
|
||||||
|
|
@ -637,6 +647,11 @@ static void linphone_iphone_global_state_changed(LinphoneCore *lc, LinphoneGloba
|
||||||
if (theLinphoneCore && linphone_core_get_global_state(theLinphoneCore) != LinphoneGlobalOff)
|
if (theLinphoneCore && linphone_core_get_global_state(theLinphoneCore) != LinphoneGlobalOff)
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneGlobalStateUpdate object:self userInfo:dict];
|
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneGlobalStateUpdate object:self userInfo:dict];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (state == LinphoneGlobalOn) {
|
||||||
|
// reload friends
|
||||||
|
[self.fastAddressBook fetchContactsInBackGroundThread];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)globalStateChangedNotificationHandler:(NSNotification *)notif {
|
- (void)globalStateChangedNotificationHandler:(NSNotification *)notif {
|
||||||
|
|
@ -1254,7 +1269,7 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
|
||||||
[LinphoneManager.instance lpConfigSetInt:0 forKey:@"must_link_account_time"];
|
[LinphoneManager.instance lpConfigSetInt:0 forKey:@"must_link_account_time"];
|
||||||
} else {
|
} else {
|
||||||
LinphoneAccount *account = linphone_core_get_default_account(LC);
|
LinphoneAccount *account = linphone_core_get_default_account(LC);
|
||||||
LinphoneAccountParams const *accountParams = linphone_account_get_params(account);
|
LinphoneAccountParams const *accountParams = account ? linphone_account_get_params(account) : NULL;
|
||||||
if (account &&
|
if (account &&
|
||||||
strcmp(linphone_account_params_get_domain(accountParams),
|
strcmp(linphone_account_params_get_domain(accountParams),
|
||||||
[LinphoneManager.instance lpConfigStringForKey:@"domain_name"
|
[LinphoneManager.instance lpConfigStringForKey:@"domain_name"
|
||||||
|
|
@ -1275,7 +1290,14 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
|
||||||
handler:^(UIAlertAction * action) {
|
handler:^(UIAlertAction * action) {
|
||||||
[PhoneMainView.instance changeCurrentView:AssistantLinkView.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:AssistantLinkView.compositeViewDescription];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
UIAlertAction* otherAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Never ask again", nil)
|
||||||
|
style:UIAlertActionStyleDefault
|
||||||
|
handler:^(UIAlertAction * action) {
|
||||||
|
[LinphoneManager.instance lpConfigSetBool:false forKey:@"display_link_account_popup"];
|
||||||
|
}];
|
||||||
defaultAction.accessibilityLabel = @"Later";
|
defaultAction.accessibilityLabel = @"Later";
|
||||||
|
[errView addAction:otherAction];
|
||||||
[errView addAction:defaultAction];
|
[errView addAction:defaultAction];
|
||||||
[errView addAction:continueAction];
|
[errView addAction:continueAction];
|
||||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||||
|
|
@ -1294,7 +1316,7 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
|
||||||
NSDate *nextTime =
|
NSDate *nextTime =
|
||||||
[NSDate dateWithTimeIntervalSince1970:[self lpConfigIntForKey:@"must_link_account_time" withDefault:1]];
|
[NSDate dateWithTimeIntervalSince1970:[self lpConfigIntForKey:@"must_link_account_time" withDefault:1]];
|
||||||
NSDate *now = [NSDate date];
|
NSDate *now = [NSDate date];
|
||||||
if (nextTime.timeIntervalSince1970 > 0 && [now earlierDate:nextTime] == nextTime) {
|
if (nextTime.timeIntervalSince1970 > 0 && [now earlierDate:nextTime] == nextTime && [LinphoneManager.instance lpConfigBoolForKey:@"display_link_account_popup"] && ![LinphoneManager.instance lpConfigIntForKey:@"hide_link_phone_number"]) {
|
||||||
LinphoneAccount *account = linphone_core_get_default_account(LC);
|
LinphoneAccount *account = linphone_core_get_default_account(LC);
|
||||||
if (account) {
|
if (account) {
|
||||||
const char *username = linphone_address_get_username(linphone_account_params_get_identity_address(linphone_account_get_params(account)));
|
const char *username = linphone_address_get_username(linphone_account_params_get_identity_address(linphone_account_get_params(account)));
|
||||||
|
|
@ -1459,6 +1481,7 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
|
||||||
- (void)destroyLinphoneCore {
|
- (void)destroyLinphoneCore {
|
||||||
// just in case
|
// just in case
|
||||||
[self removeCTCallCenterCb];
|
[self removeCTCallCenterCb];
|
||||||
|
[MagicSearchSingleton destroyInstance];
|
||||||
|
|
||||||
if (theLinphoneCore != nil) { // just in case application terminate before linphone core initialization
|
if (theLinphoneCore != nil) { // just in case application terminate before linphone core initialization
|
||||||
|
|
||||||
|
|
@ -1488,8 +1511,6 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
|
||||||
- (void)resetLinphoneCore {
|
- (void)resetLinphoneCore {
|
||||||
[self destroyLinphoneCore];
|
[self destroyLinphoneCore];
|
||||||
[self createLinphoneCore];
|
[self createLinphoneCore];
|
||||||
// reload friends
|
|
||||||
[self.fastAddressBook fetchContactsInBackGroundThread];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int comp_call_id(const LinphoneCall *call, const char *callid) {
|
static int comp_call_id(const LinphoneCall *call, const char *callid) {
|
||||||
|
|
@ -1884,7 +1905,8 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
|
||||||
}
|
}
|
||||||
[self checkLocalNetworkPermission];
|
[self checkLocalNetworkPermission];
|
||||||
// For OutgoingCall, show CallOutgoingView
|
// For OutgoingCall, show CallOutgoingView
|
||||||
[CallManager.instance startCallWithAddr:iaddr isSas:FALSE isVideo:false isConference:false];
|
BOOL initiateVideoCall = linphone_core_get_video_activation_policy(LC) && linphone_video_activation_policy_get_automatically_initiate(linphone_core_get_video_activation_policy(LC));
|
||||||
|
[CallManager.instance startCallWithAddr:iaddr isSas:FALSE isVideo:initiateVideoCall isConference:false];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Misc Functions
|
#pragma mark - Misc Functions
|
||||||
|
|
@ -2210,6 +2232,23 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
|
- (MSList *) createAccountsNotHiddenList {
|
||||||
|
MSList *list = NULL;
|
||||||
|
const MSList *accounts = linphone_core_get_account_list(LC);
|
||||||
|
while (accounts) {
|
||||||
|
const char *isHidden = linphone_account_get_custom_param(accounts->data, "hidden");
|
||||||
|
if (isHidden == NULL || strcmp(linphone_account_get_custom_param(accounts->data, "hidden"), "1") != 0) {
|
||||||
|
if (!list) {
|
||||||
|
list = bctbx_list_new(accounts->data);
|
||||||
|
} else {
|
||||||
|
bctbx_list_append(list, accounts->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
accounts = accounts->next;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)removeAllAccounts {
|
- (void)removeAllAccounts {
|
||||||
linphone_core_clear_accounts(LC);
|
linphone_core_clear_accounts(LC);
|
||||||
linphone_core_clear_all_auth_info(LC);
|
linphone_core_clear_all_auth_info(LC);
|
||||||
|
|
@ -2303,6 +2342,31 @@ void linphone_iphone_conference_state_changed(LinphoneCore *lc, LinphoneConferen
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneConfStateChanged object:nil userInfo:dict];
|
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneConfStateChanged object:nil userInfo:dict];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (BOOL) getChatroomPushEnabled:(LinphoneChatRoom *)chatroom {
|
||||||
|
bool currently_enabled = true;
|
||||||
|
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:kLinphoneMsgNotificationAppGroupId];
|
||||||
|
NSDictionary *chatroomsPushStatus = [defaults dictionaryForKey:@"chatroomsPushStatus"];
|
||||||
|
if (chatroomsPushStatus != nil && chatroom) {
|
||||||
|
char *uri = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(chatroom));
|
||||||
|
NSString* pushStatus = [chatroomsPushStatus objectForKey:[NSString stringWithUTF8String:uri]];
|
||||||
|
currently_enabled = (pushStatus == nil) || [pushStatus isEqualToString:@"enabled"];
|
||||||
|
ms_free(uri);
|
||||||
|
}
|
||||||
|
return currently_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void) setChatroomPushEnabled:(LinphoneChatRoom *)chatroom withPushEnabled:(BOOL)enabled {
|
||||||
|
if (!chatroom) return;
|
||||||
|
|
||||||
|
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:kLinphoneMsgNotificationAppGroupId];
|
||||||
|
NSMutableDictionary *chatroomsPushStatus = [[NSMutableDictionary alloc] initWithDictionary:[defaults dictionaryForKey:@"chatroomsPushStatus"]];
|
||||||
|
if (chatroomsPushStatus == nil) chatroomsPushStatus = [[NSMutableDictionary dictionary] init];
|
||||||
|
|
||||||
|
char *uri = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(chatroom));
|
||||||
|
[chatroomsPushStatus setValue:(enabled ? @"enabled" : @"disabled") forKey:[NSString stringWithUTF8String:uri]];
|
||||||
|
ms_free(uri);
|
||||||
|
|
||||||
|
[defaults setObject:chatroomsPushStatus forKey:@"chatroomsPushStatus"];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</state>
|
</state>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="onSideMenuClick:" destination="-1" eventType="touchUpInside" id="iOC-wy-MPP"/>
|
<action selector="onQualityClick:" destination="-1" eventType="touchUpInside" id="Pir-Ib-ywJ"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
|
|
@ -81,6 +81,22 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="365" height="357"/>
|
<rect key="frame" x="0.0" y="0.0" width="365" height="357"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
<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="342" 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="352" y="346" 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="285" y="346" 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 contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VAJ-tE-fsa">
|
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VAJ-tE-fsa">
|
||||||
<rect key="frame" x="0.0" y="10" width="382" height="347"/>
|
<rect key="frame" x="0.0" y="10" width="382" height="347"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
|
@ -185,22 +201,6 @@
|
||||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||||
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
||||||
</textView>
|
</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">
|
<view tag="28021" contentMode="scaleToFill" id="bhq-9n-zYF" userLabel="voiceRecording">
|
||||||
<rect key="frame" x="7" y="252" width="351" height="60"/>
|
<rect key="frame" x="7" y="252" width="351" height="60"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
||||||
|
|
@ -261,7 +261,7 @@
|
||||||
<image name="color_M.png" width="2" height="2"/>
|
<image name="color_M.png" width="2" height="2"/>
|
||||||
<image name="ephemeral_messages_color_A.png" width="136" height="158.39999389648438"/>
|
<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="linphone_logo.png" width="41.599998474121094" height="42.400001525878906"/>
|
||||||
<image name="menu_reply_default.png" width="25" height="25"/>
|
<image name="menu_reply_default.png" width="60" height="60"/>
|
||||||
<image name="vr_play.png" width="200" height="200"/>
|
<image name="vr_play.png" width="200" height="200"/>
|
||||||
<image name="vr_wave.png" width="1078" height="90"/>
|
<image name="vr_wave.png" width="1078" height="90"/>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
||||||
</textView>
|
</textView>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="chat_read.png" translatesAutoresizingMaskIntoConstraints="NO" id="Nod-GX-0kg" userLabel="imdmIcon">
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="chat_read.png" translatesAutoresizingMaskIntoConstraints="NO" id="Nod-GX-0kg" userLabel="imdmIcon">
|
||||||
<rect key="frame" x="133" y="30" width="10" height="10"/>
|
<rect key="frame" x="133" y="28" width="10" height="10"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="00:00:00" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GDJ-O8-m6J" userLabel="ephemeralTime">
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="00:00:00" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GDJ-O8-m6J" userLabel="ephemeralTime">
|
||||||
|
|
@ -93,6 +93,6 @@
|
||||||
<image name="chat_read.png" width="20" height="20"/>
|
<image name="chat_read.png" width="20" height="20"/>
|
||||||
<image name="color_A.png" width="2" height="2"/>
|
<image name="color_A.png" width="2" height="2"/>
|
||||||
<image name="ephemeral_messages_color_A.png" width="136" height="158.39999389648438"/>
|
<image name="ephemeral_messages_color_A.png" width="136" height="158.39999389648438"/>
|
||||||
<image name="menu_reply_default.png" width="25" height="25"/>
|
<image name="menu_reply_default.png" width="60" height="60"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21207"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
|
|
@ -66,15 +66,11 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view hidden="YES" autoresizesSubviews="NO" userInteractionEnabled="NO" tag="7" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7DE-KJ-9Q3" userLabel="unreadCountView" customClass="UIBouncingView">
|
<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"/>
|
<rect key="frame" x="338" y="12" width="20" height="20"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" tag="8" contentMode="scaleAspectFit" fixedFrame="YES" image="chat_list_indicator.png" translatesAutoresizingMaskIntoConstraints="NO" id="NXj-A8-YLh" userLabel="unreadCountImage">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="21" height="21"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
|
||||||
</imageView>
|
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="9" contentMode="left" fixedFrame="YES" text="99" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="7" translatesAutoresizingMaskIntoConstraints="NO" id="ZXq-Do-7Ua" userLabel="unreadCountLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="9" contentMode="left" fixedFrame="YES" text="99" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="7" translatesAutoresizingMaskIntoConstraints="NO" id="ZXq-Do-7Ua" userLabel="unreadCountLabel">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="21" height="21"/>
|
<rect key="frame" x="0.0" y="0.0" width="20" height="20"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration">
|
<accessibility key="accessibilityConfiguration">
|
||||||
<accessibilityTraits key="traits" none="YES"/>
|
<accessibilityTraits key="traits" none="YES"/>
|
||||||
|
|
@ -88,11 +84,11 @@
|
||||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</view>
|
</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">
|
<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"/>
|
<rect key="frame" x="338" y="33" width="20" height="20"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</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">
|
<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"/>
|
<rect key="frame" x="338" y="54" width="20" height="20"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|
@ -103,7 +99,6 @@
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="avatar.png" width="414.39999389648438" height="414.39999389648438"/>
|
<image name="avatar.png" width="414.39999389648438" height="414.39999389648438"/>
|
||||||
<image name="chat_list_indicator.png" width="28" height="28"/>
|
|
||||||
<image name="chat_read.png" width="20" height="20"/>
|
<image name="chat_read.png" width="20" height="20"/>
|
||||||
<image name="ephemeral_messages_color_A.png" width="136" height="158.39999389648438"/>
|
<image name="ephemeral_messages_color_A.png" width="136" height="158.39999389648438"/>
|
||||||
<image name="forward_message_default.png" width="187" height="148"/>
|
<image name="forward_message_default.png" width="187" height="148"/>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
||||||
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
|
|
@ -23,18 +24,18 @@
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="Z2U-vm-azg" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="Z2U-vm-azg" userLabel="avatarImage" customClass="UIRoundedImageView">
|
||||||
<rect key="frame" x="0.0" y="5" width="44" height="28"/>
|
<rect key="frame" x="0.0" y="8" width="44" height="28"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" text="John Doe" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="f3q-pd-EF5" userLabel="displayNameLabel">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" text="John Doe" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="f3q-pd-EF5" userLabel="displayNameLabel">
|
||||||
<rect key="frame" x="43" y="11" width="185" height="16"/>
|
<rect key="frame" x="43" y="0.0" width="185" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" text="Today - 18h42" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hEV-7I-B0v" userLabel="contactDateLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" text="Today - 18h42" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hEV-7I-B0v" userLabel="contactDateLabel">
|
||||||
<rect key="frame" x="200" y="13" width="159" height="12"/>
|
<rect key="frame" x="229" y="16" width="130" height="12"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" heightSizable="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||||
|
|
@ -42,12 +43,15 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
<point key="canvasLocation" x="61.5" y="52"/>
|
<point key="canvasLocation" x="60" y="51.27436281859071"/>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="avatar.png" width="414.39999389648438" height="414.39999389648438"/>
|
<image name="avatar.png" width="414.39999389648438" height="414.39999389648438"/>
|
||||||
|
<systemColor name="systemBackgroundColor">
|
||||||
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
</systemColor>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<nil key="simulatedStatusBarMetrics"/>
|
<nil key="simulatedStatusBarMetrics"/>
|
||||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||||
<point key="canvasLocation" x="890.39999999999998" y="192.50374812593705"/>
|
<point key="canvasLocation" x="890.39999999999998" y="192.50374812593705"/>
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
|
||||||
<dependencies>
|
|
||||||
<deployment identifier="iOS"/>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
||||||
</dependencies>
|
|
||||||
<objects>
|
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
|
||||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="UIChatCreateCollectionViewCell">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="100" height="50"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="100" height="50"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
|
||||||
<subviews>
|
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="John Doe" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fHV-en-AZD" userLabel="displayNameLabel">
|
|
||||||
<rect key="frame" x="14" y="18" width="92" height="20"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" fixedFrame="YES" image="conference_delete.png" translatesAutoresizingMaskIntoConstraints="NO" id="yfP-hQ-SXb" userLabel="selectedImage">
|
|
||||||
<rect key="frame" x="1" y="23" width="10" height="10"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
|
||||||
</imageView>
|
|
||||||
</subviews>
|
|
||||||
</view>
|
|
||||||
<size key="customSize" width="170" height="45"/>
|
|
||||||
<connections>
|
|
||||||
<outlet property="nameLabel" destination="fHV-en-AZD" id="gOU-sp-v0V"/>
|
|
||||||
</connections>
|
|
||||||
<point key="canvasLocation" x="2" y="86"/>
|
|
||||||
</collectionViewCell>
|
|
||||||
</objects>
|
|
||||||
<resources>
|
|
||||||
<image name="conference_delete.png" width="17.600000381469727" height="17.600000381469727"/>
|
|
||||||
</resources>
|
|
||||||
</document>
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="contentCollection" destination="ZgY-Ye-8DD" id="hlD-Fw-g1z"/>
|
<outlet property="contentCollection" destination="ZgY-Ye-8DD" id="hlD-Fw-g1z"/>
|
||||||
<outlet property="dismissButton" destination="KrT-j6-YOy" id="K5m-Mw-Cjx"/>
|
<outlet property="dismissButton" destination="KrT-j6-YOy" id="K5m-Mw-Cjx"/>
|
||||||
|
<outlet property="icsIcon" destination="gkH-jk-DYU" id="Xkl-Ip-skO"/>
|
||||||
<outlet property="leftBar" destination="Iov-AL-8Xz" id="eKb-4B-unZ"/>
|
<outlet property="leftBar" destination="Iov-AL-8Xz" id="eKb-4B-unZ"/>
|
||||||
<outlet property="originalMessageGone" destination="B26-sw-o4w" id="Gwh-dh-GRN"/>
|
<outlet property="originalMessageGone" destination="B26-sw-o4w" id="Gwh-dh-GRN"/>
|
||||||
<outlet property="senderName" destination="uuW-tW-1Sj" id="Yao-6A-SBh"/>
|
<outlet property="senderName" destination="uuW-tW-1Sj" id="Yao-6A-SBh"/>
|
||||||
|
|
@ -68,6 +69,10 @@
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES"/>
|
||||||
<state key="normal" image="reply_cancel.png"/>
|
<state key="normal" image="reply_cancel.png"/>
|
||||||
</button>
|
</button>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="voip_meeting_schedule.png" translatesAutoresizingMaskIntoConstraints="NO" id="gkH-jk-DYU">
|
||||||
|
<rect key="frame" x="16" y="23" width="35" height="35"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
</imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
|
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
|
|
@ -77,6 +82,7 @@
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="reply_cancel.png" width="60" height="60"/>
|
<image name="reply_cancel.png" width="60" height="60"/>
|
||||||
|
<image name="voip_meeting_schedule.png" width="20" height="20"/>
|
||||||
<systemColor name="systemBackgroundColor">
|
<systemColor name="systemBackgroundColor">
|
||||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</systemColor>
|
</systemColor>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
|
|
@ -11,8 +11,10 @@
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="authButton" destination="lWW-wB-FMR" id="C7W-JM-WFQ"/>
|
<outlet property="authButton" destination="lWW-wB-FMR" id="C7W-JM-WFQ"/>
|
||||||
<outlet property="authView" destination="CCn-Oz-I0M" id="fSM-6k-paN"/>
|
<outlet property="authView" destination="CCn-Oz-I0M" id="fSM-6k-paN"/>
|
||||||
|
<outlet property="backgroundColor" destination="cqN-1f-6SE" id="gjg-LB-xLT"/>
|
||||||
<outlet property="cancelButton" destination="B1K-CB-3of" id="KKi-Xc-ldA"/>
|
<outlet property="cancelButton" destination="B1K-CB-3of" id="KKi-Xc-ldA"/>
|
||||||
<outlet property="confirmationButton" destination="SbQ-re-fGQ" id="yiv-a9-o8E"/>
|
<outlet property="confirmationButton" destination="SbQ-re-fGQ" id="yiv-a9-o8E"/>
|
||||||
|
<outlet property="firstView" destination="ef9-Iu-Bcb" id="hKx-op-r7Z"/>
|
||||||
<outlet property="forwardImage" destination="1Wh-Yi-cUe" id="YQq-bt-pk1"/>
|
<outlet property="forwardImage" destination="1Wh-Yi-cUe" id="YQq-bt-pk1"/>
|
||||||
<outlet property="groupCallImage" destination="SVn-4k-9yc" id="sAP-8V-ttn"/>
|
<outlet property="groupCallImage" destination="SVn-4k-9yc" id="sAP-8V-ttn"/>
|
||||||
<outlet property="securityImage" destination="bbo-g3-bGy" id="qZa-li-yrl"/>
|
<outlet property="securityImage" destination="bbo-g3-bGy" id="qZa-li-yrl"/>
|
||||||
|
|
@ -25,27 +27,32 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<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">
|
<view contentMode="scaleToFill" id="ef9-Iu-Bcb" userLabel="firstView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="377" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
</imageView>
|
</view>
|
||||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2BQ-o9-xv2">
|
<view contentMode="scaleToFill" id="2BQ-o9-xv2">
|
||||||
<rect key="frame" x="28" y="139" width="320" height="365"/>
|
<rect key="frame" x="25" y="114" width="325" height="440"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_C.png" translatesAutoresizingMaskIntoConstraints="NO" id="cqN-1f-6SE" userLabel="backgroundColor">
|
||||||
|
<rect key="frame" x="-17" y="-17" width="360" height="474"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" red="0.26666668059999998" green="0.26666668059999998" blue="0.26666668059999998" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
|
</imageView>
|
||||||
<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">
|
<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"/>
|
<rect key="frame" x="130" y="15" width="64" height="68"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<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">
|
<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"/>
|
<rect key="frame" x="-8" y="15" width="347" height="350"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="21"/>
|
<fontDescription key="fontDescription" type="system" pointSize="21"/>
|
||||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<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">
|
<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"/>
|
<rect key="frame" x="16" y="383" width="139" height="36"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" title="CANCEL" backgroundImage="color_H.png">
|
<state key="normal" title="CANCEL" backgroundImage="color_H.png">
|
||||||
<color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
|
@ -57,11 +64,11 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view hidden="YES" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" 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"/>
|
<rect key="frame" x="65" y="345" width="243" height="25"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" 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"/>
|
<rect key="frame" x="24" y="0.0" width="22" height="24"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" image="checkbox_unchecked.png"/>
|
<state key="normal" image="checkbox_unchecked.png"/>
|
||||||
<state key="selected" image="checkbox_checked.png"/>
|
<state key="selected" image="checkbox_checked.png"/>
|
||||||
|
|
@ -70,7 +77,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<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">
|
<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"/>
|
<rect key="frame" x="57" y="10" width="173" height="15"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
|
@ -79,7 +86,7 @@
|
||||||
</subviews>
|
</subviews>
|
||||||
</view>
|
</view>
|
||||||
<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">
|
<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"/>
|
<rect key="frame" x="177" y="383" width="136" height="36"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" title="DELETE" backgroundImage="color_I.png">
|
<state key="normal" title="DELETE" backgroundImage="color_I.png">
|
||||||
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
|
@ -91,17 +98,16 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</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">
|
<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"/>
|
<rect key="frame" x="100" y="50" width="136" height="54"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="voip_conference_new.png" translatesAutoresizingMaskIntoConstraints="NO" id="SVn-4k-9yc">
|
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="voip_conference_new.png" translatesAutoresizingMaskIntoConstraints="NO" id="SVn-4k-9yc">
|
||||||
<rect key="frame" x="89" y="50" width="138" height="54"/>
|
<rect key="frame" x="100" y="50" width="136" height="54"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
<nil key="simulatedStatusBarMetrics"/>
|
<nil key="simulatedStatusBarMetrics"/>
|
||||||
<point key="canvasLocation" x="871.20000000000005" y="261.31934032983509"/>
|
<point key="canvasLocation" x="871.20000000000005" y="261.31934032983509"/>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
@property(weak, nonatomic) IBOutlet UIView *outcallView;
|
@property(weak, nonatomic) IBOutlet UIView *outcallView;
|
||||||
|
|
||||||
- (IBAction)onSecurityClick:(id)sender;
|
- (IBAction)onSecurityClick:(id)sender;
|
||||||
|
- (IBAction)onQualityClick:(id)sender;
|
||||||
- (IBAction)onSideMenuClick:(id)sender;
|
- (IBAction)onSideMenuClick:(id)sender;
|
||||||
- (IBAction)onRegistrationStateClick:(id)sender;
|
- (IBAction)onRegistrationStateClick:(id)sender;
|
||||||
+ (UIImage *)imageForState:(LinphoneRegistrationState)state;
|
+ (UIImage *)imageForState:(LinphoneRegistrationState)state;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#import "LinphoneManager.h"
|
#import "LinphoneManager.h"
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
#import <UserNotifications/UserNotifications.h>
|
#import <UserNotifications/UserNotifications.h>
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
@implementation StatusBarView {
|
@implementation StatusBarView {
|
||||||
|
|
||||||
|
|
@ -193,11 +194,13 @@
|
||||||
message = NSLocalizedString(@"Fetching remote configuration", nil);
|
message = NSLocalizedString(@"Fetching remote configuration", nil);
|
||||||
} else if (account == NULL) {
|
} else if (account == NULL) {
|
||||||
state = LinphoneRegistrationNone;
|
state = LinphoneRegistrationNone;
|
||||||
if (linphone_core_get_account_list(LC) != NULL) {
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
if (accounts != NULL) {
|
||||||
message = NSLocalizedString(@"No default account", nil);
|
message = NSLocalizedString(@"No default account", nil);
|
||||||
} else {
|
} else {
|
||||||
message = NSLocalizedString(@"No account configured", nil);
|
message = NSLocalizedString(@"No account configured", nil);
|
||||||
}
|
}
|
||||||
|
bctbx_free(accounts);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
state = linphone_account_get_state(account);
|
state = linphone_account_get_state(account);
|
||||||
|
|
@ -329,14 +332,9 @@
|
||||||
correspondantCode = [code substringToIndex:2];
|
correspondantCode = [code substringToIndex:2];
|
||||||
myCode = [code substringFromIndex:2];
|
myCode = [code substringFromIndex:2];
|
||||||
}
|
}
|
||||||
NSString *message =
|
NSString *message = [NSString stringWithFormat:NSLocalizedString(@"\nCommunication security:\n\nTo raise the security level, you can check the following codes with your correspondent.\n\nSay: %1$@\n\nYour correspondent must say: %2$@", nil),
|
||||||
[NSString stringWithFormat:NSLocalizedString(@"\nConfirmation security\n\n"
|
myCode.uppercaseString, correspondantCode.uppercaseString];
|
||||||
@"Say: %@\n"
|
|
||||||
@"Confirm that your interlocutor\n"
|
|
||||||
@"says: %@",
|
|
||||||
nil),
|
|
||||||
myCode.uppercaseString, correspondantCode.uppercaseString];
|
|
||||||
|
|
||||||
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive &&
|
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive &&
|
||||||
floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
|
floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
|
||||||
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
|
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
|
||||||
|
|
@ -368,14 +366,14 @@
|
||||||
UIFont *baseFont = [UIFont systemFontOfSize:21.0];
|
UIFont *baseFont = [UIFont systemFontOfSize:21.0];
|
||||||
[attrString addAttribute:NSFontAttributeName value:baseFont range:NSMakeRange(0, length)];
|
[attrString addAttribute:NSFontAttributeName value:baseFont range:NSMakeRange(0, length)];
|
||||||
UIFont *boldFont = [UIFont boldSystemFontOfSize:23.0];
|
UIFont *boldFont = [UIFont boldSystemFontOfSize:23.0];
|
||||||
[attrString addAttribute:NSFontAttributeName value:boldFont range:[message rangeOfString:@"Confirmation security"]];
|
[attrString addAttribute:NSFontAttributeName value:boldFont range:[message rangeOfString:@"Communication security"]];
|
||||||
UIColor *color = [UIColor colorWithRed:(150 / 255.0) green:(193 / 255.0) blue:(31 / 255.0) alpha:1.0];
|
UIColor *color = [UIColor colorWithRed:(150 / 255.0) green:(193 / 255.0) blue:(31 / 255.0) alpha:1.0];
|
||||||
[attrString addAttribute:NSForegroundColorAttributeName value:color range:[message rangeOfString:myCode.uppercaseString]];
|
[attrString addAttribute:NSForegroundColorAttributeName value:color range:[message rangeOfString:myCode.uppercaseString]];
|
||||||
[attrString addAttribute:NSForegroundColorAttributeName value:color range:[message rangeOfString:correspondantCode.uppercaseString]];
|
[attrString addAttribute:NSForegroundColorAttributeName value:color range:[message rangeOfString:correspondantCode.uppercaseString]];
|
||||||
|
|
||||||
securityDialog = [UIConfirmationDialog ShowWithAttributedMessage:attrString
|
securityDialog = [UIConfirmationDialog ShowWithAttributedMessage:attrString
|
||||||
cancelMessage:NSLocalizedString(@"DENY", nil)
|
cancelMessage:NSLocalizedString(@"Later", nil)
|
||||||
confirmMessage:NSLocalizedString(@"ACCEPT", nil)
|
confirmMessage:NSLocalizedString(@"Correct", nil)
|
||||||
onCancelClick:^() {
|
onCancelClick:^() {
|
||||||
if (linphone_core_get_current_call(LC) == call) {
|
if (linphone_core_get_current_call(LC) == call) {
|
||||||
linphone_call_set_authentication_token_verified(call, NO);
|
linphone_call_set_authentication_token_verified(call, NO);
|
||||||
|
|
@ -393,6 +391,7 @@
|
||||||
|
|
||||||
securityDialog.securityImage.hidden = FALSE;
|
securityDialog.securityImage.hidden = FALSE;
|
||||||
[securityDialog setSpecialColor];
|
[securityDialog setSpecialColor];
|
||||||
|
[securityDialog setWhiteCancel];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -400,6 +399,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IBAction)onQualityClick:(id)sender {
|
||||||
|
[ControlsViewModelBridge toggleStatsVisibility];
|
||||||
|
}
|
||||||
|
|
||||||
- (IBAction)onSideMenuClick:(id)sender {
|
- (IBAction)onSideMenuClick:(id)sender {
|
||||||
UICompositeView *cvc = PhoneMainView.instance.mainViewController;
|
UICompositeView *cvc = PhoneMainView.instance.mainViewController;
|
||||||
[cvc hideSideMenu:(cvc.sideMenuView.frame.origin.x == 0)];
|
[cvc hideSideMenu:(cvc.sideMenuView.frame.origin.x == 0)];
|
||||||
|
|
@ -408,10 +411,15 @@
|
||||||
- (IBAction)onRegistrationStateClick:(id)sender {
|
- (IBAction)onRegistrationStateClick:(id)sender {
|
||||||
if (linphone_core_get_default_account(LC)) {
|
if (linphone_core_get_default_account(LC)) {
|
||||||
linphone_core_refresh_registers(LC);
|
linphone_core_refresh_registers(LC);
|
||||||
} else if (linphone_core_get_account_list(LC)) {
|
|
||||||
[PhoneMainView.instance changeCurrentView:SettingsView.compositeViewDescription];
|
|
||||||
} else {
|
} else {
|
||||||
[PhoneMainView.instance changeCurrentView:AssistantView.compositeViewDescription];
|
|
||||||
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
if (accounts) {
|
||||||
|
[PhoneMainView.instance changeCurrentView:SettingsView.compositeViewDescription];
|
||||||
|
} else {
|
||||||
|
[PhoneMainView.instance changeCurrentView:AssistantView.compositeViewDescription];
|
||||||
|
}
|
||||||
|
bctbx_free(accounts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onBackToCallClick:(id)sender {
|
- (IBAction)onBackToCallClick:(id)sender {
|
||||||
[PhoneMainView.instance popToView:ActiveCallOrConferenceView.compositeViewDescription];
|
[PhoneMainView.instance popToView:[CallsViewModelBridge callViewToDisplay]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -192,14 +192,20 @@
|
||||||
_voiceRecordingFile = nil;
|
_voiceRecordingFile = nil;
|
||||||
LinphoneContent *voiceContent = [UIChatBubbleTextCell voiceContent:self.message];
|
LinphoneContent *voiceContent = [UIChatBubbleTextCell voiceContent:self.message];
|
||||||
if (voiceContent) {
|
if (voiceContent) {
|
||||||
_voiceRecordingFile = [NSString stringWithUTF8String:[VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId] ? linphone_content_get_plain_file_path(voiceContent) : linphone_content_get_file_path(voiceContent)];
|
const char *fileName = ([VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId] ? linphone_content_get_plain_file_path(voiceContent) : linphone_content_get_file_path(voiceContent));
|
||||||
if ([VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId])
|
if (fileName == nil) {
|
||||||
|
linphone_content_set_file_path(voiceContent, [[LinphoneManager imagesDirectory] stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]].UTF8String);
|
||||||
|
linphone_chat_message_download_content(self.message, voiceContent);
|
||||||
|
}
|
||||||
|
_voiceRecordingFile = fileName ? [NSString stringWithUTF8String:fileName] : nil;
|
||||||
|
if (fileName && [VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId]) {
|
||||||
[encrptedFilePaths setValue:_voiceRecordingFile forKey:[NSString stringWithUTF8String:linphone_content_get_name(voiceContent)]];
|
[encrptedFilePaths setValue:_voiceRecordingFile forKey:[NSString stringWithUTF8String:linphone_content_get_name(voiceContent)]];
|
||||||
|
}
|
||||||
_vrTimerLabel.text = [self formattedDuration:linphone_content_get_file_duration(voiceContent)/1000];
|
_vrTimerLabel.text = [self formattedDuration:linphone_content_get_file_duration(voiceContent)/1000];
|
||||||
_vrWaveMaskPlayback.frame = CGRectZero;
|
_vrWaveMaskPlayback.frame = CGRectZero;
|
||||||
_vrWaveMaskPlayback.backgroundColor = linphone_chat_message_is_outgoing(self.message) ? UIColor.orangeColor : UIColor.grayColor;
|
_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);
|
const bctbx_list_t *contents = linphone_chat_message_get_contents(self.message);
|
||||||
|
|
||||||
size_t contentCount = bctbx_list_size(contents);
|
size_t contentCount = bctbx_list_size(contents);
|
||||||
|
|
@ -234,7 +240,8 @@
|
||||||
if (strcmp(cPath, "") != 0) {
|
if (strcmp(cPath, "") != 0) {
|
||||||
NSString *tempPath = [NSString stringWithUTF8String:cPath];
|
NSString *tempPath = [NSString stringWithUTF8String:cPath];
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||||
filePath = [paths objectAtIndex:0];
|
filePath = [NSString stringWithFormat:@"%@/%s", [paths objectAtIndex:0],linphone_chat_message_get_message_id(super.message)];
|
||||||
|
[FileUtil ensureDirectoryExistsWithPath:filePath];
|
||||||
filePath = [filePath stringByAppendingPathComponent:name];
|
filePath = [filePath stringByAppendingPathComponent:name];
|
||||||
[[NSFileManager defaultManager] moveItemAtPath:tempPath toPath:filePath error:nil];
|
[[NSFileManager defaultManager] moveItemAtPath:tempPath toPath:filePath error:nil];
|
||||||
}
|
}
|
||||||
|
|
@ -300,7 +307,8 @@
|
||||||
if (strcmp(cPath, "") != 0) {
|
if (strcmp(cPath, "") != 0) {
|
||||||
NSString *tempPath = [NSString stringWithUTF8String:cPath];
|
NSString *tempPath = [NSString stringWithUTF8String:cPath];
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||||
filePath = [paths objectAtIndex:0];
|
filePath = [NSString stringWithFormat:@"%@/%s", [paths objectAtIndex:0],linphone_chat_message_get_message_id(super.message)];
|
||||||
|
[FileUtil ensureDirectoryExistsWithPath:filePath];
|
||||||
filePath = [filePath stringByAppendingPathComponent:fileName];
|
filePath = [filePath stringByAppendingPathComponent:fileName];
|
||||||
[[NSFileManager defaultManager] moveItemAtPath:tempPath toPath:filePath error:nil];
|
[[NSFileManager defaultManager] moveItemAtPath:tempPath toPath:filePath error:nil];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,8 @@
|
||||||
[self setFrame:CGRectMake(0, 0, sub.frame.size.width, sub.frame.size.height)];
|
[self setFrame:CGRectMake(0, 0, sub.frame.size.width, sub.frame.size.height)];
|
||||||
[self addSubview:sub];
|
[self addSubview:sub];
|
||||||
self.icsBubbleView = [[ICSBubbleView alloc] init];
|
self.icsBubbleView = [[ICSBubbleView alloc] init];
|
||||||
self.icsBubbleView.frame = CGRectMake(_messageText.frame.origin.x, _messageText.frame.origin.y+25, CONFERENCE_INVITATION_WIDTH-80, CONFERENCE_INVITATION_HEIGHT-20);
|
|
||||||
[self.innerView addSubview:self.icsBubbleView];
|
[self.innerView addSubview:self.icsBubbleView];
|
||||||
[(ICSBubbleView*)self.icsBubbleView setLayoutConstraintsWithView:self.backgroundColorImage];
|
[(ICSBubbleView*)self.icsBubbleView setLayoutConstraintsWithView:self.backgroundColorImage];
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +166,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_messageText && ![LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:_message]) {
|
if (_messageText && ![LinphoneManager getMessageAppDataForKey:@"localvideo" inMessage:_message] && ![ICSBubbleView isConferenceInvitationMessageWithCmessage:self.message]) {
|
||||||
[_messageText setHidden:FALSE];
|
[_messageText setHidden:FALSE];
|
||||||
/* We need to use an attributed string here so that data detector don't mess
|
/* We need to use an attributed string here so that data detector don't mess
|
||||||
* with the text style. See http://stackoverflow.com/a/20669356 */
|
* with the text style. See http://stackoverflow.com/a/20669356 */
|
||||||
|
|
@ -346,8 +344,10 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
|
||||||
}
|
}
|
||||||
|
|
||||||
static void participant_imdn_status(LinphoneChatMessage* msg, const LinphoneParticipantImdnState *state) {
|
static void participant_imdn_status(LinphoneChatMessage* msg, const LinphoneParticipantImdnState *state) {
|
||||||
ChatConversationImdnView *imdnView = VIEW(ChatConversationImdnView);
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[imdnView updateImdnList];
|
ChatConversationImdnView *imdnView = VIEW(ChatConversationImdnView);
|
||||||
|
[imdnView updateImdnList];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)displayImdmStatus:(LinphoneChatMessageState)state {
|
- (void)displayImdmStatus:(LinphoneChatMessageState)state {
|
||||||
|
|
@ -399,7 +399,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGSize size = [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_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;
|
size.height += linphone_chat_message_is_reply(chat) ? REPLY_CHAT_BUBBLE_HEIGHT+5 : 0;
|
||||||
|
|
||||||
|
|
@ -491,7 +491,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
+ (CGSize)ViewHeightForMessageText:(LinphoneChatMessage *)chat withWidth:(int)width textForImdn:(NSString *)imdnText {
|
+ (CGSize)ViewHeightForMessageText:(LinphoneChatMessage *)chat withWidth:(int)width textForImdn:(NSString *)imdnText {
|
||||||
|
|
||||||
if ([ICSBubbleView isConferenceInvitationMessageWithCmessage:chat]) {
|
if ([ICSBubbleView isConferenceInvitationMessageWithCmessage:chat]) {
|
||||||
return CGSizeMake(CONFERENCE_INVITATION_WIDTH, CONFERENCE_INVITATION_HEIGHT);
|
return CGSizeMake(CONFERENCE_INVITATION_WIDTH, CONFERENCE_INVITATION_HEIGHT+[ICSBubbleView getDescriptionHeightFromContentWithCmessage:chat]);
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *messageText = [UIChatBubbleTextCell TextMessageForChat:chat];
|
NSString *messageText = [UIChatBubbleTextCell TextMessageForChat:chat];
|
||||||
|
|
@ -791,6 +791,8 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
|
|
||||||
_replyTransferIcon.hidden = ! linphone_chat_message_is_reply(_message) && !linphone_chat_message_is_forward(_message);
|
_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);
|
_replyTransferLabel.hidden = ! linphone_chat_message_is_reply(_message) && !linphone_chat_message_is_forward(_message);
|
||||||
|
[(ICSBubbleView*)self.icsBubbleView updateTopLayoutConstraintsWithView:self.backgroundColorImage replyOrForward:linphone_chat_message_is_reply(_message)||linphone_chat_message_is_forward(_message)];
|
||||||
|
|
||||||
|
|
||||||
if (linphone_chat_message_is_reply(_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);
|
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);
|
||||||
|
|
@ -848,10 +850,13 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
|
|
||||||
-(void) buildActions {
|
-(void) buildActions {
|
||||||
LinphoneChatMessage *message = self.message;
|
LinphoneChatMessage *message = self.message;
|
||||||
|
LinphoneEventLog *event = self.event;
|
||||||
|
|
||||||
_messageActionsTitles = [[NSMutableArray alloc] init];
|
_messageActionsTitles = [[NSMutableArray alloc] init];
|
||||||
_messageActionsBlocks = [[NSMutableArray alloc] init];
|
_messageActionsBlocks = [[NSMutableArray alloc] init];
|
||||||
_messageActionsIcons = [[NSMutableArray alloc] init];
|
_messageActionsIcons = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
[VIEW(ChatConversationView).messageField resignFirstResponder];
|
||||||
UIChatBubbleTextCell *thiz = self;
|
UIChatBubbleTextCell *thiz = self;
|
||||||
|
|
||||||
LinphoneChatMessageState state = linphone_chat_message_get_state(self.message);
|
LinphoneChatMessageState state = linphone_chat_message_get_state(self.message);
|
||||||
|
|
@ -869,7 +874,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (linphone_chat_message_get_utf8_text(message)) {
|
if (linphone_chat_message_get_utf8_text(message) && ![ICSBubbleView isConferenceInvitationMessageWithCmessage:message]) {
|
||||||
[_messageActionsTitles addObject:NSLocalizedString(@"Copy text", nil)];
|
[_messageActionsTitles addObject:NSLocalizedString(@"Copy text", nil)];
|
||||||
[_messageActionsIcons addObject:@"menu_copy_text_default"];
|
[_messageActionsIcons addObject:@"menu_copy_text_default"];
|
||||||
[_messageActionsBlocks addObject:^{
|
[_messageActionsBlocks addObject:^{
|
||||||
|
|
@ -896,16 +901,43 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
[VIEW(ChatConversationView) initiateReplyViewForMessage:message];
|
[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) {
|
LinphoneChatRoom *chatroom = linphone_chat_message_get_chat_room(self.message);
|
||||||
|
|
||||||
|
if (linphone_chat_room_get_nb_participants(chatroom) > 1) {
|
||||||
[_messageActionsTitles addObject:NSLocalizedString(@"Infos", nil)];
|
[_messageActionsTitles addObject:NSLocalizedString(@"Infos", nil)];
|
||||||
[_messageActionsIcons addObject:@"menu_info"];
|
[_messageActionsIcons addObject:@"menu_info"];
|
||||||
[_messageActionsBlocks addObject:^{
|
[_messageActionsBlocks addObject:^{
|
||||||
[thiz dismissPopup];
|
[thiz dismissPopup];
|
||||||
ChatConversationImdnView *view = VIEW(ChatConversationImdnView);
|
ChatConversationImdnView *view = VIEW(ChatConversationImdnView);
|
||||||
view.msg = message;
|
view.event = event;
|
||||||
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!linphone_chat_message_is_outgoing(self.message)
|
||||||
|
&& [FastAddressBook getContactWithAddress:linphone_chat_message_get_from_address(self.message)] == nil
|
||||||
|
&& !(linphone_chat_room_get_capabilities(chatroom) & LinphoneChatRoomCapabilitiesOneToOne) ) {
|
||||||
|
|
||||||
|
LinphoneAddress *fromAddress = linphone_address_clone(linphone_chat_message_get_from_address(self.message));
|
||||||
|
[_messageActionsTitles addObject:NSLocalizedString(@"Add to contact", nil)];
|
||||||
|
[_messageActionsIcons addObject:@"contact_add_default"];
|
||||||
|
[_messageActionsBlocks addObject:^{
|
||||||
|
[thiz dismissPopup];
|
||||||
|
linphone_address_clean(fromAddress);
|
||||||
|
char *lAddress = linphone_address_as_string_uri_only(fromAddress);
|
||||||
|
if (lAddress != NULL) {
|
||||||
|
NSString *normSip = [NSString stringWithUTF8String:lAddress];
|
||||||
|
normSip = [normSip hasPrefix:@"sip:"] ? [normSip substringFromIndex:4] : normSip;
|
||||||
|
normSip = [normSip hasPrefix:@"sips:"] ? [normSip substringFromIndex:5] : normSip;
|
||||||
|
[ContactSelection setAddAddress:normSip];
|
||||||
|
[ContactSelection setSelectionMode:ContactSelectionModeEdit];
|
||||||
|
[ContactSelection enableSipFilter:FALSE];
|
||||||
|
[PhoneMainView.instance changeCurrentView:ContactsListView.compositeViewDescription];
|
||||||
|
ms_free(lAddress);
|
||||||
|
}
|
||||||
|
linphone_address_unref(fromAddress);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
[_messageActionsTitles addObject:NSLocalizedString(@"Delete", nil)];
|
[_messageActionsTitles addObject:NSLocalizedString(@"Delete", nil)];
|
||||||
[_messageActionsIcons addObject:@"menu_delete"];
|
[_messageActionsIcons addObject:@"menu_delete"];
|
||||||
|
|
@ -930,7 +962,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
int cellHeight = 45;
|
int cellHeight = 45;
|
||||||
int numberOfItems = (int) _messageActionsTitles.count;
|
int numberOfItems = (int) _messageActionsTitles.count;
|
||||||
CGRect screenRect = UIScreen.mainScreen.bounds;
|
CGRect screenRect = UIScreen.mainScreen.bounds;
|
||||||
int menuHeight = numberOfItems * cellHeight + 15;
|
int menuHeight = numberOfItems * cellHeight;
|
||||||
|
|
||||||
CGRect frame = CGRectMake(
|
CGRect frame = CGRectMake(
|
||||||
linphone_chat_message_is_outgoing(self.message) ? screenRect.size.width - width - 10 : 10,
|
linphone_chat_message_is_outgoing(self.message) ? screenRect.size.width - width - 10 : 10,
|
||||||
|
|
@ -942,7 +974,8 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
_popupMenu.scrollEnabled = false;
|
_popupMenu.scrollEnabled = false;
|
||||||
_popupMenu.dataSource = self;
|
_popupMenu.dataSource = self;
|
||||||
_popupMenu.delegate = self;
|
_popupMenu.delegate = self;
|
||||||
|
_popupMenu.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||||
|
|
||||||
_popupMenu.layer.masksToBounds = false;
|
_popupMenu.layer.masksToBounds = false;
|
||||||
|
|
||||||
_popupMenu.layer.shadowColor = [UIColor darkGrayColor].CGColor;
|
_popupMenu.layer.shadowColor = [UIColor darkGrayColor].CGColor;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
#import "LinphoneManager.h"
|
#import "LinphoneManager.h"
|
||||||
#import "Utils.h"
|
#import "Utils.h"
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
@implementation UIChatCell
|
@implementation UIChatCell
|
||||||
|
|
||||||
|
|
@ -38,6 +39,10 @@
|
||||||
[self addSubview:sub];
|
[self addSubview:sub];
|
||||||
}
|
}
|
||||||
[_imdmIcon setHidden:TRUE];
|
[_imdmIcon setHidden:TRUE];
|
||||||
|
_unreadCountView.backgroundColor = VoipTheme.primary_color;
|
||||||
|
_unreadCountView.layer.cornerRadius = 10;
|
||||||
|
_unreadCountView.clipsToBounds = true;
|
||||||
|
_unreadCountLabel.textAlignment = NSTextAlignmentCenter;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,7 +137,8 @@
|
||||||
_chatContentLabel.frame = newFrame;
|
_chatContentLabel.frame = newFrame;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
NSString *text = [[FastAddressBook displayNameForAddress:linphone_chat_message_get_from_address(last_msg)]
|
NSString *conferenceInfo = [ICSBubbleView getConferenceSummaryWithCmessage:last_msg];
|
||||||
|
NSString *text = conferenceInfo != nil ? conferenceInfo : [[FastAddressBook displayNameForAddress:linphone_chat_message_get_from_address(last_msg)]
|
||||||
stringByAppendingFormat:@" : %@", [UIChatBubbleTextCell TextMessageForChat:last_msg]];
|
stringByAppendingFormat:@" : %@", [UIChatBubbleTextCell TextMessageForChat:last_msg]];
|
||||||
// shorten long messages
|
// shorten long messages
|
||||||
/*if ([text length] > 50)
|
/*if ([text length] > 50)
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,8 @@
|
||||||
#import "ChatConversationCreateView.h"
|
#import "ChatConversationCreateView.h"
|
||||||
|
|
||||||
@interface UIChatCreateCollectionViewCell : UICollectionViewCell
|
@interface UIChatCreateCollectionViewCell : UICollectionViewCell
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
|
@property UILabel *nameLabel;
|
||||||
@property (strong, nonatomic) ChatConversationCreateView *controller;
|
@property (strong, nonatomic) ChatConversationCreateView *controller;
|
||||||
@property (strong, nonatomic) NSString *uri;
|
@property (strong, nonatomic) NSString *uri;
|
||||||
- (id)initWithName:(NSString *)identifier;
|
|
||||||
- (void)onDelete;
|
- (void)onDelete;
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -18,27 +18,31 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import "UIChatCreateCollectionViewCell.h"
|
#import "UIChatCreateCollectionViewCell.h"
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
@implementation UIChatCreateCollectionViewCell
|
@implementation UIChatCreateCollectionViewCell
|
||||||
- (void)awakeFromNib {
|
|
||||||
[super awakeFromNib];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)initWithName:(NSString *)identifier {
|
|
||||||
if (self != nil) {
|
|
||||||
NSArray *arrayOfViews =
|
|
||||||
[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil];
|
|
||||||
if ([arrayOfViews count] >= 1) {
|
|
||||||
UIChatCreateCollectionViewCell *sub = ((UIChatCreateCollectionViewCell *)[arrayOfViews objectAtIndex:0]);
|
|
||||||
[self addSubview:sub];
|
|
||||||
_nameLabel = sub.nameLabel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[_nameLabel setText:identifier];
|
|
||||||
|
|
||||||
|
- (id)initWithFrame:(CGRect)frame {
|
||||||
|
self = [super initWithFrame:frame];
|
||||||
|
self.contentView.translatesAutoresizingMaskIntoConstraints = false;
|
||||||
|
[SnapkitBridge matchParentDimensionsWithView:self.contentView topInset:10];
|
||||||
|
|
||||||
|
self.nameLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||||
|
self.nameLabel.numberOfLines = 1;
|
||||||
|
[self.contentView addSubview:self.nameLabel];
|
||||||
|
[SnapkitBridge matchParentDimensionsWithView:self.nameLabel leftInset:20];
|
||||||
|
[SnapkitBridge heightWithView:self heiht:50];
|
||||||
|
|
||||||
|
UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"conference_delete"]];
|
||||||
|
image.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
|
[self.contentView addSubview:image];
|
||||||
|
[SnapkitBridge squareWithView:image size:15];
|
||||||
|
[SnapkitBridge alignParentLeftWithView:image];
|
||||||
|
[SnapkitBridge centerYWithView:image];
|
||||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onDelete)];
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onDelete)];
|
||||||
tap.numberOfTouchesRequired = 1;
|
tap.numberOfTouchesRequired = 1;
|
||||||
[self addGestureRecognizer:tap];
|
[image addGestureRecognizer:tap];
|
||||||
|
image.userInteractionEnabled = true;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,4 +64,6 @@
|
||||||
[_controller.tableController.tableView reloadData];
|
[_controller.tableController.tableView reloadData];
|
||||||
_controller.nextButton.enabled = (_controller.tableController.contactsGroup.count > 0) || _controller.isForEditing;
|
_controller.nextButton.enabled = (_controller.tableController.contactsGroup.count > 0) || _controller.isForEditing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
@property (weak, nonatomic) IBOutlet UICollectionView *contentCollection;
|
@property (weak, nonatomic) IBOutlet UICollectionView *contentCollection;
|
||||||
@property NSArray *dataContent;
|
@property NSArray *dataContent;
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *originalMessageGone;
|
@property (weak, nonatomic) IBOutlet UILabel *originalMessageGone;
|
||||||
|
@property (weak, nonatomic) IBOutlet UIImageView *icsIcon;
|
||||||
|
|
||||||
-(void) configureForMessage:(LinphoneChatMessage *)message withDimissBlock:(void (^)(void))dismissBlock hideDismiss:(BOOL)hideDismiss withClickBlock:(void (^)(void))clickBlock;
|
-(void) configureForMessage:(LinphoneChatMessage *)message withDimissBlock:(void (^)(void))dismissBlock hideDismiss:(BOOL)hideDismiss withClickBlock:(void (^)(void))clickBlock;
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
-(void) viewDidLoad {
|
-(void) viewDidLoad {
|
||||||
_contentCollection.dataSource = self;
|
_contentCollection.dataSource = self;
|
||||||
|
[_icsIcon setImageNamed:@"voip_meeting_schedule" tintColor:VoipTheme.voip_dark_gray];
|
||||||
[_contentCollection registerClass:UICollectionViewCell.class forCellWithReuseIdentifier:@"dataContent"];
|
[_contentCollection registerClass:UICollectionViewCell.class forCellWithReuseIdentifier:@"dataContent"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,6 +52,7 @@
|
||||||
_contentCollection.hidden = true;
|
_contentCollection.hidden = true;
|
||||||
_senderName.hidden = true;
|
_senderName.hidden = true;
|
||||||
_originalMessageGone.hidden = false;
|
_originalMessageGone.hidden = false;
|
||||||
|
_icsIcon.hidden = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hideDismiss) {
|
if (hideDismiss) {
|
||||||
|
|
@ -60,9 +62,12 @@
|
||||||
_originalMessageGone.hidden = true;
|
_originalMessageGone.hidden = true;
|
||||||
self.message = message;
|
self.message = message;
|
||||||
self.dataContent = [self loadDataContent];
|
self.dataContent = [self loadDataContent];
|
||||||
|
BOOL isIcal = [ICSBubbleView isConferenceInvitationMessageWithCmessage:message];
|
||||||
|
_icsIcon.hidden = !isIcal;
|
||||||
|
|
||||||
NSString *sender = [FastAddressBook displayNameForAddress:linphone_chat_message_get_from_address(message)];
|
NSString *sender = [FastAddressBook displayNameForAddress:linphone_chat_message_get_from_address(message)];
|
||||||
_senderName.text = sender;
|
_senderName.text = sender;
|
||||||
const char * text = linphone_chat_message_get_text_content(message);
|
const char * text = isIcal ? [ICSBubbleView getSubjectFromContentWithCmessage:message].UTF8String : linphone_chat_message_get_text_content(message);
|
||||||
if (text && strlen(text) == 0)
|
if (text && strlen(text) == 0)
|
||||||
text = nil;
|
text = nil;
|
||||||
_textContent.text = text ? [NSString stringWithUTF8String:text] : @"";
|
_textContent.text = text ? [NSString stringWithUTF8String:text] : @"";
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,8 @@
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
- (void)accessoryForCell:(UITableViewCell *)cell atPath:(NSIndexPath *)indexPath {
|
- (void)accessoryForCell:(UITableViewCell *)cell atPath:(NSIndexPath *)indexPath {
|
||||||
cell.selectionStyle = UITableViewCellSelectionStyleGray;
|
|
||||||
if ([self isEditing]) {
|
if ([self isEditing]) {
|
||||||
|
cell.selectionStyle = UITableViewCellSelectionStyleGray;
|
||||||
UIButton *checkBoxButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
UIButton *checkBoxButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
UIImage *image = nil;
|
UIImage *image = nil;
|
||||||
if ([_selectedItems containsObject:indexPath]) {
|
if ([_selectedItems containsObject:indexPath]) {
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@
|
||||||
- (UIViewController *)getCurrentViewController;
|
- (UIViewController *)getCurrentViewController;
|
||||||
- (UIInterfaceOrientation)currentOrientation;
|
- (UIInterfaceOrientation)currentOrientation;
|
||||||
- (void)clearCache:(NSArray *)exclude;
|
- (void)clearCache:(NSArray *)exclude;
|
||||||
|
- (void)removeEntryFromCache:(NSString *)key;
|
||||||
- (IBAction)onRightSwipe:(id)sender;
|
- (IBAction)onRightSwipe:(id)sender;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,9 @@
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)removeEntryFromCache:(NSString *)key {
|
||||||
|
[viewControllerCache removeObjectForKey:key];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)clearCache:(NSArray *)exclude {
|
- (void)clearCache:(NSArray *)exclude {
|
||||||
|
|
||||||
|
|
@ -313,7 +316,7 @@
|
||||||
bool remove = true;
|
bool remove = true;
|
||||||
|
|
||||||
/*ImagePickerView can be used as popover and we do NOT want to free it*/;
|
/*ImagePickerView can be used as popover and we do NOT want to free it*/;
|
||||||
if ([key isEqualToString:ImagePickerView.compositeViewDescription.name] || [key isEqualToString:ActiveCallOrConferenceView.compositeViewDescription.name]) {
|
if ([key isEqualToString:ImagePickerView.compositeViewDescription.name] || [key isEqualToString:SingleCallView.compositeViewDescription.name] || [key isEqualToString:ConferenceCallView.compositeViewDescription.name]) {
|
||||||
remove = false;
|
remove = false;
|
||||||
} else if (exclude != nil) {
|
} else if (exclude != nil) {
|
||||||
for (UICompositeViewDescription *description in exclude) {
|
for (UICompositeViewDescription *description in exclude) {
|
||||||
|
|
@ -336,6 +339,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onRightSwipe:(id)sender {
|
- (IBAction)onRightSwipe:(id)sender {
|
||||||
|
if (linphone_core_get_calls_nb(LC) > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
[self hideSideMenu:NO];
|
[self hideSideMenu:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,14 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "UIRoundBorderedButton.h"
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "UICompositeView.h"
|
||||||
|
#import "UIRoundBorderedButton.h"
|
||||||
|
|
||||||
typedef void (^UIConfirmationBlock)(void);
|
typedef void (^UIConfirmationBlock)(void);
|
||||||
|
|
||||||
@interface UIConfirmationDialog : UIViewController {
|
@interface UIConfirmationDialog : UIViewController <UICompositeViewDelegate, UIGestureRecognizerDelegate, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource>{
|
||||||
UIConfirmationBlock onCancelCb;
|
UIConfirmationBlock onCancelCb;
|
||||||
UIConfirmationBlock onConfirmCb;
|
UIConfirmationBlock onConfirmCb;
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +52,9 @@ typedef void (^UIConfirmationBlock)(void);
|
||||||
@property (weak, nonatomic) IBOutlet UIImageView *groupCallImage;
|
@property (weak, nonatomic) IBOutlet UIImageView *groupCallImage;
|
||||||
@property(weak, nonatomic) IBOutlet UIRoundBorderedButton *confirmationButton;
|
@property(weak, nonatomic) IBOutlet UIRoundBorderedButton *confirmationButton;
|
||||||
@property (weak, nonatomic) IBOutlet UIView *authView;
|
@property (weak, nonatomic) IBOutlet UIView *authView;
|
||||||
|
@property (weak, nonatomic) IBOutlet UIImageView *backgroundColor;
|
||||||
@property(weak, nonatomic) IBOutlet UILabel *titleLabel;
|
@property(weak, nonatomic) IBOutlet UILabel *titleLabel;
|
||||||
|
@property(weak, nonatomic) IBOutlet UIView *firstView;
|
||||||
@property (weak, nonatomic) IBOutlet UIButton *authButton;
|
@property (weak, nonatomic) IBOutlet UIButton *authButton;
|
||||||
|
|
||||||
- (void)setSpecialColor;
|
- (void)setSpecialColor;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#import "UIConfirmationDialog.h"
|
#import "UIConfirmationDialog.h"
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
#import "linphoneapp-Swift.h""
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
@implementation UIConfirmationDialog
|
@implementation UIConfirmationDialog
|
||||||
+ (UIConfirmationDialog *)initDialog:(NSString *)cancel
|
+ (UIConfirmationDialog *)initDialog:(NSString *)cancel
|
||||||
|
|
@ -33,6 +33,8 @@
|
||||||
dialog.view.frame = PhoneMainView.instance.mainViewController.view.frame;
|
dialog.view.frame = PhoneMainView.instance.mainViewController.view.frame;
|
||||||
[controller.view addSubview:dialog.view];
|
[controller.view addSubview:dialog.view];
|
||||||
[controller addChildViewController:dialog];
|
[controller addChildViewController:dialog];
|
||||||
|
dialog.backgroundColor.layer.cornerRadius = 10;
|
||||||
|
dialog.backgroundColor.layer.masksToBounds = true;
|
||||||
|
|
||||||
dialog->onCancelCb = onCancel;
|
dialog->onCancelCb = onCancel;
|
||||||
dialog->onConfirmCb = onConfirm;
|
dialog->onConfirmCb = onConfirm;
|
||||||
|
|
@ -48,9 +50,21 @@
|
||||||
[[UIColor colorWithPatternImage:[UIImage imageNamed:@"color_A.png"]] CGColor];
|
[[UIColor colorWithPatternImage:[UIImage imageNamed:@"color_A.png"]] CGColor];
|
||||||
dialog.cancelButton.layer.borderColor =
|
dialog.cancelButton.layer.borderColor =
|
||||||
[[UIColor colorWithPatternImage:[UIImage imageNamed:@"color_F.png"]] CGColor];
|
[[UIColor colorWithPatternImage:[UIImage imageNamed:@"color_F.png"]] CGColor];
|
||||||
|
if (linphone_core_get_post_quantum_available()) {
|
||||||
|
[dialog.securityImage setImage:[UIImage imageNamed:@"post_quantum_secure.png"]];
|
||||||
|
}
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
|
||||||
|
action:@selector(onCancelClick:)];
|
||||||
|
tapGestureRecognizer.delegate = self;
|
||||||
|
[self.firstView addGestureRecognizer:tapGestureRecognizer];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+ (UIConfirmationDialog *)ShowWithMessage:(NSString *)message
|
+ (UIConfirmationDialog *)ShowWithMessage:(NSString *)message
|
||||||
cancelMessage:(NSString *)cancel
|
cancelMessage:(NSString *)cancel
|
||||||
confirmMessage:(NSString *)confirm
|
confirmMessage:(NSString *)confirm
|
||||||
|
|
|
||||||
|
|
@ -50,28 +50,34 @@
|
||||||
normAddr = linphone_account_normalize_phone_number(account,
|
normAddr = linphone_account_normalize_phone_number(account,
|
||||||
_addressLabel.text.UTF8String);
|
_addressLabel.text.UTF8String);
|
||||||
}
|
}
|
||||||
LinphoneAddress *addr = linphone_core_interpret_url(LC, normAddr);
|
LinphoneAddress *addr = linphone_core_interpret_url_2(LC, normAddr, true);
|
||||||
_chatButton.enabled = _callButton.enabled = _encryptedChatButton.enabled = (addr != NULL);
|
_chatButton.enabled = _callButton.enabled = _encryptedChatButton.enabled = (addr != NULL);
|
||||||
|
|
||||||
_chatButton.accessibilityLabel =
|
_chatButton.accessibilityLabel =
|
||||||
[NSString stringWithFormat:NSLocalizedString(@"Chat with %@", nil), _addressLabel.text];
|
[NSString stringWithFormat:NSLocalizedString(@"Chat with %@", nil), _addressLabel.text];
|
||||||
_callButton.accessibilityLabel = [NSString stringWithFormat:NSLocalizedString(@"Call %@", nil), _addressLabel.text];
|
_callButton.accessibilityLabel = [NSString stringWithFormat:NSLocalizedString(@"Call %@", nil), _addressLabel.text];
|
||||||
// Test presence
|
// Test presence
|
||||||
Contact *contact;
|
Contact *contact = addr ? [FastAddressBook getContactWithAddress:(addr)] : NULL;
|
||||||
contact = addr ? [FastAddressBook getContactWithAddress:(addr)] : NULL;
|
LinphoneFriend *contactFriend = NULL;
|
||||||
|
if (contact && contact.friend) {
|
||||||
|
contactFriend = contact.friend;
|
||||||
|
} else if (addr) {
|
||||||
|
contactFriend = linphone_core_find_friend(LC, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContactDetailsView *contactDetailsView = VIEW(ContactDetailsView);
|
||||||
_linphoneImage.hidden = TRUE;
|
_linphoneImage.hidden = TRUE;
|
||||||
if (contact) {
|
if (contactFriend) {
|
||||||
const LinphonePresenceModel *model = contact.friend ? linphone_friend_get_presence_model_for_uri_or_tel(contact.friend, _addressLabel.text.UTF8String) : NULL;
|
const LinphonePresenceModel *model = contactFriend ? linphone_friend_get_presence_model_for_uri_or_tel(contactFriend, _addressLabel.text.UTF8String) : NULL;
|
||||||
|
|
||||||
self.linphoneImage.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"] ||
|
self.linphoneImage.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"] ||
|
||||||
!((model && linphone_presence_model_get_basic_status(model) == LinphonePresenceBasicStatusOpen) ||
|
!((model && linphone_presence_model_get_basic_status(model) == LinphonePresenceBasicStatusOpen) ||
|
||||||
(account && !linphone_account_is_phone_number(account,
|
(account && !linphone_account_is_phone_number(account,
|
||||||
_addressLabel.text.UTF8String) &&
|
_addressLabel.text.UTF8String) &&
|
||||||
[FastAddressBook isSipURIValid:_addressLabel.text]));
|
[FastAddressBook isSipURIValid:_addressLabel.text]));
|
||||||
ContactDetailsView *contactDetailsView = VIEW(ContactDetailsView);
|
self.inviteButton.hidden = !ENABLE_SMS_INVITE || [[contactDetailsView.contact sipAddresses] count] > 0 || !self.linphoneImage.hidden;
|
||||||
self.inviteButton.hidden = !ENABLE_SMS_INVITE || [[contactDetailsView.contact sipAddresses] count] > 0 || !self.linphoneImage.hidden;
|
|
||||||
[self shouldHideEncryptedChatView:account && linphone_account_params_get_conference_factory_uri(linphone_account_get_params(account)) && model && linphone_presence_model_has_capability(model, LinphoneFriendCapabilityLimeX3dh)];
|
[self shouldHideEncryptedChatView:account && linphone_account_params_get_conference_factory_uri(linphone_account_get_params(account)) && model && linphone_presence_model_has_capability(model, LinphoneFriendCapabilityLimeX3dh)];
|
||||||
|
_chatButton.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"force_lime_chat_rooms"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr) {
|
if (addr) {
|
||||||
|
|
@ -103,7 +109,7 @@
|
||||||
normAddr = linphone_account_normalize_phone_number(account,
|
normAddr = linphone_account_normalize_phone_number(account,
|
||||||
_addressLabel.text.UTF8String);
|
_addressLabel.text.UTF8String);
|
||||||
}
|
}
|
||||||
LinphoneAddress *addr = linphone_core_interpret_url(LC, normAddr);
|
LinphoneAddress *addr = linphone_core_interpret_url_2(LC, normAddr, true);
|
||||||
|
|
||||||
// Test presence
|
// Test presence
|
||||||
Contact *contact = [FastAddressBook getContactWithAddress:(addr)];
|
Contact *contact = [FastAddressBook getContactWithAddress:(addr)];
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,6 @@
|
||||||
if (addressField && (!dtmf || !linphone_core_in_call(LC))) {
|
if (addressField && (!dtmf || !linphone_core_in_call(LC))) {
|
||||||
NSString *newAddress = [NSString stringWithFormat:@"%@%c", addressField.text, digit];
|
NSString *newAddress = [NSString stringWithFormat:@"%@%c", addressField.text, digit];
|
||||||
[addressField setText:newAddress];
|
[addressField setText:newAddress];
|
||||||
linphone_core_play_dtmf(LC, digit, -1);
|
|
||||||
} else {
|
} else {
|
||||||
linphone_call_send_dtmf(linphone_core_get_current_call(LC), digit);
|
linphone_call_send_dtmf(linphone_core_get_current_call(LC), digit);
|
||||||
linphone_core_play_dtmf(LC, digit, 100);
|
linphone_core_play_dtmf(LC, digit, 100);
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
// Set up the cell...
|
// Set up the cell...
|
||||||
if (linphone_call_log_was_conference(callLog)) {
|
if (linphone_call_log_was_conference(callLog)) {
|
||||||
const char *subject = linphone_conference_info_get_subject(linphone_call_log_get_conference_info(callLog));
|
const char *subject = linphone_conference_info_get_subject(linphone_call_log_get_conference_info(callLog));
|
||||||
displayNameLabel.text = [NSString stringWithFormat:@"%s",subject];
|
displayNameLabel.text = [NSString stringWithUTF8String:subject];
|
||||||
[_avatarImage setImage:[UIImage imageNamed:@"voip_multiple_contacts_avatar"]];
|
[_avatarImage setImage:[UIImage imageNamed:@"voip_multiple_contacts_avatar"]];
|
||||||
_stateImage.hidden = true;
|
_stateImage.hidden = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,6 @@
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
|
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
|
||||||
@property (strong, nonatomic) IBOutlet UIToolbar *toolbar;
|
@property (strong, nonatomic) IBOutlet UIToolbar *toolbar;
|
||||||
@property (weak, nonatomic) IBOutlet UIBarButtonItem *shareButton;
|
@property (weak, nonatomic) IBOutlet UIBarButtonItem *shareButton;
|
||||||
|
|
||||||
|
|
||||||
@property(nonatomic, assign) __block NSString *recording;
|
@property(nonatomic, assign) __block NSString *recording;
|
||||||
|
|
||||||
- (id)initWithIdentifier:(NSString*)identifier;
|
- (id)initWithIdentifier:(NSString*)identifier;
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,8 @@ static UILinphoneAudioPlayer *player;
|
||||||
NSArray *parsedRecording = [LinphoneUtils parseRecordingName:_recording];
|
NSArray *parsedRecording = [LinphoneUtils parseRecordingName:_recording];
|
||||||
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
|
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
|
||||||
[dateFormat setDateFormat:@"HH:mm:ss"];
|
[dateFormat setDateFormat:@"HH:mm:ss"];
|
||||||
_nameLabel.text = [[[parsedRecording objectAtIndex:0] stringByAppendingString:@" @ "] stringByAppendingString:[dateFormat stringFromDate:[parsedRecording objectAtIndex:1]]];
|
NSString *b = [[parsedRecording objectAtIndex:0] containsString:@"conf-id"] ? NSLocalizedString(@"Meeting", nil) : [parsedRecording objectAtIndex:0];
|
||||||
|
_nameLabel.text = [[b stringByAppendingString:@" @ "] stringByAppendingString:[dateFormat stringFromDate:[parsedRecording objectAtIndex:1]]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,7 +90,8 @@ static UILinphoneAudioPlayer *player;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
|
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
|
||||||
self.selectionStyle = UITableViewCellSelectionStyleNone;
|
if (!VIEW(RecordingsListView).tableController.isEditing)
|
||||||
|
self.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateFrame {
|
- (void)updateFrame {
|
||||||
|
|
@ -104,10 +106,11 @@ static UILinphoneAudioPlayer *player;
|
||||||
|
|
||||||
-(void)setSelected:(BOOL)selected animated:(BOOL)animated{
|
-(void)setSelected:(BOOL)selected animated:(BOOL)animated{
|
||||||
[super setSelected:selected animated:animated];
|
[super setSelected:selected animated:animated];
|
||||||
_toolbar.hidden = !selected;
|
|
||||||
if (!selected) {
|
if (!selected || (selected && VIEW(RecordingsListView).tableController.isEditing)) {
|
||||||
return;
|
_toolbar.hidden = true;
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
if (player && [player isCreated]) {
|
if (player && [player isCreated]) {
|
||||||
[player close];
|
[player close];
|
||||||
}
|
}
|
||||||
|
|
@ -121,6 +124,7 @@ static UILinphoneAudioPlayer *player;
|
||||||
player.view.frame = _playerView.frame;
|
player.view.frame = _playerView.frame;
|
||||||
player.view.bounds = _playerView.bounds;
|
player.view.bounds = _playerView.bounds;
|
||||||
[player open];
|
[player open];
|
||||||
|
_toolbar.hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onShareButtonPressed {
|
- (void)onShareButtonPressed {
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -34,6 +34,7 @@ import linphonesw
|
||||||
NotificationCenter.default.post(name: Notification.Name(kLinphoneMagicSearchFinished), object: self)
|
NotificationCenter.default.post(name: Notification.Name(kLinphoneMagicSearchFinished), object: self)
|
||||||
}, onLdapHaveMoreResults: { (magicSearch: MagicSearch, ldap: Ldap) in
|
}, onLdapHaveMoreResults: { (magicSearch: MagicSearch, ldap: Ldap) in
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "Ldap have more result")
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "Ldap have more result")
|
||||||
|
NotificationCenter.default.post(name: Notification.Name(kLinphoneMagicSearchMoreAvailable), object: self)
|
||||||
})
|
})
|
||||||
|
|
||||||
magicSearch.addDelegate(delegate: magicSearchDelegate!)
|
magicSearch.addDelegate(delegate: magicSearchDelegate!)
|
||||||
|
|
@ -47,17 +48,26 @@ import linphonesw
|
||||||
return theMagicSearchSingleton!
|
return theMagicSearchSingleton!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc static func destroyInstance() {
|
||||||
|
theMagicSearchSingleton = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func getContactFromAddr(addr: Address) -> Contact? {
|
func getContactFromAddr(addr: Address) -> Contact? {
|
||||||
return LinphoneManager.instance().fastAddressBook.addressBookMap.object(forKey: addr.asStringUriOnly() as Any) as? Contact
|
return LinphoneManager.instance().fastAddressBook.addressBookMap.object(forKey: addr.asStringUriOnly() as Any) as? Contact
|
||||||
}
|
}
|
||||||
func getContactFromPhoneNb(phoneNb: String) -> Contact? {
|
func getContactFromPhoneNb(phoneNb: String) -> Contact? {
|
||||||
let contactKey = FastAddressBook.localizedLabel(FastAddressBook.normalizeSipURI( lc?.defaultAccount?.normalizePhoneNumber(username: phoneNb) ?? phoneNb))
|
let contactKey = FastAddressBook.localizedLabel(FastAddressBook.normalizeSipURI(lc?.defaultAccount?.normalizePhoneNumber(username: phoneNb) ?? phoneNb, use_prefix: true))
|
||||||
return LinphoneManager.instance().fastAddressBook.addressBookMap.object(forKey: contactKey as Any) as? Contact
|
return LinphoneManager.instance().fastAddressBook.addressBookMap.object(forKey: contactKey as Any) as? Contact
|
||||||
}
|
}
|
||||||
|
|
||||||
func searchAndAddMatchingContact(searchResult: SearchResult) -> Contact? {
|
func searchAndAddMatchingContact(searchResult: SearchResult) -> Contact? {
|
||||||
if let friend = searchResult.friend {
|
if let friend = searchResult.friend {
|
||||||
|
if (searchResult.sourceFlags == MagicSearchSource.LdapServers.rawValue), let newContact = Contact(friend: friend.getCobject) {
|
||||||
|
// Contact comes from LDAP, creating a new one
|
||||||
|
newContact.createdFromLdapOrProvisioning = true
|
||||||
|
return newContact
|
||||||
|
}
|
||||||
if let addr = friend.address, let foundContact = getContactFromAddr(addr: addr) {
|
if let addr = friend.address, let foundContact = getContactFromAddr(addr: addr) {
|
||||||
return foundContact
|
return foundContact
|
||||||
}
|
}
|
||||||
|
|
@ -66,11 +76,6 @@ import linphonesw
|
||||||
return foundContact
|
return foundContact
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No contacts found (searchResult likely comes from LDAP), creating a new one
|
|
||||||
if let newContact = Contact(friend: friend.getCobject) {
|
|
||||||
newContact.createdFromLdap = true
|
|
||||||
return newContact
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let addr = searchResult.address, let foundContact = getContactFromAddr(addr: addr) {
|
if let addr = searchResult.address, let foundContact = getContactFromAddr(addr: addr) {
|
||||||
|
|
@ -81,6 +86,11 @@ import linphonesw
|
||||||
return foundContact
|
return foundContact
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Friend comes from provisioning
|
||||||
|
if let addr = searchResult.address, let friend = searchResult.friend, let newContact = Contact(friend: friend.getCobject) {
|
||||||
|
newContact.createdFromLdapOrProvisioning = true
|
||||||
|
return newContact
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,13 +110,9 @@ import linphonesw
|
||||||
@objc func getLastSearchContacts() -> [Contact] {
|
@objc func getLastSearchContacts() -> [Contact] {
|
||||||
if (needUpdateLastSearchContacts) {
|
if (needUpdateLastSearchContacts) {
|
||||||
lastSearchContacts = []
|
lastSearchContacts = []
|
||||||
var addedContactNames : [String] = []
|
|
||||||
for res in magicSearch.lastSearch {
|
for res in magicSearch.lastSearch {
|
||||||
if let contact = searchAndAddMatchingContact(searchResult: res) {
|
if let contact = searchAndAddMatchingContact(searchResult: res) {
|
||||||
if (!addedContactNames.contains(contact.displayName)) {
|
lastSearchContacts.append(contact)
|
||||||
addedContactNames.append(contact.displayName)
|
|
||||||
lastSearchContacts.append(contact)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
needUpdateLastSearchContacts = false
|
needUpdateLastSearchContacts = false
|
||||||
|
|
|
||||||
|
|
@ -123,3 +123,4 @@
|
||||||
@end
|
@end
|
||||||
|
|
||||||
void main_view_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomState newState);
|
void main_view_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomState newState);
|
||||||
|
void main_view_chat_room_conference_joined(LinphoneChatRoom *cr, const LinphoneEventLog *event_log);
|
||||||
|
|
|
||||||
|
|
@ -374,7 +374,6 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LinphoneCallOutgoingInit:
|
|
||||||
case LinphoneCallOutgoingEarlyMedia:
|
case LinphoneCallOutgoingEarlyMedia:
|
||||||
case LinphoneCallOutgoingProgress:
|
case LinphoneCallOutgoingProgress:
|
||||||
case LinphoneCallOutgoingRinging: {
|
case LinphoneCallOutgoingRinging: {
|
||||||
|
|
@ -386,7 +385,7 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LinphoneCallPausedByRemote:
|
case LinphoneCallPausedByRemote:break;
|
||||||
case LinphoneCallConnected: {
|
case LinphoneCallConnected: {
|
||||||
if (![LinphoneManager.instance isCTCallCenterExist]) {
|
if (![LinphoneManager.instance isCTCallCenterExist]) {
|
||||||
/*only register CT call center CB for connected call*/
|
/*only register CT call center CB for connected call*/
|
||||||
|
|
@ -418,6 +417,7 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
}
|
}
|
||||||
case LinphoneCallUpdating:
|
case LinphoneCallUpdating:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (state == LinphoneCallEnd || state == LinphoneCallError || floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max)
|
if (state == LinphoneCallEnd || state == LinphoneCallError || floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max)
|
||||||
[self updateApplicationBadgeNumber];
|
[self updateApplicationBadgeNumber];
|
||||||
|
|
@ -453,9 +453,19 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
LinphoneManager *lm = LinphoneManager.instance;
|
LinphoneManager *lm = LinphoneManager.instance;
|
||||||
LOGI(@"%s", linphone_global_state_to_string(linphone_core_get_global_state(LC)));
|
LOGI(@"%s", linphone_global_state_to_string(linphone_core_get_global_state(LC)));
|
||||||
|
|
||||||
|
NSString* groupName = [NSString stringWithFormat:@"group.%@.linphoneExtension",[[NSBundle mainBundle] bundleIdentifier]];
|
||||||
|
|
||||||
|
|
||||||
|
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:groupName];
|
||||||
|
NSDictionary *dict = [defaults valueForKey:@"photoData"];
|
||||||
|
NSDictionary *dictFile = [defaults valueForKey:@"icloudData"];
|
||||||
|
NSDictionary *dictUrl = [defaults valueForKey:@"url"];
|
||||||
|
|
||||||
// If we've been started by a remote push notification,
|
// If we've been started by a remote push notification,
|
||||||
// we'll already be on the corresponding chat conversation view, no need to go anywhere else
|
// we'll already be on the corresponding chat conversation view, no need to go anywhere else
|
||||||
if (![[self currentView].name isEqualToString:@"ChatConversationView"]) {
|
if (dict||dictFile||dictUrl){
|
||||||
|
[self changeCurrentView:ChatsListView.compositeViewDescription];
|
||||||
|
}else if (![[self currentView].name isEqualToString:@"ChatConversationView"]) {
|
||||||
|
|
||||||
if (linphone_core_get_global_state(LC) != LinphoneGlobalOn) {
|
if (linphone_core_get_global_state(LC) != LinphoneGlobalOn) {
|
||||||
[self changeCurrentView:DialerView.compositeViewDescription];
|
[self changeCurrentView:DialerView.compositeViewDescription];
|
||||||
|
|
@ -607,7 +617,8 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
}
|
}
|
||||||
[self _changeCurrentView:viewStack.lastObject ?: DialerView.compositeViewDescription
|
[self _changeCurrentView:viewStack.lastObject ?: DialerView.compositeViewDescription
|
||||||
transition:[PhoneMainView getBackwardTransition]
|
transition:[PhoneMainView getBackwardTransition]
|
||||||
animated:ANIMATED];
|
animated:ANIMATED
|
||||||
|
addViewToStack:FALSE];
|
||||||
return [mainViewController getCurrentViewController];
|
return [mainViewController getCurrentViewController];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -621,18 +632,19 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
|
|
||||||
|
|
||||||
- (void)changeCurrentView:(UICompositeViewDescription *)view {
|
- (void)changeCurrentView:(UICompositeViewDescription *)view {
|
||||||
[self _changeCurrentView:view transition:nil animated:ANIMATED];
|
[self _changeCurrentView:view transition:nil animated:ANIMATED addViewToStack:TRUE];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIViewController *)_changeCurrentView:(UICompositeViewDescription *)view
|
- (UIViewController *)_changeCurrentView:(UICompositeViewDescription *)view
|
||||||
transition:(CATransition *)transition
|
transition:(CATransition *)transition
|
||||||
animated:(BOOL)animated {
|
animated:(BOOL)animated
|
||||||
|
addViewToStack:(BOOL)addViewToStack {
|
||||||
PhoneMainView *vc = [[RootViewManager instance] setViewControllerForDescription:view];
|
PhoneMainView *vc = [[RootViewManager instance] setViewControllerForDescription:view];
|
||||||
if (![view equal:vc.currentView] || vc != self) {
|
if (![view equal:vc.currentView] || vc != self) {
|
||||||
LOGI(@"Change current view to %@", view.name);
|
LOGI(@"Change current view to %@", view.name);
|
||||||
[self setPreviousViewName:vc.currentView.name];
|
[self setPreviousViewName:vc.currentView.name];
|
||||||
NSMutableArray *viewStack = [RootViewManager instance].viewDescriptionStack;
|
NSMutableArray *viewStack = [RootViewManager instance].viewDescriptionStack;
|
||||||
[viewStack addObject:view];
|
if (addViewToStack) [viewStack addObject:view];
|
||||||
if (animated && transition == nil)
|
if (animated && transition == nil)
|
||||||
transition = [PhoneMainView getTransition:vc.currentView new:view];
|
transition = [PhoneMainView getTransition:vc.currentView new:view];
|
||||||
[vc.mainViewController setViewTransition:(animated ? transition : nil)];
|
[vc.mainViewController setViewTransition:(animated ? transition : nil)];
|
||||||
|
|
@ -653,7 +665,8 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
while (viewStack.count > 0 && ![[viewStack lastObject] equal:view]) {
|
while (viewStack.count > 0 && ![[viewStack lastObject] equal:view]) {
|
||||||
[viewStack removeLastObject];
|
[viewStack removeLastObject];
|
||||||
}
|
}
|
||||||
return [self _changeCurrentView:view transition:[PhoneMainView getBackwardTransition] animated:ANIMATED];
|
BOOL addView = (viewStack.count == 0); // if we couldn't find the view in the stack, we need to add it
|
||||||
|
return [self _changeCurrentView:view transition:[PhoneMainView getBackwardTransition] animated:ANIMATED addViewToStack:addView];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setPreviousViewName:(NSString*)previous{
|
- (void) setPreviousViewName:(NSString*)previous{
|
||||||
|
|
@ -884,6 +897,7 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
|
|
||||||
LinphoneChatRoomCbs *cbs = linphone_factory_create_chat_room_cbs(linphone_factory_get());
|
LinphoneChatRoomCbs *cbs = linphone_factory_create_chat_room_cbs(linphone_factory_get());
|
||||||
linphone_chat_room_cbs_set_state_changed(cbs, main_view_chat_room_state_changed);
|
linphone_chat_room_cbs_set_state_changed(cbs, main_view_chat_room_state_changed);
|
||||||
|
linphone_chat_room_cbs_set_conference_joined(cbs, main_view_chat_room_conference_joined);
|
||||||
linphone_chat_room_add_callbacks(room, cbs);
|
linphone_chat_room_add_callbacks(room, cbs);
|
||||||
|
|
||||||
return room;
|
return room;
|
||||||
|
|
@ -901,31 +915,34 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
[view clearMessageView];
|
[view clearMessageView];
|
||||||
view.chatRoom = cr;
|
view.chatRoom = cr;
|
||||||
view.peerAddress = linphone_address_as_string(linphone_chat_room_get_peer_address(cr));
|
view.peerAddress = linphone_address_as_string(linphone_chat_room_get_peer_address(cr));
|
||||||
|
view.localAddress = linphone_address_as_string(linphone_chat_room_get_local_address(cr));
|
||||||
self.currentRoom = view.chatRoom;
|
self.currentRoom = view.chatRoom;
|
||||||
|
|
||||||
if (PhoneMainView.instance.currentView == view.compositeViewDescription)
|
if (PhoneMainView.instance.currentView == view.compositeViewDescription)
|
||||||
[view configureForRoom:FALSE];
|
[view configureForRoom:FALSE];
|
||||||
else
|
else
|
||||||
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void main_view_chat_room_conference_joined(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) {
|
||||||
|
PhoneMainView *view = PhoneMainView.instance;
|
||||||
|
LOGI(@"Chat room [%p] conference joined.", cr);
|
||||||
|
linphone_chat_room_remove_callbacks(cr, linphone_chat_room_get_current_callbacks(cr));
|
||||||
|
[view goToChatRoom:cr];
|
||||||
|
if (!IPAD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (PhoneMainView.instance.currentView != ChatsListView.compositeViewDescription && PhoneMainView.instance.currentView != ChatConversationView.compositeViewDescription)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ChatsListView *mainView = VIEW(ChatsListView);
|
||||||
|
[mainView.tableController loadData];
|
||||||
|
[mainView.tableController selectFirstRow];
|
||||||
|
}
|
||||||
|
|
||||||
void main_view_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomState newState) {
|
void main_view_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomState newState) {
|
||||||
PhoneMainView *view = PhoneMainView.instance;
|
PhoneMainView *view = PhoneMainView.instance;
|
||||||
switch (newState) {
|
switch (newState) {
|
||||||
case LinphoneChatRoomStateCreated: {
|
|
||||||
LOGI(@"Chat room [%p] created on server.", cr);
|
|
||||||
linphone_chat_room_remove_callbacks(cr, linphone_chat_room_get_current_callbacks(cr));
|
|
||||||
[view goToChatRoom:cr];
|
|
||||||
if (!IPAD)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (PhoneMainView.instance.currentView != ChatsListView.compositeViewDescription && PhoneMainView.instance.currentView != ChatConversationView.compositeViewDescription)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ChatsListView *mainView = VIEW(ChatsListView);
|
|
||||||
[mainView.tableController loadData];
|
|
||||||
[mainView.tableController selectFirstRow];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LinphoneChatRoomStateCreationFailed:
|
case LinphoneChatRoomStateCreationFailed:
|
||||||
LOGE(@"Chat room [%p] could not be created on server.", cr);
|
LOGE(@"Chat room [%p] could not be created on server.", cr);
|
||||||
linphone_chat_room_remove_callbacks(cr, linphone_chat_room_get_current_callbacks(cr));
|
linphone_chat_room_remove_callbacks(cr, linphone_chat_room_get_current_callbacks(cr));
|
||||||
|
|
@ -958,4 +975,8 @@ void main_view_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomSta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
|
||||||
|
[UIDeviceBridge notifyDisplayModeSwitch];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -147,8 +147,6 @@
|
||||||
NSString *recordingPath = subAr[indexPath.row];
|
NSString *recordingPath = subAr[indexPath.row];
|
||||||
[cell setRecording:recordingPath];
|
[cell setRecording:recordingPath];
|
||||||
[super accessoryForCell:cell atPath:indexPath];
|
[super accessoryForCell:cell atPath:indexPath];
|
||||||
//accessoryForCell set it to gray but we don't want it
|
|
||||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
||||||
[cell updateFrame];
|
[cell updateFrame];
|
||||||
cell.contentView.userInteractionEnabled = false;
|
cell.contentView.userInteractionEnabled = false;
|
||||||
return cell;
|
return cell;
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,12 @@
|
||||||
#import "LinphoneAppDelegate.h"
|
#import "LinphoneAppDelegate.h"
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
#import "Utils.h"
|
#import "Utils.h"
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
#import "DCRoundSwitch.h"
|
#import "DCRoundSwitch.h"
|
||||||
|
|
||||||
#import "IASKSpecifierValuesViewController.h"
|
#import "IASKSpecifierValuesViewController.h"
|
||||||
#import "IASKPSTextFieldSpecifierViewCell.h"
|
#import "IASKPSTextFieldSpecifierViewCell.h"
|
||||||
#import "IASKPSTitleValueSpecifierViewCell.h"
|
|
||||||
#import "IASKSpecifier.h"
|
#import "IASKSpecifier.h"
|
||||||
#import "IASKTextField.h"
|
#import "IASKTextField.h"
|
||||||
#include "linphone/lpconfig.h"
|
#include "linphone/lpconfig.h"
|
||||||
|
|
@ -247,7 +247,7 @@
|
||||||
[field setTextColor:LINPHONE_MAIN_COLOR];
|
[field setTextColor:LINPHONE_MAIN_COLOR];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([cell isKindOfClass:[IASKPSTitleValueSpecifierViewCell class]]) {
|
if ([cell isKindOfClass:[UITableViewCell class]]) {
|
||||||
cell.detailTextLabel.textColor = [UIColor grayColor];
|
cell.detailTextLabel.textColor = [UIColor grayColor];
|
||||||
} else {
|
} else {
|
||||||
cell.detailTextLabel.textColor = LINPHONE_MAIN_COLOR;
|
cell.detailTextLabel.textColor = LINPHONE_MAIN_COLOR;
|
||||||
|
|
@ -445,8 +445,11 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
linphone_account_creator_set_password(creator, _tmpPwd.UTF8String);
|
linphone_account_creator_set_password(creator, _tmpPwd.UTF8String);
|
||||||
[settingsStore setObject:_tmpPwd forKey:@"account_mandatory_password_preference"];
|
[settingsStore setObject:_tmpPwd forKey:@"account_mandatory_password_preference"];
|
||||||
|
|
||||||
|
MSList *accountList = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
LinphoneAccount *account = bctbx_list_nth_data(linphone_core_get_account_list(LC),
|
LinphoneAccount *account = bctbx_list_nth_data(linphone_core_get_account_list(LC),
|
||||||
[settingsStore integerForKey:@"current_proxy_config_preference"]);
|
[settingsStore integerForKey:@"current_proxy_config_preference"]);
|
||||||
|
bctbx_free(accountList);
|
||||||
|
|
||||||
if (account != NULL) {
|
if (account != NULL) {
|
||||||
const LinphoneAuthInfo *auth = linphone_account_find_auth_info(account);
|
const LinphoneAuthInfo *auth = linphone_account_find_auth_info(account);
|
||||||
if (auth) {
|
if (auth) {
|
||||||
|
|
@ -521,11 +524,50 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
[keys addObject:@"download_bandwidth_preference"];
|
[keys addObject:@"download_bandwidth_preference"];
|
||||||
} else if ([@"auto_download_mode" compare:notif.object] == NSOrderedSame) {
|
} else if ([@"auto_download_mode" compare:notif.object] == NSOrderedSame) {
|
||||||
NSString *download_mode = [notif.userInfo objectForKey:@"auto_download_mode"];
|
NSString *download_mode = [notif.userInfo objectForKey:@"auto_download_mode"];
|
||||||
removeFromHiddenKeys = [download_mode isEqualToString:@"Customize"];
|
if([download_mode isEqualToString:@"Customize"]){
|
||||||
if (removeFromHiddenKeys)
|
[LinphoneManager.instance lpConfigSetBool:FALSE forKey:@"auto_download_mode_is_never"];
|
||||||
[LinphoneManager.instance lpConfigSetInt:10000000 forKey:@"auto_download_incoming_files_max_size"];
|
removeFromHiddenKeys = [download_mode isEqualToString:@"Customize"];
|
||||||
[keys addObject:@"auto_download_incoming_files_max_size"];
|
[LinphoneManager.instance lpConfigSetInt:10000000 forKey:@"auto_download_incoming_files_max_size"];
|
||||||
}
|
[keys addObject:@"auto_download_incoming_files_max_size"];
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
} else if([download_mode isEqualToString:@"Never"]){
|
||||||
|
[LinphoneManager.instance lpConfigSetBool:TRUE forKey:@"auto_download_mode_is_never"];
|
||||||
|
removeFromHiddenKeys = [download_mode isEqualToString:@"Never"];
|
||||||
|
if(![LinphoneManager.instance lpConfigBoolForKey:@"vfs_enabled_mode"])
|
||||||
|
[keys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
else
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
[hiddenKeys addObject:@"auto_download_incoming_files_max_size"];
|
||||||
|
} else {
|
||||||
|
[LinphoneManager.instance lpConfigSetBool:FALSE forKey:@"auto_download_mode_is_never"];
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
[hiddenKeys addObject:@"auto_download_incoming_files_max_size"];
|
||||||
|
}
|
||||||
|
}else if ([@"vfs_enabled_mode" compare:notif.object] == NSOrderedSame) {
|
||||||
|
removeFromHiddenKeys = [[notif.userInfo objectForKey:@"vfs_enabled_mode"] boolValue];
|
||||||
|
if(removeFromHiddenKeys){
|
||||||
|
[LinphoneManager.instance lpConfigSetBool:TRUE forKey:@"vfs_enabled_mode"];
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
[hiddenKeys addObject:@"vfs_enabled_mode"];
|
||||||
|
[keys addObject:@"vfs_enabled"];
|
||||||
|
}else{
|
||||||
|
if(![LinphoneManager.instance lpConfigBoolForKey:@"auto_download_mode_is_never"]){
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ([@"auto_write_to_gallery_mode" compare:notif.object] == NSOrderedSame) {
|
||||||
|
removeFromHiddenKeys = ![[notif.userInfo objectForKey:@"auto_write_to_gallery_mode"] boolValue];
|
||||||
|
if(![LinphoneManager.instance lpConfigBoolForKey:@"vfs_enabled_mode"]){
|
||||||
|
if(!removeFromHiddenKeys){
|
||||||
|
[LinphoneManager.instance lpConfigSetBool:TRUE forKey:@"auto_write_to_gallery_mode"];
|
||||||
|
[hiddenKeys addObject:@"auto_download_mode"];
|
||||||
|
}else{
|
||||||
|
[LinphoneManager.instance lpConfigSetBool:FALSE forKey:@"auto_write_to_gallery_mode"];
|
||||||
|
[keys addObject:@"auto_download_mode"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (NSString *key in keys) {
|
for (NSString *key in keys) {
|
||||||
if (removeFromHiddenKeys)
|
if (removeFromHiddenKeys)
|
||||||
|
|
@ -552,11 +594,12 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
return [[IASKSpecifier alloc] initWithSpecifier:dict];
|
return [[IASKSpecifier alloc] initWithSpecifier:dict];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ([[specifier key] isEqualToString:@"media_encryption_preference"]) {
|
BOOL pq_available = linphone_core_get_post_quantum_available();
|
||||||
|
if ([[specifier key] isEqualToString:pq_available ? @"media_encryption_preference_pq_enabled" : @"media_encryption_preference"]) {
|
||||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[specifier specifierDict]];
|
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[specifier specifierDict]];
|
||||||
if (!linphone_core_media_encryption_supported(LC, LinphoneMediaEncryptionZRTP)) {
|
if (!linphone_core_media_encryption_supported(LC, LinphoneMediaEncryptionZRTP)) {
|
||||||
NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]];
|
NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]];
|
||||||
[titles removeObject:@"ZRTP"];
|
[titles removeObject:pq_available ? @"ZRTP" : @"ZRTP Post Quantum"];
|
||||||
[dict setObject:titles forKey:@"Titles"];
|
[dict setObject:titles forKey:@"Titles"];
|
||||||
NSMutableArray *values = [NSMutableArray arrayWithArray:[dict objectForKey:@"Values"]];
|
NSMutableArray *values = [NSMutableArray arrayWithArray:[dict objectForKey:@"Values"]];
|
||||||
[values removeObject:@"ZRTP"];
|
[values removeObject:@"ZRTP"];
|
||||||
|
|
@ -583,7 +626,7 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([specifier.key hasPrefix:@"menu_account_"]) {
|
if ([specifier.key hasPrefix:@"menu_account_"]) {
|
||||||
const bctbx_list_t *accounts = linphone_core_get_account_list(LC);
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
int index = [specifier.key substringFromIndex:@"menu_account_".length].intValue - 1;
|
int index = [specifier.key substringFromIndex:@"menu_account_".length].intValue - 1;
|
||||||
if (index < bctbx_list_size(accounts)) {
|
if (index < bctbx_list_size(accounts)) {
|
||||||
LinphoneAccount *account = (LinphoneAccount *)bctbx_list_nth_data(accounts, index);
|
LinphoneAccount *account = (LinphoneAccount *)bctbx_list_nth_data(accounts, index);
|
||||||
|
|
@ -591,6 +634,7 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
stringWithUTF8String:linphone_address_get_username(linphone_account_params_get_identity_address(linphone_account_get_params(account)))];
|
stringWithUTF8String:linphone_address_get_username(linphone_account_params_get_identity_address(linphone_account_get_params(account)))];
|
||||||
[specifier.specifierDict setValue:name forKey:kIASKTitle];
|
[specifier.specifierDict setValue:name forKey:kIASKTitle];
|
||||||
}
|
}
|
||||||
|
bctbx_free(accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([specifier.key hasPrefix:@"ldap_"]) {
|
if ([specifier.key hasPrefix:@"ldap_"]) {
|
||||||
|
|
@ -625,18 +669,25 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
- (NSSet *)findHiddenKeys {
|
- (NSSet *)findHiddenKeys {
|
||||||
LinphoneManager *lm = LinphoneManager.instance;
|
LinphoneManager *lm = LinphoneManager.instance;
|
||||||
NSMutableSet *hiddenKeys = [NSMutableSet set];
|
NSMutableSet *hiddenKeys = [NSMutableSet set];
|
||||||
|
|
||||||
const MSList *accounts = linphone_core_get_account_list(LC);
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
for (size_t i = bctbx_list_size(accounts) + 1; i <= 5; i++) {
|
for (size_t i = bctbx_list_size(accounts) + 1; i <= 5; i++) {
|
||||||
[hiddenKeys addObject:[NSString stringWithFormat:@"menu_account_%lu", i]];
|
[hiddenKeys addObject:[NSString stringWithFormat:@"menu_account_%lu", i]];
|
||||||
}
|
}
|
||||||
|
bctbx_free(accounts);
|
||||||
const MSList *ldaps = linphone_core_get_ldap_list(LC);
|
const MSList *ldaps = linphone_core_get_ldap_list(LC);
|
||||||
for (size_t i = bctbx_list_size(ldaps) + 1; i <= 5; i++) {
|
for (size_t i = bctbx_list_size(ldaps) + 1; i <= 5; i++) {
|
||||||
[hiddenKeys addObject:[NSString stringWithFormat:@"ldap_%lu", i]];
|
[hiddenKeys addObject:[NSString stringWithFormat:@"ldap_%lu", i]];
|
||||||
}
|
}
|
||||||
if (!linphone_core_sip_transport_supported(LC, LinphoneTransportTls)) {
|
if (!linphone_core_sip_transport_supported(LC, LinphoneTransportTls)) {
|
||||||
[hiddenKeys addObject:@"media_encryption_preference"];
|
[hiddenKeys addObject:@"media_encryption_preference"];
|
||||||
|
[hiddenKeys addObject:@"media_encryption_preference_pq_enabled"];
|
||||||
|
} else {
|
||||||
|
if (linphone_core_get_post_quantum_available()) {
|
||||||
|
[hiddenKeys addObject:@"media_encryption_preference"];
|
||||||
|
} else {
|
||||||
|
[hiddenKeys addObject:@"media_encryption_preference_pq_enabled"];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!linphone_core_ldap_available(LC)) {
|
if (!linphone_core_ldap_available(LC)) {
|
||||||
|
|
@ -762,6 +813,21 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
[hiddenKeys addObject:@"auto_download_incoming_files_max_size"];
|
[hiddenKeys addObject:@"auto_download_incoming_files_max_size"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (![[lm lpConfigStringForKey:@"auto_download_mode"] isEqualToString:@"Never"]) {
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([lm lpConfigBoolForKey:@"vfs_enabled_mode"]) {
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
[hiddenKeys addObject:@"vfs_enabled_mode"];
|
||||||
|
}else{
|
||||||
|
[hiddenKeys addObject:@"vfs_enabled"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([lm lpConfigBoolForKey:@"auto_write_to_gallery_mode"]) {
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
}
|
||||||
|
|
||||||
return hiddenKeys;
|
return hiddenKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -901,8 +967,11 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
if (pwd && ![pwd isEqualToString:@""]) {
|
if (pwd && ![pwd isEqualToString:@""]) {
|
||||||
if ([pwd isEqualToString:conf_pwd]) {
|
if ([pwd isEqualToString:conf_pwd]) {
|
||||||
_tmpPwd = pwd;
|
_tmpPwd = pwd;
|
||||||
LinphoneAccount *account = bctbx_list_nth_data(linphone_core_get_account_list(LC),
|
|
||||||
[settingsStore integerForKey:@"current_proxy_config_preference"]);
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
LinphoneAccount *account = bctbx_list_nth_data(accounts,
|
||||||
|
[settingsStore integerForKey:@"current_proxy_config_preference"]);
|
||||||
|
bctbx_free(accounts);
|
||||||
const LinphoneAuthInfo *ai = linphone_account_find_auth_info(account);
|
const LinphoneAuthInfo *ai = linphone_account_find_auth_info(account);
|
||||||
|
|
||||||
LinphoneAccountCreator *account_creator = linphone_account_creator_new(
|
LinphoneAccountCreator *account_creator = linphone_account_creator_new(
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,11 @@
|
||||||
changeCurrentView:AssistantView.compositeViewDescription];
|
changeCurrentView:AssistantView.compositeViewDescription];
|
||||||
}]];
|
}]];
|
||||||
BOOL mustLink = ([LinphoneManager.instance lpConfigIntForKey:@"must_link_account_time"] > 0);
|
BOOL mustLink = ([LinphoneManager.instance lpConfigIntForKey:@"must_link_account_time"] > 0);
|
||||||
BOOL hasAccount = linphone_core_get_account_list(LC) != NULL;
|
|
||||||
if (mustLink && hasAccount) {
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
BOOL hasAccount = accounts != NULL;
|
||||||
|
bctbx_free(accounts);
|
||||||
|
if (mustLink && hasAccount && ![LinphoneManager.instance lpConfigIntForKey:@"hide_link_phone_number"]) {
|
||||||
[_sideMenuEntries
|
[_sideMenuEntries
|
||||||
addObject:[[SideMenuEntry alloc] initWithTitle:NSLocalizedString(@"Link my account", nil)
|
addObject:[[SideMenuEntry alloc] initWithTitle:NSLocalizedString(@"Link my account", nil)
|
||||||
image:[UIImage imageNamed:@"menu_link_account.png"]
|
image:[UIImage imageNamed:@"menu_link_account.png"]
|
||||||
|
|
@ -104,7 +107,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
[_sideMenuEntries addObject:[[SideMenuEntry alloc] initWithTitle:VoipTexts.conference_scheduled
|
[_sideMenuEntries addObject:[[SideMenuEntry alloc] initWithTitle:VoipTexts.conference_scheduled
|
||||||
image:[UIImage imageNamed:@"voip_conference_new.png"]
|
image:[UIImage imageNamed:@"side_menu_voip_meeting_schedule"]
|
||||||
tapBlock:^() {
|
tapBlock:^() {
|
||||||
[PhoneMainView.instance
|
[PhoneMainView.instance
|
||||||
changeCurrentView:ScheduledConferencesView.compositeViewDescription];
|
changeCurrentView:ScheduledConferencesView.compositeViewDescription];
|
||||||
|
|
@ -127,9 +130,12 @@
|
||||||
|
|
||||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||||
if (section == 0) {
|
if (section == 0) {
|
||||||
|
|
||||||
BOOL hasDefault = (linphone_core_get_default_account(LC) != NULL);
|
BOOL hasDefault = (linphone_core_get_default_account(LC) != NULL);
|
||||||
// default account is shown in the header already
|
// default account is shown in the header already
|
||||||
size_t count = bctbx_list_size(linphone_core_get_account_list(LC));
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
size_t count = bctbx_list_size(accounts);
|
||||||
|
bctbx_free(accounts);
|
||||||
return MAX(0, (int)count - (hasDefault ? 1 : 0));
|
return MAX(0, (int)count - (hasDefault ? 1 : 0));
|
||||||
} else {
|
} else {
|
||||||
return [_sideMenuEntries count];
|
return [_sideMenuEntries count];
|
||||||
|
|
@ -142,12 +148,14 @@
|
||||||
// isLcInitialized called here because this is called when going in bg after LC destroy
|
// isLcInitialized called here because this is called when going in bg after LC destroy
|
||||||
if (indexPath.section == 0 && [LinphoneManager isLcInitialized]) {
|
if (indexPath.section == 0 && [LinphoneManager isLcInitialized]) {
|
||||||
// do not display default account here, it is already in header view
|
// do not display default account here, it is already in header view
|
||||||
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
int idx =
|
int idx =
|
||||||
linphone_core_get_default_account(LC)
|
linphone_core_get_default_account(LC)
|
||||||
? bctbx_list_index(linphone_core_get_account_list(LC), linphone_core_get_default_account(LC))
|
? bctbx_list_index(accounts, linphone_core_get_default_account(LC))
|
||||||
: HUGE_VAL;
|
: HUGE_VAL;
|
||||||
LinphoneAccount *account = bctbx_list_nth_data(linphone_core_get_account_list(LC),
|
LinphoneAccount *account = bctbx_list_nth_data(accounts,
|
||||||
(int)indexPath.row + (idx <= indexPath.row ? 1 : 0));
|
(int)indexPath.row + (idx <= indexPath.row ? 1 : 0));
|
||||||
|
bctbx_free(accounts);
|
||||||
if (account) {
|
if (account) {
|
||||||
cell.textLabel.text = [NSString stringWithUTF8String:linphone_account_params_get_identity(linphone_account_get_params(account))];
|
cell.textLabel.text = [NSString stringWithUTF8String:linphone_account_params_get_identity(linphone_account_get_params(account))];
|
||||||
cell.imageView.image = [StatusBarView imageForState:linphone_account_get_state(account)];
|
cell.imageView.image = [StatusBarView imageForState:linphone_account_get_state(account)];
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,9 @@
|
||||||
_addressLabel.text = str ? [NSString stringWithUTF8String:str] : NSLocalizedString(@"No address", nil);
|
_addressLabel.text = str ? [NSString stringWithUTF8String:str] : NSLocalizedString(@"No address", nil);
|
||||||
if (str) ms_free(str);
|
if (str) ms_free(str);
|
||||||
} else {
|
} else {
|
||||||
_nameLabel.text = linphone_core_get_account_list(LC) ? NSLocalizedString(@"No default account", nil) : NSLocalizedString(@"No account", nil);
|
MSList *accounts = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
|
_nameLabel.text = accounts ? NSLocalizedString(@"No default account", nil) : NSLocalizedString(@"No account", nil);
|
||||||
|
bctbx_free(accounts);
|
||||||
// display direct IP:port address so that we can be reached
|
// display direct IP:port address so that we can be reached
|
||||||
LinphoneAddress *addr = linphone_core_get_primary_contact_parsed(LC);
|
LinphoneAddress *addr = linphone_core_get_primary_contact_parsed(LC);
|
||||||
if (addr) {
|
if (addr) {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import AVFoundation
|
||||||
@objc class CallAppData: NSObject {
|
@objc class CallAppData: NSObject {
|
||||||
@objc var batteryWarningShown = false
|
@objc var batteryWarningShown = false
|
||||||
@objc var videoRequested = false /*set when user has requested for video*/
|
@objc var videoRequested = false /*set when user has requested for video*/
|
||||||
@objc var isConference = true
|
@objc var isConference = false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,6 +49,7 @@ import AVFoundation
|
||||||
var actionsToPerformOnceWhenCoreIsOn : [(()->Void)] = []
|
var actionsToPerformOnceWhenCoreIsOn : [(()->Void)] = []
|
||||||
var conference: Conference?
|
var conference: Conference?
|
||||||
var callkitAudioSessionActivated : Bool? = nil // if "nil", ignore.
|
var callkitAudioSessionActivated : Bool? = nil // if "nil", ignore.
|
||||||
|
var actionToFulFill : CXCallAction? = nil;
|
||||||
|
|
||||||
var backgroundContextCall : Call?
|
var backgroundContextCall : Call?
|
||||||
@objc var backgroundContextCameraIsEnabled : Bool = false
|
@objc var backgroundContextCameraIsEnabled : Bool = false
|
||||||
|
|
@ -556,7 +557,7 @@ import AVFoundation
|
||||||
switch cstate {
|
switch cstate {
|
||||||
case .IncomingReceived:
|
case .IncomingReceived:
|
||||||
let addr = call.remoteAddress
|
let addr = call.remoteAddress
|
||||||
var displayName = incomingDisplayName(call: call)
|
var displayName = incomingDisplayName(call: call)
|
||||||
|
|
||||||
if (CallManager.callKitEnabled()) {
|
if (CallManager.callKitEnabled()) {
|
||||||
let isConference = isConferenceCall(call: call)
|
let isConference = isConferenceCall(call: call)
|
||||||
|
|
@ -608,7 +609,13 @@ import AVFoundation
|
||||||
CallManager.instance().speakerBeforePause = false
|
CallManager.instance().speakerBeforePause = false
|
||||||
CallManager.instance().changeRouteToSpeaker()
|
CallManager.instance().changeRouteToSpeaker()
|
||||||
}
|
}
|
||||||
|
actionToFulFill?.fulfill()
|
||||||
|
actionToFulFill = nil
|
||||||
break
|
break
|
||||||
|
case .Paused:
|
||||||
|
actionToFulFill?.fulfill()
|
||||||
|
actionToFulFill = nil
|
||||||
|
break
|
||||||
case .OutgoingInit,
|
case .OutgoingInit,
|
||||||
.OutgoingProgress,
|
.OutgoingProgress,
|
||||||
.OutgoingRinging,
|
.OutgoingRinging,
|
||||||
|
|
@ -625,7 +632,16 @@ import AVFoundation
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "CallKit: outgoing call started connecting with uuid \(uuid!) and callId \(callId!)")
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "CallKit: outgoing call started connecting with uuid \(uuid!) and callId \(callId!)")
|
||||||
CallManager.instance().providerDelegate.reportOutgoingCallStartedConnecting(uuid: uuid!)
|
CallManager.instance().providerDelegate.reportOutgoingCallStartedConnecting(uuid: uuid!)
|
||||||
} else {
|
} else {
|
||||||
CallManager.instance().referedToCall = callId
|
if CallManager.instance().isConferenceCall(call: call) {
|
||||||
|
let uuid = UUID()
|
||||||
|
let callInfo = CallInfo.newOutgoingCallInfo(addr: call.remoteAddress!, isSas: call.params?.mediaEncryption == .ZRTP, displayName: VoipTexts.conference_default_title, isVideo: call.params?.videoEnabled == true, isConference:true)
|
||||||
|
CallManager.instance().providerDelegate.callInfos.updateValue(callInfo, forKey: uuid)
|
||||||
|
CallManager.instance().providerDelegate.uuids.updateValue(uuid, forKey: "")
|
||||||
|
CallManager.instance().providerDelegate.reportOutgoingCallStartedConnecting(uuid: uuid)
|
||||||
|
Core.get().activateAudioSession(actived: true)
|
||||||
|
} else {
|
||||||
|
CallManager.instance().referedToCall = callId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
@ -706,7 +722,7 @@ import AVFoundation
|
||||||
|
|
||||||
let readyForRoutechange = CallManager.instance().callkitAudioSessionActivated == nil || (CallManager.instance().callkitAudioSessionActivated == true)
|
let readyForRoutechange = CallManager.instance().callkitAudioSessionActivated == nil || (CallManager.instance().callkitAudioSessionActivated == true)
|
||||||
if (readyForRoutechange && (cstate == .IncomingReceived || cstate == .OutgoingInit || cstate == .Connected || cstate == .StreamsRunning)) {
|
if (readyForRoutechange && (cstate == .IncomingReceived || cstate == .OutgoingInit || cstate == .Connected || cstate == .StreamsRunning)) {
|
||||||
if ((call.currentParams?.videoEnabled ?? false) && CallManager.instance().isReceiverEnabled()) {
|
if ((call.currentParams?.videoEnabled ?? false) && CallManager.instance().isReceiverEnabled() && call.conference == nil) {
|
||||||
CallManager.instance().changeRouteToSpeaker()
|
CallManager.instance().changeRouteToSpeaker()
|
||||||
} else if (isBluetoothAvailable()) {
|
} else if (isBluetoothAvailable()) {
|
||||||
// Use bluetooth device by default if one is available
|
// Use bluetooth device by default if one is available
|
||||||
|
|
@ -775,6 +791,7 @@ import AVFoundation
|
||||||
do {
|
do {
|
||||||
if let core = lc, let params = try? core.createConferenceParams(conference: nil) {
|
if let core = lc, let params = try? core.createConferenceParams(conference: nil) {
|
||||||
params.videoEnabled = false // We disable video for local conferencing (cf Android)
|
params.videoEnabled = false // We disable video for local conferencing (cf Android)
|
||||||
|
params.subject = VoipTexts.conference_local_title
|
||||||
let conference = core.conference != nil ? core.conference : try core.createConferenceWithParams(params: params)
|
let conference = core.conference != nil ? core.conference : try core.createConferenceWithParams(params: params)
|
||||||
try conference?.addParticipants(calls: core.calls)
|
try conference?.addParticipants(calls: core.calls)
|
||||||
}
|
}
|
||||||
|
|
@ -783,8 +800,12 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func applyInternationalPrefix() -> Bool {
|
||||||
|
if let account = lc?.defaultAccount, let params = account.params {
|
||||||
|
return params.useInternationalPrefixForCallsAndChats
|
||||||
|
}
|
||||||
|
return true; // Legacy behavior
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,16 @@ class ScheduledConferenceData {
|
||||||
let participantsShort = MutableLiveData<String>()
|
let participantsShort = MutableLiveData<String>()
|
||||||
let participantsExpanded = MutableLiveData<String>()
|
let participantsExpanded = MutableLiveData<String>()
|
||||||
let rawDate : Date
|
let rawDate : Date
|
||||||
|
let isConferenceCancelled = MutableLiveData(false)
|
||||||
|
let canEdit = MutableLiveData(false)
|
||||||
|
let isFinished : Bool
|
||||||
|
let selectedForDeletion = MutableLiveData(false)
|
||||||
|
private var conferenceSchedulerDelegate : ConferenceSchedulerDelegateStub? = nil
|
||||||
|
private var conferenceScheduler : ConferenceScheduler? = nil
|
||||||
|
|
||||||
|
init (conferenceInfo: ConferenceInfo, isFinished: Bool = false) {
|
||||||
init (conferenceInfo: ConferenceInfo) {
|
|
||||||
self.conferenceInfo = conferenceInfo
|
self.conferenceInfo = conferenceInfo
|
||||||
|
self.isFinished = isFinished
|
||||||
expanded.value = false
|
expanded.value = false
|
||||||
|
|
||||||
address.value = conferenceInfo.uri?.asStringUriOnly()
|
address.value = conferenceInfo.uri?.asStringUriOnly()
|
||||||
|
|
@ -51,14 +57,24 @@ class ScheduledConferenceData {
|
||||||
rawDate = Date(timeIntervalSince1970:TimeInterval(conferenceInfo.dateTime))
|
rawDate = Date(timeIntervalSince1970:TimeInterval(conferenceInfo.dateTime))
|
||||||
|
|
||||||
let durationFormatter = DateComponentsFormatter()
|
let durationFormatter = DateComponentsFormatter()
|
||||||
durationFormatter.unitsStyle = .positional
|
durationFormatter.unitsStyle = .abbreviated
|
||||||
durationFormatter.allowedUnits = [.minute, .second ]
|
duration.value = conferenceInfo.duration > 0 ? durationFormatter.string(from: TimeInterval(conferenceInfo.duration*60)) : nil
|
||||||
durationFormatter.zeroFormattingBehavior = [ .pad ]
|
|
||||||
duration.value = conferenceInfo.duration > 0 ? durationFormatter.string(from: TimeInterval(conferenceInfo.duration)) : nil
|
|
||||||
|
|
||||||
organizer.value = conferenceInfo.organizer?.addressBookEnhancedDisplayName()
|
organizer.value = conferenceInfo.organizer?.addressBookEnhancedDisplayName()
|
||||||
|
|
||||||
computeParticipantsLists()
|
computeParticipantsLists()
|
||||||
|
|
||||||
|
isConferenceCancelled.value = conferenceInfo.state == .Cancelled
|
||||||
|
|
||||||
|
if let organizerAddress = conferenceInfo.organizer {
|
||||||
|
let localAccount = Core.get().accountList.filter { account in
|
||||||
|
account.params?.identityAddress != nil && organizerAddress.weakEqual(address2: account.params!.identityAddress!)
|
||||||
|
}.first
|
||||||
|
canEdit.value = localAccount != nil
|
||||||
|
} else {
|
||||||
|
canEdit.value = false
|
||||||
|
Log.e("[Scheduled Conference] No organizer SIP URI found for: \(conferenceInfo.uri?.asStringUriOnly())")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func destroy() {
|
func destroy() {
|
||||||
|
|
@ -73,6 +89,10 @@ class ScheduledConferenceData {
|
||||||
String(describing: participant.addressBookEnhancedDisplayName())
|
String(describing: participant.addressBookEnhancedDisplayName())
|
||||||
}.joined(separator: ", ")
|
}.joined(separator: ", ")
|
||||||
|
|
||||||
|
if (participantsShort.value?.count == 0) {
|
||||||
|
participantsShort.value = " "
|
||||||
|
}
|
||||||
|
|
||||||
participantsExpanded.value = conferenceInfo.participants.map {(participant) in
|
participantsExpanded.value = conferenceInfo.participants.map {(participant) in
|
||||||
String(describing: participant.addressBookEnhancedDisplayName())+" ("+String(describing: participant.asStringUriOnly())+")"
|
String(describing: participant.addressBookEnhancedDisplayName())+" ("+String(describing: participant.asStringUriOnly())+")"
|
||||||
}.joined(separator: "\n")
|
}.joined(separator: "\n")
|
||||||
|
|
@ -81,4 +101,30 @@ class ScheduledConferenceData {
|
||||||
func gotoAssociatedChat() {
|
func gotoAssociatedChat() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func deleteConference() {
|
||||||
|
conferenceSchedulerDelegate = ConferenceSchedulerDelegateStub(
|
||||||
|
onStateChanged: { scheduler, state in
|
||||||
|
Log.i("[Conference Deletion] Conference scheduler state is \(state)")
|
||||||
|
if (state == .Ready) {
|
||||||
|
if let chatRoomParams = ConferenceSchedulingViewModel.shared.getConferenceInvitationsChatRoomParams() {
|
||||||
|
scheduler.sendInvitations(chatRoomParams: chatRoomParams) // Send cancel ICS
|
||||||
|
Log.e("[Conference Deletion] sent cancel ICS.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (conferenceInfo.state != .Cancelled && canEdit.value == true) {
|
||||||
|
Log.i("[Scheduled Conferences] Cancelling conference \(conferenceInfo.subject)")
|
||||||
|
self.conferenceScheduler = try? Core.get().createConferenceScheduler()
|
||||||
|
if (self.conferenceScheduler != nil) {
|
||||||
|
self.conferenceScheduler?.addDelegate(delegate: conferenceSchedulerDelegate!)
|
||||||
|
self.conferenceScheduler?.cancelConference(conferenceInfo: conferenceInfo)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Core.get().deleteConferenceInformation(conferenceInfo: conferenceInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,9 @@ class ConferenceSchedulingViewModel {
|
||||||
let description = MutableLiveData<String>()
|
let description = MutableLiveData<String>()
|
||||||
|
|
||||||
let scheduleForLater = MutableLiveData<Bool>()
|
let scheduleForLater = MutableLiveData<Bool>()
|
||||||
let scheduledDateTime = MutableLiveData<Date>()
|
let scheduledDate = MutableLiveData<Date>()
|
||||||
|
let scheduledTime = MutableLiveData<Date>()
|
||||||
|
|
||||||
var scheduledTimeZone = MutableLiveData<Int>()
|
var scheduledTimeZone = MutableLiveData<Int>()
|
||||||
static let timeZones: [TimeZoneData] = computeTimeZonesList()
|
static let timeZones: [TimeZoneData] = computeTimeZonesList()
|
||||||
|
|
||||||
|
|
@ -64,7 +65,7 @@ class ConferenceSchedulingViewModel {
|
||||||
private var chatRooomDelegate : ChatRoomDelegate? = nil
|
private var chatRooomDelegate : ChatRoomDelegate? = nil
|
||||||
private var conferenceSchedulerDelegate : ConferenceSchedulerDelegateStub? = nil
|
private var conferenceSchedulerDelegate : ConferenceSchedulerDelegateStub? = nil
|
||||||
|
|
||||||
var existingConfInfo:ConferenceInfo? = nil
|
var existingConfInfo:MutableLiveData<ConferenceInfo?> = MutableLiveData()
|
||||||
|
|
||||||
init () {
|
init () {
|
||||||
|
|
||||||
|
|
@ -79,14 +80,10 @@ class ConferenceSchedulingViewModel {
|
||||||
}
|
}
|
||||||
self.address.value = conferenceAddress
|
self.address.value = conferenceAddress
|
||||||
|
|
||||||
if (self.sendInviteViaChat.value == true) {
|
if (self.scheduleForLater.value == true && self.sendInviteViaChat.value == true) {
|
||||||
// Send conference info even when conf is not scheduled for later
|
// Send conference info even when conf is not scheduled for later
|
||||||
// as the conference server doesn't invite participants automatically
|
// as the conference server doesn't invite participants automatically
|
||||||
if let chatRoomParams = try?self.core.createDefaultChatRoomParams() {
|
if let chatRoomParams = self.getConferenceInvitationsChatRoomParams() {
|
||||||
chatRoomParams.backend = ChatRoomBackend.FlexisipChat
|
|
||||||
chatRoomParams.groupEnabled = false
|
|
||||||
chatRoomParams.encryptionEnabled = true
|
|
||||||
chatRoomParams.subject = self.subject.value!
|
|
||||||
scheduler.sendInvitations(chatRoomParams: chatRoomParams)
|
scheduler.sendInvitations(chatRoomParams: chatRoomParams)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -133,13 +130,23 @@ class ConferenceSchedulingViewModel {
|
||||||
scheduleForLater.observe { _ in
|
scheduleForLater.observe { _ in
|
||||||
self.continueEnabled.value = self.allMandatoryFieldsFilled()
|
self.continueEnabled.value = self.allMandatoryFieldsFilled()
|
||||||
}
|
}
|
||||||
scheduledDateTime.observe { _ in
|
scheduledDate.observe { _ in
|
||||||
|
self.continueEnabled.value = self.allMandatoryFieldsFilled()
|
||||||
|
}
|
||||||
|
scheduledTime.observe { _ in
|
||||||
self.continueEnabled.value = self.allMandatoryFieldsFilled()
|
self.continueEnabled.value = self.allMandatoryFieldsFilled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isEndToEndEncryptedChatAvailable() -> Bool {
|
||||||
|
let core = Core.get()
|
||||||
|
return core.limeX3DhEnabled &&
|
||||||
|
((core.limeX3DhServerUrl != nil && core.limeX3DhServerUrl.count > 0) || core.defaultAccount?.params?.limeServerUrl != nil) &&
|
||||||
|
core.defaultAccount?.params?.conferenceFactoryUri != nil
|
||||||
|
}
|
||||||
|
|
||||||
func reset() {
|
func reset() {
|
||||||
|
|
||||||
subject.value = ""
|
subject.value = ""
|
||||||
|
|
@ -147,8 +154,9 @@ class ConferenceSchedulingViewModel {
|
||||||
isEncrypted.value = false
|
isEncrypted.value = false
|
||||||
sendInviteViaChat.value = true
|
sendInviteViaChat.value = true
|
||||||
sendInviteViaEmail.value = false
|
sendInviteViaEmail.value = false
|
||||||
scheduledDateTime.value = Date()
|
scheduledDate.value = nil
|
||||||
|
scheduledTime.value = nil
|
||||||
|
|
||||||
scheduledTimeZone.value = ConferenceSchedulingViewModel.timeZones.indices.filter {
|
scheduledTimeZone.value = ConferenceSchedulingViewModel.timeZones.indices.filter {
|
||||||
ConferenceSchedulingViewModel.timeZones[$0].timeZone.identifier == NSTimeZone.default.identifier
|
ConferenceSchedulingViewModel.timeZones[$0].timeZone.identifier == NSTimeZone.default.identifier
|
||||||
}.first
|
}.first
|
||||||
|
|
@ -158,7 +166,7 @@ class ConferenceSchedulingViewModel {
|
||||||
}.first
|
}.first
|
||||||
continueEnabled.value = false
|
continueEnabled.value = false
|
||||||
selectedAddresses.value = []
|
selectedAddresses.value = []
|
||||||
existingConfInfo = nil
|
existingConfInfo.value = nil
|
||||||
description.value = ""
|
description.value = ""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -191,7 +199,7 @@ class ConferenceSchedulingViewModel {
|
||||||
conferenceScheduler = try? Core.get().createConferenceScheduler()
|
conferenceScheduler = try? Core.get().createConferenceScheduler()
|
||||||
conferenceScheduler?.addDelegate(delegate: conferenceSchedulerDelegate!)
|
conferenceScheduler?.addDelegate(delegate: conferenceSchedulerDelegate!)
|
||||||
|
|
||||||
guard let conferenceInfo = existingConfInfo != nil ? existingConfInfo : try Factory.Instance.createConferenceInfo() else {
|
guard let conferenceInfo = existingConfInfo.value != nil ? existingConfInfo.value??.clone() : try Factory.Instance.createConferenceInfo() else {
|
||||||
Log.e("[Conference Creation/Update] Failed, unable to get conf info.")
|
Log.e("[Conference Creation/Update] Failed, unable to get conf info.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -206,7 +214,7 @@ class ConferenceSchedulingViewModel {
|
||||||
}
|
}
|
||||||
conferenceScheduler?.account = localAccount
|
conferenceScheduler?.account = localAccount
|
||||||
conferenceScheduler?.info = conferenceInfo // Will trigger the conference creation automatically
|
conferenceScheduler?.info = conferenceInfo // Will trigger the conference creation automatically
|
||||||
existingConfInfo = conferenceInfo
|
existingConfInfo.value = conferenceInfo
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
Log.e("[Conference Creation] Failed \(error)")
|
Log.e("[Conference Creation] Failed \(error)")
|
||||||
|
|
@ -216,14 +224,15 @@ class ConferenceSchedulingViewModel {
|
||||||
|
|
||||||
|
|
||||||
private func allMandatoryFieldsFilled() -> Bool {
|
private func allMandatoryFieldsFilled() -> Bool {
|
||||||
return subject.value != nil && subject.value!.count > 0 && (scheduleForLater.value != true || scheduledDateTime.value != nil);
|
return subject.value != nil && subject.value!.count > 0 && (scheduleForLater.value != true || (scheduledDate.value != nil && scheduledTime.value != nil) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private func getConferenceStartTimestamp() -> Double {
|
private func getConferenceStartTimestamp() -> Double {
|
||||||
return scheduleForLater.value == true ?
|
let days = Int32(scheduledDate.value!.timeIntervalSince1970)/86400
|
||||||
scheduledDateTime.value!.timeIntervalSince1970 +
|
let time = Int32(scheduledTime.value!.timeIntervalSince1970)%86400
|
||||||
Double(ConferenceSchedulingViewModel.timeZones[scheduledTimeZone.value!].timeZone.secondsFromGMT()-TimeZone.current.secondsFromGMT())
|
|
||||||
|
return scheduleForLater.value == true ? TimeInterval(days * 86400 + time) + Double(ConferenceSchedulingViewModel.timeZones[scheduledTimeZone.value!].timeZone.secondsFromGMT()-TimeZone.current.secondsFromGMT())
|
||||||
: Date().timeIntervalSince1970
|
: Date().timeIntervalSince1970
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,5 +247,16 @@ class ConferenceSchedulingViewModel {
|
||||||
return [Duration(value: 30, display: "30min"), Duration(value: 60, display: "1h"), Duration(value: 120, display: "2h")]
|
return [Duration(value: 30, display: "30min"), Duration(value: 60, display: "1h"), Duration(value: 120, display: "2h")]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getConferenceInvitationsChatRoomParams() -> ChatRoomParams? {
|
||||||
|
if let chatRoomParams = try?self.core.createDefaultChatRoomParams() {
|
||||||
|
chatRoomParams.encryptionEnabled = self.isEndToEndEncryptedChatAvailable()
|
||||||
|
chatRoomParams.groupEnabled = false
|
||||||
|
chatRoomParams.backend = chatRoomParams.encryptionEnabled ? .FlexisipChat : .Basic
|
||||||
|
chatRoomParams.subject = self.subject.value!
|
||||||
|
return chatRoomParams
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,17 @@ class ScheduledConferencesViewModel {
|
||||||
var conferences : MutableLiveData<[ScheduledConferenceData]> = MutableLiveData([])
|
var conferences : MutableLiveData<[ScheduledConferenceData]> = MutableLiveData([])
|
||||||
var daySplitted : [Date : [ScheduledConferenceData]] = [:]
|
var daySplitted : [Date : [ScheduledConferenceData]] = [:]
|
||||||
var coreDelegate: CoreDelegateStub?
|
var coreDelegate: CoreDelegateStub?
|
||||||
|
var showTerminated = MutableLiveData(false)
|
||||||
|
let editionEnabled = MutableLiveData(false)
|
||||||
|
let conferenceScheduler = try? Core.get().createConferenceScheduler()
|
||||||
|
|
||||||
|
|
||||||
init () {
|
init () {
|
||||||
|
|
||||||
coreDelegate = CoreDelegateStub(
|
coreDelegate = CoreDelegateStub(
|
||||||
onConferenceInfoReceived: { (core, conferenceInfo) in
|
onConferenceInfoReceived: { (core, conferenceInfo) in
|
||||||
Log.i("[Scheduled Conferences] New conference info received")
|
Log.i("[Scheduled Conferences] New conference info received")
|
||||||
self.conferences.value!.append(ScheduledConferenceData(conferenceInfo: conferenceInfo))
|
self.conferences.value!.append(ScheduledConferenceData(conferenceInfo: conferenceInfo,isFinished: false))
|
||||||
self.conferences.notifyValue()
|
self.conferences.notifyValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,11 +52,20 @@ class ScheduledConferencesViewModel {
|
||||||
func computeConferenceInfoList() {
|
func computeConferenceInfoList() {
|
||||||
conferences.value!.removeAll()
|
conferences.value!.removeAll()
|
||||||
let now = Date().timeIntervalSince1970 // Linphone uses time_t in seconds
|
let now = Date().timeIntervalSince1970 // Linphone uses time_t in seconds
|
||||||
let oneHourAgo = now - 3600 // Show all conferences from 1 hour ago and forward
|
|
||||||
core.getConferenceInformationListAfterTime(time: time_t(oneHourAgo)).filter{$0.duration != 0}.forEach { conferenceInfo in
|
if (showTerminated.value == true) {
|
||||||
conferences.value!.append(ScheduledConferenceData(conferenceInfo: conferenceInfo))
|
core.conferenceInformationList.filter{$0.duration != 0 && (TimeInterval($0.dateTime) + TimeInterval($0.duration) < now)}.forEach { conferenceInfo in
|
||||||
|
conferences.value!.append(ScheduledConferenceData(conferenceInfo: conferenceInfo,isFinished: true))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let twoHoursAgo = now - 7200 // Show all conferences from 2 hour ago and forward
|
||||||
|
core.getConferenceInformationListAfterTime(time: time_t(twoHoursAgo)).filter{$0.duration != 0}.forEach { conferenceInfo in
|
||||||
|
conferences.value!.append(ScheduledConferenceData(conferenceInfo: conferenceInfo,isFinished: false))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
daySplitted = [:]
|
daySplitted = [:]
|
||||||
conferences.value!.forEach { (conferenceInfo) in
|
conferences.value!.forEach { (conferenceInfo) in
|
||||||
let startDateDay = dateAtBeginningOfDay(for: conferenceInfo.rawDate)
|
let startDateDay = dateAtBeginningOfDay(for: conferenceInfo.rawDate)
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ import linphonesw
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static let compositeDescription = UICompositeViewDescription(ConferenceHistoryDetailsView.self, statusBar: StatusBarView.self, tabBar: nil, sideMenu: SideMenuView.self, fullscreen: false, isLeftFragment: false,fragmentWith: nil)
|
static let compositeDescription = UICompositeViewDescription(ConferenceHistoryDetailsView.self, statusBar: StatusBarView.self, tabBar: TabBarView.classForCoder(), sideMenu: SideMenuView.self, fullscreen: false, isLeftFragment: false,fragmentWith: HistoryListView.classForCoder())
|
||||||
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
||||||
func compositeViewDescription() -> UICompositeViewDescription! { return type(of: self).compositeDescription }
|
func compositeViewDescription() -> UICompositeViewDescription! { return type(of: self).compositeDescription }
|
||||||
|
|
||||||
|
|
@ -65,6 +65,7 @@ import linphonesw
|
||||||
title:"")
|
title:"")
|
||||||
super.nextButton.isHidden = true
|
super.nextButton.isHidden = true
|
||||||
|
|
||||||
|
super.backButton.isHidden = UIDevice.ipad()
|
||||||
|
|
||||||
let schedulingStack = UIStackView()
|
let schedulingStack = UIStackView()
|
||||||
schedulingStack.axis = .vertical
|
schedulingStack.axis = .vertical
|
||||||
|
|
@ -106,7 +107,6 @@ import linphonesw
|
||||||
|
|
||||||
// Organiser
|
// Organiser
|
||||||
|
|
||||||
organiserLabel.backgroundColor = VoipTheme.voipFormBackgroundColor.get()
|
|
||||||
contentView.addSubview(organiserLabel)
|
contentView.addSubview(organiserLabel)
|
||||||
organiserLabel.matchParentSideBorders().height(form_input_height).alignUnder(view: schedulingStack,withMargin: form_margin*2).done()
|
organiserLabel.matchParentSideBorders().height(form_input_height).alignUnder(view: schedulingStack,withMargin: form_margin*2).done()
|
||||||
organiserLabel.textAlignment = .left
|
organiserLabel.textAlignment = .left
|
||||||
|
|
@ -120,12 +120,10 @@ import linphonesw
|
||||||
organizerTableView.allowsFocus = false
|
organizerTableView.allowsFocus = false
|
||||||
}
|
}
|
||||||
organizerTableView.separatorStyle = .singleLine
|
organizerTableView.separatorStyle = .singleLine
|
||||||
organizerTableView.separatorColor = VoipTheme.light_grey_color
|
|
||||||
organizerTableView.tag = 1;
|
organizerTableView.tag = 1;
|
||||||
organizerTableView.matchParentSideBorders().height(VoipParticipantCell.cell_height).alignUnder(view: organiserLabel,withMargin: form_margin).done()
|
organizerTableView.matchParentSideBorders().height(VoipParticipantCell.cell_height).alignUnder(view: organiserLabel,withMargin: form_margin).done()
|
||||||
|
|
||||||
// Participants
|
// Participants
|
||||||
participantsLabel.backgroundColor = VoipTheme.voipFormBackgroundColor.get()
|
|
||||||
contentView.addSubview(participantsLabel)
|
contentView.addSubview(participantsLabel)
|
||||||
participantsLabel.matchParentSideBorders().height(form_input_height).alignUnder(view: organizerTableView,withMargin: form_margin).done()
|
participantsLabel.matchParentSideBorders().height(form_input_height).alignUnder(view: organizerTableView,withMargin: form_margin).done()
|
||||||
participantsLabel.textAlignment = .left
|
participantsLabel.textAlignment = .left
|
||||||
|
|
@ -139,7 +137,6 @@ import linphonesw
|
||||||
participantsListTableView.allowsFocus = false
|
participantsListTableView.allowsFocus = false
|
||||||
}
|
}
|
||||||
participantsListTableView.separatorStyle = .singleLine
|
participantsListTableView.separatorStyle = .singleLine
|
||||||
participantsListTableView.separatorColor = VoipTheme.light_grey_color
|
|
||||||
|
|
||||||
// Goto chat - v2
|
// Goto chat - v2
|
||||||
/*
|
/*
|
||||||
|
|
@ -152,6 +149,14 @@ import linphonesw
|
||||||
|
|
||||||
chatButton.centerX().alignParentBottom(withMargin: 3*self.form_margin).alignUnder(view: participantsListTableView,withMargin: 3*self.form_margin).done()
|
chatButton.centerX().alignParentBottom(withMargin: 3*self.form_margin).alignUnder(view: participantsListTableView,withMargin: 3*self.form_margin).done()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in
|
||||||
|
self.organiserLabel.backgroundColor = VoipTheme.voipFormBackgroundColor.get()
|
||||||
|
self.organizerTableView.separatorColor = VoipTheme.separatorColor.get()
|
||||||
|
self.participantsLabel.backgroundColor = VoipTheme.voipFormBackgroundColor.get()
|
||||||
|
self.participantsListTableView.separatorColor = VoipTheme.separatorColor.get()
|
||||||
|
self.view.backgroundColor = VoipTheme.voipBackgroundBWColor.get()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,16 @@ import SVProgressHUD
|
||||||
|
|
||||||
let participantsListTableView = UITableView()
|
let participantsListTableView = UITableView()
|
||||||
|
|
||||||
let datePicker = StyledDatePicker(liveValue: ConferenceSchedulingViewModel.shared.scheduledDateTime,pickerMode: .date, readOnly:true)
|
let datePicker = StyledDatePicker(liveValue: ConferenceSchedulingViewModel.shared.scheduledDate,pickerMode: .date, readOnly:true)
|
||||||
let timeZoneValue = StyledValuePicker(liveIndex: ConferenceSchedulingViewModel.shared.scheduledTimeZone,options: ConferenceSchedulingViewModel.timeZones.map({ (tzd: TimeZoneData) -> String in tzd.descWithOffset()}), readOnly:true)
|
let timeZoneValue = StyledValuePicker(liveIndex: ConferenceSchedulingViewModel.shared.scheduledTimeZone,options: ConferenceSchedulingViewModel.timeZones.map({ (tzd: TimeZoneData) -> String in tzd.descWithOffset()}), readOnly:true)
|
||||||
let durationValue = StyledValuePicker(liveIndex: ConferenceSchedulingViewModel.shared.scheduledDuration,options: ConferenceSchedulingViewModel.durationList.map({ (duration: Duration) -> String in duration.display}), readOnly:true)
|
let durationValue = StyledValuePicker(liveIndex: ConferenceSchedulingViewModel.shared.scheduledDuration,options: ConferenceSchedulingViewModel.durationList.map({ (duration: Duration) -> String in duration.display}), readOnly:true)
|
||||||
let timePicker = StyledDatePicker(liveValue: ConferenceSchedulingViewModel.shared.scheduledDateTime,pickerMode: .time, readOnly:true)
|
let timePicker = StyledDatePicker(liveValue: ConferenceSchedulingViewModel.shared.scheduledTime,pickerMode: .time, readOnly:true)
|
||||||
|
let descriptionLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_description_hint)
|
||||||
let descriptionInput = StyledTextView(VoipTheme.conference_scheduling_font, placeHolder:VoipTexts.conference_schedule_description_hint,liveValue: ConferenceSchedulingViewModel.shared.description, readOnly:true)
|
let descriptionInput = StyledTextView(VoipTheme.conference_scheduling_font, placeHolder:VoipTexts.conference_schedule_description_hint,liveValue: ConferenceSchedulingViewModel.shared.description, readOnly:true)
|
||||||
let createButton = FormButton(backgroundStateColors: VoipTheme.primary_colors_background)
|
let createButton = FormButton(backgroundStateColors: VoipTheme.primary_colors_background)
|
||||||
|
let leftColumn = UIView()
|
||||||
|
let rightColumn = UIView()
|
||||||
|
let scheduleForm = UIView()
|
||||||
|
|
||||||
static let compositeDescription = UICompositeViewDescription(ConferenceSchedulingSummaryView.self, statusBar: StatusBarView.self, tabBar: nil, sideMenu: SideMenuView.self, fullscreen: false, isLeftFragment: false,fragmentWith: nil)
|
static let compositeDescription = UICompositeViewDescription(ConferenceSchedulingSummaryView.self, statusBar: StatusBarView.self, tabBar: nil, sideMenu: SideMenuView.self, fullscreen: false, isLeftFragment: false,fragmentWith: nil)
|
||||||
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
||||||
|
|
@ -76,15 +79,12 @@ import SVProgressHUD
|
||||||
schedulingStack.alignUnder(view: subjectInput,withMargin: 3*form_margin).matchParentSideBorders(insetedByDx: form_margin).done()
|
schedulingStack.alignUnder(view: subjectInput,withMargin: 3*form_margin).matchParentSideBorders(insetedByDx: form_margin).done()
|
||||||
|
|
||||||
|
|
||||||
let scheduleForm = UIView()
|
|
||||||
schedulingStack.addArrangedSubview(scheduleForm)
|
schedulingStack.addArrangedSubview(scheduleForm)
|
||||||
scheduleForm.matchParentSideBorders().done()
|
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { (forLater) in self.scheduleForm.isHidden = forLater != true }
|
||||||
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { (forLater) in scheduleForm.isHidden = forLater != true }
|
|
||||||
|
|
||||||
// Left column (Date & Time)
|
// Left column (Date & Time)
|
||||||
let leftColumn = UIView()
|
|
||||||
scheduleForm.addSubview(leftColumn)
|
scheduleForm.addSubview(leftColumn)
|
||||||
leftColumn.matchParentWidthDividedBy(2.2).alignParentLeft(withMargin: form_margin).alignParentTop(withMargin: form_margin).done()
|
leftColumn.matchParentWidthDividedBy(2.2).alignParentLeft().alignParentTop(withMargin: form_margin).done()
|
||||||
|
|
||||||
let dateLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_date)
|
let dateLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_date)
|
||||||
leftColumn.addSubview(dateLabel)
|
leftColumn.addSubview(dateLabel)
|
||||||
|
|
@ -104,9 +104,8 @@ import SVProgressHUD
|
||||||
|
|
||||||
|
|
||||||
// Right column (Duration & Timezone)
|
// Right column (Duration & Timezone)
|
||||||
let rightColumn = UIView()
|
|
||||||
scheduleForm.addSubview(rightColumn)
|
scheduleForm.addSubview(rightColumn)
|
||||||
rightColumn.matchParentWidthDividedBy(2.2).alignParentRight(withMargin: form_margin).alignParentTop().done()
|
rightColumn.matchParentWidthDividedBy(2.2).alignParentRight().alignParentTop().done()
|
||||||
|
|
||||||
let durationLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_duration)
|
let durationLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_duration)
|
||||||
rightColumn.addSubview(durationLabel)
|
rightColumn.addSubview(durationLabel)
|
||||||
|
|
@ -125,31 +124,26 @@ import SVProgressHUD
|
||||||
rightColumn.wrapContentY().done()
|
rightColumn.wrapContentY().done()
|
||||||
|
|
||||||
// Description
|
// Description
|
||||||
let descriptionLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_description_title)
|
|
||||||
scheduleForm.addSubview(descriptionLabel)
|
scheduleForm.addSubview(descriptionLabel)
|
||||||
descriptionLabel.alignUnder(view: leftColumn,withMargin: form_margin).alignUnder(view: rightColumn,withMargin: form_margin).matchParentSideBorders(insetedByDx: form_margin).done()
|
|
||||||
|
|
||||||
descriptionInput.textContainer.maximumNumberOfLines = 5
|
descriptionInput.textContainer.maximumNumberOfLines = 5
|
||||||
descriptionInput.textContainer.lineBreakMode = .byWordWrapping
|
descriptionInput.textContainer.lineBreakMode = .byWordWrapping
|
||||||
scheduleForm.addSubview(descriptionInput)
|
scheduleForm.addSubview(descriptionInput)
|
||||||
descriptionInput.alignUnder(view: descriptionLabel,withMargin: form_margin).matchParentSideBorders(insetedByDx: form_margin).height(description_height).alignParentBottom(withMargin: form_margin*2).done()
|
|
||||||
|
|
||||||
scheduleForm.wrapContentY().done()
|
|
||||||
|
|
||||||
// Sending method
|
// Sending method
|
||||||
let viaChatLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_send_invite_chat_summary)
|
let viaChatLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_send_invite_chat_summary)
|
||||||
contentView.addSubview(viaChatLabel)
|
contentView.addSubview(viaChatLabel)
|
||||||
viaChatLabel.matchParentSideBorders(insetedByDx: form_margin).alignUnder(view: schedulingStack,withMargin: 2*form_margin).done()
|
viaChatLabel.matchParentSideBorders(insetedByDx: form_margin).alignUnder(view: schedulingStack,withMargin: 2*form_margin).done()
|
||||||
|
viaChatLabel.numberOfLines = 2
|
||||||
ConferenceSchedulingViewModel.shared.sendInviteViaChat.readCurrentAndObserve { (sendChat) in
|
ConferenceSchedulingViewModel.shared.sendInviteViaChat.readCurrentAndObserve { (sendChat) in
|
||||||
viaChatLabel.isHidden = sendChat != true || ConferenceSchedulingViewModel.shared.scheduleForLater.value != true
|
viaChatLabel.isHidden = sendChat != true || ConferenceSchedulingViewModel.shared.scheduleForLater.value != true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Participants
|
// Participants
|
||||||
let participantsLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_participants_list)
|
let participantsLabel = StyledLabel(VoipTheme.conference_scheduling_font, " "+VoipTexts.conference_schedule_participants_list)
|
||||||
participantsLabel.backgroundColor = VoipTheme.voipFormBackgroundColor.get()
|
|
||||||
contentView.addSubview(participantsLabel)
|
contentView.addSubview(participantsLabel)
|
||||||
participantsLabel.matchParentSideBorders().height(form_input_height).alignUnder(view: viaChatLabel,withMargin: form_margin*2).done()
|
participantsLabel.matchParentSideBorders().height(form_input_height).alignUnder(view: viaChatLabel,withMargin: form_margin).done()
|
||||||
participantsLabel.textAlignment = .center
|
participantsLabel.textAlignment = .left
|
||||||
|
|
||||||
|
|
||||||
contentView.addSubview(participantsListTableView)
|
contentView.addSubview(participantsListTableView)
|
||||||
|
|
@ -161,7 +155,7 @@ import SVProgressHUD
|
||||||
participantsListTableView.allowsFocus = false
|
participantsListTableView.allowsFocus = false
|
||||||
}
|
}
|
||||||
participantsListTableView.separatorStyle = .singleLine
|
participantsListTableView.separatorStyle = .singleLine
|
||||||
participantsListTableView.separatorColor = VoipTheme.light_grey_color
|
participantsListTableView.backgroundColor = .clear
|
||||||
|
|
||||||
ConferenceSchedulingViewModel.shared.selectedAddresses.readCurrentAndObserve { (addresses) in
|
ConferenceSchedulingViewModel.shared.selectedAddresses.readCurrentAndObserve { (addresses) in
|
||||||
self.participantsListTableView.reloadData()
|
self.participantsListTableView.reloadData()
|
||||||
|
|
@ -172,8 +166,13 @@ import SVProgressHUD
|
||||||
|
|
||||||
// Create / Schedule
|
// Create / Schedule
|
||||||
contentView.addSubview(createButton)
|
contentView.addSubview(createButton)
|
||||||
|
createButton.centerX().alignParentBottom(withMargin: 3*self.form_margin).alignUnder(view: participantsListTableView,withMargin: 3*self.form_margin).width(0).done()
|
||||||
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { _ in
|
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { _ in
|
||||||
self.createButton.title = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? VoipTexts.conference_schedule_start.uppercased() : VoipTexts.conference_group_call_create.uppercased()
|
self.createButton.title = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? ConferenceSchedulingViewModel.shared.existingConfInfo.value != nil ? VoipTexts.conference_schedule_edit.uppercased() : VoipTexts.conference_schedule_start.uppercased() : VoipTexts.conference_group_call_create.uppercased()
|
||||||
|
self.createButton.addSidePadding()
|
||||||
|
}
|
||||||
|
ConferenceSchedulingViewModel.shared.existingConfInfo.readCurrentAndObserve { _ in
|
||||||
|
self.createButton.title = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? ConferenceSchedulingViewModel.shared.existingConfInfo.value != nil ? VoipTexts.conference_schedule_edit.uppercased() : VoipTexts.conference_schedule_start.uppercased() : VoipTexts.conference_group_call_create.uppercased()
|
||||||
self.createButton.addSidePadding()
|
self.createButton.addSidePadding()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,21 +209,40 @@ import SVProgressHUD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { (later) in
|
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { (later) in
|
||||||
self.createButton.title = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? VoipTexts.conference_schedule_start.uppercased() : VoipTexts.conference_group_call_create.uppercased()
|
self.createButton.title = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? ConferenceSchedulingViewModel.shared.existingConfInfo.value != nil ? VoipTexts.conference_schedule_edit.uppercased() : VoipTexts.conference_schedule_start.uppercased() : VoipTexts.conference_group_call_create.uppercased()
|
||||||
viaChatLabel.isHidden = later != true || ConferenceSchedulingViewModel.shared.sendInviteViaChat.value != true
|
viaChatLabel.isHidden = later != true || ConferenceSchedulingViewModel.shared.sendInviteViaChat.value != true
|
||||||
|
viaChatLabel.removeConstraints().matchParentSideBorders(insetedByDx: self.form_margin).alignUnder(view: schedulingStack,withMargin: (viaChatLabel.isHidden ? 0 : 1)*self.form_margin).done()
|
||||||
|
if (viaChatLabel.isHidden) {
|
||||||
|
viaChatLabel.height(0).done()
|
||||||
|
}
|
||||||
|
|
||||||
self.createButton.addSidePadding()
|
self.createButton.addSidePadding()
|
||||||
}
|
}
|
||||||
|
|
||||||
createButton.centerX().alignParentBottom(withMargin: 3*self.form_margin).alignUnder(view: participantsListTableView,withMargin: 3*self.form_margin).done()
|
UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in
|
||||||
|
self.view.backgroundColor = VoipTheme.voipBackgroundBWColor.get()
|
||||||
|
participantsLabel.backgroundColor = VoipTheme.voipFormBackgroundColor.get()
|
||||||
|
self.participantsListTableView.separatorColor = VoipTheme.separatorColor.get()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
datePicker.liveValue = ConferenceSchedulingViewModel.shared.scheduledDateTime
|
datePicker.liveValue = ConferenceSchedulingViewModel.shared.scheduledDate
|
||||||
timeZoneValue.setIndex(index: ConferenceSchedulingViewModel.shared.scheduledTimeZone.value!)
|
timeZoneValue.setIndex(index: ConferenceSchedulingViewModel.shared.scheduledTimeZone.value!)
|
||||||
durationValue.setIndex(index: ConferenceSchedulingViewModel.shared.scheduledDuration.value!)
|
durationValue.setIndex(index: ConferenceSchedulingViewModel.shared.scheduledDuration.value!)
|
||||||
timePicker.liveValue = ConferenceSchedulingViewModel.shared.scheduledDateTime
|
timePicker.liveValue = ConferenceSchedulingViewModel.shared.scheduledTime
|
||||||
|
|
||||||
descriptionInput.text = ConferenceSchedulingViewModel.shared.description.value
|
descriptionInput.text = ConferenceSchedulingViewModel.shared.description.value
|
||||||
|
descriptionLabel.removeConstraints().alignUnder(view: leftColumn,withMargin: form_margin).alignUnder(view: rightColumn,withMargin: form_margin).matchParentSideBorders().done()
|
||||||
|
descriptionInput.removeConstraints().alignUnder(view: descriptionLabel,withMargin: form_margin).matchParentSideBorders().height(description_height).alignParentBottom(withMargin: form_margin*2).done()
|
||||||
|
if (ConferenceSchedulingViewModel.shared.description.value == nil || ConferenceSchedulingViewModel.shared.description.value!.count == 0) {
|
||||||
|
descriptionLabel.height(0).done()
|
||||||
|
descriptionInput.height(0).done()
|
||||||
|
}
|
||||||
|
// Wrap form
|
||||||
|
scheduleForm.removeConstraints().matchParentSideBorders().wrapContentY().done()
|
||||||
|
|
||||||
createButton.addSidePadding()
|
createButton.addSidePadding()
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
}
|
}
|
||||||
|
|
@ -233,6 +251,7 @@ import SVProgressHUD
|
||||||
|
|
||||||
func goBackParticipantsListSelection() {
|
func goBackParticipantsListSelection() {
|
||||||
let view: ChatConversationCreateView = VIEW(ChatConversationCreateView.compositeViewDescription())
|
let view: ChatConversationCreateView = VIEW(ChatConversationCreateView.compositeViewDescription())
|
||||||
|
view.unfragmentCompositeDescription()
|
||||||
let addresses = ConferenceSchedulingViewModel.shared.selectedAddresses.value!.map { (address) in String(address.asStringUriOnly()) }
|
let addresses = ConferenceSchedulingViewModel.shared.selectedAddresses.value!.map { (address) in String(address.asStringUriOnly()) }
|
||||||
view.tableController.contactsGroup = (addresses as NSArray).mutableCopy() as? NSMutableArray
|
view.tableController.contactsGroup = (addresses as NSArray).mutableCopy() as? NSMutableArray
|
||||||
view.tableController.notFirstTime = true
|
view.tableController.notFirstTime = true
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import Foundation
|
import Foundation
|
||||||
import linphonesw
|
import linphonesw
|
||||||
|
import IQKeyboardManager
|
||||||
|
|
||||||
@objc class ConferenceSchedulingView: BackNextNavigationView, UICompositeViewDelegate {
|
@objc class ConferenceSchedulingView: BackNextNavigationView, UICompositeViewDelegate {
|
||||||
|
|
||||||
|
|
@ -29,17 +30,19 @@ import linphonesw
|
||||||
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
||||||
func compositeViewDescription() -> UICompositeViewDescription! { return type(of: self).compositeDescription }
|
func compositeViewDescription() -> UICompositeViewDescription! { return type(of: self).compositeDescription }
|
||||||
|
|
||||||
let datePicker = StyledDatePicker(liveValue: ConferenceSchedulingViewModel.shared.scheduledDateTime,pickerMode: .date)
|
let datePicker = StyledDatePicker(liveValue: ConferenceSchedulingViewModel.shared.scheduledDate,pickerMode: .date)
|
||||||
let timeZoneValue = StyledValuePicker(liveIndex: ConferenceSchedulingViewModel.shared.scheduledTimeZone,options: ConferenceSchedulingViewModel.timeZones.map({ (tzd: TimeZoneData) -> String in tzd.descWithOffset()}))
|
let timeZoneValue = StyledValuePicker(liveIndex: ConferenceSchedulingViewModel.shared.scheduledTimeZone,options: ConferenceSchedulingViewModel.timeZones.map({ (tzd: TimeZoneData) -> String in tzd.descWithOffset()}))
|
||||||
let durationValue = StyledValuePicker(liveIndex: ConferenceSchedulingViewModel.shared.scheduledDuration,options: ConferenceSchedulingViewModel.durationList.map({ (duration: Duration) -> String in duration.display}))
|
let durationValue = StyledValuePicker(liveIndex: ConferenceSchedulingViewModel.shared.scheduledDuration,options: ConferenceSchedulingViewModel.durationList.map({ (duration: Duration) -> String in duration.display}))
|
||||||
let timePicker = StyledDatePicker(liveValue: ConferenceSchedulingViewModel.shared.scheduledDateTime,pickerMode: .time)
|
let timePicker = StyledDatePicker(liveValue: ConferenceSchedulingViewModel.shared.scheduledTime,pickerMode: .time)
|
||||||
let descriptionInput = StyledTextView(VoipTheme.conference_scheduling_font, placeHolder:VoipTexts.conference_schedule_description_hint,liveValue: ConferenceSchedulingViewModel.shared.description)
|
let descriptionInput = StyledTextView(VoipTheme.conference_scheduling_font, placeHolder:VoipTexts.conference_schedule_description_hint,liveValue: ConferenceSchedulingViewModel.shared.description)
|
||||||
|
let subjectInput = StyledTextView(VoipTheme.conference_scheduling_font, placeHolder:VoipTexts.conference_schedule_subject_hint, liveValue: ConferenceSchedulingViewModel.shared.subject,maxLines:1)
|
||||||
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
|
|
||||||
super.viewDidLoad(
|
super.viewDidLoad(
|
||||||
backAction: {
|
backAction: {
|
||||||
|
ConferenceSchedulingViewModel.shared.reset()
|
||||||
PhoneMainView.instance().popView(self.compositeViewDescription())
|
PhoneMainView.instance().popView(self.compositeViewDescription())
|
||||||
},nextAction: {
|
},nextAction: {
|
||||||
self.gotoParticipantsListSelection()
|
self.gotoParticipantsListSelection()
|
||||||
|
|
@ -52,13 +55,11 @@ import linphonesw
|
||||||
contentView.addSubview(subjectLabel)
|
contentView.addSubview(subjectLabel)
|
||||||
subjectLabel.alignParentLeft(withMargin: form_margin).alignParentTop().done()
|
subjectLabel.alignParentLeft(withMargin: form_margin).alignParentTop().done()
|
||||||
|
|
||||||
let subjectInput = StyledTextView(VoipTheme.conference_scheduling_font, placeHolder:VoipTexts.conference_schedule_subject_hint, liveValue: ConferenceSchedulingViewModel.shared.subject,maxLines:1)
|
|
||||||
contentView.addSubview(subjectInput)
|
contentView.addSubview(subjectInput)
|
||||||
subjectInput.alignUnder(view: subjectLabel,withMargin: form_margin).matchParentSideBorders(insetedByDx: form_margin).height(form_input_height).done()
|
subjectInput.alignUnder(view: subjectLabel,withMargin: form_margin).matchParentSideBorders(insetedByDx: form_margin).height(form_input_height).done()
|
||||||
|
|
||||||
let schedulingStack = UIStackView()
|
let schedulingStack = UIStackView()
|
||||||
schedulingStack.axis = .vertical
|
schedulingStack.axis = .vertical
|
||||||
schedulingStack.backgroundColor = VoipTheme.voipFormBackgroundColor.get()
|
|
||||||
contentView.addSubview(schedulingStack)
|
contentView.addSubview(schedulingStack)
|
||||||
schedulingStack.alignUnder(view: subjectInput,withMargin: form_margin).matchParentSideBorders(insetedByDx: form_margin).done()
|
schedulingStack.alignUnder(view: subjectInput,withMargin: form_margin).matchParentSideBorders(insetedByDx: form_margin).done()
|
||||||
|
|
||||||
|
|
@ -132,19 +133,25 @@ import linphonesw
|
||||||
descriptionInput.textContainer.maximumNumberOfLines = 5
|
descriptionInput.textContainer.maximumNumberOfLines = 5
|
||||||
descriptionInput.textContainer.lineBreakMode = .byWordWrapping
|
descriptionInput.textContainer.lineBreakMode = .byWordWrapping
|
||||||
scheduleForm.addSubview(descriptionInput)
|
scheduleForm.addSubview(descriptionInput)
|
||||||
descriptionInput.alignUnder(view: descriptionLabel,withMargin: form_margin).matchParentSideBorders(insetedByDx: form_margin).height(description_height).alignParentBottom(withMargin: form_margin*2).done()
|
descriptionInput.alignUnder(view: descriptionLabel,withMargin: 2*form_margin).matchParentSideBorders(insetedByDx: form_margin).height(description_height).done()
|
||||||
|
|
||||||
scheduleForm.wrapContentY().done()
|
|
||||||
|
|
||||||
// Sending methods
|
// Sending methods
|
||||||
let viaChatSwitch = StyledCheckBox(liveValue: ConferenceSchedulingViewModel.shared.sendInviteViaChat)
|
|
||||||
contentView.addSubview(viaChatSwitch)
|
let viaChatView = UIView()
|
||||||
viaChatSwitch.alignParentLeft(withMargin: form_margin).alignUnder(view: schedulingStack,withMargin: 2*form_margin).done()
|
scheduleForm.addSubview(viaChatView)
|
||||||
|
viaChatView.alignUnder(view: descriptionInput,withMargin: form_margin).matchParentSideBorders(insetedByDx: form_margin).alignParentBottom(withMargin: form_margin*4).done()
|
||||||
|
|
||||||
|
let viaChatSwitch = StyledCheckBox()
|
||||||
|
viaChatSwitch.liveValue = ConferenceSchedulingViewModel.shared.sendInviteViaChat
|
||||||
|
viaChatView.addSubview(viaChatSwitch)
|
||||||
|
viaChatSwitch.alignParentLeft().done()
|
||||||
|
|
||||||
let viaChatLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_send_invite_chat)
|
let viaChatLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_send_invite_chat)
|
||||||
contentView.addSubview(viaChatLabel)
|
viaChatView.addSubview(viaChatLabel)
|
||||||
viaChatLabel.toRightOf(viaChatSwitch,withLeftMargin: form_margin).alignUnder(view: schedulingStack,withMargin: 2*form_margin).alignHorizontalCenterWith(viaChatSwitch).done()
|
viaChatLabel.toRightOf(viaChatSwitch,withLeftMargin: form_margin).alignHorizontalCenterWith(viaChatSwitch).done()
|
||||||
|
|
||||||
|
viaChatView.wrapContentY().done()
|
||||||
|
|
||||||
/* Hidden as in Android 9.6.2022
|
/* Hidden as in Android 9.6.2022
|
||||||
|
|
||||||
let viaMailSwitch = StyledCheckBox(liveValue: ConferenceSchedulingViewModel.shared.sendInviteViaEmail)
|
let viaMailSwitch = StyledCheckBox(liveValue: ConferenceSchedulingViewModel.shared.sendInviteViaEmail)
|
||||||
|
|
@ -183,34 +190,51 @@ import linphonesw
|
||||||
let mandatoryLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_mandatory_field)
|
let mandatoryLabel = StyledLabel(VoipTheme.conference_scheduling_font, VoipTexts.conference_schedule_mandatory_field)
|
||||||
mandatoryLabel.addIndicatorIcon(iconName: "voip_mandatory", trailing: false)
|
mandatoryLabel.addIndicatorIcon(iconName: "voip_mandatory", trailing: false)
|
||||||
contentView.addSubview(mandatoryLabel)
|
contentView.addSubview(mandatoryLabel)
|
||||||
mandatoryLabel.alignUnder(view: viaChatSwitch,withMargin: 2*form_margin).centerX().matchParentSideBorders().done()
|
|
||||||
mandatoryLabel.textAlignment = .center
|
mandatoryLabel.textAlignment = .center
|
||||||
|
|
||||||
mandatoryLabel.alignParentBottom().done()
|
let lastView = UIView()
|
||||||
|
contentView.addSubview(lastView)
|
||||||
|
lastView.alignUnder(view: mandatoryLabel).alignParentBottom().done()
|
||||||
|
|
||||||
// Schedule for later observer
|
// Schedule for later observer
|
||||||
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { (forLater) in
|
ConferenceSchedulingViewModel.shared.scheduleForLater.readCurrentAndObserve { (forLater) in
|
||||||
|
self.subjectInput.setPlaceHolder(phText: forLater == true ? VoipTexts.conference_schedule_subject_hint : VoipTexts.conference_group_call_subject_hint)
|
||||||
scheduleForm.isHidden = forLater != true
|
scheduleForm.isHidden = forLater != true
|
||||||
super.titleLabel.text = forLater == true ? VoipTexts.conference_schedule_title : VoipTexts.conference_group_call_title
|
super.titleLabel.text = forLater == true ? ConferenceSchedulingViewModel.shared.existingConfInfo.value != nil ? VoipTexts.conference_schedule_edit : VoipTexts.conference_schedule_title : VoipTexts.conference_group_call_title
|
||||||
viaChatSwitch.isHidden = forLater != true
|
mandatoryLabel.removeConstraints().done()
|
||||||
viaChatLabel.isHidden = forLater != true
|
mandatoryLabel.alignUnder(view: forLater == true ? scheduleForm : scheduleForLater,withMargin: 2*self.form_margin).centerX().matchParentSideBorders().done()
|
||||||
}
|
}
|
||||||
|
ConferenceSchedulingViewModel.shared.existingConfInfo.readCurrentAndObserve { (confInfo) in
|
||||||
|
super.titleLabel.text = ConferenceSchedulingViewModel.shared.scheduleForLater.value == true ? ConferenceSchedulingViewModel.shared.existingConfInfo.value != nil ? VoipTexts.conference_schedule_edit : VoipTexts.conference_schedule_title : VoipTexts.conference_group_call_title
|
||||||
|
}
|
||||||
|
|
||||||
|
UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in
|
||||||
|
self.view.backgroundColor = VoipTheme.voipBackgroundBWColor.get()
|
||||||
|
schedulingStack.backgroundColor = VoipTheme.voipFormBackgroundColor.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
datePicker.liveValue = ConferenceSchedulingViewModel.shared.scheduledDateTime
|
datePicker.liveValue = ConferenceSchedulingViewModel.shared.scheduledDate
|
||||||
timeZoneValue.setIndex(index: ConferenceSchedulingViewModel.shared.scheduledTimeZone.value!)
|
timeZoneValue.setIndex(index: ConferenceSchedulingViewModel.shared.scheduledTimeZone.value!)
|
||||||
durationValue.setIndex(index: ConferenceSchedulingViewModel.shared.scheduledDuration.value!)
|
durationValue.setIndex(index: ConferenceSchedulingViewModel.shared.scheduledDuration.value!)
|
||||||
timePicker.liveValue = ConferenceSchedulingViewModel.shared.scheduledDateTime
|
timePicker.liveValue = ConferenceSchedulingViewModel.shared.scheduledTime
|
||||||
descriptionInput.text = ConferenceSchedulingViewModel.shared.description.value
|
descriptionInput.text = ConferenceSchedulingViewModel.shared.description.value
|
||||||
|
IQKeyboardManager.shared().isEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
|
IQKeyboardManager.shared().isEnabled = false
|
||||||
|
super.viewWillDisappear(animated)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func gotoParticipantsListSelection() {
|
func gotoParticipantsListSelection() {
|
||||||
let view: ChatConversationCreateView = self.VIEW(ChatConversationCreateView.compositeViewDescription());
|
let view: ChatConversationCreateView = self.VIEW(ChatConversationCreateView.compositeViewDescription())
|
||||||
|
view.unfragmentCompositeDescription()
|
||||||
let addresses = ConferenceSchedulingViewModel.shared.selectedAddresses.value!.map { (address) in String(address.asStringUriOnly()) }
|
let addresses = ConferenceSchedulingViewModel.shared.selectedAddresses.value!.map { (address) in String(address.asStringUriOnly()) }
|
||||||
view.tableController.contactsGroup = (addresses as NSArray).mutableCopy() as? NSMutableArray
|
view.tableController.contactsGroup = (addresses as NSArray).mutableCopy() as? NSMutableArray
|
||||||
view.isForEditing = false
|
view.isForEditing = false
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,17 @@ import UIKit
|
||||||
import linphonesw
|
import linphonesw
|
||||||
|
|
||||||
|
|
||||||
@objc class ConferenceWaitingRoomFragment: UIViewController, UICompositeViewDelegate { // Replaces CallView
|
@objc class ConferenceWaitingRoomView: UIViewController, UICompositeViewDelegate { // Replaces CallView
|
||||||
|
|
||||||
// Layout constants
|
// Layout constants
|
||||||
let common_margin = 17.0
|
let common_margin = 17.0
|
||||||
let switch_camera_button_size = 50
|
let switch_camera_button_size = 35
|
||||||
let switch_camera_button_margins = 7.0
|
let switch_camera_button_margins = 7.0
|
||||||
let content_inset = 12.0
|
let content_inset = 12.0
|
||||||
let button_spacing = 15.0
|
let button_spacing = 15.0
|
||||||
let center_view_corner_radius = 20.0
|
let center_view_corner_radius = 20.0
|
||||||
let button_width = 150
|
let button_width = 150
|
||||||
|
let layout_picker_inset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
|
||||||
|
|
||||||
|
|
||||||
var audioRoutesView : AudioRoutesView? = nil
|
var audioRoutesView : AudioRoutesView? = nil
|
||||||
|
|
@ -47,15 +48,19 @@ import linphonesw
|
||||||
|
|
||||||
var conferenceUrl : String? = nil
|
var conferenceUrl : String? = nil
|
||||||
let conferenceSubject = MutableLiveData<String>()
|
let conferenceSubject = MutableLiveData<String>()
|
||||||
|
|
||||||
|
let controlsView = ControlsView(showVideo: true, controlsViewModel: ConferenceWaitingRoomViewModel.sharedModel)
|
||||||
|
var layoutPicker : CallControlButton? = nil
|
||||||
|
let layoutPickerView = ConferenceLayoutPickerView(orientation: UIDevice.current.orientation)
|
||||||
|
|
||||||
static let compositeDescription = UICompositeViewDescription(ConferenceWaitingRoomFragment.self, statusBar: StatusBarView.self, tabBar: nil, sideMenu: nil, fullscreen: false, isLeftFragment: false,fragmentWith: nil)
|
|
||||||
|
static let compositeDescription = UICompositeViewDescription(ConferenceWaitingRoomView.self, statusBar: StatusBarView.self, tabBar: nil, sideMenu: SideMenuView.self, fullscreen: false, isLeftFragment: false,fragmentWith: nil)
|
||||||
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
||||||
func compositeViewDescription() -> UICompositeViewDescription! { return type(of: self).compositeDescription }
|
func compositeViewDescription() -> UICompositeViewDescription! { return type(of: self).compositeDescription }
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
view.backgroundColor = VoipTheme.voipBackgroundColor.get()
|
|
||||||
|
|
||||||
view.addSubview(subject)
|
view.addSubview(subject)
|
||||||
subject.centerX().alignParentTop(withMargin: common_margin).done()
|
subject.centerX().alignParentTop(withMargin: common_margin).done()
|
||||||
|
|
@ -64,16 +69,15 @@ import linphonesw
|
||||||
}
|
}
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
let controlsView = ControlsView(showVideo: true, controlsViewModel: ConferenceWaitingRoomViewModel.sharedModel)
|
|
||||||
view.addSubview(controlsView)
|
view.addSubview(controlsView)
|
||||||
controlsView.alignParentBottom(withMargin:SharedLayoutConstants.buttons_bottom_margin).centerX().done()
|
controlsView.alignParentBottom(withMargin:SharedLayoutConstants.buttons_bottom_margin).centerX().done()
|
||||||
|
|
||||||
// Layoout picker
|
// Layoout picker
|
||||||
let layoutPicker = CallControlButton(imageInset : UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8),buttonTheme: VoipTheme.conf_waiting_room_layout_picker, onClickAction: {
|
layoutPicker = CallControlButton(imageInset : layout_picker_inset,buttonTheme: VoipTheme.conf_waiting_room_layout_picker, onClickAction: {
|
||||||
ConferenceWaitingRoomViewModel.sharedModel.showLayoutPicker.value = ConferenceWaitingRoomViewModel.sharedModel.showLayoutPicker.value != true
|
ConferenceWaitingRoomViewModel.sharedModel.showLayoutPicker.value = ConferenceWaitingRoomViewModel.sharedModel.showLayoutPicker.value != true
|
||||||
})
|
})
|
||||||
view.addSubview(layoutPicker)
|
view.addSubview(layoutPicker!)
|
||||||
layoutPicker.alignParentBottom(withMargin:SharedLayoutConstants.buttons_bottom_margin).alignParentRight(withMargin:SharedLayoutConstants.buttons_bottom_margin).done()
|
layoutPicker!.alignParentBottom(withMargin:SharedLayoutConstants.buttons_bottom_margin).alignParentRight(withMargin:SharedLayoutConstants.buttons_bottom_margin).done()
|
||||||
|
|
||||||
ConferenceWaitingRoomViewModel.sharedModel.joinLayout.readCurrentAndObserve { layout in
|
ConferenceWaitingRoomViewModel.sharedModel.joinLayout.readCurrentAndObserve { layout in
|
||||||
var icon = ""
|
var icon = ""
|
||||||
|
|
@ -85,18 +89,28 @@ import linphonesw
|
||||||
ConferenceWaitingRoomViewModel.sharedModel.isVideoEnabled.value = false
|
ConferenceWaitingRoomViewModel.sharedModel.isVideoEnabled.value = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
layoutPicker.applyTintedIcons(tintedIcons: [UIButton.State.normal.rawValue : TintableIcon(name: icon ,tintColor: LightDarkColor(.white,.white))])
|
self.layoutPicker?.applyTintedIcons(tintedIcons: [UIButton.State.normal.rawValue : TintableIcon(name: icon ,tintColor: LightDarkColor(.white,.white))])
|
||||||
|
}
|
||||||
|
|
||||||
|
ConferenceWaitingRoomViewModel.sharedModel.isVideoEnabled.observe { video in
|
||||||
|
if (video == true && ConferenceWaitingRoomViewModel.sharedModel.joinLayout.value == .AudioOnly) {
|
||||||
|
ConferenceWaitingRoomViewModel.sharedModel.joinLayout.value = .ActiveSpeaker
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let layoutPickerView = ConferenceLayoutPickerView()
|
|
||||||
view.addSubview(layoutPickerView)
|
view.addSubview(layoutPickerView)
|
||||||
layoutPickerView.alignAbove(view:layoutPicker,withMargin:button_spacing).alignVerticalCenterWith(layoutPicker).done()
|
|
||||||
|
|
||||||
ConferenceWaitingRoomViewModel.sharedModel.showLayoutPicker.readCurrentAndObserve { show in
|
ConferenceWaitingRoomViewModel.sharedModel.showLayoutPicker.readCurrentAndObserve { show in
|
||||||
layoutPicker.isSelected = show == true
|
self.layoutPicker?.isSelected = show == true
|
||||||
layoutPickerView.isHidden = show != true
|
self.layoutPickerView.isHidden = show != true
|
||||||
if (show == true) {
|
if (show == true) {
|
||||||
self.view.bringSubviewToFront(layoutPickerView)
|
self.view.bringSubviewToFront(self.layoutPickerView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.view.onClick{
|
||||||
|
if (ConferenceWaitingRoomViewModel.sharedModel.showLayoutPicker.value == true) {
|
||||||
|
ConferenceWaitingRoomViewModel.sharedModel.showLayoutPicker.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,16 +145,16 @@ import linphonesw
|
||||||
self.start.isEnabled = joining != true
|
self.start.isEnabled = joining != true
|
||||||
//self.localVideo.isHidden = joining == true (UX question as video window goes black by the core, better black or hidden ?)
|
//self.localVideo.isHidden = joining == true (UX question as video window goes black by the core, better black or hidden ?)
|
||||||
self.noVideoLabel.isHidden = joining == true
|
self.noVideoLabel.isHidden = joining == true
|
||||||
layoutPicker.isHidden = joining == true
|
self.layoutPicker?.isHidden = joining == true
|
||||||
if (joining == true) {
|
if (joining == true) {
|
||||||
self.view.addSubview(self.conferenceJoinSpinner)
|
self.view.addSubview(self.conferenceJoinSpinner)
|
||||||
self.conferenceJoinSpinner.square(IncomingOutgoingCommonView.spinner_size).center().done()
|
self.conferenceJoinSpinner.square(AbstractIncomingOutgoingCallView.spinner_size).center().done()
|
||||||
self.conferenceJoinSpinner.startRotation()
|
self.conferenceJoinSpinner.startRotation()
|
||||||
controlsView.isHidden = true
|
self.controlsView.isHidden = true
|
||||||
} else {
|
} else {
|
||||||
self.conferenceJoinSpinner.stopRotation()
|
self.conferenceJoinSpinner.stopRotation()
|
||||||
self.conferenceJoinSpinner.removeFromSuperview()
|
self.conferenceJoinSpinner.removeFromSuperview()
|
||||||
controlsView.isHidden = false
|
self.controlsView.isHidden = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,9 +165,7 @@ import linphonesw
|
||||||
localVideo.contentMode = .scaleAspectFill
|
localVideo.contentMode = .scaleAspectFill
|
||||||
localVideo.backgroundColor = .black
|
localVideo.backgroundColor = .black
|
||||||
self.view.addSubview(localVideo)
|
self.view.addSubview(localVideo)
|
||||||
localVideo.matchParentSideBorders(insetedByDx: content_inset).alignAbove(view:buttonsView,withMargin:SharedLayoutConstants.buttons_bottom_margin).alignUnder(view: subject,withMargin: common_margin).done()
|
|
||||||
localVideo.addSubview(switchCamera)
|
localVideo.addSubview(switchCamera)
|
||||||
switchCamera.alignParentTop(withMargin: switch_camera_button_margins).alignParentRight(withMargin: switch_camera_button_margins).square(switch_camera_button_size).done()
|
|
||||||
switchCamera.contentMode = .scaleAspectFit
|
switchCamera.contentMode = .scaleAspectFit
|
||||||
switchCamera.onClick {
|
switchCamera.onClick {
|
||||||
Core.get().videoPreviewEnabled = false
|
Core.get().videoPreviewEnabled = false
|
||||||
|
|
@ -182,7 +194,41 @@ import linphonesw
|
||||||
}
|
}
|
||||||
audioRoutesView!.alignAbove(view:controlsView,withMargin:SharedLayoutConstants.buttons_bottom_margin).centerX().done()
|
audioRoutesView!.alignAbove(view:controlsView,withMargin:SharedLayoutConstants.buttons_bottom_margin).centerX().done()
|
||||||
|
|
||||||
|
|
||||||
|
layoutRotatableElements()
|
||||||
|
|
||||||
|
UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in
|
||||||
|
self.view.backgroundColor = VoipTheme.voipBackgroundColor.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func layoutRotatableElements() {
|
||||||
|
layoutPickerView.removeConstraints().done()
|
||||||
|
localVideo.removeConstraints().done()
|
||||||
|
switchCamera.removeConstraints().done()
|
||||||
|
if ([.landscapeLeft, .landscapeRight].contains( UIDevice.current.orientation)) {
|
||||||
|
layoutPickerView.alignAbove(view:layoutPicker!,withMargin:button_spacing).alignVerticalCenterWith(layoutPicker!).done()
|
||||||
|
localVideo.matchParentSideBorders().alignParentBottom().alignParentTop().done()
|
||||||
|
localVideo.layer.cornerRadius = 0
|
||||||
|
switchCamera.alignParentTop(withMargin: switch_camera_button_margins).alignParentRight(withMargin: switch_camera_button_margins + (UIDevice.hasNotch() && UIDevice.current.orientation == .landscapeRight ? 30.0 : 0.0)).square(switch_camera_button_size).done()
|
||||||
|
} else {
|
||||||
|
layoutPickerView.alignAbove(view:layoutPicker!,withMargin:button_spacing).alignVerticalCenterWith(layoutPicker!).done()
|
||||||
|
localVideo.matchParentSideBorders(insetedByDx: content_inset).alignAbove(view:buttonsView,withMargin:SharedLayoutConstants.buttons_bottom_margin).alignUnder(view: subject,withMargin: common_margin).done()
|
||||||
|
localVideo.layer.cornerRadius = center_view_corner_radius
|
||||||
|
switchCamera.alignParentTop(withMargin: switch_camera_button_margins).alignParentRight(withMargin: switch_camera_button_margins).square(switch_camera_button_size).done()
|
||||||
|
}
|
||||||
|
view.sendSubviewToBack(localVideo)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
|
||||||
|
super.didRotate(from: fromInterfaceOrientation)
|
||||||
|
self.layoutRotatableElements()
|
||||||
|
Core.get().videoPreviewEnabled = ConferenceWaitingRoomViewModel.sharedModel.isVideoEnabled.value == true
|
||||||
|
}
|
||||||
|
|
||||||
|
override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {
|
||||||
|
Core.get().videoPreviewEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
|
|
@ -20,19 +20,25 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import Foundation
|
import Foundation
|
||||||
import linphonesw
|
import linphonesw
|
||||||
|
import EventKit
|
||||||
|
import EventKitUI
|
||||||
|
|
||||||
@objc class ICSBubbleView: UIView {
|
@objc class ICSBubbleView: UIView, EKEventEditViewDelegate {
|
||||||
|
|
||||||
|
|
||||||
let corner_radius = 7.0
|
let corner_radius = 7.0
|
||||||
let border_width = 2.0
|
let border_width = 2.0
|
||||||
let rows_spacing = 6.0
|
let rows_spacing = 6.0
|
||||||
let inner_padding = 8.0
|
let inner_padding = 8.0
|
||||||
|
let forward_reply_title_height = 10.0
|
||||||
let indicator_y = 3.0
|
let indicator_y = 3.0
|
||||||
let share_size = 25
|
let share_size = 25
|
||||||
let join_share_width = 150.0
|
let join_share_width = 150.0
|
||||||
|
|
||||||
|
|
||||||
let inviteTitle = StyledLabel(VoipTheme.conference_invite_title_font, VoipTexts.conference_invite_title)
|
let inviteTitle = StyledLabel(VoipTheme.conference_invite_title_font, VoipTexts.conference_invite_title)
|
||||||
|
let inviteCancelled = StyledLabel(VoipTheme.conference_cancelled_title_font, VoipTexts.conference_cancel_title)
|
||||||
|
let inviteUpdated = StyledLabel(VoipTheme.conference_updated_title_font, VoipTexts.conference_update_title)
|
||||||
|
|
||||||
let subject = StyledLabel(VoipTheme.conference_invite_subject_font)
|
let subject = StyledLabel(VoipTheme.conference_invite_subject_font)
|
||||||
let participants = StyledLabel(VoipTheme.conference_invite_desc_font)
|
let participants = StyledLabel(VoipTheme.conference_invite_desc_font)
|
||||||
let date = StyledLabel(VoipTheme.conference_invite_desc_font)
|
let date = StyledLabel(VoipTheme.conference_invite_desc_font)
|
||||||
|
|
@ -42,40 +48,46 @@ import linphonesw
|
||||||
let joinShare = UIStackView()
|
let joinShare = UIStackView()
|
||||||
let join = FormButton(title:VoipTexts.conference_invite_join.uppercased(), backgroundStateColors: VoipTheme.button_green_background)
|
let join = FormButton(title:VoipTexts.conference_invite_join.uppercased(), backgroundStateColors: VoipTheme.button_green_background)
|
||||||
let share = UIImageView(image:UIImage(named:"voip_export")?.tinted(with: VoipTheme.primaryTextColor.get()))
|
let share = UIImageView(image:UIImage(named:"voip_export")?.tinted(with: VoipTheme.primaryTextColor.get()))
|
||||||
|
|
||||||
var icsFile : String? = nil
|
|
||||||
|
|
||||||
var conferenceData: ScheduledConferenceData? = nil {
|
var conferenceData: ScheduledConferenceData? = nil {
|
||||||
didSet {
|
didSet {
|
||||||
if let data = conferenceData {
|
if let data = conferenceData {
|
||||||
subject.text = data.subject.value
|
subject.text = data.subject.value
|
||||||
participants.text = VoipTexts.conference_invite_participants_count.replacingOccurrences(of: "%d", with: String(data.conferenceInfo.participants.count+1))
|
participants.text = VoipTexts.conference_invite_participants_count.replacingOccurrences(of: "%d", with: String(data.conferenceInfo.participants.count+1))
|
||||||
participants.addIndicatorIcon(iconName: "conference_schedule_participants_default",padding : 0.0, y: -indicator_y, trailing: false)
|
participants.addIndicatorIcon(iconName: "conference_schedule_participants_default",padding : 0.0, y: -indicator_y, trailing: false)
|
||||||
date.text = " "+TimestampUtils.dateToString(date: data.rawDate)
|
date.text = TimestampUtils.dateToString(date: data.rawDate)
|
||||||
date.addIndicatorIcon(iconName: "conference_schedule_calendar_default", padding: 0.0, y:-indicator_y, trailing:false)
|
date.addIndicatorIcon(iconName: "conference_schedule_calendar_default", padding: 0.0, y:-indicator_y, trailing:false)
|
||||||
timeDuration.text = " \(data.time.value) ( \(data.duration.value) )"
|
timeDuration.text = "\(data.time.value)" + (data.duration.value != nil ? " ( \(data.duration.value) )" : "")
|
||||||
timeDuration.addIndicatorIcon(iconName: "conference_schedule_time_default",padding : 0.0, y: -indicator_y, trailing: false)
|
timeDuration.addIndicatorIcon(iconName: "conference_schedule_time_default",padding : 0.0, y: -indicator_y, trailing: false)
|
||||||
descriptionTitle.isHidden = data.description.value == nil || data.description.value!.count == 0
|
descriptionTitle.isHidden = data.description.value == nil || data.description.value!.count == 0
|
||||||
descriptionValue.isHidden = descriptionTitle.isHidden
|
descriptionValue.isHidden = descriptionTitle.isHidden
|
||||||
descriptionValue.text = data.description.value
|
descriptionValue.text = data.description.value
|
||||||
|
inviteTitle.isHidden = [.Cancelled,.Updated].contains(data.conferenceInfo.state)
|
||||||
|
inviteCancelled.isHidden = data.conferenceInfo.state != .Cancelled
|
||||||
|
inviteUpdated.isHidden = data.conferenceInfo.state != .Updated
|
||||||
|
join.isEnabled = data.isConferenceCancelled.value != true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
super.init(frame:.zero)
|
super.init(frame:.zero)
|
||||||
|
|
||||||
layer.cornerRadius = corner_radius
|
layer.cornerRadius = corner_radius
|
||||||
clipsToBounds = true
|
clipsToBounds = true
|
||||||
backgroundColor = VoipTheme.voip_light_gray
|
UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in
|
||||||
|
self.backgroundColor = VoipTheme.chatBubbleBGColor.get()
|
||||||
|
}
|
||||||
|
|
||||||
let rows = UIStackView()
|
let rows = UIStackView()
|
||||||
rows.axis = .vertical
|
rows.axis = .vertical
|
||||||
rows.spacing = rows_spacing
|
rows.spacing = rows_spacing
|
||||||
|
|
||||||
addSubview(rows)
|
addSubview(rows)
|
||||||
|
|
||||||
rows.addArrangedSubview(inviteTitle)
|
rows.addArrangedSubview(inviteTitle)
|
||||||
|
rows.addArrangedSubview(inviteCancelled)
|
||||||
|
rows.addArrangedSubview(inviteUpdated)
|
||||||
rows.addArrangedSubview(subject)
|
rows.addArrangedSubview(subject)
|
||||||
rows.addArrangedSubview(participants)
|
rows.addArrangedSubview(participants)
|
||||||
rows.addArrangedSubview(date)
|
rows.addArrangedSubview(date)
|
||||||
|
|
@ -83,6 +95,8 @@ import linphonesw
|
||||||
rows.addArrangedSubview(descriptionTitle)
|
rows.addArrangedSubview(descriptionTitle)
|
||||||
rows.addArrangedSubview(descriptionValue)
|
rows.addArrangedSubview(descriptionValue)
|
||||||
|
|
||||||
|
descriptionValue.numberOfLines = 5
|
||||||
|
|
||||||
|
|
||||||
addSubview(joinShare)
|
addSubview(joinShare)
|
||||||
joinShare.axis = .horizontal
|
joinShare.axis = .horizontal
|
||||||
|
|
@ -92,19 +106,48 @@ import linphonesw
|
||||||
joinShare.addArrangedSubview(join)
|
joinShare.addArrangedSubview(join)
|
||||||
rows.matchParentSideBorders(insetedByDx: inner_padding).alignParentTop(withMargin: inner_padding).done()
|
rows.matchParentSideBorders(insetedByDx: inner_padding).alignParentTop(withMargin: inner_padding).done()
|
||||||
joinShare.alignParentBottom(withMargin: inner_padding).width(join_share_width).alignParentRight(withMargin: inner_padding).done()
|
joinShare.alignParentBottom(withMargin: inner_padding).width(join_share_width).alignParentRight(withMargin: inner_padding).done()
|
||||||
|
|
||||||
join.onClick {
|
join.onClick {
|
||||||
let view : ConferenceWaitingRoomFragment = self.VIEW(ConferenceWaitingRoomFragment.compositeViewDescription())
|
let view : ConferenceWaitingRoomView = self.VIEW(ConferenceWaitingRoomView.compositeViewDescription())
|
||||||
PhoneMainView.instance().changeCurrentView(view.compositeViewDescription())
|
PhoneMainView.instance().changeCurrentView(view.compositeViewDescription())
|
||||||
view.setDetails(subject: (self.conferenceData?.subject.value)!, url: (self.conferenceData?.address.value)!)
|
view.setDetails(subject: (self.conferenceData?.subject.value)!, url: (self.conferenceData?.address.value)!)
|
||||||
}
|
}
|
||||||
|
|
||||||
share.onClick {
|
share.onClick {
|
||||||
let ics = URL(string: "file://"+self.icsFile!)
|
let eventStore = EKEventStore()
|
||||||
UIApplication.shared.open(ics!)
|
eventStore.requestAccess( to: EKEntityType.event, completion:{(granted, error) in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
if (granted) && (error == nil) {
|
||||||
|
let event = EKEvent(eventStore: eventStore)
|
||||||
|
event.title = self.conferenceData?.subject.value
|
||||||
|
event.startDate = self.conferenceData?.rawDate
|
||||||
|
if let duration = self.conferenceData?.conferenceInfo.duration, duration > 0 {
|
||||||
|
event.endDate = event.startDate.addingTimeInterval(TimeInterval(duration*60))
|
||||||
|
} else {
|
||||||
|
event.endDate = event.startDate.addingTimeInterval(TimeInterval(3600))
|
||||||
|
}
|
||||||
|
event.calendar = eventStore.defaultCalendarForNewEvents
|
||||||
|
if let description = self.conferenceData?.description.value, description.count > 0 {
|
||||||
|
event.notes = description + "\n\n"
|
||||||
|
}
|
||||||
|
event.notes = (event.notes != nil ? event.notes! : "") + "\(VoipTexts.call_action_participants_list):\n\(self.conferenceData?.participantsExpanded.value)"
|
||||||
|
if let urlString = self.conferenceData?.conferenceInfo.uri?.asStringUriOnly() {
|
||||||
|
event.url = URL(string:urlString)
|
||||||
|
}
|
||||||
|
let addController = EKEventEditViewController()
|
||||||
|
addController.event = event
|
||||||
|
addController.eventStore = eventStore
|
||||||
|
PhoneMainView.instance().present(addController, animated: false)
|
||||||
|
addController.editViewDelegate = self;
|
||||||
|
} else {
|
||||||
|
VoipDialog.toast(message: VoipTexts.conference_unable_to_share_via_calendar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +158,6 @@ import linphonesw
|
||||||
if (content.isIcalendar) {
|
if (content.isIcalendar) {
|
||||||
if let conferenceInfo = try? Factory.Instance.createConferenceInfoFromIcalendarContent(content: content) {
|
if let conferenceInfo = try? Factory.Instance.createConferenceInfoFromIcalendarContent(content: content) {
|
||||||
self.conferenceData = ScheduledConferenceData(conferenceInfo: conferenceInfo)
|
self.conferenceData = ScheduledConferenceData(conferenceInfo: conferenceInfo)
|
||||||
self.icsFile = content.filePath
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +174,76 @@ import linphonesw
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func setLayoutConstraints(view:UIView) {
|
@objc func setLayoutConstraints(view:UIView) {
|
||||||
matchDimensionsWith(view: view, insetedByDx: inner_padding).done()
|
matchBordersWith(view: view, insetedByDx: inner_padding).done()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func updateTopLayoutConstraints(view:UIView, replyOrForward: Bool) {
|
||||||
|
updateTopBorderWith(view: view, inset: inner_padding + (replyOrForward ? forward_reply_title_height : 0.0)).done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
|
||||||
|
controller.dismiss(animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static func getSubjectFromContent(cmessage: OpaquePointer) -> String {
|
||||||
|
let message = ChatMessage.getSwiftObject(cObject: cmessage)
|
||||||
|
var subject = ""
|
||||||
|
message.contents.forEach { content in
|
||||||
|
if (content.isIcalendar) {
|
||||||
|
if let conferenceInfo = try? Factory.Instance.createConferenceInfoFromIcalendarContent(content: content) {
|
||||||
|
subject = conferenceInfo.subject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return subject
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static func getConferenceInfo(cmessage: OpaquePointer) -> OpaquePointer? {
|
||||||
|
let message = ChatMessage.getSwiftObject(cObject: cmessage)
|
||||||
|
var result : OpaquePointer? = nil
|
||||||
|
message.contents.forEach { content in
|
||||||
|
if (content.isIcalendar) {
|
||||||
|
if let conferenceInfo = try? Factory.Instance.createConferenceInfoFromIcalendarContent(content: content) {
|
||||||
|
result = conferenceInfo.getCobject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static func getConferenceSummary(cmessage: OpaquePointer) -> String? {
|
||||||
|
let message = ChatMessage.getSwiftObject(cObject: cmessage)
|
||||||
|
var subject:String? = nil
|
||||||
|
message.contents.forEach { content in
|
||||||
|
if (content.isIcalendar) {
|
||||||
|
if let conferenceInfo = try? Factory.Instance.createConferenceInfoFromIcalendarContent(content: content) {
|
||||||
|
subject = conferenceInfo.state == .New ? VoipTexts.conference_invite_title + conferenceInfo.subject :
|
||||||
|
conferenceInfo.state == .Updated ? VoipTexts.conference_update_title + conferenceInfo.subject :
|
||||||
|
VoipTexts.conference_cancel_title + conferenceInfo.subject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return subject
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@objc static func getDescriptionHeightFromContent(cmessage: OpaquePointer) -> CGFloat {
|
||||||
|
let message = ChatMessage.getSwiftObject(cObject: cmessage)
|
||||||
|
var height = 0.0
|
||||||
|
message.contents.forEach { content in
|
||||||
|
if (content.isIcalendar) {
|
||||||
|
if let conferenceInfo = try? Factory.Instance.createConferenceInfoFromIcalendarContent(content: content) {
|
||||||
|
let description = NSString(string: conferenceInfo.description)
|
||||||
|
if (description.length > 0) {
|
||||||
|
let dummyTitle = StyledLabel(VoipTheme.conference_invite_desc_title_font, VoipTexts.conference_description_title)
|
||||||
|
let dummyLabel = StyledLabel(VoipTheme.conference_invite_desc_font)
|
||||||
|
let rect = CGSize(width: CGFloat(CONFERENCE_INVITATION_WIDTH-80), height: CGFloat.greatestFiniteMagnitude)
|
||||||
|
height = dummyTitle.intrinsicContentSize.height + description.boundingRect(with: rect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedString.Key.font: dummyLabel.font!], context: nil).height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return height
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,18 +27,20 @@ class ScheduledConferencesCell: UITableViewCell {
|
||||||
let corner_radius = 7.0
|
let corner_radius = 7.0
|
||||||
let border_width = 2.0
|
let border_width = 2.0
|
||||||
static let button_size = 40
|
static let button_size = 40
|
||||||
|
let delete_checkbox_margin = 5
|
||||||
|
|
||||||
let clockIcon = UIImageView(image: UIImage(named: "conference_schedule_time_default"))
|
let clockIcon = UIImageView()
|
||||||
let timeDuration = StyledLabel(VoipTheme.conference_invite_desc_font)
|
let timeDuration = StyledLabel(VoipTheme.conference_invite_desc_font)
|
||||||
let organiser = StyledLabel(VoipTheme.conference_invite_desc_font)
|
let organiser = StyledLabel(VoipTheme.conference_invite_desc_font)
|
||||||
let subject = StyledLabel(VoipTheme.conference_invite_subject_font)
|
let subject = StyledLabel(VoipTheme.conference_list_subject_font)
|
||||||
let participantsIcon = UIImageView(image: UIImage(named: "conference_schedule_participants_default"))
|
let cancelledLabel = StyledLabel(VoipTheme.conference_cancelled_title_font)
|
||||||
|
let participantsIcon = UIImageView()
|
||||||
let participants = StyledLabel(VoipTheme.conference_invite_desc_font)
|
let participants = StyledLabel(VoipTheme.conference_invite_desc_font)
|
||||||
let infoConf = UIButton()
|
let infoConf = UIButton()
|
||||||
|
|
||||||
let descriptionTitle = StyledLabel(VoipTheme.conference_invite_desc_font, VoipTexts.conference_description_title)
|
let descriptionTitle = StyledLabel(VoipTheme.conference_list_address_desc_font, VoipTexts.conference_description_title)
|
||||||
let descriptionValue = StyledLabel(VoipTheme.conference_invite_desc_font)
|
let descriptionValue = StyledLabel(VoipTheme.conference_list_address_desc_font)
|
||||||
let urlTitle = StyledLabel(VoipTheme.conference_invite_desc_font, VoipTexts.conference_schedule_address_title)
|
let urlTitle = StyledLabel(VoipTheme.conference_list_address_desc_font, VoipTexts.conference_schedule_address_title)
|
||||||
let urlValue = StyledLabel(VoipTheme.conference_scheduling_font)
|
let urlValue = StyledLabel(VoipTheme.conference_scheduling_font)
|
||||||
let copyLink = CallControlButton(width:button_size,height:button_size,buttonTheme: VoipTheme.scheduled_conference_action("voip_copy"))
|
let copyLink = CallControlButton(width:button_size,height:button_size,buttonTheme: VoipTheme.scheduled_conference_action("voip_copy"))
|
||||||
let joinConf = FormButton(title:VoipTexts.conference_invite_join.uppercased(), backgroundStateColors: VoipTheme.button_green_background)
|
let joinConf = FormButton(title:VoipTexts.conference_invite_join.uppercased(), backgroundStateColors: VoipTheme.button_green_background)
|
||||||
|
|
@ -47,17 +49,29 @@ class ScheduledConferencesCell: UITableViewCell {
|
||||||
var owningTableView : UITableView? = nil
|
var owningTableView : UITableView? = nil
|
||||||
let joinEditDelete = UIStackView()
|
let joinEditDelete = UIStackView()
|
||||||
let expandedRows = UIStackView()
|
let expandedRows = UIStackView()
|
||||||
|
let selectionCheckBox = StyledCheckBox()
|
||||||
|
let myContentView = UIView()
|
||||||
|
|
||||||
var conferenceData: ScheduledConferenceData? = nil {
|
var conferenceData: ScheduledConferenceData? = nil {
|
||||||
didSet {
|
didSet {
|
||||||
if let data = conferenceData {
|
if let data = conferenceData {
|
||||||
timeDuration.text = "\(data.time.value)"+(data.duration.value != nil ? " ( \(data.duration.value) )" : "")
|
timeDuration.text = "\(data.time.value)"+(data.duration.value != nil ? " (\(data.duration.value))" : "")
|
||||||
organiser.text = VoipTexts.conference_schedule_organizer+data.organizer.value!
|
organiser.text = VoipTexts.conference_schedule_organizer+data.organizer.value!
|
||||||
subject.text = data.subject.value!
|
subject.text = data.subject.value!
|
||||||
|
cancelledLabel.text = data.isConferenceCancelled.value == true ? ( data.canEdit.value == true ? VoipTexts.conference_scheduled_cancelled_by_me: VoipTexts.conference_scheduled_cancelled_by_organizer) : nil
|
||||||
|
cancelledLabel.isHidden = data.isConferenceCancelled.value != true
|
||||||
descriptionValue.text = data.description.value!
|
descriptionValue.text = data.description.value!
|
||||||
urlValue.text = data.address.value!
|
urlValue.text = data.address.value!
|
||||||
|
self.joinConf.isHidden = data.isConferenceCancelled.value == true
|
||||||
|
self.editConf.isHidden = data.canEdit.value != true || data.isConferenceCancelled.value == true
|
||||||
|
self.urlTitle.isHidden = data.isConferenceCancelled.value == true
|
||||||
|
self.urlValue.isHidden = data.isConferenceCancelled.value == true
|
||||||
|
self.copyLink.isHidden = data.isConferenceCancelled.value == true
|
||||||
data.expanded.readCurrentAndObserve { expanded in
|
data.expanded.readCurrentAndObserve { expanded in
|
||||||
self.contentView.layer.borderWidth = expanded == true ? 2.0 : 0.0
|
self.myContentView.backgroundColor =
|
||||||
|
data.conferenceInfo.state == .Cancelled ? VoipTheme.voip_conference_cancelled_bg_color :
|
||||||
|
data.isFinished ? VoipTheme.backgroundColor3.get() : VoipTheme.backgroundColor4.get()
|
||||||
|
self.myContentView.layer.borderWidth = expanded == true ? 2.0 : 0.0
|
||||||
self.descriptionTitle.isHidden = expanded != true || self.descriptionValue.text?.count == 0
|
self.descriptionTitle.isHidden = expanded != true || self.descriptionValue.text?.count == 0
|
||||||
self.descriptionValue.isHidden = expanded != true || self.descriptionValue.text?.count == 0
|
self.descriptionValue.isHidden = expanded != true || self.descriptionValue.text?.count == 0
|
||||||
self.infoConf.isSelected = expanded == true
|
self.infoConf.isSelected = expanded == true
|
||||||
|
|
@ -66,18 +80,18 @@ class ScheduledConferencesCell: UITableViewCell {
|
||||||
self.expandedRows.isHidden = expanded != true
|
self.expandedRows.isHidden = expanded != true
|
||||||
self.joinEditDelete.isHidden = expanded != true
|
self.joinEditDelete.isHidden = expanded != true
|
||||||
if let myAddress = Core.get().defaultAccount?.params?.identityAddress {
|
if let myAddress = Core.get().defaultAccount?.params?.identityAddress {
|
||||||
self.editConf.isHidden = expanded != true || data.conferenceInfo.organizer?.weakEqual(address2: myAddress) != true
|
self.editConf.isHidden = expanded != true || data.conferenceInfo.organizer?.weakEqual(address2: myAddress) != true || data.conferenceInfo.state == .Cancelled
|
||||||
} else {
|
} else {
|
||||||
self.editConf.isHidden = true
|
self.editConf.isHidden = true
|
||||||
}
|
}
|
||||||
self.participants.removeConstraints().alignUnder(view: self.subject,withMargin: 15).toRightOf(self.participantsIcon,withLeftMargin:10).toRightOf(self.participantsIcon,withLeftMargin:10).toLeftOf(self.infoConf,withRightMargin: 15).done()
|
self.participants.removeConstraints().alignUnder(view: self.subject,withMargin: 10).toRightOf(self.participantsIcon,withLeftMargin:10).toRightOf(self.participantsIcon,withLeftMargin:10).toLeftOf(self.infoConf,withRightMargin: 15).done()
|
||||||
self.joinEditDelete.removeConstraints().alignUnder(view: self.expandedRows,withMargin: 15).alignParentRight(withMargin: 10).done()
|
self.joinEditDelete.removeConstraints().alignUnder(view: self.expandedRows,withMargin: 10).alignParentRight(withMargin: 10).done()
|
||||||
if (expanded == true) {
|
if (expanded == true) {
|
||||||
self.joinEditDelete.alignParentBottom(withMargin: 10).done()
|
self.joinEditDelete.alignParentBottom(withMargin: 10).done()
|
||||||
} else {
|
} else {
|
||||||
self.participants.alignParentBottom(withMargin: 10).done()
|
self.participants.alignParentBottom(withMargin: 10).done()
|
||||||
}
|
}
|
||||||
|
self.selectionCheckBox.liveValue = data.selectedForDeletion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -86,46 +100,55 @@ class ScheduledConferencesCell: UITableViewCell {
|
||||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||||
|
|
||||||
contentView.layer.cornerRadius = corner_radius
|
contentView.addSubview(myContentView)
|
||||||
contentView.clipsToBounds = true
|
contentView.backgroundColor = .clear
|
||||||
contentView.backgroundColor = VoipTheme.header_background_color
|
backgroundColor = .clear
|
||||||
contentView.layer.borderColor = VoipTheme.primary_color.cgColor
|
myContentView.layer.cornerRadius = corner_radius
|
||||||
|
myContentView.clipsToBounds = true
|
||||||
|
myContentView.backgroundColor = VoipTheme.header_background_color
|
||||||
|
myContentView.layer.borderColor = VoipTheme.primary_color.cgColor
|
||||||
|
myContentView.matchParentDimmensions(insetedBy: UIEdgeInsets(top: 5,left: 0,bottom: 5,right: 0)).done()
|
||||||
|
|
||||||
|
myContentView.addSubview(clockIcon)
|
||||||
|
clockIcon.alignParentTop(withMargin: 10).square(20).alignParentLeft(withMargin: 10).done()
|
||||||
|
|
||||||
|
myContentView.addSubview(timeDuration)
|
||||||
|
timeDuration.alignParentTop(withMargin: 10).toRightOf(clockIcon,withLeftMargin:10).alignHorizontalCenterWith(clockIcon).done()
|
||||||
|
|
||||||
|
myContentView.addSubview(organiser)
|
||||||
|
organiser.alignParentTop(withMargin: 10).toRightOf(timeDuration, withLeftMargin:10).alignParentRight(withMargin:10).alignHorizontalCenterWith(clockIcon).done()
|
||||||
|
|
||||||
|
|
||||||
contentView.addSubview(clockIcon)
|
let subjectCancel = UIStackView()
|
||||||
clockIcon.alignParentTop(withMargin: 15).square(15).alignParentLeft(withMargin: 10).done()
|
subjectCancel.axis = .vertical
|
||||||
|
myContentView.addSubview(subjectCancel)
|
||||||
contentView.addSubview(timeDuration)
|
subjectCancel.alignUnder(view: timeDuration,withMargin: 10).matchParentSideBorders(insetedByDx: 10.0).done()
|
||||||
timeDuration.alignParentTop(withMargin: 15).toRightOf(clockIcon,withLeftMargin:10).alignHorizontalCenterWith(clockIcon).done()
|
|
||||||
|
|
||||||
contentView.addSubview(organiser)
|
subjectCancel.addArrangedSubview(cancelledLabel)
|
||||||
organiser.alignParentTop(withMargin: 15).toRightOf(timeDuration, withLeftMargin:10).alignParentRight(withMargin:10).alignHorizontalCenterWith(clockIcon).done()
|
subjectCancel.addArrangedSubview(subject)
|
||||||
|
|
||||||
contentView.addSubview(subject)
|
myContentView.addSubview(participantsIcon)
|
||||||
subject.alignUnder(view: timeDuration,withMargin: 15).alignParentLeft(withMargin: 10).done()
|
participantsIcon.alignUnder(view: subject,withMargin: 5).square(25).alignParentLeft(withMargin: 10).done()
|
||||||
|
|
||||||
contentView.addSubview(participantsIcon)
|
|
||||||
participantsIcon.alignUnder(view: subject,withMargin: 15).square(15).alignParentLeft(withMargin: 10).done()
|
|
||||||
|
|
||||||
//infoConf.onClick {
|
//infoConf.onClick {
|
||||||
contentView.onClick {
|
contentView.onClick {
|
||||||
self.conferenceData?.toggleExpand()
|
self.conferenceData?.toggleExpand()
|
||||||
self.owningTableView?.reloadData()
|
self.owningTableView?.reloadData()
|
||||||
}
|
}
|
||||||
contentView.addSubview(infoConf)
|
myContentView.addSubview(infoConf)
|
||||||
infoConf.imageView?.contentMode = .scaleAspectFit
|
infoConf.imageView?.contentMode = .scaleAspectFit
|
||||||
infoConf.alignUnder(view: subject,withMargin: 15).square(30).alignParentRight(withMargin: 10).alignHorizontalCenterWith(participantsIcon).done()
|
infoConf.alignUnder(view: subject,withMargin: 5).square(25).alignParentRight(withMargin: 10).done()
|
||||||
infoConf.applyTintedIcons(tintedIcons: VoipTheme.conference_info_button)
|
infoConf.applyTintedIcons(tintedIcons: VoipTheme.conference_info_button)
|
||||||
|
|
||||||
|
|
||||||
contentView.addSubview(participants)
|
myContentView.addSubview(participants)
|
||||||
participants.alignUnder(view: subject,withMargin: 15).toRightOf(participantsIcon,withLeftMargin:10).toRightOf(participantsIcon,withLeftMargin:10).toLeftOf(infoConf,withRightMargin: 15).done()
|
participants.alignUnder(view: subject,withMargin: 10).toRightOf(participantsIcon,withLeftMargin:10).toRightOf(participantsIcon,withLeftMargin:10).toLeftOf(infoConf,withRightMargin: 15).done()
|
||||||
|
|
||||||
expandedRows.axis = .vertical
|
expandedRows.axis = .vertical
|
||||||
expandedRows.spacing = 10
|
expandedRows.spacing = 10
|
||||||
contentView.addSubview(expandedRows)
|
myContentView.addSubview(expandedRows)
|
||||||
expandedRows.alignUnder(view: participants,withMargin: 15).matchParentSideBorders(insetedByDx:10).done()
|
expandedRows.alignUnder(view: participants,withMargin: 15).matchParentSideBorders(insetedByDx:10).done()
|
||||||
|
|
||||||
expandedRows.addArrangedSubview(descriptionTitle)
|
expandedRows.addArrangedSubview(descriptionTitle)
|
||||||
expandedRows.addArrangedSubview(descriptionValue)
|
expandedRows.addArrangedSubview(descriptionValue)
|
||||||
|
|
||||||
|
|
@ -146,15 +169,15 @@ class ScheduledConferencesCell: UITableViewCell {
|
||||||
joinEditDelete.axis = .horizontal
|
joinEditDelete.axis = .horizontal
|
||||||
joinEditDelete.spacing = 10
|
joinEditDelete.spacing = 10
|
||||||
joinEditDelete.distribution = .equalSpacing
|
joinEditDelete.distribution = .equalSpacing
|
||||||
|
|
||||||
contentView.addSubview(joinEditDelete)
|
myContentView.addSubview(joinEditDelete)
|
||||||
joinEditDelete.alignUnder(view: expandedRows,withMargin: 15).alignParentRight(withMargin: 10).done()
|
joinEditDelete.alignUnder(view: expandedRows,withMargin: 10).alignParentRight(withMargin: 10).done()
|
||||||
|
|
||||||
|
|
||||||
joinEditDelete.addArrangedSubview(joinConf)
|
joinEditDelete.addArrangedSubview(joinConf)
|
||||||
joinConf.width(150).done()
|
joinConf.width(150).done()
|
||||||
joinConf.onClick {
|
joinConf.onClick {
|
||||||
let view : ConferenceWaitingRoomFragment = self.VIEW(ConferenceWaitingRoomFragment.compositeViewDescription())
|
let view : ConferenceWaitingRoomView = self.VIEW(ConferenceWaitingRoomView.compositeViewDescription())
|
||||||
PhoneMainView.instance().changeCurrentView(view.compositeViewDescription())
|
PhoneMainView.instance().changeCurrentView(view.compositeViewDescription())
|
||||||
view.setDetails(subject: (self.conferenceData?.subject.value)!, url: (self.conferenceData?.address.value)!)
|
view.setDetails(subject: (self.conferenceData?.subject.value)!, url: (self.conferenceData?.address.value)!)
|
||||||
}
|
}
|
||||||
|
|
@ -166,9 +189,10 @@ class ScheduledConferencesCell: UITableViewCell {
|
||||||
VoipDialog.toast(message: VoipTexts.conference_edit_error)
|
VoipDialog.toast(message: VoipTexts.conference_edit_error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let infoDate = Date(timeIntervalSince1970: Double(confData.conferenceInfo.dateTime))
|
|
||||||
ConferenceSchedulingViewModel.shared.reset()
|
ConferenceSchedulingViewModel.shared.reset()
|
||||||
ConferenceSchedulingViewModel.shared.scheduledDateTime.value = infoDate
|
let seconds = confData.conferenceInfo.dateTime % 86400
|
||||||
|
ConferenceSchedulingViewModel.shared.scheduledDate.value = Date(timeIntervalSince1970:TimeInterval(confData.conferenceInfo.dateTime - seconds))
|
||||||
|
ConferenceSchedulingViewModel.shared.scheduledTime.value = Date(timeIntervalSince1970:TimeInterval(seconds))
|
||||||
ConferenceSchedulingViewModel.shared.description.value = confData.description.value
|
ConferenceSchedulingViewModel.shared.description.value = confData.description.value
|
||||||
ConferenceSchedulingViewModel.shared.subject.value = confData.subject.value
|
ConferenceSchedulingViewModel.shared.subject.value = confData.subject.value
|
||||||
ConferenceSchedulingViewModel.shared.scheduledDuration.value = ConferenceSchedulingViewModel.durationList.firstIndex(where: {$0.value == confData.conferenceInfo.duration})
|
ConferenceSchedulingViewModel.shared.scheduledDuration.value = ConferenceSchedulingViewModel.durationList.firstIndex(where: {$0.value == confData.conferenceInfo.duration})
|
||||||
|
|
@ -177,7 +201,7 @@ class ScheduledConferencesCell: UITableViewCell {
|
||||||
confData.conferenceInfo.participants.forEach {
|
confData.conferenceInfo.participants.forEach {
|
||||||
ConferenceSchedulingViewModel.shared.selectedAddresses.value?.append($0)
|
ConferenceSchedulingViewModel.shared.selectedAddresses.value?.append($0)
|
||||||
}
|
}
|
||||||
ConferenceSchedulingViewModel.shared.existingConfInfo = confData.conferenceInfo
|
ConferenceSchedulingViewModel.shared.existingConfInfo.value = confData.conferenceInfo
|
||||||
// TOODO TimeZone (as Android 14.6.2022) ConferenceSchedulingViewModel.shared.scheduledTimeZone.value = self.conferenceData?.timezone
|
// TOODO TimeZone (as Android 14.6.2022) ConferenceSchedulingViewModel.shared.scheduledTimeZone.value = self.conferenceData?.timezone
|
||||||
let view : ConferenceSchedulingView = self.VIEW(ConferenceSchedulingView.compositeViewDescription())
|
let view : ConferenceSchedulingView = self.VIEW(ConferenceSchedulingView.compositeViewDescription())
|
||||||
PhoneMainView.instance().changeCurrentView(view.compositeViewDescription())
|
PhoneMainView.instance().changeCurrentView(view.compositeViewDescription())
|
||||||
|
|
@ -185,16 +209,35 @@ class ScheduledConferencesCell: UITableViewCell {
|
||||||
|
|
||||||
joinEditDelete.addArrangedSubview(deleteConf)
|
joinEditDelete.addArrangedSubview(deleteConf)
|
||||||
deleteConf.onClick {
|
deleteConf.onClick {
|
||||||
let delete = ButtonAttributes(text:VoipTexts.conference_info_confirm_removal_delete, action: {
|
self.askConfirmationTodeleteEntry()
|
||||||
Core.get().deleteConferenceInformation(conferenceInfo: self.conferenceData!.conferenceInfo)
|
|
||||||
ScheduledConferencesViewModel.shared.computeConferenceInfoList()
|
|
||||||
self.owningTableView?.reloadData()
|
|
||||||
VoipDialog.toast(message: VoipTexts.conference_info_removed)
|
|
||||||
}, isDestructive:false)
|
|
||||||
let cancel = ButtonAttributes(text:VoipTexts.cancel, action: {}, isDestructive:true)
|
|
||||||
VoipDialog(message:VoipTexts.conference_info_confirm_removal, givenButtons: [cancel,delete]).show()
|
|
||||||
}
|
}
|
||||||
|
myContentView.addSubview(selectionCheckBox)
|
||||||
|
selectionCheckBox.alignParentRight(withMargin: delete_checkbox_margin).alignUnder(view:organiser, withMargin: delete_checkbox_margin).done()
|
||||||
|
ScheduledConferencesViewModel.shared.editionEnabled.readCurrentAndObserve { editing in
|
||||||
|
self.selectionCheckBox.isHidden = editing != true
|
||||||
|
}
|
||||||
|
onLongClick {
|
||||||
|
ScheduledConferencesViewModel.shared.editionEnabled.value = true
|
||||||
|
}
|
||||||
|
UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in
|
||||||
|
self.clockIcon.image = UIImage(named: "conference_schedule_time_default")?.tinted(with: VoipTheme.voipDrawableColor.get())
|
||||||
|
self.participantsIcon.image = UIImage(named: "conference_schedule_participants_default")?.tinted(with: VoipTheme.voipDrawableColor.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func askConfirmationTodeleteEntry() {
|
||||||
|
let delete = ButtonAttributes(text:VoipTexts.conference_info_confirm_removal_delete, action: {
|
||||||
|
self.deleteEntry()
|
||||||
|
VoipDialog.toast(message: VoipTexts.conference_info_removed)
|
||||||
|
}, isDestructive:false)
|
||||||
|
let cancel = ButtonAttributes(text:VoipTexts.cancel, action: {}, isDestructive:true)
|
||||||
|
VoipDialog(message:VoipTexts.conference_info_confirm_removal, givenButtons: [cancel,delete]).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteEntry() {
|
||||||
|
self.conferenceData?.deleteConference()
|
||||||
|
ScheduledConferencesViewModel.shared.computeConferenceInfoList()
|
||||||
|
self.owningTableView?.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,12 @@ import Foundation
|
||||||
import linphonesw
|
import linphonesw
|
||||||
|
|
||||||
@objc class ScheduledConferencesView: BackNextNavigationView, UICompositeViewDelegate, UITableViewDataSource, UITableViewDelegate {
|
@objc class ScheduledConferencesView: BackNextNavigationView, UICompositeViewDelegate, UITableViewDataSource, UITableViewDelegate {
|
||||||
|
|
||||||
let conferenceListView = UITableView()
|
let conferenceListView = UITableView()
|
||||||
let noConference = StyledLabel(VoipTheme.empty_list_font,VoipTexts.conference_no_schedule)
|
let noConference = StyledLabel(VoipTheme.empty_list_font,VoipTexts.conference_no_schedule)
|
||||||
|
let filters = UIStackView()
|
||||||
|
let selectAllButton = CallControlButton(buttonTheme:VoipTheme.nav_button("deselect_all"))
|
||||||
|
let separator = UIView()
|
||||||
|
|
||||||
static let compositeDescription = UICompositeViewDescription(ScheduledConferencesView.self, statusBar: StatusBarView.self, tabBar: nil, sideMenu: SideMenuView.self, fullscreen: false, isLeftFragment: false,fragmentWith: nil)
|
static let compositeDescription = UICompositeViewDescription(ScheduledConferencesView.self, statusBar: StatusBarView.self, tabBar: nil, sideMenu: SideMenuView.self, fullscreen: false, isLeftFragment: false,fragmentWith: nil)
|
||||||
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
||||||
|
|
@ -35,17 +38,63 @@ import linphonesw
|
||||||
|
|
||||||
super.viewDidLoad(
|
super.viewDidLoad(
|
||||||
backAction: {
|
backAction: {
|
||||||
PhoneMainView.instance().popView(self.compositeViewDescription())
|
if (ScheduledConferencesViewModel.shared.editionEnabled.value == true) {
|
||||||
|
ScheduledConferencesViewModel.shared.editionEnabled.value = false
|
||||||
|
} else {
|
||||||
|
PhoneMainView.instance().popView(self.compositeViewDescription())
|
||||||
|
}
|
||||||
},nextAction: {
|
},nextAction: {
|
||||||
ConferenceSchedulingViewModel.shared.reset()
|
if (ScheduledConferencesViewModel.shared.editionEnabled.value == true) {
|
||||||
PhoneMainView.instance().changeCurrentView(ConferenceSchedulingView.compositeDescription)
|
self.deleteSelection()
|
||||||
|
} else {
|
||||||
|
ConferenceSchedulingViewModel.shared.reset()
|
||||||
|
PhoneMainView.instance().changeCurrentView(ConferenceSchedulingView.compositeDescription)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
nextActionEnableCondition: MutableLiveData(),
|
nextActionEnableCondition: MutableLiveData(),
|
||||||
title:VoipTexts.conference_scheduled)
|
title:VoipTexts.conference_scheduled)
|
||||||
|
super.titleLabel.applyStyle(VoipTheme.navigation_header_font)
|
||||||
|
|
||||||
|
// Select all
|
||||||
|
selectAllButton.setImage(UIImage(named: "deselect_all"), for: .selected)
|
||||||
|
selectAllButton.setImage(UIImage(named: "select_all_default"), for: .normal)
|
||||||
|
topBar.addSubview(selectAllButton)
|
||||||
|
selectAllButton.toLeftOf(nextButton,withRightMargin: CGFloat(side_buttons_margin)).matchParentHeight().done()
|
||||||
|
|
||||||
|
// Filter buttons
|
||||||
|
let showTerminated = getFilterButton(title: VoipTexts.conference_scheduled_terminated_filter)
|
||||||
|
showTerminated.onClick {
|
||||||
|
ScheduledConferencesViewModel.shared.showTerminated.value = true
|
||||||
|
}
|
||||||
|
filters.addArrangedSubview(showTerminated)
|
||||||
|
|
||||||
|
let showScheduled = getFilterButton(title: VoipTexts.conference_scheduled_future_filter)
|
||||||
|
showScheduled.onClick {
|
||||||
|
ScheduledConferencesViewModel.shared.showTerminated.value = false
|
||||||
|
|
||||||
|
}
|
||||||
|
filters.addArrangedSubview(showScheduled)
|
||||||
|
|
||||||
|
ScheduledConferencesViewModel.shared.showTerminated.readCurrentAndObserve { it in
|
||||||
|
showTerminated.isSelected = it == true
|
||||||
|
showScheduled.isSelected = it != true
|
||||||
|
self.noConference.text = it != true ? VoipTexts.conference_no_schedule : VoipTexts.conference_no_terminated_schedule
|
||||||
|
ScheduledConferencesViewModel.shared.computeConferenceInfoList()
|
||||||
|
self.conferenceListView.reloadData()
|
||||||
|
self.noConference.isHidden = !ScheduledConferencesViewModel.shared.daySplitted.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
self.view.addSubview(filters)
|
||||||
|
filters.spacing = 10
|
||||||
|
filters.alignParentLeft(withMargin: 10).alignUnder(view: super.topBar,withMargin: self.form_margin).done()
|
||||||
|
|
||||||
super.nextButton.applyTintedIcons(tintedIcons: VoipTheme.conference_create_button)
|
self.view.addSubview(separator)
|
||||||
|
separator.matchParentSideBorders().height(1).alignUnder(view: filters,withMargin: self.form_margin).done()
|
||||||
|
|
||||||
|
// Conference list
|
||||||
|
|
||||||
self.view.addSubview(conferenceListView)
|
self.view.addSubview(conferenceListView)
|
||||||
|
conferenceListView.alignUnder(view: filters).done()
|
||||||
conferenceListView.isScrollEnabled = true
|
conferenceListView.isScrollEnabled = true
|
||||||
conferenceListView.dataSource = self
|
conferenceListView.dataSource = self
|
||||||
conferenceListView.delegate = self
|
conferenceListView.delegate = self
|
||||||
|
|
@ -56,11 +105,53 @@ import linphonesw
|
||||||
conferenceListView.allowsFocus = false
|
conferenceListView.allowsFocus = false
|
||||||
}
|
}
|
||||||
conferenceListView.separatorStyle = .singleLine
|
conferenceListView.separatorStyle = .singleLine
|
||||||
conferenceListView.separatorColor = .white
|
conferenceListView.backgroundColor = .clear
|
||||||
|
|
||||||
view.addSubview(noConference)
|
view.addSubview(noConference)
|
||||||
noConference.center().done()
|
noConference.center().done()
|
||||||
|
|
||||||
|
ScheduledConferencesViewModel.shared.editionEnabled.readCurrentAndObserve { editing in
|
||||||
|
if (editing == true) {
|
||||||
|
self.selectAllButton.isSelected = false
|
||||||
|
self.selectAllButton.isHidden = false
|
||||||
|
super.nextButton.applyTintedIcons(tintedIcons: VoipTheme.generic_delete_button)
|
||||||
|
super.backButton.applyTintedIcons(tintedIcons: VoipTheme.generic_cancel)
|
||||||
|
self.nextButton.isEnabled = ScheduledConferencesViewModel.shared.conferences.value?.filter{$0.selectedForDeletion.value == true}.count ?? 0 > 0
|
||||||
|
} else {
|
||||||
|
self.selectAllButton.isHidden = true
|
||||||
|
ScheduledConferencesViewModel.shared.conferences.value?.forEach {$0.selectedForDeletion.value = false}
|
||||||
|
super.nextButton.applyTintedIcons(tintedIcons: VoipTheme.conference_create_button)
|
||||||
|
super.backButton.applyTintedIcons(tintedIcons: VoipTheme.generic_back)
|
||||||
|
self.nextButton.isEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.selectAllButton.onClick {
|
||||||
|
let selectIt = !self.selectAllButton.isSelected
|
||||||
|
ScheduledConferencesViewModel.shared.conferences.value?.forEach {$0.selectedForDeletion.value = selectIt}
|
||||||
|
}
|
||||||
|
|
||||||
|
UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in
|
||||||
|
self.view.backgroundColor = VoipTheme.voipBackgroundBWColor.get()
|
||||||
|
self.separator.backgroundColor = VoipTheme.separatorColor.get()
|
||||||
|
self.conferenceListView.separatorColor = .clear
|
||||||
|
self.conferenceListView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFilterButton(title:String) -> UIButton {
|
||||||
|
let filter_button_height = 35.0
|
||||||
|
let button = ButtonWithStateBackgrounds(backgroundStateColors: VoipTheme.button_conference_list_filter)
|
||||||
|
button.setTitle(title, for: .normal)
|
||||||
|
button.setTitleColor(.black, for: .normal)
|
||||||
|
button.setTitleColor(VoipTheme.primary_color, for: .selected)
|
||||||
|
button.height(filter_button_height).done()
|
||||||
|
button.layer.cornerRadius = filter_button_height / 2
|
||||||
|
button.clipsToBounds = true
|
||||||
|
button.applyTitleStyle(VoipTheme.conf_list_filter_button_font)
|
||||||
|
button.width(0).done()
|
||||||
|
button.addSidePadding()
|
||||||
|
return button
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -69,9 +160,10 @@ import linphonesw
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
self.conferenceListView.reloadData()
|
self.conferenceListView.reloadData()
|
||||||
self.conferenceListView.removeConstraints().done()
|
self.conferenceListView.removeConstraints().done()
|
||||||
self.conferenceListView.matchParentSideBorders(insetedByDx: 10).alignUnder(view: super.topBar,withMargin: self.form_margin).alignParentBottom().done()
|
self.conferenceListView.matchParentSideBorders(insetedByDx: 10).alignUnder(view: separator).alignParentBottom().done()
|
||||||
noConference.isHidden = !ScheduledConferencesViewModel.shared.daySplitted.isEmpty
|
noConference.isHidden = !ScheduledConferencesViewModel.shared.daySplitted.isEmpty
|
||||||
super.nextButton.isEnabled = Core.get().defaultAccount != nil
|
super.nextButton.isEnabled = Core.get().defaultAccount != nil
|
||||||
|
ScheduledConferencesViewModel.shared.editionEnabled.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableView datasource delegate
|
// TableView datasource delegate
|
||||||
|
|
@ -99,12 +191,7 @@ import linphonesw
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||||
let daysArray = Array(ScheduledConferencesViewModel.shared.daySplitted.keys.sorted().reversed())
|
return UITableView.automaticDimension
|
||||||
let day = daysArray[indexPath.section]
|
|
||||||
guard let data = ScheduledConferencesViewModel.shared.daySplitted[day]?[indexPath.row] else {
|
|
||||||
return UITableView.automaticDimension
|
|
||||||
}
|
|
||||||
return data.expanded.value! ? UITableView.automaticDimension : 100
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -117,8 +204,38 @@ import linphonesw
|
||||||
}
|
}
|
||||||
cell.conferenceData = data
|
cell.conferenceData = data
|
||||||
cell.owningTableView = tableView
|
cell.owningTableView = tableView
|
||||||
|
data.selectedForDeletion.readCurrentAndObserve { selected in
|
||||||
|
let selectedCount = ScheduledConferencesViewModel.shared.conferences.value?.filter{$0.selectedForDeletion.value == true}.count ?? 0
|
||||||
|
let totalCount = ScheduledConferencesViewModel.shared.conferences.value?.count ?? 0
|
||||||
|
self.nextButton.isEnabled = ScheduledConferencesViewModel.shared.editionEnabled.value == false || selectedCount > 0
|
||||||
|
self.selectAllButton.isSelected = selectedCount == totalCount
|
||||||
|
}
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
|
||||||
|
if editingStyle == .delete {
|
||||||
|
let cell = tableView.cellForRow(at: indexPath) as! ScheduledConferencesCell
|
||||||
|
cell.askConfirmationTodeleteEntry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteSelection () {
|
||||||
|
let selectedCount = ScheduledConferencesViewModel.shared.conferences.value?.filter{$0.selectedForDeletion.value == true}.count ?? 0
|
||||||
|
let delete = ButtonAttributes(text:VoipTexts.conference_info_confirm_removal_delete, action: {
|
||||||
|
ScheduledConferencesViewModel.shared.conferences.value?.forEach {
|
||||||
|
$0.deleteConference()
|
||||||
|
}
|
||||||
|
ScheduledConferencesViewModel.shared.computeConferenceInfoList()
|
||||||
|
self.conferenceListView.reloadData()
|
||||||
|
VoipDialog.toast(message: selectedCount == 1 ? VoipTexts.conference_info_removed : VoipTexts.conference_infos_removed)
|
||||||
|
ScheduledConferencesViewModel.shared.editionEnabled.value = false
|
||||||
|
}, isDestructive:false)
|
||||||
|
let cancel = ButtonAttributes(text:VoipTexts.cancel, action: {}, isDestructive:true)
|
||||||
|
VoipDialog(message:selectedCount == 1 ? VoipTexts.conference_info_confirm_removal : VoipTexts.conference_infos_confirm_removal, givenButtons: [cancel,delete]).show()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
54
Classes/Swift/Extensions/IOS/SnapkitBridge.swift
Normal file
54
Classes/Swift/Extensions/IOS/SnapkitBridge.swift
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
import Photos
|
||||||
|
import linphonesw
|
||||||
|
|
||||||
|
|
||||||
|
@objc class SnapkitBridge: NSObject {
|
||||||
|
@objc static func matchParentDimensions(view:UIView) {
|
||||||
|
view.matchParentDimmensions().done()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static func matchParentDimensions(view:UIView,leftInset:CGFloat) {
|
||||||
|
view.matchParentDimmensions(insetedBy: UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: 0)).done()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static func matchParentDimensions(view:UIView,topInset:CGFloat) {
|
||||||
|
view.matchParentDimmensions(insetedBy: UIEdgeInsets(top: topInset, left: 0, bottom: 0, right: 0)).done()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static func height(view:UIView,heiht:Int) {
|
||||||
|
view.height(heiht).done()
|
||||||
|
}
|
||||||
|
@objc static func square(view:UIView,size:Int) {
|
||||||
|
view.square(size).done()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static func alignParentLeft(view:UIView) {
|
||||||
|
view.alignParentLeft().done()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static func centerY(view:UIView) {
|
||||||
|
view.centerY().done()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -22,9 +22,9 @@ import SnapKit
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
extension UIButton {
|
extension UIButton {
|
||||||
func addSidePadding(p:CGFloat = 10) {
|
func addSidePadding(p:CGFloat = 10) { // Requires a width to be set prior to this ! SnapKit does not support updateOrCreate.
|
||||||
if let w = titleLabel?.textWidth {
|
if let w = titleLabel?.textWidth {
|
||||||
width(w+2*p).done()
|
updateWidth(w+2*p).done()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,32 @@ extension UIDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
static func notchHeight() -> CGFloat {
|
static func notchHeight() -> CGFloat {
|
||||||
guard #available(iOS 11.0, *), let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top else {
|
guard #available(iOS 11.0, *), let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top, let sidePadding = UIApplication.shared.keyWindow?.safeAreaInsets.left else {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return topPadding
|
return [.landscapeRight,.landscapeLeft].contains(UIDevice.current.orientation) ? sidePadding : topPadding
|
||||||
|
}
|
||||||
|
|
||||||
|
static func switchedDisplayMode() -> Bool {
|
||||||
|
let displayMode = UserDefaults.standard.string(forKey: "displayMode")
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
if UITraitCollection.current.userInterfaceStyle == .light {
|
||||||
|
UserDefaults.standard.set("light", forKey: "displayMode")
|
||||||
|
} else {
|
||||||
|
UserDefaults.standard.set("dark", forKey: "displayMode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return displayMode != nil && displayMode != UserDefaults.standard.string(forKey: "displayMode")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc class UIDeviceBridge : NSObject {
|
||||||
|
static let displayModeSwitched = MutableLiveData<Bool>()
|
||||||
|
@objc static func switchedDisplayMode() -> Bool {
|
||||||
|
return UIDevice.switchedDisplayMode()
|
||||||
|
}
|
||||||
|
@objc static func notifyDisplayModeSwitch() {
|
||||||
|
displayModeSwitched.notifyValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,4 +29,10 @@ extension UILabel {
|
||||||
let labelSize = myText.boundingRect(with: rect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: myFont], context: nil)
|
let labelSize = myText.boundingRect(with: rect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: myFont], context: nil)
|
||||||
return ceil(labelSize.width)
|
return ceil(labelSize.width)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addSidePadding(p:CGFloat = 5.0) {
|
||||||
|
if let w = textWidth {
|
||||||
|
width(w+2*p).done()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,14 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func squareMax(_ size:Int) -> UIView {
|
||||||
|
snp.makeConstraints { (make) in
|
||||||
|
make.height.lessThanOrEqualTo(size).priority(.high)
|
||||||
|
make.width.equalTo(snp.height).priority(.high)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func makeHeightMatchWidth() -> UIView {
|
func makeHeightMatchWidth() -> UIView {
|
||||||
snp.makeConstraints { (make) in
|
snp.makeConstraints { (make) in
|
||||||
|
|
@ -47,6 +55,13 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeWidthMatchHeight() -> UIView {
|
||||||
|
snp.makeConstraints { (make) in
|
||||||
|
make.width.equalTo(snp.height)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func size(w:CGFloat,h:CGFloat) -> UIView {
|
func size(w:CGFloat,h:CGFloat) -> UIView {
|
||||||
snp.makeConstraints { (make) in
|
snp.makeConstraints { (make) in
|
||||||
make.width.equalTo(w)
|
make.width.equalTo(w)
|
||||||
|
|
@ -55,6 +70,14 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateSize(w:CGFloat,h:CGFloat) -> UIView {
|
||||||
|
snp.updateConstraints { (make) in
|
||||||
|
make.width.equalTo(w)
|
||||||
|
make.height.equalTo(h)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func height(_ h:CGFloat) -> UIView {
|
func height(_ h:CGFloat) -> UIView {
|
||||||
snp.makeConstraints { (make) in
|
snp.makeConstraints { (make) in
|
||||||
make.height.equalTo(h)
|
make.height.equalTo(h)
|
||||||
|
|
@ -73,6 +96,13 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateWidth(_ h:CGFloat) -> UIView {
|
||||||
|
snp.updateConstraints { (make) in
|
||||||
|
make.width.equalTo(h)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func width(_ h:Int) -> UIView {
|
func width(_ h:Int) -> UIView {
|
||||||
return width(CGFloat(h))
|
return width(CGFloat(h))
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +152,17 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchDimensionsWith(view:UIView, insetedByDx:CGFloat = 0) -> UIView {
|
func matchParentDimmensions(insetedBy:UIEdgeInsets) -> UIView {
|
||||||
|
snp.makeConstraints { (make) in
|
||||||
|
make.left.equalToSuperview().offset(insetedBy.left)
|
||||||
|
make.top.equalToSuperview().offset(insetedBy.top)
|
||||||
|
make.right.equalToSuperview().offset(-insetedBy.right)
|
||||||
|
make.bottom.equalToSuperview().offset(-insetedBy.bottom)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchBordersWith(view:UIView, insetedByDx:CGFloat = 0) -> UIView {
|
||||||
snp.makeConstraints { (make) in
|
snp.makeConstraints { (make) in
|
||||||
make.left.top.equalTo(view).offset(insetedByDx)
|
make.left.top.equalTo(view).offset(insetedByDx)
|
||||||
make.right.bottom.equalTo(view).offset(-insetedByDx)
|
make.right.bottom.equalTo(view).offset(-insetedByDx)
|
||||||
|
|
@ -130,6 +170,13 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateTopBorderWith(view:UIView, inset:CGFloat = 0) -> UIView {
|
||||||
|
snp.updateConstraints { (make) in
|
||||||
|
make.top.equalTo(view).offset(inset)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func matchParentEdges() -> UIView {
|
func matchParentEdges() -> UIView {
|
||||||
snp.makeConstraints { (make) in
|
snp.makeConstraints { (make) in
|
||||||
make.edges.equalToSuperview()
|
make.edges.equalToSuperview()
|
||||||
|
|
@ -222,10 +269,21 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateAlignParentBottom(withMargin:CGFloat = 0.0) -> UIView {
|
||||||
|
snp.updateConstraints { (make) in
|
||||||
|
make.bottom.equalToSuperview().offset(-withMargin)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func alignParentBottom(withMargin:Int) -> UIView {
|
func alignParentBottom(withMargin:Int) -> UIView {
|
||||||
return alignParentBottom(withMargin:CGFloat(withMargin))
|
return alignParentBottom(withMargin:CGFloat(withMargin))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateAlignParentBottom(withMargin:Int) -> UIView {
|
||||||
|
return updateAlignParentBottom(withMargin:CGFloat(withMargin))
|
||||||
|
}
|
||||||
|
|
||||||
func alignAbove(view:UIView, withMargin:CGFloat = 0.0) -> UIView {
|
func alignAbove(view:UIView, withMargin:CGFloat = 0.0) -> UIView {
|
||||||
snp.makeConstraints { (make) in
|
snp.makeConstraints { (make) in
|
||||||
make.bottom.equalTo(view.snp.top).offset(-withMargin)
|
make.bottom.equalTo(view.snp.top).offset(-withMargin)
|
||||||
|
|
@ -258,6 +316,13 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateAlignParentLeft(withMargin:CGFloat = 0.0) -> UIView {
|
||||||
|
snp.updateConstraints { (make) in
|
||||||
|
make.left.equalToSuperview().offset(withMargin)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func alignParentLeft(withMargin:Int) -> UIView {
|
func alignParentLeft(withMargin:Int) -> UIView {
|
||||||
return alignParentLeft(withMargin:CGFloat(withMargin))
|
return alignParentLeft(withMargin:CGFloat(withMargin))
|
||||||
}
|
}
|
||||||
|
|
@ -269,10 +334,23 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateAlignParentRight(withMargin:CGFloat = 0) -> UIView {
|
||||||
|
snp.updateConstraints { (make) in
|
||||||
|
make.right.equalToSuperview().offset(-withMargin)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func alignParentRight(withMargin:CGFloat) -> UIView {
|
func alignParentRight(withMargin:CGFloat) -> UIView {
|
||||||
return alignParentRight(withMargin:Int(withMargin))
|
return alignParentRight(withMargin:Int(withMargin))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func alignRightWith(_ view:UIView) -> UIView {
|
||||||
|
snp.makeConstraints { (make) in
|
||||||
|
make.right.equalTo(view.snp.right)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func toRightOf(_ view:UIView, withLeftMargin:Int = 0) -> UIView {
|
func toRightOf(_ view:UIView, withLeftMargin:Int = 0) -> UIView {
|
||||||
snp.makeConstraints { (make) in
|
snp.makeConstraints { (make) in
|
||||||
|
|
@ -363,12 +441,28 @@ extension UIView {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func wrapContent(inset:UIEdgeInsets) -> UIView {
|
||||||
|
subviews.first?.snp.makeConstraints({ make in
|
||||||
|
make.left.equalToSuperview().offset(inset.left)
|
||||||
|
})
|
||||||
|
subviews.last?.snp.makeConstraints({ make in
|
||||||
|
make.right.equalToSuperview().offset(-inset.right)
|
||||||
|
})
|
||||||
|
subviews.first?.snp.makeConstraints({ make in
|
||||||
|
make.top.equalToSuperview().offset(inset.top)
|
||||||
|
})
|
||||||
|
subviews.last?.snp.makeConstraints({ make in
|
||||||
|
make.bottom.equalToSuperview().offset(-inset.bottom)
|
||||||
|
})
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func done() {
|
func done() {
|
||||||
// to avoid the unused variable warning
|
// to avoid the unused variable warning
|
||||||
}
|
}
|
||||||
|
|
||||||
// Onclick
|
// Single click
|
||||||
|
|
||||||
class TapGestureRecognizer: UITapGestureRecognizer {
|
class TapGestureRecognizer: UITapGestureRecognizer {
|
||||||
var action : (()->Void)? = nil
|
var action : (()->Void)? = nil
|
||||||
}
|
}
|
||||||
|
|
@ -387,6 +481,22 @@ extension UIView {
|
||||||
sender.action!()
|
sender.action!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Long click
|
||||||
|
class LongPressGestureRecognizer: UILongPressGestureRecognizer {
|
||||||
|
var action : (()->Void)? = nil
|
||||||
|
}
|
||||||
|
func onLongClick(action : @escaping ()->Void ){
|
||||||
|
let tap = LongPressGestureRecognizer(target: self , action: #selector(self.handleLongClick(_:)))
|
||||||
|
tap.action = action
|
||||||
|
tap.cancelsTouchesInView = false
|
||||||
|
self.addGestureRecognizer(tap)
|
||||||
|
self.isUserInteractionEnabled = true
|
||||||
|
|
||||||
|
}
|
||||||
|
@objc func handleLongClick(_ sender: LongPressGestureRecognizer) {
|
||||||
|
sender.action!()
|
||||||
|
}
|
||||||
|
|
||||||
func VIEW<T>( _ desc: UICompositeViewDescription) -> T{
|
func VIEW<T>( _ desc: UICompositeViewDescription) -> T{
|
||||||
return PhoneMainView.instance().mainViewController.getCachedController(desc.name) as! T
|
return PhoneMainView.instance().mainViewController.getCachedController(desc.name) as! T
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,16 @@ import linphonesw
|
||||||
extension Address {
|
extension Address {
|
||||||
|
|
||||||
func initials() -> String? {
|
func initials() -> String? {
|
||||||
var initials = initials(displayName: addressBookEnhancedDisplayName())
|
var initials = Address.initials(displayName: addressBookEnhancedDisplayName())
|
||||||
if (initials == nil || initials!.isEmpty) {
|
if (initials == nil || initials!.isEmpty) {
|
||||||
initials = String(username.prefix(1))
|
initials = String(username.prefix(1))
|
||||||
}
|
}
|
||||||
return initials
|
return initials
|
||||||
}
|
}
|
||||||
|
|
||||||
private func initials(displayName: String?) -> String? { // Basic ImproveMe
|
static func initials(displayName: String?) -> String? { // Basic ImproveMe
|
||||||
return displayName?.components(separatedBy: " ")
|
let separator = displayName?.contains(" ") == true ? " " : "."
|
||||||
|
return displayName?.components(separatedBy: separator)
|
||||||
.reduce("") {
|
.reduce("") {
|
||||||
($0.isEmpty ? "" : "\($0.first?.uppercased() ?? "")") +
|
($0.isEmpty ? "" : "\($0.first?.uppercased() ?? "")") +
|
||||||
($1.isEmpty ? "" : "\($1.first?.uppercased() ?? "")")
|
($1.isEmpty ? "" : "\($1.first?.uppercased() ?? "")")
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,7 @@ extension Call {
|
||||||
|
|
||||||
extension Call : CustomStringConvertible {
|
extension Call : CustomStringConvertible {
|
||||||
public var description: String {
|
public var description: String {
|
||||||
if let callId = callLog?.callId {
|
return "<Call-ID: \(callLog?.callId ?? "pending") pointer:\(Unmanaged.passUnretained(self).toOpaque()) is conference:\(conference != nil) >"
|
||||||
return "<Call-ID: \(callId)>"
|
|
||||||
}
|
|
||||||
return "<Raw pointer:\(Unmanaged.passUnretained(self).toOpaque())>"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
139
Classes/Swift/FileUtil.swift
Normal file
139
Classes/Swift/FileUtil.swift
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
import linphonesw
|
||||||
|
|
||||||
|
@objc class FileUtil: NSObject {
|
||||||
|
public class func bundleFilePath(_ file: NSString) -> String? {
|
||||||
|
return Bundle.main.path(forResource: file.deletingPathExtension, ofType: file.pathExtension)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func bundleFilePathAsUrl(_ file: NSString) -> URL? {
|
||||||
|
if let bPath = bundleFilePath(file) {
|
||||||
|
return URL.init(fileURLWithPath: bPath)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func documentsDirectory() -> URL {
|
||||||
|
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
||||||
|
let documentsDirectory = paths[0]
|
||||||
|
return documentsDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func libraryDirectory() -> URL {
|
||||||
|
let paths = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask)
|
||||||
|
let documentsDirectory = paths[0]
|
||||||
|
return documentsDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func sharedContainerUrl(appGroupName:String) -> URL {
|
||||||
|
return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupName)!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@objc public class func ensureDirectoryExists(path:String) {
|
||||||
|
if !FileManager.default.fileExists(atPath: path) {
|
||||||
|
do {
|
||||||
|
try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
|
||||||
|
} catch {
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func ensureFileExists(path:String) {
|
||||||
|
if !FileManager.default.fileExists(atPath: path) {
|
||||||
|
FileManager.default.createFile(atPath: path, contents: nil, attributes: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func fileExists(path:String) -> Bool {
|
||||||
|
return FileManager.default.fileExists(atPath: path)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func fileExistsAndIsNotEmpty(path:String) -> Bool {
|
||||||
|
guard FileManager.default.fileExists(atPath: path) else {return false}
|
||||||
|
do {
|
||||||
|
let attribute = try FileManager.default.attributesOfItem(atPath: path)
|
||||||
|
if let size = attribute[FileAttributeKey.size] as? NSNumber {
|
||||||
|
return size.doubleValue > 0
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
print(error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func write(string:String, toPath:String) {
|
||||||
|
do {
|
||||||
|
try string.write(to: URL(fileURLWithPath:toPath), atomically: true, encoding: String.Encoding.utf8)
|
||||||
|
} catch {
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func delete(path:String) {
|
||||||
|
do {
|
||||||
|
try FileManager.default.removeItem(atPath: path)
|
||||||
|
print("FIle \(path) was removed")
|
||||||
|
} catch {
|
||||||
|
print("Error deleting file at path \(path) error is \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class func mkdir(path:String) {
|
||||||
|
do {
|
||||||
|
try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
|
||||||
|
print("Dir \(path) was created")
|
||||||
|
} catch {
|
||||||
|
print("Error creating dir at path \(path) error is \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class func copy(_ fromPath:String, _ toPath: String, overWrite:Bool) {
|
||||||
|
do {
|
||||||
|
if (overWrite && fileExists(path: toPath)) {
|
||||||
|
delete(path: toPath)
|
||||||
|
}
|
||||||
|
try FileManager.default.copyItem(at: URL(fileURLWithPath:fromPath), to: URL(fileURLWithPath:toPath))
|
||||||
|
} catch {
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For debugging
|
||||||
|
|
||||||
|
public class func showListOfFilesInSharedDir(appGroupName:String) {
|
||||||
|
let fileManager = FileManager.default
|
||||||
|
do {
|
||||||
|
let fileURLs = try fileManager.contentsOfDirectory(at: FileUtil.sharedContainerUrl(appGroupName: appGroupName), includingPropertiesForKeys: nil)
|
||||||
|
fileURLs.forEach{print($0)}
|
||||||
|
} catch {
|
||||||
|
print("Error while enumerating files \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -192,7 +192,7 @@ extension ProviderDelegate: CXProviderDelegate {
|
||||||
|
|
||||||
if (UIApplication.shared.applicationState != .active) {
|
if (UIApplication.shared.applicationState != .active) {
|
||||||
CallManager.instance().backgroundContextCall = call
|
CallManager.instance().backgroundContextCall = call
|
||||||
CallManager.instance().backgroundContextCameraIsEnabled = call!.params?.videoEnabled ?? false
|
CallManager.instance().backgroundContextCameraIsEnabled = call?.params?.videoEnabled == true || call?.callLog?.wasConference() == true
|
||||||
call?.cameraEnabled = false // Disable camera while app is not on foreground
|
call?.cameraEnabled = false // Disable camera while app is not on foreground
|
||||||
}
|
}
|
||||||
CallManager.instance().callkitAudioSessionActivated = false
|
CallManager.instance().callkitAudioSessionActivated = false
|
||||||
|
|
@ -205,8 +205,10 @@ extension ProviderDelegate: CXProviderDelegate {
|
||||||
let uuid = action.callUUID
|
let uuid = action.callUUID
|
||||||
let callId = callInfos[uuid]?.callId
|
let callId = callInfos[uuid]?.callId
|
||||||
let call = CallManager.instance().callByCallId(callId: callId)
|
let call = CallManager.instance().callByCallId(callId: callId)
|
||||||
action.fulfill()
|
|
||||||
if (call == nil) {
|
if (call == nil) {
|
||||||
|
Log.directLog(BCTBX_LOG_ERROR, text: "CXSetHeldCallAction: no call !")
|
||||||
|
action.fail()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,33 +217,46 @@ extension ProviderDelegate: CXProviderDelegate {
|
||||||
try CallManager.instance().lc?.leaveConference()
|
try CallManager.instance().lc?.leaveConference()
|
||||||
Log.directLog(BCTBX_LOG_DEBUG, text: "CallKit: call-id: [\(String(describing: callId))] leaving conference")
|
Log.directLog(BCTBX_LOG_DEBUG, text: "CallKit: call-id: [\(String(describing: callId))] leaving conference")
|
||||||
NotificationCenter.default.post(name: Notification.Name("LinphoneCallUpdate"), object: self)
|
NotificationCenter.default.post(name: Notification.Name("LinphoneCallUpdate"), object: self)
|
||||||
return
|
action.fulfill()
|
||||||
}
|
}else{
|
||||||
|
let state = action.isOnHold ? "Paused" : "Resumed"
|
||||||
let state = action.isOnHold ? "Paused" : "Resumed"
|
Log.directLog(BCTBX_LOG_DEBUG, text: "CallKit: Call with call-id: [\(String(describing: callId))] and UUID: [\(uuid)] paused status changed to: [\(state)]")
|
||||||
Log.directLog(BCTBX_LOG_DEBUG, text: "CallKit: Call with call-id: [\(String(describing: callId))] and UUID: [\(uuid)] paused status changed to: [\(state)]")
|
if (action.isOnHold) {
|
||||||
if (action.isOnHold) {
|
CallManager.instance().speakerBeforePause = CallManager.instance().isSpeakerEnabled()
|
||||||
if (call!.params?.localConferenceMode ?? false) {
|
try call!.pause()
|
||||||
return
|
CallManager.instance().actionToFulFill = action;
|
||||||
}
|
|
||||||
CallManager.instance().speakerBeforePause = CallManager.instance().isSpeakerEnabled()
|
|
||||||
try call!.pause()
|
|
||||||
} else {
|
|
||||||
if (CallManager.instance().lc?.conference != nil && CallManager.instance().lc?.callsNb ?? 0 > 1) {
|
|
||||||
try CallManager.instance().lc?.enterConference()
|
|
||||||
NotificationCenter.default.post(name: Notification.Name("LinphoneCallUpdate"), object: self)
|
|
||||||
} else {
|
} else {
|
||||||
try call!.resume()
|
if (CallManager.instance().lc?.conference != nil && CallManager.instance().lc?.callsNb ?? 0 > 1) {
|
||||||
|
try CallManager.instance().lc?.enterConference()
|
||||||
|
action.fulfill()
|
||||||
|
NotificationCenter.default.post(name: Notification.Name("LinphoneCallUpdate"), object: self)
|
||||||
|
} else {
|
||||||
|
try call!.resume()
|
||||||
|
CallManager.instance().actionToFulFill = action;
|
||||||
|
// HORRIBLE HACK HERE - PLEASE APPLE FIX THIS !!
|
||||||
|
// When resuming a SIP call after a native call has ended remotely, didActivate: audioSession
|
||||||
|
// is never called.
|
||||||
|
// It looks like in this case, it is implicit.
|
||||||
|
// As a result we have to notify the Core that the AudioSession is active.
|
||||||
|
// The SpeakerBox demo application written by Apple exhibits this behavior.
|
||||||
|
// https://developer.apple.com/documentation/callkit/making_and_receiving_voip_calls_with_callkit
|
||||||
|
// We can clearly see there that startAudio() is called immediately in the CXSetHeldCallAction
|
||||||
|
// handler, while it is called from didActivate: audioSession otherwise.
|
||||||
|
// Callkit's design is not consistent, or its documentation imcomplete, wich is somewhat disapointing.
|
||||||
|
//
|
||||||
|
Log.directLog(BCTBX_LOG_DEBUG, text: "Assuming AudioSession is active when executing a CXSetHeldCallAction with isOnHold=false.")
|
||||||
|
CallManager.instance().lc?.activateAudioSession(actived: true)
|
||||||
|
CallManager.instance().callkitAudioSessionActivated = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Log.directLog(BCTBX_LOG_ERROR, text: "CallKit: Call set held (paused or resumed) \(uuid) failed because \(error)")
|
Log.directLog(BCTBX_LOG_ERROR, text: "CallKit: Call set held (paused or resumed) \(uuid) failed because \(error)")
|
||||||
|
action.fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
||||||
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
let uuid = action.callUUID
|
let uuid = action.callUUID
|
||||||
|
|
|
||||||
|
|
@ -79,14 +79,9 @@ import linphonesw
|
||||||
scrollView.alignUnder(view: topBar, withMargin: content_margin_top).alignParentBottom().matchParentSideBorders().done()
|
scrollView.alignUnder(view: topBar, withMargin: content_margin_top).alignParentBottom().matchParentSideBorders().done()
|
||||||
scrollView.addSubview(contentView)
|
scrollView.addSubview(contentView)
|
||||||
contentView.matchBordersOf(view: view).alignParentBottom().alignParentTop().done() // don't forget a bottom constraint b/w last element of contentview and contentview
|
contentView.matchBordersOf(view: view).alignParentBottom().alignParentTop().done() // don't forget a bottom constraint b/w last element of contentview and contentview
|
||||||
|
UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in
|
||||||
}
|
self.topBar.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get()
|
||||||
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
|
||||||
super.viewWillAppear(animated)
|
|
||||||
topBar.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,10 @@ class TimestampUtils {
|
||||||
let dateFormatter = DateFormatter()
|
let dateFormatter = DateFormatter()
|
||||||
dateFormatter.dateStyle = .long
|
dateFormatter.dateStyle = .long
|
||||||
dateFormatter.timeStyle = .none
|
dateFormatter.timeStyle = .none
|
||||||
return dateFormatter.string(from: date)
|
let dayFormatter = DateFormatter()
|
||||||
|
dayFormatter.dateFormat = "EEEE"
|
||||||
|
let day = dayFormatter.string(from: date)
|
||||||
|
return day.prefix(1).uppercased() + day.dropFirst()+" "+dateFormatter.string(from: date)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func timeToString(date:Date) -> String {
|
static func timeToString(date:Date) -> String {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class LightDarkColor {
|
@objc class LightDarkColor : NSObject {
|
||||||
var light: UIColor
|
var light: UIColor
|
||||||
var dark : UIColor
|
var dark : UIColor
|
||||||
init(_ l:UIColor,_ d:UIColor){
|
init(_ l:UIColor,_ d:UIColor){
|
||||||
|
|
@ -27,7 +27,7 @@ class LightDarkColor {
|
||||||
dark = d
|
dark = d
|
||||||
}
|
}
|
||||||
|
|
||||||
func get() -> UIColor {
|
@objc func get() -> UIColor {
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
if UITraitCollection.current.userInterfaceStyle == .light {
|
if UITraitCollection.current.userInterfaceStyle == .light {
|
||||||
return light
|
return light
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,14 @@ struct TextStyle {
|
||||||
|
|
||||||
|
|
||||||
extension UILabel {
|
extension UILabel {
|
||||||
func applyStyle(_ style:TextStyle) {
|
|
||||||
|
func applyStyleColors(_ style:TextStyle) {
|
||||||
textColor = style.fgColor.get()
|
textColor = style.fgColor.get()
|
||||||
backgroundColor = style.bgColor.get()
|
backgroundColor = style.bgColor.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyStyle(_ style:TextStyle) {
|
||||||
|
applyStyleColors(style)
|
||||||
if (style.allCaps) {
|
if (style.allCaps) {
|
||||||
text = self.text?.uppercased()
|
text = self.text?.uppercased()
|
||||||
tag = 1
|
tag = 1
|
||||||
|
|
@ -49,10 +54,10 @@ extension UILabel {
|
||||||
|
|
||||||
func addIndicatorIcon(iconName:String, padding:CGFloat = 5.0, y:CGFloat = 4.0, trailing: Bool = true) {
|
func addIndicatorIcon(iconName:String, padding:CGFloat = 5.0, y:CGFloat = 4.0, trailing: Bool = true) {
|
||||||
let imageAttachment = NSTextAttachment()
|
let imageAttachment = NSTextAttachment()
|
||||||
imageAttachment.image = UIImage(named:iconName)
|
imageAttachment.image = UIImage(named:iconName)?.tinted(with: VoipTheme.voipDrawableColor.get())
|
||||||
imageAttachment.bounds = CGRect(x: 5.0, y: y , width: font.lineHeight - 2*padding, height: font.lineHeight - 2*padding)
|
imageAttachment.bounds = CGRect(x: 0.0, y: y , width: font.lineHeight - 2*padding, height: font.lineHeight - 2*padding)
|
||||||
let iconString = NSMutableAttributedString(attachment: imageAttachment)
|
let iconString = NSMutableAttributedString(attachment: imageAttachment)
|
||||||
let textXtring = NSMutableAttributedString(string: text != nil ? text! : "")
|
let textXtring = NSMutableAttributedString(string: text != nil ? (!trailing ? " " : "") + text! + (trailing ? " " : "") : "")
|
||||||
if (trailing) {
|
if (trailing) {
|
||||||
textXtring.append(iconString)
|
textXtring.append(iconString)
|
||||||
self.text = nil
|
self.text = nil
|
||||||
|
|
@ -78,9 +83,14 @@ extension UIButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UITextView {
|
extension UITextView {
|
||||||
func applyStyle(_ style:TextStyle) {
|
|
||||||
|
func applyStyleColors(_ style:TextStyle) {
|
||||||
textColor = style.fgColor.get()
|
textColor = style.fgColor.get()
|
||||||
backgroundColor = style.bgColor.get()
|
backgroundColor = style.bgColor.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyStyle(_ style:TextStyle) {
|
||||||
|
applyStyleColors(style)
|
||||||
if (style.allCaps) {
|
if (style.allCaps) {
|
||||||
text = self.text?.uppercased()
|
text = self.text?.uppercased()
|
||||||
tag = 1
|
tag = 1
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue