forked from mirrors/linphone-iphone
Merge release/5.1 into master.
This includes the rework of the chat conversation in Swift, and every fixes since the 5.0 release.
This commit is contained in:
parent
329193d2fa
commit
0d602260be
225 changed files with 12199 additions and 2946 deletions
131
.gitlab-ci.yml
131
.gitlab-ci.yml
|
|
@ -1,55 +1,98 @@
|
||||||
variables:
|
# COMMENTED FOR NOW - TODO : ENABLE CALLUI TESTS IN THE CI
|
||||||
workspace: linphone.xcworkspace
|
# USE ONLY THE release/5.1 VERSION OF THIS FILE FOR NOW
|
||||||
scheme: linphone
|
#
|
||||||
destination: name=iPhone 13 Pro
|
#
|
||||||
testResult_path: derivedData/Logs/Test
|
#
|
||||||
|
#variables:
|
||||||
|
# workspace: linphone.xcworkspace
|
||||||
|
# scheme: linphone
|
||||||
|
# destination: name=iPhone 13 Pro
|
||||||
|
# testResult_path: derivedData/Logs/Test
|
||||||
|
|
||||||
stages:
|
#stages:
|
||||||
- Build
|
# - Build
|
||||||
- UITests
|
# - UITests
|
||||||
|
|
||||||
before_script:
|
#before_script:
|
||||||
- pod install
|
# - pod install
|
||||||
- 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
|
# - 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
|
||||||
|
|
||||||
Compile & Build:
|
#Compile & Build:
|
||||||
stage: Build
|
# stage: Build
|
||||||
tags: ["macmini-m1-xcode13"]
|
# tags: ["macmini-m1-xcode13"]
|
||||||
before_script:
|
# before_script:
|
||||||
|
# - pod install --repo-update
|
||||||
|
# - 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
|
||||||
|
# - xcrun simctl shutdown "$destination" && xcrun simctl erase "$destination"
|
||||||
|
# script:
|
||||||
|
# - xcodebuild -workspace $workspace -scheme $scheme -UseModernBuildSystem=YES -destination "$destination" -derivedDataPath derivedData
|
||||||
|
# after_script: []
|
||||||
|
#
|
||||||
|
# stage: build
|
||||||
|
# tags: [ "macos-xcode13" ]
|
||||||
|
|
||||||
|
# script:
|
||||||
|
# - pod install --repo-update
|
||||||
|
# - 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 -exportArchive -archivePath ./$archive_path -exportPath ./$export_path -exportOptionsPlist ./$export_options_plist -allowProvisioningUpdates -UseModernBuildSystem=YES -destination 'generic/platform=iOS'
|
||||||
|
|
||||||
|
# artifacts:
|
||||||
|
# paths:
|
||||||
|
# - derivedData/Build
|
||||||
|
# when: always
|
||||||
|
# expire_in: 2 hour
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#after_script:
|
||||||
|
# - ${TRAINER_EXE} -p $testResult_path/*.xcresult -o $testResult_path/
|
||||||
|
# - ${XCPARSE_EXE} attachments $testResult_path/*.xcresult results --uti public.image
|
||||||
|
# - mv $testResult_path/*.xcresult results && mv derivedData/logs.txt results
|
||||||
|
|
||||||
|
#Call Views:
|
||||||
|
# stage: UITests
|
||||||
|
# tags: ["macmini-m1-xcode13"]
|
||||||
|
# dependencies: ["Compile & Build"]
|
||||||
|
# script:
|
||||||
|
# - xcodebuild test -workspace $workspace -scheme $scheme -sdk iphonesimulator -destination "$destination" -UseModernBuildSystem=YES -testPlan Default -derivedDataPath derivedData | tee derivedData/logs.txt
|
||||||
|
|
||||||
|
# artifacts:
|
||||||
|
# paths:
|
||||||
|
# - results/*
|
||||||
|
# when: always
|
||||||
|
# reports:
|
||||||
|
# junit:
|
||||||
|
# - $testResult_path/*.xml
|
||||||
|
# expire_in: 4 week
|
||||||
|
|
||||||
|
|
||||||
|
variables:
|
||||||
|
archive_scheme: linphone
|
||||||
|
archive_path: linphone.xcarchive
|
||||||
|
export_path: linphone-adhoc-ipa
|
||||||
|
export_options_plist: linphone-adhoc.plist
|
||||||
|
|
||||||
|
job-ios:
|
||||||
|
|
||||||
|
stage: build
|
||||||
|
tags: [ "macos-xcode13" ]
|
||||||
|
|
||||||
|
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
|
- 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
|
||||||
- xcrun simctl shutdown "$destination" && xcrun simctl erase "$destination"
|
- xcodebuild archive -scheme $archive_scheme -archivePath ./$archive_path -configuration Release -workspace ./linphone.xcworkspace -UseModernBuildSystem=YES -destination 'generic/platform=iOS'
|
||||||
script:
|
- xcodebuild -exportArchive -archivePath ./$archive_path -exportPath ./$export_path -exportOptionsPlist ./$export_options_plist -allowProvisioningUpdates -UseModernBuildSystem=YES -destination 'generic/platform=iOS'
|
||||||
- xcodebuild -workspace $workspace -scheme $scheme -UseModernBuildSystem=YES -destination "$destination" -derivedDataPath derivedData
|
|
||||||
after_script: []
|
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- derivedData/Build
|
- $archive_path
|
||||||
|
- $export_path
|
||||||
when: always
|
when: always
|
||||||
expire_in: 2 hour
|
expire_in: 1 week
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
after_script:
|
|
||||||
- ${TRAINER_EXE} -p $testResult_path/*.xcresult -o $testResult_path/
|
|
||||||
- ${XCPARSE_EXE} attachments $testResult_path/*.xcresult results --uti public.image
|
|
||||||
- mv $testResult_path/*.xcresult results && mv derivedData/logs.txt results
|
|
||||||
|
|
||||||
Call Views:
|
|
||||||
stage: UITests
|
|
||||||
tags: ["macmini-m1-xcode13"]
|
|
||||||
dependencies: ["Compile & Build"]
|
|
||||||
script:
|
|
||||||
- xcodebuild test -workspace $workspace -scheme $scheme -sdk iphonesimulator -destination "$destination" -UseModernBuildSystem=YES -testPlan Default -derivedDataPath derivedData | tee derivedData/logs.txt
|
|
||||||
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- results/*
|
|
||||||
when: always
|
|
||||||
reports:
|
|
||||||
junit:
|
|
||||||
- $testResult_path/*.xml
|
|
||||||
expire_in: 4 week
|
|
||||||
|
|
|
||||||
56
CHANGELOG.md
56
CHANGELOG.md
|
|
@ -10,15 +10,61 @@ Group changes to describe their impact on the project, as follows:
|
||||||
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.2] - 2023-16-03
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Update linphone SDK to 5.2.32
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Performance issue causing a global slowing of the app, especially at launch
|
||||||
|
- Fix several memory leaks and crashes
|
||||||
|
|
||||||
|
## [5.0.1] - 2023-10-01
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Update linphone SDK to 5.2.11
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Makes sure sip.linphone.org accounts have a LIME X3DH server URL for E2E chat messages encryption
|
||||||
|
- Fix potential crash when displaying images received in a chatroom
|
||||||
|
- Fix bug that would cause the previous call to be terminated when resuming another call that was paused
|
||||||
|
- Fix participant video display in conferences when a second participant joined with video enabled
|
||||||
|
|
||||||
|
## [5.0.0] - 2022-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] - 2022-08-06
|
||||||
### Changed
|
### Changed
|
||||||
- Update linphone SDK to 5.1.42
|
- Update linphone SDK to 5.1.42
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Prevent possible application freeze and crash when creating a new chatroom, depending on the phone's contacts.
|
- Prevent possible application freeze and crash when creating a new chatroom, depending on the phone's contacts.
|
||||||
|
|
||||||
## [4.6.3] - 2021-02-06
|
## [4.6.3] - 2022-02-06
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- New "Contacts" menu in the settings, which allows the use of LDAP configurations
|
- New "Contacts" menu in the settings, which allows the use of LDAP configurations
|
||||||
|
|
@ -33,7 +79,7 @@ Group changes to describe their impact on the project, as follows:
|
||||||
- Display bug when changing audio device
|
- Display bug when changing audio device
|
||||||
|
|
||||||
|
|
||||||
## [4.6.2] - 2021-07-03
|
## [4.6.2] - 2022-07-03
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Bug preventing the activation of the phone speaker during calls
|
- Bug preventing the activation of the phone speaker during calls
|
||||||
|
|
@ -41,7 +87,7 @@ Group changes to describe their impact on the project, as follows:
|
||||||
- Bug causing IMDNs to be missing in some chatrooms
|
- Bug causing IMDNs to be missing in some chatrooms
|
||||||
- Update linphone SDK to 5.1.7
|
- Update linphone SDK to 5.1.7
|
||||||
|
|
||||||
## [4.6.1] - 2021-04-03
|
## [4.6.1] - 2022-04-03
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Crash in chatroom info view after entering background and re-entering foreground
|
- Crash in chatroom info view after entering background and re-entering foreground
|
||||||
|
|
@ -49,7 +95,7 @@ Group changes to describe their impact on the project, as follows:
|
||||||
- Hard to see text (written in black) on dark mode
|
- Hard to see text (written in black) on dark mode
|
||||||
- Removed duplicate push authorization request pop up on install
|
- Removed duplicate push authorization request pop up on install
|
||||||
|
|
||||||
## [4.6.0] - 2021-31-02
|
## [4.6.0] - 2022-31-02
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Reply to chat message feature (with original message preview)
|
- Reply to chat message feature (with original message preview)
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
@ -1568,7 +1581,6 @@ UIColor *previousColor = (UIColor*)[sender backgroundColor]; \
|
||||||
- (IBAction)onRemoteProvisioningLoginClick:(id)sender {
|
- (IBAction)onRemoteProvisioningLoginClick:(id)sender {
|
||||||
ONCLICKBUTTON(sender, 100, {
|
ONCLICKBUTTON(sender, 100, {
|
||||||
_waitView.hidden = NO;
|
_waitView.hidden = NO;
|
||||||
[LinphoneManager.instance lpConfigSetInt:1 forKey:@"transient_provisioning" inSection:@"misc"];
|
|
||||||
[self configureAccount];
|
[self configureAccount];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1584,10 +1596,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,14 +1,13 @@
|
||||||
<?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="21225" 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_12" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||||
<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>
|
||||||
<objects>
|
<objects>
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ChatConversationView">
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ChatConversationViewSwift">
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="addressLabel" destination="40" id="43"/>
|
<outlet property="addressLabel" destination="40" id="43"/>
|
||||||
<outlet property="backButton" destination="9" id="Jcb-ET-bKd"/>
|
<outlet property="backButton" destination="9" id="Jcb-ET-bKd"/>
|
||||||
|
|
@ -50,19 +49,19 @@
|
||||||
</placeholder>
|
</placeholder>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
<view contentMode="scaleToFill" id="v2I-ka-LYa" userLabel="iphone6MetricsView">
|
<view contentMode="scaleToFill" id="v2I-ka-LYa" userLabel="iphone6MetricsView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||||
<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="6">
|
<view tag="1" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6">
|
||||||
<rect key="frame" x="0.0" y="42" width="414" height="788"/>
|
<rect key="frame" x="-1" y="41" width="393" height="744"/>
|
||||||
<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="7" userLabel="topBar">
|
<view alpha="0.90000000000000002" tag="2" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7" userLabel="topBar">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="66"/>
|
||||||
<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="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="82" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="77" 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"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
|
@ -77,7 +76,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button hidden="YES" opaque="NO" tag="11" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bci-3K-AcG" userLabel="cancelButton" customClass="UIInterfaceStyleButton">
|
<button hidden="YES" opaque="NO" tag="11" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bci-3K-AcG" userLabel="cancelButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="82" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="77" 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="Cancel"/>
|
<accessibility key="accessibilityConfiguration" label="Cancel"/>
|
||||||
<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"/>
|
||||||
|
|
@ -92,7 +91,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="5" contentMode="left" fixedFrame="YES" text="Contact1" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="40" userLabel="addressLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="5" contentMode="left" fixedFrame="YES" text="Contact1" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="40" userLabel="addressLabel">
|
||||||
<rect key="frame" x="75" y="0.0" width="160" height="44"/>
|
<rect key="frame" x="75" y="0.0" width="149" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact name">
|
<accessibility key="accessibilityConfiguration" label="Contact name">
|
||||||
<accessibilityTraits key="traits" none="YES"/>
|
<accessibilityTraits key="traits" none="YES"/>
|
||||||
|
|
@ -102,7 +101,7 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<button opaque="NO" tag="6" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Wzg-i0-spp" userLabel="callButton" customClass="UIInterfaceStyleButton">
|
<button opaque="NO" tag="6" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Wzg-i0-spp" userLabel="callButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="248" y="0.0" width="83" height="66"/>
|
<rect key="frame" x="234" y="0.0" width="79" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<state key="normal" image="call_alt_start_default.png">
|
<state key="normal" image="call_alt_start_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"/>
|
||||||
|
|
@ -114,7 +113,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button hidden="YES" opaque="NO" tag="7" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Hc0-GX-fC5" userLabel="backToCallButton" customClass="UIBackToCallButton">
|
<button hidden="YES" opaque="NO" tag="7" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Hc0-GX-fC5" userLabel="backToCallButton" customClass="UIBackToCallButton">
|
||||||
<rect key="frame" x="248" y="0.0" width="83" height="66"/>
|
<rect key="frame" x="234" y="0.0" width="79" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<state key="normal" image="call_back_default.png">
|
<state key="normal" image="call_back_default.png">
|
||||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
|
@ -127,7 +126,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button hidden="YES" opaque="NO" tag="8" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Wag-Nx-kd6" userLabel="deleteButton" customClass="UIInterfaceStyleButton">
|
<button hidden="YES" opaque="NO" tag="8" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Wag-Nx-kd6" userLabel="deleteButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="331" y="0.0" width="83" height="66"/>
|
<rect key="frame" x="313" y="0.0" width="80" 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="Delete all"/>
|
<accessibility key="accessibilityConfiguration" label="Delete all"/>
|
||||||
<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"/>
|
||||||
|
|
@ -141,7 +140,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FqM-Ud-i58" userLabel="editButton" customClass="UIInterfaceStyleButton">
|
<button opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FqM-Ud-i58" userLabel="editButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="331" y="0.0" width="83" height="66"/>
|
<rect key="frame" x="313" y="0.0" width="80" 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="Edit"/>
|
<accessibility key="accessibilityConfiguration" label="Edit"/>
|
||||||
<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"/>
|
||||||
|
|
@ -156,7 +155,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button hidden="YES" opaque="NO" tag="4697" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CPn-Oc-9PX" userLabel="toggleMenuButton" customClass="UIInterfaceStyleButton">
|
<button hidden="YES" opaque="NO" tag="4697" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CPn-Oc-9PX" userLabel="toggleMenuButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="331" y="0.0" width="83" height="66"/>
|
<rect key="frame" x="313" y="0.0" width="80" 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="Edit"/>
|
<accessibility key="accessibilityConfiguration" label="Edit"/>
|
||||||
<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"/>
|
||||||
|
|
@ -169,7 +168,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button hidden="YES" opaque="NO" tag="10" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" reversesTitleShadowWhenHighlighted="YES" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="c9z-aq-2UP" userLabel="toggleSelectionButton" customClass="UIInterfaceStyleButton">
|
<button hidden="YES" opaque="NO" tag="10" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" reversesTitleShadowWhenHighlighted="YES" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="c9z-aq-2UP" userLabel="toggleSelectionButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="248" y="0.0" width="83" height="66"/>
|
<rect key="frame" x="234" y="0.0" width="79" 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="Select all"/>
|
<accessibility key="accessibilityConfiguration" label="Select all"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
|
@ -185,7 +184,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="5" contentMode="left" fixedFrame="YES" text="addresses" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ncq-Zc-X6j" userLabel="participantsLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="5" contentMode="left" fixedFrame="YES" text="addresses" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ncq-Zc-X6j" userLabel="participantsLabel">
|
||||||
<rect key="frame" x="75" y="36" width="160" height="25"/>
|
<rect key="frame" x="75" y="35" width="149" height="25"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact name">
|
<accessibility key="accessibilityConfiguration" label="Contact name">
|
||||||
<accessibilityTraits key="traits" none="YES"/>
|
<accessibilityTraits key="traits" none="YES"/>
|
||||||
|
|
@ -198,11 +197,11 @@
|
||||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
<view tag="12" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="49" userLabel="contentView">
|
<view tag="12" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="49" userLabel="contentView">
|
||||||
<rect key="frame" x="0.0" y="66" width="414" height="722"/>
|
<rect key="frame" x="0.0" y="65" width="393" height="679"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView clipsSubviews="YES" tag="13" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="none" allowsSelection="NO" allowsSelectionDuringEditing="YES" allowsMultipleSelectionDuringEditing="YES" rowHeight="60" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="8" userLabel="messagesTableView">
|
<tableView clipsSubviews="YES" tag="13" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="none" allowsSelection="NO" allowsSelectionDuringEditing="YES" allowsMultipleSelectionDuringEditing="YES" rowHeight="60" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="8" userLabel="messagesTableView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="574"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="529"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<gestureRecognizers/>
|
<gestureRecognizers/>
|
||||||
|
|
@ -214,11 +213,11 @@
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<view hidden="YES" tag="14" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fx4-ao-53M" userLabel="composeIndicatorView">
|
<view hidden="YES" tag="14" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fx4-ao-53M" userLabel="composeIndicatorView">
|
||||||
<rect key="frame" x="0.0" y="574" width="414" height="22"/>
|
<rect key="frame" x="0.0" y="529" width="393" height="23"/>
|
||||||
<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="385" 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"/>
|
||||||
|
|
@ -229,7 +228,7 @@
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="16" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No conversation." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p7C-WH-uR1" userLabel="emptyTableLabel">
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="16" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No conversation." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p7C-WH-uR1" userLabel="emptyTableLabel">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="574"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="539"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
|
@ -237,11 +236,11 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view alpha="0.90000000000000002" tag="17" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="14" userLabel="messageView">
|
<view alpha="0.90000000000000002" tag="17" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="14" userLabel="messageView">
|
||||||
<rect key="frame" x="0.0" y="656" width="414" height="66"/>
|
<rect key="frame" x="0.0" y="612" width="393" height="67"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" tag="19" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="73" userLabel="pictureButton">
|
<button opaque="NO" tag="19" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="73" userLabel="pictureButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="66" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="66" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Send picture"/>
|
<accessibility key="accessibilityConfiguration" label="Send picture"/>
|
||||||
<state key="normal" image="chat_attachment_default.png">
|
<state key="normal" image="chat_attachment_default.png">
|
||||||
|
|
@ -254,7 +253,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="9019" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aTi-pm-fAG" userLabel="audioRecordingButton">
|
<button opaque="NO" tag="9019" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aTi-pm-fAG" userLabel="audioRecordingButton">
|
||||||
<rect key="frame" x="66" y="0.0" width="56" height="66"/>
|
<rect key="frame" x="66" y="0.0" width="56" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Send picture"/>
|
<accessibility key="accessibilityConfiguration" label="Send picture"/>
|
||||||
<inset key="imageEdgeInsets" minX="15" minY="20" maxX="15" maxY="20"/>
|
<inset key="imageEdgeInsets" minX="15" minY="20" maxX="15" maxY="20"/>
|
||||||
|
|
@ -267,7 +266,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="21" contentMode="scaleToFill" fixedFrame="YES" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="15" userLabel="sendButton">
|
<button opaque="NO" tag="21" contentMode="scaleToFill" fixedFrame="YES" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="15" userLabel="sendButton">
|
||||||
<rect key="frame" x="349" y="0.0" width="66" height="66"/>
|
<rect key="frame" x="328" y="0.0" width="65" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Send"/>
|
<accessibility key="accessibilityConfiguration" label="Send"/>
|
||||||
<inset key="titleEdgeInsets" minX="0.0" minY="30" maxX="0.0" maxY="0.0"/>
|
<inset key="titleEdgeInsets" minX="0.0" minY="30" maxX="0.0" maxY="0.0"/>
|
||||||
|
|
@ -281,24 +280,24 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view tag="20" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pqa-tg-5ml" userLabel="messageField" customClass="HPGrowingTextView">
|
<view tag="20" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pqa-tg-5ml" userLabel="messageField" customClass="HPGrowingTextView">
|
||||||
<rect key="frame" x="130" y="13" width="208" height="40"/>
|
<rect key="frame" x="123" y="11" width="197" height="43"/>
|
||||||
<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"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Message field"/>
|
<accessibility key="accessibilityConfiguration" label="Message field"/>
|
||||||
</view>
|
</view>
|
||||||
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" tag="44536" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="ephemeral_messages_color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="LN7-ci-kNn" userLabel="ephemeralIndicator">
|
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" tag="44536" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="ephemeral_messages_color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="LN7-ci-kNn" userLabel="ephemeralIndicator">
|
||||||
<rect key="frame" x="393" y="44" width="15" height="15"/>
|
<rect key="frame" x="372" y="44" width="14" height="15"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
<view hidden="YES" tag="28021" contentMode="scaleToFill" id="Tru-Zm-4EZ" userLabel="VoiceRecording">
|
<view hidden="YES" tag="28021" contentMode="scaleToFill" id="Tru-Zm-4EZ" userLabel="VoiceRecording">
|
||||||
<rect key="frame" x="0.0" y="596" width="414" height="60"/>
|
<rect key="frame" x="0.0" y="596" width="393" height="60"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" tag="28022" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wi9-en-JCZ">
|
<button opaque="NO" tag="28022" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wi9-en-JCZ">
|
||||||
<rect key="frame" x="12" y="13" width="24" height="34"/>
|
<rect key="frame" x="12" y="12" width="24" height="35"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" image="delete_default.png"/>
|
<state key="normal" image="delete_default.png"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
@ -306,26 +305,26 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view tag="28023" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eXD-Gd-FXA">
|
<view tag="28023" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eXD-Gd-FXA">
|
||||||
<rect key="frame" x="50" y="8" width="302" height="44"/>
|
<rect key="frame" x="50" y="7" width="280" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view tag="28024" contentMode="scaleToFill" id="OTf-Od-TDn" userLabel="vr_wave_mask_playback">
|
<view tag="28024" contentMode="scaleToFill" id="OTf-Od-TDn" userLabel="vr_wave_mask_playback">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="240" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="217" height="43"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<color key="backgroundColor" red="0.93333333330000001" green="0.93333333330000001" blue="0.93333333330000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.93333333330000001" green="0.93333333330000001" blue="0.93333333330000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</view>
|
</view>
|
||||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" tag="28025" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="vr_wave.png" translatesAutoresizingMaskIntoConstraints="NO" id="m9m-2e-T7E">
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" tag="28025" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="vr_wave.png" translatesAutoresizingMaskIntoConstraints="NO" id="m9m-2e-T7E">
|
||||||
<rect key="frame" x="8" y="8" width="232" height="28"/>
|
<rect key="frame" x="7" y="8" width="210" height="27"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<view tag="28026" contentMode="scaleToFill" id="TzM-ND-yp4" userLabel="vr_wave_mask_record">
|
<view tag="28026" contentMode="scaleToFill" id="TzM-ND-yp4" userLabel="vr_wave_mask_record">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="240" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="217" height="43"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</view>
|
</view>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" tag="28027" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dMW-Ix-4k0">
|
<label opaque="NO" userInteractionEnabled="NO" tag="28027" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dMW-Ix-4k0">
|
||||||
<rect key="frame" x="245" y="12" width="49" height="21"/>
|
<rect key="frame" x="222" y="12" width="48" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
|
|
@ -335,7 +334,7 @@
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
<button opaque="NO" tag="28028" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FNM-bb-AlC">
|
<button opaque="NO" tag="28028" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FNM-bb-AlC">
|
||||||
<rect key="frame" x="366" y="13" width="35" height="35"/>
|
<rect key="frame" x="343" y="12" width="37" height="35"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" image="vr_play.png"/>
|
<state key="normal" image="vr_play.png"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
@ -346,11 +345,11 @@
|
||||||
<color key="backgroundColor" red="0.93333333330000001" green="0.93333333330000001" blue="0.93333333330000001" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="backgroundColor" red="0.93333333330000001" green="0.93333333330000001" blue="0.93333333330000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
</view>
|
</view>
|
||||||
<view clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3qd-ys-t2L" userLabel="imagesView">
|
<view clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3qd-ys-t2L" userLabel="imagesView">
|
||||||
<rect key="frame" x="0.0" y="625" width="414" height="0.0"/>
|
<rect key="frame" x="0.0" y="587" width="393" height="0.0"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" showsVerticalScrollIndicator="NO" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="JGQ-p2-HCX" userLabel="imagesCollectionView">
|
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" showsVerticalScrollIndicator="NO" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="JGQ-p2-HCX" userLabel="imagesCollectionView">
|
||||||
<rect key="frame" x="2" y="0.0" width="413" height="0.0"/>
|
<rect key="frame" x="2" y="0.0" width="391" height="0.0"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="0.98780487804878048" green="1" blue="1" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.98780487804878048" green="1" blue="1" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="c7z-F2-r1y">
|
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="c7z-F2-r1y">
|
||||||
|
|
@ -364,7 +363,7 @@
|
||||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tjL-Vc-5gN" userLabel="encryptedButton">
|
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tjL-Vc-5gN" userLabel="encryptedButton">
|
||||||
<rect key="frame" x="359" y="10" width="34" height="40"/>
|
<rect key="frame" x="372" y="8" width="34" height="40"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<state key="normal" image="security_1_indicator.png"/>
|
<state key="normal" image="security_1_indicator.png"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
@ -372,7 +371,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view hidden="YES" tag="290392" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wve-MK-7ME" userLabel="ReplyView">
|
<view hidden="YES" tag="290392" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wve-MK-7ME" userLabel="ReplyView">
|
||||||
<rect key="frame" x="0.0" y="536" width="414" height="120"/>
|
<rect key="frame" x="0.0" y="536" width="393" height="120"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -380,7 +379,7 @@
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
<tableView hidden="YES" clipsSubviews="YES" tag="6992" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="gdT-1Q-vU2" userLabel="popupMenu">
|
<tableView hidden="YES" clipsSubviews="YES" tag="6992" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="gdT-1Q-vU2" userLabel="popupMenu">
|
||||||
<rect key="frame" x="142" y="66" width="273" height="132"/>
|
<rect key="frame" x="121" y="66" width="272" height="132"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</tableView>
|
</tableView>
|
||||||
|
|
@ -393,23 +392,23 @@
|
||||||
<point key="canvasLocation" x="365.21739130434787" y="-36.830357142857139"/>
|
<point key="canvasLocation" x="365.21739130434787" y="-36.830357142857139"/>
|
||||||
</view>
|
</view>
|
||||||
<view contentMode="scaleToFill" id="680-UL-sil" userLabel="iphone6MetricsView">
|
<view contentMode="scaleToFill" id="680-UL-sil" userLabel="iphone6MetricsView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||||
<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="VoU-7Q-fgp">
|
<view tag="1" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VoU-7Q-fgp">
|
||||||
<rect key="frame" x="90" y="42" width="324" height="854"/>
|
<rect key="frame" x="90" y="42" width="303" height="810"/>
|
||||||
<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="Z3y-hY-5xp" userLabel="topBar">
|
<view tag="2" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Z3y-hY-5xp" userLabel="topBar">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="324" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="303" height="66"/>
|
||||||
<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="3" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_F.png" translatesAutoresizingMaskIntoConstraints="NO" id="Uvs-m3-GPj" userLabel="backgroundColor">
|
<imageView userInteractionEnabled="NO" tag="3" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_F.png" translatesAutoresizingMaskIntoConstraints="NO" id="Uvs-m3-GPj" userLabel="backgroundColor">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="324" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="303" 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="N2g-vL-3x8" userLabel="backButton" customClass="UIIconButton">
|
<button opaque="NO" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="N2g-vL-3x8" userLabel="backButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="37" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="34" 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"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
|
@ -424,7 +423,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button hidden="YES" opaque="NO" tag="11" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Bqf-Gg-2Rw" userLabel="cancelButton" customClass="UIIconButton">
|
<button hidden="YES" opaque="NO" tag="11" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Bqf-Gg-2Rw" userLabel="cancelButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="37" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="34" 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="Cancel"/>
|
<accessibility key="accessibilityConfiguration" label="Cancel"/>
|
||||||
<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"/>
|
||||||
|
|
@ -449,7 +448,7 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<button hidden="YES" opaque="NO" tag="8" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RDW-7W-25T" userLabel="deleteButton" customClass="UIIconButton">
|
<button hidden="YES" opaque="NO" tag="8" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RDW-7W-25T" userLabel="deleteButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="285" y="0.0" width="39" height="66"/>
|
<rect key="frame" x="264" y="0.0" width="39" 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="Delete all"/>
|
<accessibility key="accessibilityConfiguration" label="Delete all"/>
|
||||||
<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"/>
|
||||||
|
|
@ -463,7 +462,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KeL-Ej-92j" userLabel="editButton" customClass="UIIconButton">
|
<button opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KeL-Ej-92j" userLabel="editButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="285" y="0.0" width="39" height="66"/>
|
<rect key="frame" x="264" y="0.0" width="39" 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="Edit"/>
|
<accessibility key="accessibilityConfiguration" label="Edit"/>
|
||||||
<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"/>
|
||||||
|
|
@ -478,7 +477,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button hidden="YES" opaque="NO" tag="4697" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pQX-Ll-9wL" userLabel="toggleMenuButton" customClass="UIInterfaceStyleButton">
|
<button hidden="YES" opaque="NO" tag="4697" contentMode="scaleAspectFit" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pQX-Ll-9wL" userLabel="toggleMenuButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="285" y="0.0" width="39" height="66"/>
|
<rect key="frame" x="264" y="0.0" width="39" 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="Edit"/>
|
<accessibility key="accessibilityConfiguration" label="Edit"/>
|
||||||
<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"/>
|
||||||
|
|
@ -491,7 +490,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="6" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wag-QV-oUD" userLabel="callButton" customClass="UIIconButton">
|
<button opaque="NO" tag="6" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wag-QV-oUD" userLabel="callButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="248" y="0.0" width="37" height="66"/>
|
<rect key="frame" x="230" y="0.0" width="34" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<state key="normal" image="call_alt_start_default.png">
|
<state key="normal" image="call_alt_start_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"/>
|
||||||
|
|
@ -503,7 +502,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button hidden="YES" opaque="NO" tag="7" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="t25-en-4LP" userLabel="backToCallButton" customClass="UIBackToCallButton">
|
<button hidden="YES" opaque="NO" tag="7" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="t25-en-4LP" userLabel="backToCallButton" customClass="UIBackToCallButton">
|
||||||
<rect key="frame" x="248" y="0.0" width="37" height="66"/>
|
<rect key="frame" x="230" y="0.0" width="34" height="65"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<state key="normal" image="call_back_default.png">
|
<state key="normal" image="call_back_default.png">
|
||||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
|
@ -515,7 +514,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button hidden="YES" opaque="NO" tag="10" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" reversesTitleShadowWhenHighlighted="YES" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4RV-US-Kr1" userLabel="toggleSelectionButton" customClass="UIIconButton">
|
<button hidden="YES" opaque="NO" tag="10" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" reversesTitleShadowWhenHighlighted="YES" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4RV-US-Kr1" userLabel="toggleSelectionButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="248" y="0.0" width="37" height="66"/>
|
<rect key="frame" x="230" y="0.0" width="34" 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="Select all"/>
|
<accessibility key="accessibilityConfiguration" label="Select all"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
|
@ -531,7 +530,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="5" contentMode="left" fixedFrame="YES" text="addresses" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="tyU-Wy-rLs" userLabel="participantsLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="5" contentMode="left" fixedFrame="YES" text="addresses" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="tyU-Wy-rLs" userLabel="participantsLabel">
|
||||||
<rect key="frame" x="67" y="37" width="366" height="25"/>
|
<rect key="frame" x="67" y="36" width="366" height="25"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Contact name">
|
<accessibility key="accessibilityConfiguration" label="Contact name">
|
||||||
<accessibilityTraits key="traits" none="YES"/>
|
<accessibilityTraits key="traits" none="YES"/>
|
||||||
|
|
@ -543,11 +542,11 @@
|
||||||
</subviews>
|
</subviews>
|
||||||
</view>
|
</view>
|
||||||
<view tag="12" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OTt-fc-941" userLabel="contentView">
|
<view tag="12" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OTt-fc-941" userLabel="contentView">
|
||||||
<rect key="frame" x="0.0" y="66" width="324" height="788"/>
|
<rect key="frame" x="0.0" y="66" width="303" height="744"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<tableView clipsSubviews="YES" tag="13" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="none" allowsSelection="NO" allowsSelectionDuringEditing="YES" allowsMultipleSelectionDuringEditing="YES" rowHeight="60" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="CU7-Za-RwN" userLabel="messagesTableView">
|
<tableView clipsSubviews="YES" tag="13" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="none" allowsSelection="NO" allowsSelectionDuringEditing="YES" allowsMultipleSelectionDuringEditing="YES" rowHeight="60" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="CU7-Za-RwN" userLabel="messagesTableView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="324" height="700"/>
|
<rect key="frame" x="0.0" y="0.0" width="303" height="657"/>
|
||||||
<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"/>
|
||||||
<gestureRecognizers/>
|
<gestureRecognizers/>
|
||||||
|
|
@ -557,7 +556,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="16" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No conversation." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pzm-tk-LH0" userLabel="emptyTableLabel">
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="16" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No conversation." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pzm-tk-LH0" userLabel="emptyTableLabel">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="324" height="617"/>
|
<rect key="frame" x="0.0" y="0.0" width="303" height="582"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="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"/>
|
||||||
|
|
@ -565,11 +564,11 @@
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view hidden="YES" tag="14" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nTf-7h-Z4z" userLabel="composeIndicatorView">
|
<view hidden="YES" tag="14" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nTf-7h-Z4z" userLabel="composeIndicatorView">
|
||||||
<rect key="frame" x="0.0" y="700" width="324" height="22"/>
|
<rect key="frame" x="0.0" y="657" width="303" height="21"/>
|
||||||
<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="I34-aL-yuS" 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="I34-aL-yuS" userLabel="composeLabel">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="324" height="22"/>
|
<rect key="frame" x="0.0" y="0.0" width="303" height="22"/>
|
||||||
<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"/>
|
||||||
|
|
@ -579,11 +578,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>
|
||||||
<view tag="17" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LA5-wD-ftj" userLabel="messageView">
|
<view tag="17" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LA5-wD-ftj" userLabel="messageView">
|
||||||
<rect key="frame" x="0.0" y="722" width="324" height="66"/>
|
<rect key="frame" x="0.0" y="678" width="303" height="67"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" tag="18" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_F.png" translatesAutoresizingMaskIntoConstraints="NO" id="kKc-DG-gwg" userLabel="backgroundColor">
|
<imageView userInteractionEnabled="NO" tag="18" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="color_F.png" translatesAutoresizingMaskIntoConstraints="NO" id="kKc-DG-gwg" userLabel="backgroundColor">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="324" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="303" height="67"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<button opaque="NO" tag="19" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gSL-jE-GYO" userLabel="pictureButton">
|
<button opaque="NO" tag="19" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gSL-jE-GYO" userLabel="pictureButton">
|
||||||
|
|
@ -612,13 +611,13 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view tag="20" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="C02-2r-vXK" userLabel="messageField" customClass="HPGrowingTextView">
|
<view tag="20" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="C02-2r-vXK" userLabel="messageField" customClass="HPGrowingTextView">
|
||||||
<rect key="frame" x="59" y="13" width="230" height="40"/>
|
<rect key="frame" x="53" y="12" width="215" height="42"/>
|
||||||
<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"/>
|
||||||
<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"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Message field"/>
|
<accessibility key="accessibilityConfiguration" label="Message field"/>
|
||||||
</view>
|
</view>
|
||||||
<button opaque="NO" tag="21" contentMode="scaleToFill" fixedFrame="YES" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nV9-xZ-oSM" userLabel="sendButton">
|
<button opaque="NO" tag="21" contentMode="scaleToFill" fixedFrame="YES" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nV9-xZ-oSM" userLabel="sendButton">
|
||||||
<rect key="frame" x="258" y="0.0" width="66" height="66"/>
|
<rect key="frame" x="236" y="0.0" width="67" height="66"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Send"/>
|
<accessibility key="accessibilityConfiguration" label="Send"/>
|
||||||
<inset key="titleEdgeInsets" minX="0.0" minY="30" maxX="0.0" maxY="0.0"/>
|
<inset key="titleEdgeInsets" minX="0.0" minY="30" maxX="0.0" maxY="0.0"/>
|
||||||
|
|
@ -632,7 +631,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" tag="44536" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="ephemeral_messages_color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="Gsu-3J-HRp" userLabel="ephemeralIndicator">
|
<imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" tag="44536" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="ephemeral_messages_color_A.png" translatesAutoresizingMaskIntoConstraints="NO" id="Gsu-3J-HRp" userLabel="ephemeralIndicator">
|
||||||
<rect key="frame" x="305" y="40" width="15" height="15"/>
|
<rect key="frame" x="284" y="41" width="13" height="15"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|
@ -640,7 +639,7 @@
|
||||||
</subviews>
|
</subviews>
|
||||||
</view>
|
</view>
|
||||||
<tableView hidden="YES" clipsSubviews="YES" tag="6992" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="iwm-pi-mku" userLabel="popupMenu">
|
<tableView hidden="YES" clipsSubviews="YES" tag="6992" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="iwm-pi-mku" userLabel="popupMenu">
|
||||||
<rect key="frame" x="13" y="66" width="311" height="132"/>
|
<rect key="frame" x="-10" y="66" width="313" height="132"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</tableView>
|
</tableView>
|
||||||
|
|
|
||||||
|
|
@ -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="21701" 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="21678"/>
|
||||||
<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>
|
||||||
|
|
@ -212,6 +212,7 @@
|
||||||
<outlet property="toggleSelectionButton" destination="uqG-2T-VOa" id="ytx-bj-7Qr"/>
|
<outlet property="toggleSelectionButton" destination="uqG-2T-VOa" id="ytx-bj-7Qr"/>
|
||||||
<outlet property="view" destination="6" id="13"/>
|
<outlet property="view" destination="6" id="13"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
<point key="canvasLocation" x="460" y="-11"/>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
|
||||||
|
|
@ -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="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
|
<device id="retina6_12" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||||
|
<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>
|
||||||
|
|
@ -16,6 +19,7 @@
|
||||||
<outlet property="emptyLabel" destination="Mdj-Pz-nu4" id="ijc-2c-waE"/>
|
<outlet property="emptyLabel" destination="Mdj-Pz-nu4" id="ijc-2c-waE"/>
|
||||||
<outlet property="landscapeView" destination="lgD-Mw-h57" id="DTS-80-rMM"/>
|
<outlet property="landscapeView" destination="lgD-Mw-h57" id="DTS-80-rMM"/>
|
||||||
<outlet property="nameLabel" destination="moZ-Bg-zcv" id="Lt9-h0-2o1"/>
|
<outlet property="nameLabel" destination="moZ-Bg-zcv" id="Lt9-h0-2o1"/>
|
||||||
|
<outlet property="organizationLabel" destination="pAA-jk-E4s" id="J0M-Ms-5dp"/>
|
||||||
<outlet property="portraitView" destination="1" id="k69-5P-ieM"/>
|
<outlet property="portraitView" destination="1" id="k69-5P-ieM"/>
|
||||||
<outlet property="tableController" destination="20" id="27"/>
|
<outlet property="tableController" destination="20" id="27"/>
|
||||||
<outlet property="view" destination="1" id="3"/>
|
<outlet property="view" destination="1" id="3"/>
|
||||||
|
|
@ -24,19 +28,19 @@
|
||||||
</placeholder>
|
</placeholder>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
<view contentMode="scaleToFill" id="XnN-PU-Vk7" userLabel="iphone6MetricsView">
|
<view contentMode="scaleToFill" id="XnN-PU-Vk7" userLabel="iphone6MetricsView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1">
|
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1">
|
||||||
<rect key="frame" x="0.0" y="42" width="375" height="559"/>
|
<rect key="frame" x="0.0" y="42" width="393" height="744"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view alpha="0.90000000000000002" tag="1" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4" userLabel="topBar">
|
<view alpha="0.90000000000000002" tag="1" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4" userLabel="topBar">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="66"/>
|
||||||
<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 hidden="YES" opaque="NO" tag="3" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bPQ-aJ-Lk6" userLabel="cancelButton" customClass="UIInterfaceStyleButton">
|
<button hidden="YES" opaque="NO" tag="3" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bPQ-aJ-Lk6" userLabel="cancelButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="75" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="79" height="66"/>
|
||||||
<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="Delete all"/>
|
<accessibility key="accessibilityConfiguration" label="Delete all"/>
|
||||||
<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="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9" userLabel="backButton" customClass="UIInterfaceStyleButton">
|
<button opaque="NO" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9" userLabel="backButton" customClass="UIInterfaceStyleButton">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="75" height="66"/>
|
<rect key="frame" x="0.0" y="0.0" width="79" height="66"/>
|
||||||
<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"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
|
@ -66,7 +70,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="5" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MuB-yy-R9o" userLabel="deleteButton" customClass="UIInterfaceStyleToggleButton">
|
<button opaque="NO" tag="5" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MuB-yy-R9o" userLabel="deleteButton" customClass="UIInterfaceStyleToggleButton">
|
||||||
<rect key="frame" x="225" y="0.0" width="75" height="66"/>
|
<rect key="frame" x="236" y="0.0" width="78" height="66"/>
|
||||||
<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="Delete"/>
|
<accessibility key="accessibilityConfiguration" label="Delete"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
|
@ -82,7 +86,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" tag="6" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8" userLabel="editButton" customClass="UIInterfaceStyleToggleButton">
|
<button opaque="NO" tag="6" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8" userLabel="editButton" customClass="UIInterfaceStyleToggleButton">
|
||||||
<rect key="frame" x="300" y="0.0" width="75" height="66"/>
|
<rect key="frame" x="314" y="0.0" width="79" height="66"/>
|
||||||
<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="Edit"/>
|
<accessibility key="accessibilityConfiguration" label="Edit"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
|
@ -99,30 +103,37 @@
|
||||||
</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>
|
||||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" tag="7" contentMode="scaleToFill" fixedFrame="YES" directionalLockEnabled="YES" showsHorizontalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8D6-vy-obt" userLabel="contentView">
|
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" tag="7" contentMode="scaleToFill" fixedFrame="YES" directionalLockEnabled="YES" showsHorizontalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8D6-vy-obt" userLabel="contentView">
|
||||||
<rect key="frame" x="0.0" y="66" width="375" height="493"/>
|
<rect key="frame" x="0.0" y="66" width="393" height="678"/>
|
||||||
<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"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView tag="8" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="B6X-C9-2vm" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView tag="8" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="B6X-C9-2vm" userLabel="avatarImage">
|
||||||
<rect key="frame" x="142" y="10" width="90" height="90"/>
|
<rect key="frame" x="150" y="10" width="90" height="90"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<connections>
|
<connections>
|
||||||
<outletCollection property="gestureRecognizers" destination="8bV-f4-pLL" appends="YES" id="4V5-Px-aHT"/>
|
<outletCollection property="gestureRecognizers" destination="8bV-f4-pLL" appends="YES" id="4V5-Px-aHT"/>
|
||||||
</connections>
|
</connections>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" tag="9" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="John Doe" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="moZ-Bg-zcv" userLabel="nameLabel">
|
<label opaque="NO" userInteractionEnabled="NO" tag="9" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="John Doe" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="moZ-Bg-zcv" userLabel="nameLabel" customClass="CopyableLabel" customModule="linphoneapp" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="108" width="375" height="40"/>
|
<rect key="frame" x="0.0" y="108" width="393" height="40"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="27"/>
|
<fontDescription key="fontDescription" type="system" pointSize="27"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Organization" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="pAA-jk-E4s" userLabel="organizationLabel">
|
||||||
|
<rect key="frame" x="0.0" y="148" width="393" height="30"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="22"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
<tableView clipsSubviews="YES" tag="10" contentMode="scaleToFill" fixedFrame="YES" directionalLockEnabled="YES" alwaysBounceVertical="YES" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" style="plain" allowsSelection="NO" allowsSelectionDuringEditing="YES" rowHeight="44" sectionHeaderHeight="1" sectionFooterHeight="1" translatesAutoresizingMaskIntoConstraints="NO" id="19" userLabel="tableView">
|
<tableView clipsSubviews="YES" tag="10" contentMode="scaleToFill" fixedFrame="YES" directionalLockEnabled="YES" alwaysBounceVertical="YES" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" style="plain" allowsSelection="NO" allowsSelectionDuringEditing="YES" rowHeight="44" sectionHeaderHeight="1" sectionFooterHeight="1" translatesAutoresizingMaskIntoConstraints="NO" id="19" userLabel="tableView">
|
||||||
<rect key="frame" x="0.0" y="156" width="375" height="337"/>
|
<rect key="frame" x="0.0" y="176" width="393" height="502"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<inset key="scrollIndicatorInsets" minX="0.0" minY="0.0" maxX="0.0" maxY="10"/>
|
<inset key="scrollIndicatorInsets" minX="0.0" minY="0.0" maxX="0.0" maxY="10"/>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="dataSource" destination="20" id="28"/>
|
<outlet property="dataSource" destination="20" id="28"/>
|
||||||
|
|
@ -130,26 +141,26 @@
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</scrollView>
|
</scrollView>
|
||||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="40" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No contact selected" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mdj-Pz-nu4" userLabel="emptyLabel">
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" tag="40" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="No contact selected" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mdj-Pz-nu4" userLabel="emptyLabel">
|
||||||
<rect key="frame" x="0.0" y="66" width="375" height="493"/>
|
<rect key="frame" x="0.0" y="66" width="393" height="678"/>
|
||||||
<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="JK8-Td-I1i" userLabel="waitView">
|
<view hidden="YES" tag="8" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JK8-Td-I1i" userLabel="waitView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="559"/>
|
<rect key="frame" x="0.0" y="0.0" width="393" height="744"/>
|
||||||
<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="J67-KE-kHm" userLabel="activityIndicatorView">
|
<activityIndicatorView opaque="NO" tag="9" contentMode="scaleToFill" fixedFrame="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="J67-KE-kHm" userLabel="activityIndicatorView">
|
||||||
<rect key="frame" x="179" y="267" width="20" height="20"/>
|
<rect key="frame" x="188" y="358" 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"/>
|
||||||
</activityIndicatorView>
|
</activityIndicatorView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<gestureRecognizers/>
|
<gestureRecognizers/>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|
@ -244,7 +255,7 @@
|
||||||
<rect key="frame" x="0.0" y="66" width="667" height="267"/>
|
<rect key="frame" x="0.0" y="66" width="667" height="267"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView tag="8" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="IJJ-eZ-rC2" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView tag="8" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="IJJ-eZ-rC2" userLabel="avatarImage">
|
||||||
<rect key="frame" x="46" y="8" width="62" height="62"/>
|
<rect key="frame" x="46" y="8" width="62" height="62"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
|
@ -321,5 +332,11 @@
|
||||||
<image name="edit_default.png" width="46.400001525878906" height="46.400001525878906"/>
|
<image name="edit_default.png" width="46.400001525878906" height="46.400001525878906"/>
|
||||||
<image name="edit_disabled.png" width="46.400001525878906" height="46.400001525878906"/>
|
<image name="edit_disabled.png" width="46.400001525878906" height="46.400001525878906"/>
|
||||||
<image name="valid_default.png" width="44.799999237060547" height="30.399999618530273"/>
|
<image name="valid_default.png" width="44.799999237060547" height="30.399999618530273"/>
|
||||||
|
<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>
|
||||||
|
|
|
||||||
|
|
@ -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="21701" 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="21678"/>
|
||||||
<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>
|
||||||
|
|
@ -12,11 +12,14 @@
|
||||||
<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="deleteButton" destination="DZc-zR-1Q7" id="M6N-vO-UIb"/>
|
||||||
|
<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"/>
|
||||||
<outlet property="searchBar" destination="5jE-oF-d45" id="xfS-xo-2Bm"/>
|
<outlet property="searchBar" destination="5jE-oF-d45" id="xfS-xo-2Bm"/>
|
||||||
<outlet property="selectedButtonImage" destination="A9k-KU-Dlm" id="4dX-pd-Y2D"/>
|
<outlet property="selectedButtonImage" destination="A9k-KU-Dlm" id="4dX-pd-Y2D"/>
|
||||||
|
<outlet property="switchView" destination="93" id="4iM-Fl-F9B"/>
|
||||||
<outlet property="tableController" destination="TJG-JZ-YRR" id="0lt-gC-EOm"/>
|
<outlet property="tableController" destination="TJG-JZ-YRR" id="0lt-gC-EOm"/>
|
||||||
<outlet property="toggleSelectionButton" destination="5lZ-u7-Yex" id="ULR-WM-Yuo"/>
|
<outlet property="toggleSelectionButton" destination="5lZ-u7-Yex" id="ULR-WM-Yuo"/>
|
||||||
<outlet property="topBar" destination="3" id="w1O-2o-b18"/>
|
<outlet property="topBar" destination="3" id="w1O-2o-b18"/>
|
||||||
|
|
@ -179,6 +182,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 +198,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 +220,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="21507" 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="21505"/>
|
||||||
|
<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,22 +66,22 @@
|
||||||
</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">
|
||||||
<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"/>
|
||||||
<bool key="isElement" value="YES"/>
|
<bool key="isElement" value="YES"/>
|
||||||
</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" customClass="CopyableLabel" customModule="linphoneapp" customModuleProvider="target">
|
||||||
<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,15 +89,15 @@
|
||||||
<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"/>
|
||||||
<bool key="isElement" value="YES"/>
|
<bool key="isElement" value="YES"/>
|
||||||
</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" customClass="CopyableLabel" customModule="linphoneapp" customModuleProvider="target">
|
||||||
<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">
|
||||||
<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
|
||||||
|
|
@ -82,10 +82,47 @@
|
||||||
[self searchBar:_searchBar textDidChange:_searchBar.text];
|
[self searchBar:_searchBar textDidChange:_searchBar.text];
|
||||||
self.tableView.accessibilityIdentifier = @"Suggested addresses";
|
self.tableView.accessibilityIdentifier = @"Suggested addresses";
|
||||||
|
|
||||||
|
NSDictionary* userInfo;
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector: @selector(receivePresenceNotification:)
|
||||||
|
name: @"LinphoneFriendPresenceUpdate"
|
||||||
|
object: userInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) receivePresenceNotification:(NSNotification*)notification
|
||||||
|
{
|
||||||
|
if ([notification.name isEqualToString:@"LinphoneFriendPresenceUpdate"])
|
||||||
|
{
|
||||||
|
NSDictionary* userInfo = notification.userInfo;
|
||||||
|
NSString* friend = (NSString*)userInfo[@"friend"];
|
||||||
|
|
||||||
|
for (int i = 0; i < _addresses.count; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
NSString *key = [_addresses objectAtIndex:i];
|
||||||
|
Contact *contact = [LinphoneManager.instance.fastAddressBook.addressBookMap objectForKey:[FastAddressBook normalizeSipURI:key use_prefix:[CallManager.instance applyInternationalPrefix]]];
|
||||||
|
if (!contact) {
|
||||||
|
contact = [_ldapAndProvisioningContactAddressBookMap objectForKey:key];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contact.friend != nil && linphone_friend_get_address(contact.friend) != nil) {
|
||||||
|
char *curi = linphone_address_as_string_uri_only(linphone_friend_get_address(contact.friend));
|
||||||
|
NSString *uri = [NSString stringWithUTF8String:curi];
|
||||||
|
|
||||||
|
if([uri isEqual:friend]){
|
||||||
|
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:i inSection:0];
|
||||||
|
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
|
||||||
|
[self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationFade];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) viewWillDisappear:(BOOL)animated {
|
- (void) viewWillDisappear:(BOOL)animated {
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"LinphoneFriendPresenceUpdate" object:nil];
|
||||||
|
[AvatarBridge removeAllObserver];
|
||||||
_notFirstTime = FALSE;
|
_notFirstTime = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,64 +134,76 @@
|
||||||
_loadingView.hidden = TRUE;
|
_loadingView.hidden = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(BOOL) isSecureChatable:(const LinphoneFriend*)friend {
|
||||||
|
if (!friend)
|
||||||
|
return false;
|
||||||
|
const LinphonePresenceModel *model = linphone_friend_get_presence_model(friend);
|
||||||
|
return model && linphone_presence_model_has_capability(model, LinphoneFriendCapabilityLimeX3dh);
|
||||||
|
}
|
||||||
|
|
||||||
- (void) buildChatContactTable {
|
- (void) buildChatContactTable {
|
||||||
|
|
||||||
bctbx_list_t *results = [MagicSearchSingleton.instance getLastSearchResults];
|
bctbx_list_t *result_list = [MagicSearchSingleton.instance getLastSearchResults];
|
||||||
while (results) {
|
bctbx_list_t *it;
|
||||||
|
LinphoneAccount *account = linphone_core_get_default_account(LC);
|
||||||
LinphoneSearchResult *result = results->data;
|
|
||||||
|
for (it = result_list; it != NULL; it = it->next) {
|
||||||
|
LinphoneSearchResult *result = it->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);
|
||||||
|
|
||||||
|
if (([LinphoneManager.instance lpConfigBoolForKey:@"force_lime_chat_rooms"] && ![self isSecureChatable:friend]) || [LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinphoneAccount *account = linphone_core_get_default_account(LC);
|
|
||||||
if (account) {
|
if (account) {
|
||||||
const char *normalizedPhoneNumber = linphone_account_normalize_phone_number(account, phoneNumber);
|
char *normalizedPhoneNumber = linphone_account_normalize_phone_number(account, phoneNumber);
|
||||||
if (!normalizedPhoneNumber) {
|
if (!normalizedPhoneNumber) {
|
||||||
// get invalid phone number, continue
|
// get invalid phone number, continue
|
||||||
results = results->next;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
addr = linphone_account_normalize_sip_uri(account, normalizedPhoneNumber);
|
addr = linphone_account_normalize_sip_uri(account, normalizedPhoneNumber);
|
||||||
|
bctbx_free(normalizedPhoneNumber);
|
||||||
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 = [[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];
|
||||||
|
linphone_address_unref(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (uri) ms_free(uri);
|
||||||
|
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
results = results->next;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ms_free(uri);
|
|
||||||
|
|
||||||
[_addresses addObject:address];
|
[_addresses addObject:address];
|
||||||
[_phoneOrAddr addObject:phoneNumber ? [NSString stringWithUTF8String:phoneNumber] : address];
|
[_phoneOrAddr addObject:phoneNumber ? [NSString stringWithUTF8String:phoneNumber] : address];
|
||||||
[_addressesCached addObject:[NSString stringWithFormat:@"%d",linphone_search_result_get_capabilities(result)]];
|
[_addressesCached addObject:[NSString stringWithFormat:@"%d",linphone_search_result_get_capabilities(result)]];
|
||||||
|
|
||||||
results = results->next;
|
|
||||||
}
|
}
|
||||||
|
bctbx_list_free(result_list);
|
||||||
[self.tableView reloadData];
|
[self.tableView reloadData];
|
||||||
_reloadMagicSearch = FALSE;
|
_reloadMagicSearch = FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +217,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 +241,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 +252,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 +265,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]];
|
||||||
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 +302,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];
|
||||||
|
|
|
||||||
|
|
@ -69,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;
|
||||||
|
|
@ -90,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"]) {
|
||||||
|
|
@ -98,8 +102,17 @@ 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"] || [LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"]) {
|
||||||
|
_chiffreOptionView.hidden = true;
|
||||||
|
_isEncrypted = true;
|
||||||
|
_tableController.isEncrypted = true;
|
||||||
|
_allButton.hidden = true;
|
||||||
|
_linphoneButton.hidden = true;
|
||||||
|
_selectedButtonImage.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_isForVoipConference) {
|
if (_isForVoipConference) {
|
||||||
_switchView.hidden = true;
|
_switchView.hidden = true;
|
||||||
|
|
@ -110,13 +123,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 {
|
||||||
|
|
@ -131,14 +159,14 @@ 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"] || [LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"]; // 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 && !(_isForVoipConference||_isForOngoingVoipConference);
|
_backButton.hidden = IPAD && !(_isForVoipConference||_isForOngoingVoipConference);
|
||||||
|
|
@ -164,9 +192,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
|
||||||
|
|
@ -184,7 +211,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
[_tableController.contactsGroup removeAllObjects];
|
[_tableController.contactsGroup removeAllObjects];
|
||||||
if (_isForVoipConference) {
|
if (_isForVoipConference) {
|
||||||
if (_isForOngoingVoipConference) {
|
if (_isForOngoingVoipConference) {
|
||||||
[PhoneMainView.instance changeCurrentView:VIEW(ActiveCallOrConferenceView).compositeViewDescription];
|
[PhoneMainView.instance popToView:VIEW(ConferenceCallView).compositeViewDescription];
|
||||||
[ControlsViewModelBridge showParticipants];
|
[ControlsViewModelBridge showParticipants];
|
||||||
} else {
|
} else {
|
||||||
[PhoneMainView.instance popToView:ConferenceSchedulingView.compositeViewDescription];
|
[PhoneMainView.instance popToView:ConferenceSchedulingView.compositeViewDescription];
|
||||||
|
|
@ -200,7 +227,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];
|
||||||
|
|
@ -280,7 +307,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;
|
||||||
}
|
}
|
||||||
|
|
@ -302,9 +329,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,23 +85,33 @@ 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,
|
if (messageSize.height > self.view.bounds.size.height/2) {
|
||||||
_msgView.frame.origin.y,
|
[_msgView setFrame:CGRectMake(_msgView.frame.origin.x,
|
||||||
self.view.frame.size.width,
|
_msgView.frame.origin.y,
|
||||||
messageSize.height+5)];
|
self.view.frame.size.width,
|
||||||
|
self.view.bounds.size.height/2 +5)];
|
||||||
|
} else {
|
||||||
|
[_msgView setFrame:CGRectMake(_msgView.frame.origin.x,
|
||||||
|
_msgView.frame.origin.y,
|
||||||
|
self.view.frame.size.width,
|
||||||
|
messageSize.height+5)];
|
||||||
|
}
|
||||||
|
|
||||||
[_tableView setFrame:CGRectMake(_tableView.frame.origin.x,
|
[_tableView setFrame:CGRectMake(_tableView.frame.origin.x,
|
||||||
_msgView.frame.origin.y + _msgView.frame.size.height + 10,
|
_msgView.frame.origin.y + _msgView.frame.size.height + 10,
|
||||||
|
|
@ -299,7 +304,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;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#import "ChatConversationInfoView.h"
|
#import "ChatConversationInfoView.h"
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
#import "UIChatConversationInfoTableViewCell.h"
|
#import "UIChatConversationInfoTableViewCell.h"
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
#import "linphone/core.h"
|
#import "linphone/core.h"
|
||||||
|
|
||||||
|
|
@ -84,6 +85,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 {
|
||||||
|
|
@ -95,10 +97,45 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
selector:@selector(onLinphoneCoreReady:)
|
selector:@selector(onLinphoneCoreReady:)
|
||||||
name:kLinphoneGlobalStateUpdate
|
name:kLinphoneGlobalStateUpdate
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
|
NSDictionary* userInfo;
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector: @selector(receivePresenceNotification:)
|
||||||
|
name: @"LinphoneFriendPresenceUpdate"
|
||||||
|
object: userInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) receivePresenceNotification:(NSNotification*)notification
|
||||||
|
{
|
||||||
|
if ([notification.name isEqualToString:@"LinphoneFriendPresenceUpdate"])
|
||||||
|
{
|
||||||
|
NSDictionary* userInfo = notification.userInfo;
|
||||||
|
NSString* friend = (NSString*)userInfo[@"friend"];
|
||||||
|
|
||||||
|
for (int i = 0; i < _contacts.count; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
NSString *uri = _contacts[i];
|
||||||
|
LinphoneAddress *addr = linphone_address_new(uri.UTF8String);
|
||||||
|
|
||||||
|
if (addr != nil) {
|
||||||
|
char *curi = linphone_address_as_string_uri_only(addr);
|
||||||
|
NSString *uri = [NSString stringWithUTF8String:curi];
|
||||||
|
|
||||||
|
if([uri isEqual:friend]){
|
||||||
|
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:i inSection:0];
|
||||||
|
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
|
||||||
|
[self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationFade];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"LinphoneFriendPresenceUpdate" object:nil];
|
||||||
|
[AvatarBridge removeAllObserver];
|
||||||
if (!_room || !_chatRoomCbs)
|
if (!_room || !_chatRoomCbs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -153,10 +190,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];
|
||||||
}
|
}
|
||||||
|
|
@ -181,7 +219,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onValidate {
|
- (void)onValidate {
|
||||||
ChatConversationView *view = VIEW(ChatConversationView);
|
ChatConversationViewSwift *view = VIEW(ChatConversationViewSwift);
|
||||||
// Change subject if necessary
|
// Change subject if necessary
|
||||||
if (![_oldSubject isEqualToString:_nameLabel.text])
|
if (![_oldSubject isEqualToString:_nameLabel.text])
|
||||||
linphone_chat_room_set_subject(_room, _nameLabel.text.UTF8String);
|
linphone_chat_room_set_subject(_room, _nameLabel.text.UTF8String);
|
||||||
|
|
@ -277,7 +315,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
view.isForVoipConference = FALSE;
|
view.isForVoipConference = FALSE;
|
||||||
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
} else {
|
} else {
|
||||||
ChatConversationView *view = VIEW(ChatConversationView);
|
ChatConversationViewSwift *view = VIEW(ChatConversationViewSwift);
|
||||||
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -326,7 +364,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
cell.uri = _contacts[indexPath.row];
|
cell.uri = _contacts[indexPath.row];
|
||||||
LinphoneAddress *addr = linphone_address_new(cell.uri.UTF8String);
|
LinphoneAddress *addr = linphone_address_new(cell.uri.UTF8String);
|
||||||
cell.nameLabel.text = (addr == nil? cell.uri : [FastAddressBook displayNameForAddress:addr]);
|
cell.nameLabel.text = (addr == nil? cell.uri : [FastAddressBook displayNameForAddress:addr]);
|
||||||
[cell.avatarImage setImage:[FastAddressBook imageForAddress:addr] bordered:YES withRoundedRadius:YES];
|
[cell.avatarImage setImage:[FastAddressBook imageForAddress:addr]];
|
||||||
cell.controllerView = self;
|
cell.controllerView = self;
|
||||||
if(![_admins containsObject:cell.uri]) {
|
if(![_admins containsObject:cell.uri]) {
|
||||||
cell.adminLabel.enabled = FALSE;
|
cell.adminLabel.enabled = FALSE;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -60,6 +61,7 @@
|
||||||
@property(nonatomic) NSTimer *ephemeralDisplayTimer;
|
@property(nonatomic) NSTimer *ephemeralDisplayTimer;
|
||||||
@property (nullable, nonatomic) UIButton *floatingScrollButton;
|
@property (nullable, nonatomic) UIButton *floatingScrollButton;
|
||||||
@property (nullable, nonatomic) UILabel *scrollBadge;
|
@property (nullable, nonatomic) UILabel *scrollBadge;
|
||||||
|
@property (nullable, nonatomic) UIButton *floatingScrollBackground;
|
||||||
|
|
||||||
- (void)addEventEntry:(LinphoneEventLog *)event;
|
- (void)addEventEntry:(LinphoneEventLog *)event;
|
||||||
- (void)scrollToBottom:(BOOL)animated;
|
- (void)scrollToBottom:(BOOL)animated;
|
||||||
|
|
@ -70,5 +72,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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,9 +168,9 @@
|
||||||
//[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:(count - 1) inSection:0]];
|
//[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:(count - 1) inSection:0]];
|
||||||
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(count - 1) inSection:0]
|
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(count - 1) inSection:0]
|
||||||
atScrollPosition:UITableViewScrollPositionBottom
|
atScrollPosition:UITableViewScrollPositionBottom
|
||||||
animated:YES];
|
animated:animated];
|
||||||
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
|
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
|
||||||
[ChatConversationView markAsRead:_chatRoom];
|
[ChatConversationViewSwift markAsRead:_chatRoom];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)scrollToLastUnread:(BOOL)animated {
|
- (void)scrollToLastUnread:(BOOL)animated {
|
||||||
|
|
@ -203,7 +200,7 @@
|
||||||
index = (int)count - 1;
|
index = (int)count - 1;
|
||||||
|
|
||||||
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
|
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
|
||||||
[ChatConversationView markAsRead:_chatRoom];
|
[ChatConversationViewSwift markAsRead:_chatRoom];
|
||||||
|
|
||||||
// Scroll to unread
|
// Scroll to unread
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
|
|
@ -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)
|
||||||
|
[ChatConversationViewSwift 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 {
|
||||||
|
|
@ -423,7 +431,7 @@ static const CGFloat MESSAGE_SPACING_PERCENTAGE = 1.f;
|
||||||
title:NSLocalizedString(@"Reply", nil)
|
title:NSLocalizedString(@"Reply", 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);
|
LinphoneChatMessage *msg = linphone_event_log_get_chat_message(event);
|
||||||
[VIEW(ChatConversationView) initiateReplyViewForMessage:msg];
|
[VIEW(ChatConversationViewSwift) initiateReplyViewForMessage:msg];
|
||||||
[self scrollToBottom:TRUE];
|
[self scrollToBottom:TRUE];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -213,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
|
||||||
|
|
@ -233,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:)
|
||||||
|
|
@ -247,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.
|
||||||
|
|
@ -309,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 {
|
||||||
|
|
@ -325,27 +333,33 @@ 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];
|
if (peerAddr) linphone_address_unref(peerAddr);
|
||||||
_backButton.hidden = _tableController.isEditing;
|
if (localAddr) linphone_address_unref(localAddr);
|
||||||
[_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)
|
||||||
|
|
@ -353,9 +367,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) {
|
||||||
|
|
@ -375,7 +398,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
linphone_chat_room_cbs_set_is_composing_received(_chatRoomCbs, on_chat_room_is_composing_received);
|
linphone_chat_room_cbs_set_is_composing_received(_chatRoomCbs, on_chat_room_is_composing_received);
|
||||||
linphone_chat_room_cbs_set_conference_joined(_chatRoomCbs, on_chat_room_conference_joined);
|
linphone_chat_room_cbs_set_conference_joined(_chatRoomCbs, on_chat_room_conference_joined);
|
||||||
linphone_chat_room_cbs_set_conference_left(_chatRoomCbs, on_chat_room_conference_left);
|
linphone_chat_room_cbs_set_conference_left(_chatRoomCbs, on_chat_room_conference_left);
|
||||||
linphone_chat_room_cbs_set_security_event(_chatRoomCbs, on_chat_room_conference_alert);
|
linphone_chat_room_cbs_set_security_event(_chatRoomCbs, on_chat_room_conference_alert);
|
||||||
linphone_chat_room_cbs_set_user_data(_chatRoomCbs, (__bridge void*)self);
|
linphone_chat_room_cbs_set_user_data(_chatRoomCbs, (__bridge void*)self);
|
||||||
linphone_chat_room_add_callbacks(_chatRoom, _chatRoomCbs);
|
linphone_chat_room_add_callbacks(_chatRoom, _chatRoomCbs);
|
||||||
}
|
}
|
||||||
|
|
@ -397,6 +420,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
LinphoneParticipant *firstParticipant = participants ? (LinphoneParticipant *)participants->data : NULL;
|
LinphoneParticipant *firstParticipant = participants ? (LinphoneParticipant *)participants->data : NULL;
|
||||||
const LinphoneAddress *addr = firstParticipant ? linphone_participant_get_address(firstParticipant) : linphone_chat_room_get_peer_address(_chatRoom);
|
const LinphoneAddress *addr = firstParticipant ? linphone_participant_get_address(firstParticipant) : linphone_chat_room_get_peer_address(_chatRoom);
|
||||||
[ContactDisplay setDisplayNameLabel:_addressLabel forAddress:addr];
|
[ContactDisplay setDisplayNameLabel:_addressLabel forAddress:addr];
|
||||||
|
bctbx_list_free(participants);
|
||||||
} else
|
} else
|
||||||
_addressLabel.text = [NSString stringWithUTF8String:linphone_chat_room_get_subject(_chatRoom) ?: LINPHONE_DUMMY_SUBJECT];
|
_addressLabel.text = [NSString stringWithUTF8String:linphone_chat_room_get_subject(_chatRoom) ?: LINPHONE_DUMMY_SUBJECT];
|
||||||
|
|
||||||
|
|
@ -428,7 +452,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -485,23 +509,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 {
|
||||||
|
|
@ -600,9 +627,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)];
|
||||||
|
|
@ -659,6 +686,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 {
|
||||||
|
|
@ -773,9 +805,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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -783,7 +815,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 {
|
||||||
|
|
@ -939,6 +979,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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1051,84 +1092,86 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)writeMediaToGallery:(NSString *)name fileType:(NSString *)fileType {
|
+ (void)writeMediaToGallery:(NSString *)name fileType:(NSString *)fileType {
|
||||||
NSString *filePath = [LinphoneManager validFilePath:name];
|
if (![LinphoneManager.instance lpConfigBoolForKey:@"vfs_enabled_mode"]) {
|
||||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
NSString *filePath = [LinphoneManager validFilePath:name];
|
||||||
if ([fileManager fileExistsAtPath:filePath]) {
|
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||||
NSData* data = [NSData dataWithContentsOfFile:filePath];
|
if ([fileManager fileExistsAtPath:filePath]) {
|
||||||
|
NSData* data = [NSData dataWithContentsOfFile:filePath];
|
||||||
|
|
||||||
// define a block , not called immediately. To avoid crash when saving photo before PHAuthorizationStatusNotDetermined.
|
// define a block , not called immediately. To avoid crash when saving photo before PHAuthorizationStatusNotDetermined.
|
||||||
void (^block)(void)= ^ {
|
void (^block)(void)= ^ {
|
||||||
if ([fileType isEqualToString:@"image"] ) {
|
if ([fileType isEqualToString:@"image"] ) {
|
||||||
// we're finished, save the image and update the message
|
// we're finished, save the image and update the message
|
||||||
UIImage *image = [UIImage imageWithData:data];
|
UIImage *image = [UIImage imageWithData:data];
|
||||||
if (!image) {
|
if (!image) {
|
||||||
ChatConversationView *view = VIEW(ChatConversationView);
|
ChatConversationView *view = VIEW(ChatConversationView);
|
||||||
[view showFileDownloadError];
|
[view showFileDownloadError];
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
__block PHObjectPlaceholder *placeHolder;
|
||||||
|
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
||||||
|
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
|
||||||
|
placeHolder = [request placeholderForCreatedAsset];
|
||||||
|
} completionHandler:^(BOOL success, NSError *error) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (error) {
|
||||||
|
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
|
||||||
|
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||||
|
message:NSLocalizedString(@"Cannot write image to photo library",nil)
|
||||||
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|
||||||
|
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||||
|
style:UIAlertActionStyleDefault
|
||||||
|
handler:^(UIAlertAction * action) {}];
|
||||||
|
|
||||||
|
[errView addAction:defaultAction];
|
||||||
|
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||||
|
} else {
|
||||||
|
LOGI(@"Image saved to [%@]", [placeHolder localIdentifier]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
} else if([fileType isEqualToString:@"video"]) {
|
||||||
|
__block PHObjectPlaceholder *placeHolder;
|
||||||
|
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
||||||
|
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]];
|
||||||
|
placeHolder = [request placeholderForCreatedAsset];
|
||||||
|
} completionHandler:^(BOOL success, NSError * _Nullable error) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (error) {
|
||||||
|
LOGE(@"Cannot save video data downloaded [%@]", [error localizedDescription]);
|
||||||
|
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
||||||
|
message:NSLocalizedString(@"Cannot write video to photo library", nil)
|
||||||
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|
||||||
|
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
||||||
|
style:UIAlertActionStyleDefault
|
||||||
|
handler:^(UIAlertAction * action) {}];
|
||||||
|
|
||||||
|
[errView addAction:defaultAction];
|
||||||
|
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
||||||
|
} else {
|
||||||
|
LOGI(@"video saved to [%@]", [placeHolder localIdentifier]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
__block PHObjectPlaceholder *placeHolder;
|
};
|
||||||
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
|
||||||
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
|
// When you save an image or video to a photo library, make sure that it is allowed. Otherwise, there will be a backup error.
|
||||||
placeHolder = [request placeholderForCreatedAsset];
|
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||||
} completionHandler:^(BOOL success, NSError *error) {
|
block();
|
||||||
|
} else {
|
||||||
|
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if (error) {
|
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
||||||
LOGE(@"Cannot save image data downloaded [%@]", [error localizedDescription]);
|
block();
|
||||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
|
||||||
message:NSLocalizedString(@"Cannot write image to photo library",nil)
|
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
|
|
||||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
|
||||||
style:UIAlertActionStyleDefault
|
|
||||||
handler:^(UIAlertAction * action) {}];
|
|
||||||
|
|
||||||
[errView addAction:defaultAction];
|
|
||||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
|
||||||
} else {
|
} else {
|
||||||
LOGI(@"Image saved to [%@]", [placeHolder localIdentifier]);
|
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Photo's permission", nil) message:NSLocalizedString(@"Photo not authorized", nil) delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil] show];
|
||||||
}
|
|
||||||
});
|
|
||||||
}];
|
|
||||||
} else if([fileType isEqualToString:@"video"]) {
|
|
||||||
__block PHObjectPlaceholder *placeHolder;
|
|
||||||
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
|
||||||
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]];
|
|
||||||
placeHolder = [request placeholderForCreatedAsset];
|
|
||||||
} completionHandler:^(BOOL success, NSError * _Nullable error) {
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
|
||||||
if (error) {
|
|
||||||
LOGE(@"Cannot save video data downloaded [%@]", [error localizedDescription]);
|
|
||||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Transfer error", nil)
|
|
||||||
message:NSLocalizedString(@"Cannot write video to photo library", nil)
|
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
|
|
||||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK"
|
|
||||||
style:UIAlertActionStyleDefault
|
|
||||||
handler:^(UIAlertAction * action) {}];
|
|
||||||
|
|
||||||
[errView addAction:defaultAction];
|
|
||||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
|
||||||
} else {
|
|
||||||
LOGI(@"video saved to [%@]", [placeHolder localIdentifier]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// When you save an image or video to a photo library, make sure that it is allowed. Otherwise, there will be a backup error.
|
|
||||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
|
||||||
block();
|
|
||||||
} else {
|
|
||||||
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
|
||||||
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) {
|
|
||||||
block();
|
|
||||||
} else {
|
|
||||||
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Photo's permission", nil) message:NSLocalizedString(@"Photo not authorized", nil) delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Continue", nil] show];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1417,12 +1460,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]];
|
||||||
}
|
}
|
||||||
|
|
@ -1723,13 +1765,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));
|
||||||
|
|
@ -1756,8 +1791,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)
|
||||||
|
|
@ -1775,12 +1809,12 @@ 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];
|
|
||||||
|
|
||||||
int firstIndex = isOneToOne ? 0 : 1;
|
int firstIndex = isOneToOne ? 0 : 1;
|
||||||
|
|
||||||
|
|
@ -1791,7 +1825,14 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
||||||
|
|
||||||
if (indexPath.row == firstIndex) {
|
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];
|
||||||
}
|
}
|
||||||
|
|
@ -1808,7 +1849,8 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
||||||
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
if ((!isEncrypted && indexPath.row == 1+firstIndex) || (isEncrypted && indexPath.row == 3+firstIndex)) {
|
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+firstIndex) || (isEncrypted && indexPath.row == 4+firstIndex)) {
|
if ((!isEncrypted && indexPath.row == 2+firstIndex) || (isEncrypted && indexPath.row == 4+firstIndex)) {
|
||||||
|
|
@ -1849,31 +1891,44 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
||||||
- (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 (!_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;
|
int firstIndex = isOneToOne ? 0 : 1;
|
||||||
|
|
||||||
if (!isOneToOne && indexPath.row == 0) {
|
if (!isOneToOne && indexPath.row == 0) {
|
||||||
cell.imageView.image = [LinphoneUtils resizeImage:[UIImage imageNamed:@"menu_voip_meeting_schedule"] newSize:CGSizeMake(25, 25)];
|
cell.imageView.image = [UIImage imageNamed:@"menu_voip_meeting_schedule"];
|
||||||
cell.textLabel.text = NSLocalizedString(@"Schedule a meeting",nil);
|
cell.textLabel.text = NSLocalizedString(@"Schedule a meeting",nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexPath.row == firstIndex) {
|
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+firstIndex) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1884,27 +1939,32 @@ void on_chat_room_conference_alert(LinphoneChatRoom *cr, const LinphoneEventLog
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isEncrypted && indexPath.row == 3+firstIndex) || (!isEncrypted && indexPath.row == 1+firstIndex)) {
|
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+firstIndex) || (!isEncrypted && indexPath.row == 2+firstIndex)) {
|
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+firstIndex)||(canEphemeral && indexPath.row == 5+firstIndex)))
|
if ((isEncrypted && ((!canEphemeral && indexPath.row == 4+firstIndex)||(canEphemeral && indexPath.row == 5+firstIndex)))
|
||||||
|| (!isEncrypted && indexPath.row == 3+firstIndex)) {
|
|| (!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 {
|
||||||
|
|
@ -2213,6 +2273,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 {
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,5 @@
|
||||||
|
|
||||||
- (void)loadData;
|
- (void)loadData;
|
||||||
- (void)markCellAsRead:(LinphoneChatRoom *)chatRoom;
|
- (void)markCellAsRead:(LinphoneChatRoom *)chatRoom;
|
||||||
|
- (void)updateEventEntry:(LinphoneChatMessage *)msg;
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
#import "ChatsListTableView.h"
|
#import "ChatsListTableView.h"
|
||||||
#import "UIChatCell.h"
|
#import "UIChatCell.h"
|
||||||
#import "FileTransferDelegate.h"
|
#import "FileTransferDelegate.h"
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
#import "linphone/linphonecore.h"
|
#import "linphone/linphonecore.h"
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
#import "Utils.h"
|
#import "Utils.h"
|
||||||
|
|
@ -41,6 +41,11 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
bctbx_list_free(_data);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - ViewController Functions
|
#pragma mark - ViewController Functions
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
|
@ -48,15 +53,53 @@
|
||||||
self.tableView.accessibilityIdentifier = @"Chat list";
|
self.tableView.accessibilityIdentifier = @"Chat list";
|
||||||
[self loadData];
|
[self loadData];
|
||||||
_chatRooms = NULL;
|
_chatRooms = NULL;
|
||||||
|
|
||||||
|
NSDictionary* userInfo;
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector: @selector(receivePresenceNotification:)
|
||||||
|
name: @"LinphoneFriendPresenceUpdate"
|
||||||
|
object: userInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) receivePresenceNotification:(NSNotification*)notification
|
||||||
|
{
|
||||||
|
if ([notification.name isEqualToString:@"LinphoneFriendPresenceUpdate"])
|
||||||
|
{
|
||||||
|
NSDictionary* userInfo = notification.userInfo;
|
||||||
|
NSString* friend = (NSString*)userInfo[@"friend"];
|
||||||
|
|
||||||
|
for (int i = 0; i < bctbx_list_size(_data); i++)
|
||||||
|
{
|
||||||
|
LinphoneChatRoom *chatRoom = (LinphoneChatRoom *)bctbx_list_nth_data(_data, i);
|
||||||
|
|
||||||
|
bctbx_list_t *participants = linphone_chat_room_get_participants(chatRoom);
|
||||||
|
if (linphone_chat_room_get_nb_participants(chatRoom) == 1) {
|
||||||
|
LinphoneParticipant *firstParticipant = participants ? (LinphoneParticipant *)participants->data : NULL;
|
||||||
|
|
||||||
|
char *curi = linphone_address_as_string_uri_only(linphone_participant_get_address(firstParticipant));
|
||||||
|
NSString *uri = [NSString stringWithUTF8String:curi];
|
||||||
|
|
||||||
|
LinphoneChatRoomCapabilitiesMask capabilities = linphone_chat_room_get_capabilities(chatRoom);
|
||||||
|
bool oneToOne = capabilities & LinphoneChatRoomCapabilitiesOneToOne;
|
||||||
|
if(oneToOne && [uri isEqual:friend]){
|
||||||
|
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:i inSection:0];
|
||||||
|
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
|
||||||
|
[self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationFade];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidAppear:(BOOL)animated {
|
- (void)viewDidAppear:(BOOL)animated {
|
||||||
[super viewDidAppear:animated];
|
[super viewDidAppear:animated];
|
||||||
// we cannot do that in viewWillAppear because we will change view while previous transition
|
// we cannot do that in viewWillAppear because we will change view while previous transition
|
||||||
// was not finished, leading to "[CALayer retain]: message sent to deallocated instance" error msg
|
// was not finished, leading to "[CALayer retain]: message sent to deallocated instance" error msg
|
||||||
|
/*
|
||||||
if (IPAD && [self totalNumberOfItems] > 0) {
|
if (IPAD && [self totalNumberOfItems] > 0) {
|
||||||
[PhoneMainView.instance changeCurrentView:ChatConversationView.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:ChatConversationView.compositeViewDescription];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
|
@ -72,6 +115,9 @@
|
||||||
}
|
}
|
||||||
_chatRooms = _chatRooms->next;
|
_chatRooms = _chatRooms->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"LinphoneFriendPresenceUpdate" object:nil];
|
||||||
|
[AvatarBridge removeAllObserver];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)layoutSubviews {
|
- (void)layoutSubviews {
|
||||||
|
|
@ -114,6 +160,7 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
|
||||||
_data = [self sortChatRooms];
|
_data = [self sortChatRooms];
|
||||||
[super loadData];
|
[super loadData];
|
||||||
|
|
||||||
|
/*
|
||||||
if (IPAD) {
|
if (IPAD) {
|
||||||
int idx = bctbx_list_index(_data, VIEW(ChatConversationView).chatRoom);
|
int idx = bctbx_list_index(_data, VIEW(ChatConversationView).chatRoom);
|
||||||
// if conversation view is using a chatroom that does not exist anymore, update it
|
// if conversation view is using a chatroom that does not exist anymore, update it
|
||||||
|
|
@ -131,15 +178,28 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
|
||||||
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateEventEntry:(LinphoneChatMessage *)msg {
|
||||||
|
int idx = bctbx_list_index(_data, linphone_chat_message_get_chat_room(msg));
|
||||||
|
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
|
||||||
|
if (idx < 0) {
|
||||||
|
LOGW(@"event entry doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:FALSE];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)markCellAsRead:(LinphoneChatRoom *)chatRoom {
|
- (void)markCellAsRead:(LinphoneChatRoom *)chatRoom {
|
||||||
int idx = bctbx_list_index(_data, VIEW(ChatConversationView).chatRoom);
|
int idx = bctbx_list_index(_data, VIEW(ChatConversationView).chatRoom);
|
||||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
|
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
|
||||||
|
/*
|
||||||
if (IPAD) {
|
if (IPAD) {
|
||||||
UIChatCell *cell = (UIChatCell *)[self.tableView cellForRowAtIndexPath:indexPath];
|
UIChatCell *cell = (UIChatCell *)[self.tableView cellForRowAtIndexPath:indexPath];
|
||||||
[cell updateUnreadBadge];
|
[cell updateUnreadBadge];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - UITableViewDataSource Functions
|
#pragma mark - UITableViewDataSource Functions
|
||||||
|
|
@ -164,7 +224,7 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
|
||||||
|
|
||||||
[cell setChatRoom:(LinphoneChatRoom *)bctbx_list_nth_data(_data, (int)[indexPath row])];
|
[cell setChatRoom:(LinphoneChatRoom *)bctbx_list_nth_data(_data, (int)[indexPath row])];
|
||||||
[super accessoryForCell:cell atPath:indexPath];
|
[super accessoryForCell:cell atPath:indexPath];
|
||||||
BOOL forwardMode = VIEW(ChatConversationView).pendingForwardMessage != nil;
|
BOOL forwardMode = VIEW(ChatConversationViewSwift).pendingForwardMessage != nil;
|
||||||
cell.forwardIcon.hidden = !forwardMode;
|
cell.forwardIcon.hidden = !forwardMode;
|
||||||
if (forwardMode) {
|
if (forwardMode) {
|
||||||
cell.ephemeral.hidden = true;
|
cell.ephemeral.hidden = true;
|
||||||
|
|
@ -186,12 +246,12 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LinphoneChatRoom *chatRoom = (LinphoneChatRoom *)bctbx_list_nth_data(_data, (int)[indexPath row]);
|
LinphoneChatRoom *chatRoom = (LinphoneChatRoom *)bctbx_list_nth_data(_data, (int)[indexPath row]);
|
||||||
[PhoneMainView.instance goToChatRoom:chatRoom];
|
[PhoneMainView.instance goToChatRoomSwift:chatRoom];
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
|
@ -232,7 +292,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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,10 @@
|
||||||
|
|
||||||
- (IBAction)onAddGroupChatClick:(id)event;
|
- (IBAction)onAddGroupChatClick:(id)event;
|
||||||
- (IBAction)onAddClick:(id)event;
|
- (IBAction)onAddClick:(id)event;
|
||||||
|
- (IBAction)onChatRoomSwiftClick:(id)event;
|
||||||
- (IBAction)onEditionChangeClick:(id)sender;
|
- (IBAction)onEditionChangeClick:(id)sender;
|
||||||
- (IBAction)onDeleteClick:(id)sender;
|
- (IBAction)onDeleteClick:(id)sender;
|
||||||
|
|
||||||
|
-(void) mediaSharing;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
|
|
||||||
#import "ChatConversationCreateView.h"
|
#import "ChatConversationCreateView.h"
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
@implementation ChatsListView
|
@implementation ChatsListView
|
||||||
|
|
||||||
#pragma mark - ViewController Functions
|
#pragma mark - ViewController Functions
|
||||||
|
|
@ -39,6 +40,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 +59,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(ChatConversationViewSwift).sharingMedia = TRUE;
|
||||||
|
|
||||||
|
if(VIEW(ChatConversationViewSwift).sharingMedia == false){
|
||||||
|
forwardMode = VIEW(ChatConversationViewSwift).pendingForwardMessage != nil;
|
||||||
|
}else{
|
||||||
|
forwardMode = VIEW(ChatConversationViewSwift).sharingMedia != false;
|
||||||
|
}
|
||||||
_tableController.editButton.hidden = forwardMode;
|
_tableController.editButton.hidden = forwardMode;
|
||||||
_forwardTitle.text = NSLocalizedString(@"Select a discussion or create a new one",nil);
|
if(VIEW(ChatConversationViewSwift).sharingMedia == false){
|
||||||
|
_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];
|
||||||
|
|
@ -128,14 +156,18 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
- (IBAction)onAddGroupChatClick:(id)event {
|
- (IBAction)onAddGroupChatClick:(id)event {
|
||||||
[self newChatCreate:TRUE];
|
[self newChatCreate:TRUE];
|
||||||
if (IPAD)
|
//if (IPAD)
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneChatCreateViewChange object:VIEW(ChatConversationCreateView) userInfo:nil];
|
//[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneChatCreateViewChange object:VIEW(ChatConversationCreateView) userInfo:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)onChatRoomSwiftClick:(id)event {
|
||||||
|
[PhoneMainView.instance changeCurrentView:ChatConversationViewSwift.compositeViewDescription];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onAddClick:(id)event {
|
- (IBAction)onAddClick:(id)event {
|
||||||
[self newChatCreate:FALSE];
|
[self newChatCreate:FALSE];
|
||||||
if (IPAD)
|
//if (IPAD)
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneChatCreateViewChange object:VIEW(ChatConversationCreateView) userInfo:nil];
|
//[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneChatCreateViewChange object:VIEW(ChatConversationCreateView) userInfo:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onEditionChangeClick:(id)sender {
|
- (IBAction)onEditionChangeClick:(id)sender {
|
||||||
|
|
@ -173,8 +205,16 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onCancelForwardClicked:(id)sender {
|
- (IBAction)onCancelForwardClicked:(id)sender {
|
||||||
VIEW(ChatConversationView).pendingForwardMessage = nil;
|
VIEW(ChatConversationViewSwift).sharingMedia = false;
|
||||||
|
VIEW(ChatConversationViewSwift).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
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,12 @@
|
||||||
@property(nonatomic, retain) NSString *identifier;
|
@property(nonatomic, retain) NSString *identifier;
|
||||||
@property(nonatomic, retain) NSString *firstName;
|
@property(nonatomic, retain) NSString *firstName;
|
||||||
@property(nonatomic, retain) NSString *lastName;
|
@property(nonatomic, retain) NSString *lastName;
|
||||||
|
@property(nonatomic, retain) NSString *organizationName;
|
||||||
@property(nonatomic, retain) NSString *displayName;
|
@property(nonatomic, retain) NSString *displayName;
|
||||||
@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 +59,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];
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
_identifier = _person.identifier;
|
_identifier = _person.identifier;
|
||||||
_firstName = _person.givenName;
|
_firstName = _person.givenName;
|
||||||
_lastName = _person.familyName;
|
_lastName = _person.familyName;
|
||||||
|
_organizationName = _person.organizationName;
|
||||||
_displayName = [NSString stringWithFormat:@"%@ %@", _firstName, _lastName];
|
_displayName = [NSString stringWithFormat:@"%@ %@", _firstName, _lastName];
|
||||||
for (CNLabeledValue<CNPhoneNumber *> *phoneNumber in _person.phoneNumbers) {
|
for (CNLabeledValue<CNPhoneNumber *> *phoneNumber in _person.phoneNumbers) {
|
||||||
[_phones addObject:phoneNumber.value.stringValue];
|
[_phones addObject:phoneNumber.value.stringValue];
|
||||||
|
|
@ -64,13 +65,17 @@
|
||||||
}
|
}
|
||||||
const char *key = [NSString stringWithFormat:@"ab%@", acncontact.identifier].UTF8String;
|
const char *key = [NSString stringWithFormat:@"ab%@", acncontact.identifier].UTF8String;
|
||||||
// try to find friend associated with that person
|
// try to find friend associated with that person
|
||||||
|
if (_friend){
|
||||||
|
linphone_friend_unref(_friend);
|
||||||
|
_friend = nil;
|
||||||
|
}
|
||||||
_friend = linphone_friend_list_find_friend_by_ref_key(linphone_core_get_default_friend_list(LC), key);
|
_friend = linphone_friend_list_find_friend_by_ref_key(linphone_core_get_default_friend_list(LC), key);
|
||||||
if (!_friend) {
|
if (!_friend) {
|
||||||
_friend = linphone_friend_ref(linphone_core_create_friend(LC));
|
_friend = linphone_core_create_friend(LC);
|
||||||
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);
|
||||||
|
|
@ -80,14 +85,15 @@
|
||||||
for (NSString *phone in _phones) {
|
for (NSString *phone in _phones) {
|
||||||
linphone_friend_add_phone_number(_friend, phone.UTF8String);
|
linphone_friend_add_phone_number(_friend, phone.UTF8String);
|
||||||
}
|
}
|
||||||
|
if (_organizationName) {
|
||||||
|
linphone_friend_set_organization(_friend, [_organizationName UTF8String]);
|
||||||
|
}
|
||||||
if (_friend) {
|
if (_friend) {
|
||||||
linphone_friend_enable_subscribes(_friend, FALSE);
|
linphone_friend_enable_subscribes(_friend, FALSE);
|
||||||
linphone_friend_set_inc_subscribe_policy(_friend, LinphoneSPDeny);
|
linphone_friend_set_inc_subscribe_policy(_friend, LinphoneSPDeny);
|
||||||
linphone_core_add_friend(LC, _friend);
|
linphone_core_add_friend(LC, _friend);
|
||||||
}
|
}
|
||||||
}
|
}else linphone_friend_ref(_friend);
|
||||||
linphone_friend_ref(_friend);
|
|
||||||
|
|
||||||
} else if (_friend) {
|
} else if (_friend) {
|
||||||
[self loadFriend];
|
[self loadFriend];
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -287,7 +293,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 +376,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;
|
||||||
|
|
||||||
|
|
@ -461,11 +467,11 @@
|
||||||
// try to find friend associated with that person
|
// try to find friend associated with that person
|
||||||
_friend = linphone_friend_list_find_friend_by_ref_key(linphone_core_get_default_friend_list(LC), key);
|
_friend = linphone_friend_list_find_friend_by_ref_key(linphone_core_get_default_friend_list(LC), key);
|
||||||
if (!_friend) {
|
if (!_friend) {
|
||||||
_friend = linphone_friend_ref(linphone_core_create_friend(LC));
|
_friend = linphone_core_create_friend(LC);
|
||||||
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);
|
||||||
|
|
@ -480,12 +486,31 @@
|
||||||
linphone_friend_set_inc_subscribe_policy(_friend, LinphoneSPDeny);
|
linphone_friend_set_inc_subscribe_policy(_friend, LinphoneSPDeny);
|
||||||
linphone_core_add_friend(LC, _friend);
|
linphone_core_add_friend(LC, _friend);
|
||||||
}
|
}
|
||||||
}
|
} else linphone_friend_ref(_friend);
|
||||||
linphone_friend_ref(_friend);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)clearFriend {
|
- (void)clearFriend {
|
||||||
|
if (_friend) linphone_friend_unref(_friend);
|
||||||
_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
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ typedef enum _ContactSections {
|
||||||
ContactSections_None = 0, // first section is empty because we cannot set header for first section
|
ContactSections_None = 0, // first section is empty because we cannot set header for first section
|
||||||
ContactSections_FirstName,
|
ContactSections_FirstName,
|
||||||
ContactSections_LastName,
|
ContactSections_LastName,
|
||||||
|
ContactSections_Organization,
|
||||||
ContactSections_Sip,
|
ContactSections_Sip,
|
||||||
ContactSections_Number,
|
ContactSections_Number,
|
||||||
ContactSections_Email,
|
ContactSections_Email,
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isValid {
|
- (BOOL)isValid {
|
||||||
BOOL hasName = (_contact.firstName.length + _contact.lastName.length > 0);
|
BOOL hasName = (_contact.firstName.length + _contact.lastName.length + _contact.organizationName.length > 0);
|
||||||
BOOL hasAddr =
|
BOOL hasAddr =
|
||||||
(_contact.phones.count + _contact.sipAddresses.count) > 0;
|
(_contact.phones.count + _contact.sipAddresses.count) > 0;
|
||||||
return hasName && hasAddr;
|
return hasName && hasAddr;
|
||||||
|
|
@ -156,19 +156,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||||
if (section == ContactSections_FirstName || section == ContactSections_LastName) {
|
if (section == ContactSections_FirstName || section == ContactSections_LastName || section == ContactSections_Organization) {
|
||||||
/*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 {
|
||||||
|
|
@ -192,6 +192,9 @@
|
||||||
} else if (indexPath.section == ContactSections_LastName) {
|
} else if (indexPath.section == ContactSections_LastName) {
|
||||||
value = _contact.lastName;
|
value = _contact.lastName;
|
||||||
[cell hideDeleteButton:YES];
|
[cell hideDeleteButton:YES];
|
||||||
|
} else if (indexPath.section == ContactSections_Organization) {
|
||||||
|
value = _contact.organizationName;
|
||||||
|
[cell hideDeleteButton:YES];
|
||||||
} else if ([indexPath section] == ContactSections_Number) {
|
} else if ([indexPath section] == ContactSections_Number) {
|
||||||
value = _contact.phones[indexPath.row];
|
value = _contact.phones[indexPath.row];
|
||||||
[cell.editTextfield setKeyboardType:UIKeyboardTypePhonePad];
|
[cell.editTextfield setKeyboardType:UIKeyboardTypePhonePad];
|
||||||
|
|
@ -200,7 +203,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]];
|
||||||
|
|
@ -279,11 +282,14 @@
|
||||||
} else if (section == ContactSections_LastName && self.tableView.isEditing) {
|
} else if (section == ContactSections_LastName && self.tableView.isEditing) {
|
||||||
text = NSLocalizedString(@"Last name", nil);
|
text = NSLocalizedString(@"Last name", nil);
|
||||||
canAddEntry = NO;
|
canAddEntry = NO;
|
||||||
|
} else if (section == ContactSections_Organization && self.tableView.isEditing) {
|
||||||
|
text = NSLocalizedString(@"Organization", nil);
|
||||||
|
canAddEntry = NO;
|
||||||
} else if ([self getSectionData:section].count > 0 || self.tableView.isEditing) {
|
} else if ([self getSectionData:section].count > 0 || self.tableView.isEditing) {
|
||||||
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 &&
|
||||||
|
|
@ -358,7 +364,7 @@
|
||||||
|
|
||||||
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
|
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
|
||||||
if (section == 0 ||
|
if (section == 0 ||
|
||||||
(!self.tableView.isEditing && (section == ContactSections_FirstName || section == ContactSections_LastName))) {
|
(!self.tableView.isEditing && (section == ContactSections_FirstName || section == ContactSections_LastName || section == ContactSections_LastName))) {
|
||||||
return 1e-5;
|
return 1e-5;
|
||||||
}
|
}
|
||||||
return [self tableView:tableView viewForHeaderInSection:section].frame.size.height;
|
return [self tableView:tableView viewForHeaderInSection:section].frame.size.height;
|
||||||
|
|
@ -390,6 +396,9 @@
|
||||||
case ContactSections_LastName:
|
case ContactSections_LastName:
|
||||||
_contact.lastName = value;
|
_contact.lastName = value;
|
||||||
break;
|
break;
|
||||||
|
case ContactSections_Organization:
|
||||||
|
_contact.organizationName = value;
|
||||||
|
break;
|
||||||
case ContactSections_Sip:
|
case ContactSections_Sip:
|
||||||
[_contact setSipAddress:value atIndex:path.row];
|
[_contact setSipAddress:value atIndex:path.row];
|
||||||
value = _contact.sipAddresses[path.row]; // in case of reformatting
|
value = _contact.sipAddresses[path.row]; // in case of reformatting
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,9 @@
|
||||||
@property(nonatomic, strong) IBOutlet UIToggleButton *editButton;
|
@property(nonatomic, strong) IBOutlet UIToggleButton *editButton;
|
||||||
@property(nonatomic, strong) IBOutlet UIButton *backButton;
|
@property(nonatomic, strong) IBOutlet UIButton *backButton;
|
||||||
@property(nonatomic, strong) IBOutlet UIButton *cancelButton;
|
@property(nonatomic, strong) IBOutlet UIButton *cancelButton;
|
||||||
@property(weak, nonatomic) IBOutlet UIRoundedImageView *avatarImage;
|
@property(weak, nonatomic) IBOutlet UIImageView *avatarImage;
|
||||||
@property(weak, nonatomic) IBOutlet UILabel *nameLabel;
|
@property(weak, nonatomic) IBOutlet UILabel *nameLabel;
|
||||||
|
@property(weak, nonatomic) IBOutlet UILabel *organizationLabel;
|
||||||
@property(weak, nonatomic) IBOutlet UIToggleButton *deleteButton;
|
@property(weak, nonatomic) IBOutlet UIToggleButton *deleteButton;
|
||||||
@property(weak, nonatomic) IBOutlet UIScrollView *contentView;
|
@property(weak, nonatomic) IBOutlet UIScrollView *contentView;
|
||||||
@property(weak, nonatomic) IBOutlet UILabel *emptyLabel;
|
@property(weak, nonatomic) IBOutlet UILabel *emptyLabel;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#import "ContactDetailsView.h"
|
#import "ContactDetailsView.h"
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
#import "UIContactDetailsCell.h"
|
#import "UIContactDetailsCell.h"
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
@implementation ContactDetailsView
|
@implementation ContactDetailsView
|
||||||
|
|
||||||
|
|
@ -63,7 +64,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGI(@"Reset data to contact %p", _contact);
|
LOGI(@"Reset data to contact %p", _contact);
|
||||||
[_avatarImage setImage:[FastAddressBook imageForContact:_contact] bordered:NO withRoundedRadius:YES];
|
[_avatarImage setImage:[FastAddressBook imageForContact:_contact]];
|
||||||
[_tableController setContact:_contact];
|
[_tableController setContact:_contact];
|
||||||
_emptyLabel.hidden = YES;
|
_emptyLabel.hidden = YES;
|
||||||
_avatarImage.hidden = !_emptyLabel.hidden;
|
_avatarImage.hidden = !_emptyLabel.hidden;
|
||||||
|
|
@ -91,24 +92,25 @@
|
||||||
[PhoneMainView.instance popCurrentView];
|
[PhoneMainView.instance popCurrentView];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PhoneMainView.instance.currentName = _contact.displayName;
|
PhoneMainView.instance.currentName = _contact.displayName;
|
||||||
_nameLabel.text = PhoneMainView.instance.currentName;
|
_nameLabel.text = PhoneMainView.instance.currentName;
|
||||||
|
_organizationLabel.text = _contact.organizationName;
|
||||||
// fix no sipaddresses in contact.friend
|
|
||||||
const MSList *sips = linphone_friend_get_addresses(_contact.friend);
|
// fix no sipaddresses in contact.friend
|
||||||
while (sips) {
|
const MSList *sips = linphone_friend_get_addresses(_contact.friend);
|
||||||
linphone_friend_remove_address(_contact.friend, sips->data);
|
while (sips) {
|
||||||
sips = sips->next;
|
linphone_friend_remove_address(_contact.friend, sips->data);
|
||||||
}
|
sips = sips->next;
|
||||||
|
}
|
||||||
for (NSString *sipAddr in _contact.sipAddresses) {
|
|
||||||
LinphoneAddress *addr = linphone_core_interpret_url(LC, sipAddr.UTF8String);
|
for (NSString *sipAddr in _contact.sipAddresses) {
|
||||||
if (addr) {
|
LinphoneAddress *addr = linphone_core_interpret_url_2(LC, sipAddr.UTF8String, true);
|
||||||
linphone_friend_add_address(_contact.friend, addr);
|
if (addr) {
|
||||||
linphone_address_destroy(addr);
|
linphone_friend_add_address(_contact.friend, addr);
|
||||||
}
|
linphone_address_destroy(addr);
|
||||||
}
|
}
|
||||||
[LinphoneManager.instance.fastAddressBook saveContact:_contact];
|
}
|
||||||
|
[LinphoneManager.instance.fastAddressBook saveContact:_contact];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)selectContact:(Contact *)acontact andReload:(BOOL)reload {
|
- (void)selectContact:(Contact *)acontact andReload:(BOOL)reload {
|
||||||
|
|
@ -119,11 +121,12 @@
|
||||||
_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]];
|
||||||
[ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
|
[ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
|
||||||
|
_organizationLabel.text = _contact.organizationName;
|
||||||
[_tableController setContact:_contact];
|
[_tableController setContact:_contact];
|
||||||
|
|
||||||
if (reload) {
|
if (reload) {
|
||||||
|
|
@ -146,7 +149,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 +287,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 +302,21 @@
|
||||||
[_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];
|
||||||
|
|
||||||
|
NSDictionary* userInfo;
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector: @selector(receivePresenceNotification:)
|
||||||
|
name: @"LinphoneFriendPresenceUpdate"
|
||||||
|
object: userInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) receivePresenceNotification:(NSNotification*)notification
|
||||||
|
{
|
||||||
|
if ([notification.name isEqualToString:@"LinphoneFriendPresenceUpdate"])
|
||||||
|
{
|
||||||
|
[self resetData];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)deviceOrientationDidChange:(NSNotification*)notif {
|
- (void)deviceOrientationDidChange:(NSNotification*)notif {
|
||||||
|
|
@ -310,9 +331,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self.contact != NULL && self.contact.createdFromLdapOrProvisioning) {
|
||||||
|
_editButton.hidden = TRUE;
|
||||||
|
_deleteButton.hidden = TRUE;
|
||||||
|
}
|
||||||
|
_nameLabel.hidden = self.tableController.isEditing;
|
||||||
|
_organizationLabel.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 {
|
||||||
|
|
@ -343,6 +369,9 @@
|
||||||
if (rm) {
|
if (rm) {
|
||||||
[LinphoneManager.instance.fastAddressBook deleteContact:_contact];
|
[LinphoneManager.instance.fastAddressBook deleteContact:_contact];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"LinphoneFriendPresenceUpdate" object:nil];
|
||||||
|
[AvatarBridge removeAllObserver];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - UICompositeViewDelegate Functions
|
#pragma mark - UICompositeViewDelegate Functions
|
||||||
|
|
@ -397,7 +426,9 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
_cancelButton.hidden = !editing;
|
_cancelButton.hidden = !editing;
|
||||||
_backButton.hidden = editing;
|
_backButton.hidden = editing;
|
||||||
_nameLabel.hidden = editing;
|
_nameLabel.hidden = editing;
|
||||||
|
_organizationLabel.hidden = editing;
|
||||||
[ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
|
[ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
|
||||||
|
_organizationLabel.text = _contact.organizationName;
|
||||||
|
|
||||||
[self recomputeTableViewSize:editing];
|
[self recomputeTableViewSize:editing];
|
||||||
|
|
||||||
|
|
@ -408,10 +439,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 = _organizationLabel.frame.origin.y + _organizationLabel.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;
|
||||||
|
|
@ -442,7 +474,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
_contact.firstName = _tmpContact.firstName.copy;
|
_contact.firstName = _tmpContact.firstName.copy;
|
||||||
_contact.lastName = _tmpContact.lastName.copy;
|
_contact.lastName = _tmpContact.lastName.copy;
|
||||||
_contact.avatar = _tmpContact.avatar.copy;
|
_contact.avatar = _tmpContact.avatar.copy;
|
||||||
[_avatarImage setImage:[FastAddressBook imageForContact:_contact] bordered:NO withRoundedRadius:YES];
|
[_avatarImage setImage:[FastAddressBook imageForContact:_contact]];
|
||||||
|
|
||||||
while (_contact.sipAddresses.count > 0) {
|
while (_contact.sipAddresses.count > 0) {
|
||||||
[_contact removeSipAddressAtIndex:0];
|
[_contact removeSipAddressAtIndex:0];
|
||||||
|
|
@ -514,11 +546,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 +620,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;
|
||||||
}
|
}
|
||||||
|
|
@ -619,7 +651,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
[_contact setAvatar:image];
|
[_contact setAvatar:image];
|
||||||
|
|
||||||
[_avatarImage setImage:[FastAddressBook imageForContact:_contact] bordered:NO withRoundedRadius:YES];
|
[_avatarImage setImage:[FastAddressBook imageForContact:_contact]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)imagePickerDelegateVideo:(NSURL*)url info:(NSDictionary *)info {
|
- (void)imagePickerDelegateVideo:(NSURL*)url info:(NSDictionary *)info {
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,60 @@
|
||||||
[view setContact:nil];
|
[view setContact:nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
NSDictionary* userInfo;
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector: @selector(receivePresenceNotification:)
|
||||||
|
name: @"LinphoneFriendPresenceUpdate"
|
||||||
|
object: userInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)viewWillDisappear:(BOOL)animated{
|
||||||
|
[super viewWillDisappear:animated];
|
||||||
|
[AvatarBridge removeAllObserver];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)viewDidDisappear:(BOOL)animated{
|
||||||
|
[super viewDidDisappear:animated];
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"LinphoneFriendPresenceUpdate" object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) receivePresenceNotification:(NSNotification*)notification
|
||||||
|
{
|
||||||
|
if ([notification.name isEqualToString:@"LinphoneFriendPresenceUpdate"])
|
||||||
|
{
|
||||||
|
NSDictionary* userInfo = notification.userInfo;
|
||||||
|
NSString* friend = (NSString*)userInfo[@"friend"];
|
||||||
|
|
||||||
|
NSArray<NSIndexPath *> *indexPathsVisible = self.tableView.indexPathsForVisibleRows;
|
||||||
|
|
||||||
|
for (int i = 0; i < indexPathsVisible.count; i++)
|
||||||
|
{
|
||||||
|
NSMutableArray *subAr = [addressBookMap objectForKey:[addressBookMap keyAtIndex:indexPathsVisible[i].section]];
|
||||||
|
Contact *contact = subAr[indexPathsVisible[i].row];
|
||||||
|
|
||||||
|
if (contact.sipAddresses.count > 0){
|
||||||
|
for (NSString *sip in contact.sipAddresses) {
|
||||||
|
NSString *uri = [@"sip:" stringByAppendingString:sip];
|
||||||
|
|
||||||
|
if([uri isEqual:friend]){
|
||||||
|
NSIndexPath* indexPath = indexPathsVisible[i];
|
||||||
|
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
|
||||||
|
[self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationFade];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if (contact.phones.count > 0){
|
||||||
|
for (NSString *phone in contact.phones) {
|
||||||
|
NSString *uri = phone;
|
||||||
|
|
||||||
|
if([uri isEqual:friend]){
|
||||||
|
NSIndexPath* indexPath = indexPathsVisible[i];
|
||||||
|
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
|
||||||
|
[self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationFade];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init {
|
- (id)init {
|
||||||
|
|
@ -231,7 +285,7 @@ static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) {
|
||||||
|
|
||||||
// Cached avatar
|
// Cached avatar
|
||||||
UIImage *image = [FastAddressBook imageForContact:contact];
|
UIImage *image = [FastAddressBook imageForContact:contact];
|
||||||
[cell.avatarImage setImage:image bordered:NO withRoundedRadius:YES];
|
[cell.avatarImage setImage:image];
|
||||||
[cell setContact:contact];
|
[cell setContact:contact];
|
||||||
[super accessoryForCell:cell atPath:indexPath];
|
[super accessoryForCell:cell atPath:indexPath];
|
||||||
cell.contentView.userInteractionEnabled = false;
|
cell.contentView.userInteractionEnabled = false;
|
||||||
|
|
|
||||||
|
|
@ -50,14 +50,17 @@ typedef enum _ContactSelectionMode { ContactSelectionModeNone, ContactSelectionM
|
||||||
|
|
||||||
@property(strong, nonatomic) IBOutlet ContactsListTableView *tableController;
|
@property(strong, nonatomic) IBOutlet ContactsListTableView *tableController;
|
||||||
@property(strong, nonatomic) IBOutlet UIView *topBar;
|
@property(strong, nonatomic) IBOutlet UIView *topBar;
|
||||||
|
@property(strong, nonatomic) IBOutlet UIView *switchView;
|
||||||
@property(nonatomic, strong) IBOutlet UIButton *allButton;
|
@property(nonatomic, strong) IBOutlet UIButton *allButton;
|
||||||
@property(nonatomic, strong) IBOutlet UIButton *linphoneButton;
|
@property(nonatomic, strong) IBOutlet UIButton *linphoneButton;
|
||||||
@property(nonatomic, strong) IBOutlet UIButton *addButton;
|
@property(nonatomic, strong) IBOutlet UIButton *addButton;
|
||||||
|
@property(nonatomic, strong) IBOutlet UIButton *deleteButton;
|
||||||
@property(strong, nonatomic) IBOutlet UISearchBar *searchBar;
|
@property(strong, nonatomic) IBOutlet UISearchBar *searchBar;
|
||||||
@property(weak, nonatomic) IBOutlet UIImageView *selectedButtonImage;
|
@property(weak, nonatomic) IBOutlet UIImageView *selectedButtonImage;
|
||||||
@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;
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ static BOOL addAddressFromOthers = FALSE;
|
||||||
@synthesize allButton;
|
@synthesize allButton;
|
||||||
@synthesize linphoneButton;
|
@synthesize linphoneButton;
|
||||||
@synthesize addButton;
|
@synthesize addButton;
|
||||||
|
@synthesize deleteButton;
|
||||||
@synthesize topBar;
|
@synthesize topBar;
|
||||||
|
|
||||||
typedef enum { ContactsAll, ContactsLinphone, ContactsMAX } ContactsCategory;
|
typedef enum { ContactsAll, ContactsLinphone, ContactsMAX } ContactsCategory;
|
||||||
|
|
@ -96,7 +97,16 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
if (![[PhoneMainView.instance getPreviousViewName] isEqualToString:@"ContactDetailsView"]) {
|
if (![[PhoneMainView.instance getPreviousViewName] isEqualToString:@"ContactDetailsView"]) {
|
||||||
_searchBar.text = @"";
|
_searchBar.text = @"";
|
||||||
}
|
}
|
||||||
[self changeView:ContactsAll];
|
|
||||||
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"only_show_sip_contacts_list"]) {
|
||||||
|
_switchView.hidden = true;
|
||||||
|
[self changeView:ContactsLinphone];
|
||||||
|
} else if ([LinphoneManager.instance lpConfigBoolForKey:@"hide_sip_contacts_list"]){
|
||||||
|
_switchView.hidden = true;
|
||||||
|
[self changeView:ContactsAll];
|
||||||
|
} else {
|
||||||
|
[self changeView:ContactsAll];
|
||||||
|
}
|
||||||
|
|
||||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
|
||||||
initWithTarget:self
|
initWithTarget:self
|
||||||
|
|
@ -142,6 +152,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 +169,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 +247,11 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)refreshButtons {
|
- (void)refreshButtons {
|
||||||
[addButton setHidden:FALSE];
|
[addButton setHidden:![LinphoneManager.instance lpConfigBoolForKey:@"enable_native_address_book"] || [LinphoneManager.instance lpConfigBoolForKey:@"read_only_native_address_book"]];
|
||||||
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"read_only_native_address_book"]) {
|
||||||
|
addButton.hidden = true;
|
||||||
|
deleteButton.hidden = true;
|
||||||
|
}
|
||||||
[self changeView:[ContactSelection getSipFilterEnabled] ? ContactsLinphone : ContactsAll];
|
[self changeView:[ContactSelection getSipFilterEnabled] ? ContactsLinphone : ContactsAll];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,6 +276,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 +298,13 @@ 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;
|
||||||
|
}
|
||||||
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"read_only_native_address_book"]) {
|
||||||
|
addButton.hidden = true;
|
||||||
|
deleteButton.hidden = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
|
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
|
||||||
|
|
@ -292,6 +329,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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
#pragma mark - Action Functions
|
#pragma mark - Action Functions
|
||||||
- (IBAction)onBackClick:(id)sender {
|
- (IBAction)onBackClick:(id)sender {
|
||||||
ChatConversationView *view = VIEW(ChatConversationView);
|
ChatConversationViewSwift *view = VIEW(ChatConversationViewSwift);
|
||||||
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -277,16 +285,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
- (BOOL)displayDebugPopup:(NSString *)address {
|
- (BOOL)displayDebugPopup:(NSString *)address {
|
||||||
LinphoneManager *mgr = LinphoneManager.instance;
|
LinphoneManager *mgr = LinphoneManager.instance;
|
||||||
NSString *debugAddress = [mgr lpConfigStringForKey:@"debug_popup_magic" withDefault:@""];
|
NSString *debugAddress = [mgr lpConfigStringForKey:@"debug_popup_magic" withDefault:@""];
|
||||||
if (![debugAddress isEqualToString:@""] && [address isEqualToString:debugAddress]) {
|
if ((![debugAddress isEqualToString:@""] && [address isEqualToString:debugAddress]) || [_addressField.text isEqual: @"#1234#"]) {
|
||||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Debug", nil)
|
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Debug", nil)
|
||||||
message:NSLocalizedString(@"Choose an action", nil)
|
message:NSLocalizedString(@"Choose an action", nil)
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|
||||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil)
|
|
||||||
style:UIAlertActionStyleDefault
|
|
||||||
handler:^(UIAlertAction * action) {}];
|
|
||||||
|
|
||||||
[errView addAction:defaultAction];
|
|
||||||
|
|
||||||
int debugLevel = [LinphoneManager.instance lpConfigIntForKey:@"debugenable_preference"];
|
int debugLevel = [LinphoneManager.instance lpConfigIntForKey:@"debugenable_preference"];
|
||||||
BOOL debugEnabled = (debugLevel >= ORTP_DEBUG && debugLevel < ORTP_ERROR);
|
BOOL debugEnabled = (debugLevel >= ORTP_DEBUG && debugLevel < ORTP_ERROR);
|
||||||
|
|
@ -314,31 +316,24 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}];
|
}];
|
||||||
[errView addAction:logAction];
|
[errView addAction:logAction];
|
||||||
|
|
||||||
UIAlertAction* remAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Remove account(s) and self destruct", nil)
|
UIAlertAction* configAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"View config file", nil)
|
||||||
style:UIAlertActionStyleDefault
|
style:UIAlertActionStyleDefault
|
||||||
handler:^(UIAlertAction * action) {
|
handler:^(UIAlertAction * action) {
|
||||||
linphone_core_clear_accounts([LinphoneManager getLc]);
|
TextViewer *view = VIEW(TextViewer);
|
||||||
linphone_core_clear_all_auth_info([LinphoneManager getLc]);
|
LpConfig *conf = LinphoneManager.instance.configDb;
|
||||||
@try {
|
char *config = linphone_config_dump(conf);
|
||||||
[LinphoneManager.instance destroyLinphoneCore];
|
view.textViewer = [NSString stringWithUTF8String: config];
|
||||||
} @catch (NSException *e) {
|
view.textNameViewer = @"";
|
||||||
LOGW(@"Exception while destroying linphone core: %@", e);
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
} @finally {
|
}];
|
||||||
if ([NSFileManager.defaultManager
|
|
||||||
isDeletableFileAtPath:[LinphoneManager preferenceFile:@"linphonerc"]] == YES) {
|
[errView addAction:configAction];
|
||||||
[NSFileManager.defaultManager
|
|
||||||
removeItemAtPath:[LinphoneManager preferenceFile:@"linphonerc"]
|
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil)
|
||||||
error:nil];
|
style:UIAlertActionStyleDefault
|
||||||
}
|
handler:^(UIAlertAction * action) {}];
|
||||||
#ifdef DEBUG
|
|
||||||
[LinphoneManager instanceRelease];
|
[errView addAction:defaultAction];
|
||||||
#endif
|
|
||||||
}
|
|
||||||
[UIApplication sharedApplication].keyWindow.rootViewController = nil;
|
|
||||||
// make the application crash to be sure that user restart it properly
|
|
||||||
LOGF(@"Self-destructing in 3..2..1..0!");
|
|
||||||
}];
|
|
||||||
[errView addAction:remAction];
|
|
||||||
|
|
||||||
[self presentViewController:errView animated:YES completion:nil];
|
[self presentViewController:errView animated:YES completion:nil];
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -393,19 +388,39 @@ 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 ([_addressField.text isEqual: @"#1234#"]) {
|
||||||
|
[self displayDebugPopup:_addressField.text];
|
||||||
_addressField.text = @"";
|
_addressField.text = @"";
|
||||||
}
|
}
|
||||||
|
LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC);
|
||||||
|
if (!(defaultAccount && linphone_account_params_get_audio_video_conference_factory_address(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 {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#import "EphemeralSettingsView.h"
|
#import "EphemeralSettingsView.h"
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
#import "UIDeviceCell.h"
|
#import "UIDeviceCell.h"
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -74,14 +75,14 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
|
|
||||||
#pragma mark - Action Functions
|
#pragma mark - Action Functions
|
||||||
- (IBAction)onBackClick:(id)sender {
|
- (IBAction)onBackClick:(id)sender {
|
||||||
ChatConversationView *view = VIEW(ChatConversationView);
|
ChatConversationViewSwift *view = VIEW(ChatConversationViewSwift);
|
||||||
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (IBAction)onSaveClick:(id)sender {
|
- (IBAction)onSaveClick:(id)sender {
|
||||||
[self setRoomSettingsBasedOnIndex];
|
[self setRoomSettingsBasedOnIndex];
|
||||||
ChatConversationView *view = VIEW(ChatConversationView);
|
ChatConversationViewSwift *view = VIEW(ChatConversationViewSwift);
|
||||||
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
[PhoneMainView.instance popToView:view.compositeViewDescription];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,66 +8,90 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
public extension ChatConversationTableView {
|
extension ChatConversationTableViewSwift {
|
||||||
|
|
||||||
private enum Constants {
|
private enum Constants {
|
||||||
static let trailingValue: CGFloat = 20.0
|
static let trailingValue: CGFloat = 30.0
|
||||||
static let leadingValue: CGFloat = 85.0
|
static let leadingValue: CGFloat = 85.0
|
||||||
static let buttonHeight: CGFloat = 40.0
|
static let buttonHeight: CGFloat = 16.0
|
||||||
static let buttonWidth: CGFloat = 40.0
|
static let buttonWidth: CGFloat = 16.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
tableView.tableFooterView = UIView()
|
tableView.tableFooterView = UIView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
createFloatingButton()
|
createFloatingButton()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
override func viewDidDisappear(_ animated: Bool) {
|
||||||
if let lastCellRowIndex = tableView.indexPathsForVisibleRows?.last?.row {
|
super.viewDidAppear(animated)
|
||||||
if( lastCellRowIndex != self.totalNumberOfItems() - 1) {
|
self.floatingScrollButton?.removeFromSuperview()
|
||||||
self.floatingScrollButton?.isHidden = false
|
self.floatingScrollBackground?.removeFromSuperview()
|
||||||
self.scrollBadge?.isHidden = (self.scrollBadge?.text == nil)
|
|
||||||
} else {
|
|
||||||
self.floatingScrollButton?.isHidden = true
|
|
||||||
self.scrollBadge?.text = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createFloatingButton() {
|
func createFloatingButton() {
|
||||||
self.floatingScrollButton = UIButton(type: .custom)
|
self.floatingScrollButton = UIButton(type: .custom)
|
||||||
|
self.floatingScrollBackground = UIButton(type: .custom)
|
||||||
self.floatingScrollButton?.translatesAutoresizingMaskIntoConstraints = false
|
self.floatingScrollButton?.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
self.floatingScrollBackground?.translatesAutoresizingMaskIntoConstraints = false
|
||||||
constrainFloatingButtonToWindow()
|
constrainFloatingButtonToWindow()
|
||||||
self.floatingScrollButton?.setImage(UIImage(named: "scroll_to_bottom_default"), for: .normal)
|
var imageFloatingScrollButton = UIImage()
|
||||||
self.floatingScrollButton?.addTarget(self, action: #selector(scrollToBottomButtonAction(_:)), for: .touchUpInside)
|
if #available(iOS 13.0, *) {
|
||||||
|
imageFloatingScrollButton = UIImage(named: "scroll_to_bottom_default")!.withTintColor(.darkGray)
|
||||||
|
} else {
|
||||||
|
imageFloatingScrollButton = UIImage(named: "scroll_to_bottom_default")!
|
||||||
|
}
|
||||||
|
self.floatingScrollButton?.setImage(imageFloatingScrollButton, for: .normal)
|
||||||
self.floatingScrollButton?.isHidden = true;
|
self.floatingScrollButton?.isHidden = true;
|
||||||
addBadgeToButon(badge: nil)
|
self.floatingScrollBackground?.backgroundColor = .lightGray
|
||||||
|
self.floatingScrollBackground?.layer.cornerRadius = 25
|
||||||
|
self.floatingScrollBackground?.isHidden = true;
|
||||||
|
|
||||||
|
self.floatingScrollButton?.onClick(action: {
|
||||||
|
self.scrollToBottomButtonAction()
|
||||||
|
})
|
||||||
|
self.floatingScrollBackground?.onClick(action: {
|
||||||
|
self.scrollToBottomButtonAction()
|
||||||
|
})
|
||||||
|
addBadgeToButton(badge: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func constrainFloatingButtonToWindow() {
|
private func constrainFloatingButtonToWindow() {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
guard let keyWindow = UIApplication.shared.keyWindow,
|
guard let keyWindow = self.view,
|
||||||
let floatingButton = self.floatingScrollButton else { return }
|
let floatingButton = self.floatingScrollButton else { return }
|
||||||
|
keyWindow.addSubview(self.floatingScrollBackground!)
|
||||||
keyWindow.addSubview(floatingButton)
|
keyWindow.addSubview(floatingButton)
|
||||||
keyWindow.trailingAnchor.constraint(equalTo: floatingButton.trailingAnchor,
|
keyWindow.trailingAnchor.constraint(equalTo: floatingButton.trailingAnchor, constant: Constants.trailingValue).isActive = true
|
||||||
constant: Constants.trailingValue).isActive = true
|
|
||||||
keyWindow.bottomAnchor.constraint(equalTo: floatingButton.bottomAnchor,
|
floatingButton.bottomAnchor.constraint(equalTo: keyWindow.bottomAnchor, constant: -25).isActive = true
|
||||||
constant: Constants.leadingValue).isActive = true
|
|
||||||
floatingButton.widthAnchor.constraint(equalToConstant:
|
floatingButton.widthAnchor.constraint(equalToConstant:
|
||||||
Constants.buttonWidth).isActive = true
|
Constants.buttonWidth).isActive = true
|
||||||
floatingButton.heightAnchor.constraint(equalToConstant:
|
floatingButton.heightAnchor.constraint(equalToConstant:
|
||||||
Constants.buttonHeight).isActive = true
|
Constants.buttonHeight).isActive = true
|
||||||
|
self.floatingScrollBackground?.centerYAnchor.constraint(equalTo: floatingButton.centerYAnchor).isActive = true
|
||||||
|
self.floatingScrollBackground?.centerXAnchor.constraint(equalTo: floatingButton.centerXAnchor).isActive = true
|
||||||
|
self.floatingScrollBackground!.widthAnchor.constraint(equalToConstant:
|
||||||
|
Constants.buttonHeight*3).isActive = true
|
||||||
|
self.floatingScrollBackground!.heightAnchor.constraint(equalToConstant:
|
||||||
|
Constants.buttonHeight*3).isActive = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction private func scrollToBottomButtonAction(_ sender: Any) {
|
@IBAction private func scrollToBottomButtonAction() {
|
||||||
scroll(toBottom: true)
|
scrollToBottom(animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private func addBadgeToButon(badge: String?) {
|
private func addBadgeToButton(badge: String?) {
|
||||||
self.scrollBadge = UILabel()
|
self.scrollBadge = UILabel()
|
||||||
self.scrollBadge?.text = badge
|
self.scrollBadge?.text = badge
|
||||||
self.scrollBadge?.textColor = UIColor.white
|
self.scrollBadge?.textColor = UIColor.white
|
||||||
|
|
@ -86,8 +110,8 @@ public extension ChatConversationTableView {
|
||||||
vertical = Double(badgeInset.top) - Double(badgeInset.bottom)
|
vertical = Double(badgeInset.top) - Double(badgeInset.bottom)
|
||||||
horizontal = Double(badgeInset.left) - Double(badgeInset.right)
|
horizontal = Double(badgeInset.left) - Double(badgeInset.right)
|
||||||
|
|
||||||
let x = (Double(scrollButton.bounds.size.width) - 10 + horizontal!)
|
let x = (Double(scrollButton.bounds.size.width) + 34 + horizontal!)
|
||||||
let y = -(Double(badgeSize.height) / 2) - 10 + vertical!
|
let y = -(Double(badgeSize.height) / 2) - 38 + vertical!
|
||||||
self.scrollBadge?.frame = CGRect(x: x, y: y, width: width, height: height)
|
self.scrollBadge?.frame = CGRect(x: x, y: y, width: width, height: height)
|
||||||
|
|
||||||
self.scrollBadge!.layer.cornerRadius = self.scrollBadge!.frame.height/2
|
self.scrollBadge!.layer.cornerRadius = self.scrollBadge!.frame.height/2
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
}
|
}
|
||||||
@property(weak, nonatomic) IBOutlet UIButton *backButton;
|
@property(weak, nonatomic) IBOutlet UIButton *backButton;
|
||||||
@property(weak, nonatomic) IBOutlet UILabel *contactLabel;
|
@property(weak, nonatomic) IBOutlet UILabel *contactLabel;
|
||||||
@property(nonatomic, strong) IBOutlet UIRoundedImageView *avatarImage;
|
@property(nonatomic, strong) IBOutlet UIImageView *avatarImage;
|
||||||
@property(nonatomic, strong) IBOutlet UILabel *addressLabel;
|
@property(nonatomic, strong) IBOutlet UILabel *addressLabel;
|
||||||
@property(nonatomic, strong) IBOutlet UIButton *addContactButton;
|
@property(nonatomic, strong) IBOutlet UIButton *addContactButton;
|
||||||
@property(nonatomic, copy, setter=setCallLogId:) NSString *callLogId;
|
@property(nonatomic, copy, setter=setCallLogId:) NSString *callLogId;
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#import "HistoryDetailsView.h"
|
#import "HistoryDetailsView.h"
|
||||||
#import "PhoneMainView.h"
|
#import "PhoneMainView.h"
|
||||||
#import "FastAddressBook.h"
|
#import "FastAddressBook.h"
|
||||||
|
#import "linphoneapp-Swift.h"
|
||||||
|
|
||||||
@implementation HistoryDetailsView
|
@implementation HistoryDetailsView
|
||||||
|
|
||||||
|
|
@ -68,6 +69,12 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
[_headerView addGestureRecognizer:headerTapGesture];
|
[_headerView addGestureRecognizer:headerTapGesture];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
|
||||||
|
_chatButton.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"force_lime_chat_rooms"] || [LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"];
|
||||||
|
[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;
|
||||||
|
|
@ -87,11 +94,27 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
selector: @selector(deviceOrientationDidChange:)
|
selector: @selector(deviceOrientationDidChange:)
|
||||||
name: UIDeviceOrientationDidChangeNotification
|
name: UIDeviceOrientationDidChangeNotification
|
||||||
object: nil];
|
object: nil];
|
||||||
|
|
||||||
|
NSDictionary* userInfo;
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector: @selector(receivePresenceNotification:)
|
||||||
|
name: @"LinphoneFriendPresenceUpdate"
|
||||||
|
object: userInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) receivePresenceNotification:(NSNotification*)notification
|
||||||
|
{
|
||||||
|
if ([notification.name isEqualToString:@"LinphoneFriendPresenceUpdate"])
|
||||||
|
{
|
||||||
|
[self update];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
[super viewWillDisappear:animated];
|
[super viewWillDisappear:animated];
|
||||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"LinphoneFriendPresenceUpdate" object:nil];
|
||||||
|
[AvatarBridge removeAllObserver];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Event Functions
|
#pragma mark - Event Functions
|
||||||
|
|
@ -144,7 +167,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
const LinphoneAddress *addr = linphone_call_log_get_remote_address(callLog);
|
const LinphoneAddress *addr = linphone_call_log_get_remote_address(callLog);
|
||||||
_addContactButton.hidden = ([FastAddressBook getContactWithAddress:addr] != nil);
|
_addContactButton.hidden = ([FastAddressBook getContactWithAddress:addr] != nil);
|
||||||
[ContactDisplay setDisplayNameLabel:_contactLabel forAddress:addr withAddressLabel:_addressLabel];
|
[ContactDisplay setDisplayNameLabel:_contactLabel forAddress:addr withAddressLabel:_addressLabel];
|
||||||
[_avatarImage setImage:[FastAddressBook imageForAddress:addr] bordered:NO withRoundedRadius:YES];
|
[_avatarImage setImage:[FastAddressBook imageForAddress:addr]];
|
||||||
Contact *contact = [FastAddressBook getContactWithAddress:addr];
|
Contact *contact = [FastAddressBook getContactWithAddress:addr];
|
||||||
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;
|
||||||
_linphoneImage.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"] ||
|
_linphoneImage.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"] ||
|
||||||
|
|
@ -158,7 +181,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)shouldHideEncryptedChatView:(BOOL)hasLime {
|
- (void)shouldHideEncryptedChatView:(BOOL)hasLime {
|
||||||
_encryptedChatView.hidden = !hasLime;
|
_encryptedChatView.hidden = !hasLime || [LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"];
|
||||||
CGRect newFrame = _optionsView.frame;
|
CGRect newFrame = _optionsView.frame;
|
||||||
if (!hasLime) {
|
if (!hasLime) {
|
||||||
newFrame.origin.x = _encryptedChatView.frame.size.width * 2/3;
|
newFrame.origin.x = _encryptedChatView.frame.size.width * 2/3;
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,36 @@
|
||||||
name:kLinphoneCoreUpdate
|
name:kLinphoneCoreUpdate
|
||||||
object:nil];
|
object:nil];
|
||||||
[self loadData];
|
[self loadData];
|
||||||
|
NSDictionary* userInfo;
|
||||||
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
|
selector: @selector(receivePresenceNotification:)
|
||||||
|
name: @"LinphoneFriendPresenceUpdate"
|
||||||
|
object: userInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) receivePresenceNotification:(NSNotification*)notification
|
||||||
|
{
|
||||||
|
if ([notification.name isEqualToString:@"LinphoneFriendPresenceUpdate"])
|
||||||
|
{
|
||||||
|
NSDictionary* userInfo = notification.userInfo;
|
||||||
|
NSString* friend = (NSString*)userInfo[@"friend"];
|
||||||
|
|
||||||
|
const MSList *list = linphone_core_get_call_logs(LC);
|
||||||
|
int i = 0;
|
||||||
|
while (list != NULL) {
|
||||||
|
LinphoneCallLog *log = (LinphoneCallLog *)list->data;
|
||||||
|
const char *curi = linphone_address_as_string_uri_only(linphone_call_log_get_remote_address(log));
|
||||||
|
NSString *uri = [NSString stringWithUTF8String:curi];
|
||||||
|
|
||||||
|
if([uri isEqual:friend]){
|
||||||
|
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:i inSection:0];
|
||||||
|
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
|
||||||
|
[self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationFade];
|
||||||
|
}
|
||||||
|
i = i + 1;
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
|
@ -79,6 +109,8 @@
|
||||||
[NSNotificationCenter.defaultCenter removeObserver:self name:kLinphoneAddressBookUpdate object:nil];
|
[NSNotificationCenter.defaultCenter removeObserver:self name:kLinphoneAddressBookUpdate object:nil];
|
||||||
[NSNotificationCenter.defaultCenter removeObserver:self name:kLinphoneCoreUpdate object:nil];
|
[NSNotificationCenter.defaultCenter removeObserver:self name:kLinphoneCoreUpdate object:nil];
|
||||||
[NSNotificationCenter.defaultCenter removeObserver:self name:kLinphoneCallUpdate object:nil];
|
[NSNotificationCenter.defaultCenter removeObserver:self name:kLinphoneCallUpdate object:nil];
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"LinphoneFriendPresenceUpdate" object:nil];
|
||||||
|
[AvatarBridge removeAllObserver];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Event Functions
|
#pragma mark - Event Functions
|
||||||
|
|
@ -272,9 +304,9 @@
|
||||||
[ConferenceViewModelBridge showCancelledMeetingWithCConferenceInfo:confInfo];
|
[ConferenceViewModelBridge showCancelledMeetingWithCConferenceInfo:confInfo];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ConferenceWaitingRoomFragment *view = VIEW(ConferenceWaitingRoomFragment);
|
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);
|
||||||
[tableView deselectRowAtIndexPath:indexPath animated:NO];
|
[tableView deselectRowAtIndexPath:indexPath animated:NO];
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
@ -61,6 +63,9 @@
|
||||||
|
|
||||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||||
LOGI(@"%@", NSStringFromSelector(_cmd));
|
LOGI(@"%@", NSStringFromSelector(_cmd));
|
||||||
|
if([LinphoneManager.instance lpConfigBoolForKey:@"account_push_presence_preference"]){
|
||||||
|
linphone_core_set_consolidated_presence(LC, LinphoneConsolidatedPresenceOffline);
|
||||||
|
}
|
||||||
if (linphone_core_get_global_state(LC) != LinphoneGlobalOff) {
|
if (linphone_core_get_global_state(LC) != LinphoneGlobalOff) {
|
||||||
[LinphoneManager.instance enterBackgroundMode];
|
[LinphoneManager.instance enterBackgroundMode];
|
||||||
[LinphoneManager.instance.fastAddressBook clearFriends];
|
[LinphoneManager.instance.fastAddressBook clearFriends];
|
||||||
|
|
@ -73,6 +78,7 @@
|
||||||
// To avoid crash
|
// To avoid crash
|
||||||
[PhoneMainView.instance changeCurrentView:DialerView.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:DialerView.compositeViewDescription];
|
||||||
}
|
}
|
||||||
|
|
||||||
[CallManager.instance stopLinphoneCore];
|
[CallManager.instance stopLinphoneCore];
|
||||||
}
|
}
|
||||||
[SwiftUtil resetCachedAsset];
|
[SwiftUtil resetCachedAsset];
|
||||||
|
|
@ -83,14 +89,24 @@
|
||||||
|
|
||||||
[LinphoneManager.instance startLinphoneCore];
|
[LinphoneManager.instance startLinphoneCore];
|
||||||
[LinphoneManager.instance.fastAddressBook reloadFriends];
|
[LinphoneManager.instance.fastAddressBook reloadFriends];
|
||||||
|
[AvatarBridge clearFriends];
|
||||||
|
if([LinphoneManager.instance lpConfigBoolForKey:@"account_push_presence_preference"]){
|
||||||
|
linphone_core_set_consolidated_presence(LC, LinphoneConsolidatedPresenceOnline);
|
||||||
|
}
|
||||||
|
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:nil];
|
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:nil];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||||
LOGI(@"%@", NSStringFromSelector(_cmd));
|
LOGI(@"%@", NSStringFromSelector(_cmd));
|
||||||
LinphoneCall *call = linphone_core_get_current_call(LC);
|
LinphoneCall *call = linphone_core_get_current_call(LC);
|
||||||
|
|
||||||
|
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:kLinphoneMsgNotificationAppGroupId];
|
||||||
|
if (defaults) {
|
||||||
|
[defaults setBool:false forKey:@"appactive"];
|
||||||
|
}
|
||||||
|
|
||||||
if (!call)
|
if (!call)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -113,7 +129,12 @@
|
||||||
}
|
}
|
||||||
LinphoneManager *instance = LinphoneManager.instance;
|
LinphoneManager *instance = LinphoneManager.instance;
|
||||||
[instance becomeActive];
|
[instance becomeActive];
|
||||||
|
|
||||||
|
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:kLinphoneMsgNotificationAppGroupId];
|
||||||
|
if (defaults) {
|
||||||
|
[defaults setBool:true forKey:@"appactive"];
|
||||||
|
}
|
||||||
|
|
||||||
if (instance.fastAddressBook.needToUpdate) {
|
if (instance.fastAddressBook.needToUpdate) {
|
||||||
//Update address book for external changes
|
//Update address book for external changes
|
||||||
if (PhoneMainView.instance.currentView == ContactsListView.compositeViewDescription || PhoneMainView.instance.currentView == ContactDetailsView.compositeViewDescription) {
|
if (PhoneMainView.instance.currentView == ContactsListView.compositeViewDescription || PhoneMainView.instance.currentView == ContactDetailsView.compositeViewDescription) {
|
||||||
|
|
@ -137,7 +158,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 +176,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 +204,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 +363,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,31 +398,39 @@
|
||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options{
|
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options{
|
||||||
NSString *scheme = [[url scheme] lowercaseString];
|
NSString *scheme = [[url scheme] lowercaseString];
|
||||||
if ([scheme isEqualToString:@"linphone-config"] || [scheme isEqualToString:@"linphone-config"]) {
|
if ([scheme isEqualToString:@"linphone-config"]) {
|
||||||
NSString *encodedURL =
|
NSString *encodedURL =
|
||||||
[[url absoluteString] stringByReplacingOccurrencesOfString:@"linphone-config://" withString:@""];
|
[[url absoluteString] stringByReplacingOccurrencesOfString:@"linphone-config:" withString:@""];
|
||||||
self.configURL = [encodedURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
self.configURL = [encodedURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Remote configuration", nil)
|
|
||||||
message:NSLocalizedString(@"This operation will load a remote configuration. Continue ?", nil)
|
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
|
|
||||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"No", nil)
|
BOOL auto_apply_provisioning = [LinphoneManager.instance lpConfigBoolForKey:@"auto_apply_provisioning_config_uri_handler" inSection:@"app" withDefault:FALSE];
|
||||||
style:UIAlertActionStyleDefault
|
if (auto_apply_provisioning) {
|
||||||
handler:^(UIAlertAction * action) {}];
|
[SVProgressHUD show];
|
||||||
|
[self attemptRemoteConfiguration];
|
||||||
UIAlertAction* yesAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Yes", nil)
|
[SVProgressHUD dismiss];
|
||||||
style:UIAlertActionStyleDefault
|
} else {
|
||||||
handler:^(UIAlertAction * action) {
|
NSString *msg = [NSString stringWithFormat:NSLocalizedString(@" Do you want to download and apply configuration from this URL?\n\n%@", nil), encodedURL];
|
||||||
[self showWaitingIndicator];
|
UIConfirmationDialog* remoteConfigurationDialog =[UIConfirmationDialog ShowWithMessage:msg
|
||||||
[self attemptRemoteConfiguration];
|
cancelMessage:nil
|
||||||
}];
|
confirmMessage:NSLocalizedString(@"APPLY", nil)
|
||||||
|
onCancelClick:^() {}
|
||||||
[errView addAction:defaultAction];
|
onConfirmationClick:^() {
|
||||||
[errView addAction:yesAction];
|
[SVProgressHUD show];
|
||||||
|
[self attemptRemoteConfiguration];
|
||||||
[PhoneMainView.instance presentViewController:errView animated:YES completion:nil];
|
[SVProgressHUD dismiss];
|
||||||
|
}];
|
||||||
|
[remoteConfigurationDialog setSpecialColor];
|
||||||
|
}
|
||||||
} 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(ChatConversationViewSwift).sharingMedia = TRUE;
|
||||||
|
ChatsListView *view = VIEW(ChatsListView);
|
||||||
|
[view mediaSharing];
|
||||||
|
}else{
|
||||||
|
[SVProgressHUD dismiss];
|
||||||
|
VIEW(ChatConversationViewSwift).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 "/"
|
||||||
|
|
@ -414,8 +455,8 @@
|
||||||
linphone_address_unref(peer);
|
linphone_address_unref(peer);
|
||||||
linphone_address_unref(local);
|
linphone_address_unref(local);
|
||||||
// TODO : Find a better fix
|
// TODO : Find a better fix
|
||||||
VIEW(ChatConversationView).markAsRead = FALSE;
|
VIEW(ChatConversationViewSwift).markAsRead = FALSE;
|
||||||
[PhoneMainView.instance goToChatRoom:cr];
|
[PhoneMainView.instance goToChatRoomSwift:cr];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
|
|
@ -504,33 +545,57 @@
|
||||||
|
|
||||||
- (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 == ChatConversationViewSwift.compositeViewDescription) {
|
||||||
NSDictionary *userInfo = [[[notification request] content] userInfo];
|
NSDictionary *userInfo = [[[notification request] content] userInfo];
|
||||||
NSString *peerAddress = userInfo[@"peer_addr"];
|
NSString *peerAddress = userInfo[@"peer_addr"];
|
||||||
NSString *localAddress = userInfo[@"local_addr"];
|
NSString *localAddress = userInfo[@"local_addr"];
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
|
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
|
||||||
|
LOGD(@"didReceiveRemoteNotification -- backgroundPush");
|
||||||
|
if (linphone_core_get_global_state(LC) != LinphoneGlobalOn) {
|
||||||
|
[LinphoneManager.instance startLinphoneCore];
|
||||||
|
[LinphoneManager.instance.fastAddressBook reloadFriends];
|
||||||
|
}
|
||||||
|
|
||||||
|
const MSList *accounts = linphone_core_get_account_list(LC);
|
||||||
|
while (accounts) {
|
||||||
|
LinphoneAccount *account = (LinphoneAccount *)accounts->data;
|
||||||
|
linphone_account_refresh_register(account);
|
||||||
|
accounts = accounts->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
|
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:kLinphoneMsgNotificationAppGroupId];
|
||||||
|
NSMutableDictionary *chatroomsPushStatus = [[NSMutableDictionary alloc] initWithDictionary:[defaults dictionaryForKey:@"appactive"]];
|
||||||
|
|
||||||
|
if ([defaults boolForKey:@"appactive"] != TRUE) {
|
||||||
|
linphone_core_enter_background(LC);
|
||||||
|
if (linphone_core_get_calls_nb(LC) == 0) {
|
||||||
|
linphone_core_stop(LC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
completionHandler(UIBackgroundFetchResultNewData);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
||||||
|
|
@ -570,7 +635,7 @@
|
||||||
LinphoneAddress *local = linphone_address_new(local_address.UTF8String);
|
LinphoneAddress *local = linphone_address_new(local_address.UTF8String);
|
||||||
LinphoneChatRoom *room = linphone_core_find_chat_room(LC, peer, local);
|
LinphoneChatRoom *room = linphone_core_find_chat_room(LC, peer, local);
|
||||||
if (room)
|
if (room)
|
||||||
[ChatConversationView markAsRead:room];
|
[ChatConversationViewSwift markAsRead:room];
|
||||||
|
|
||||||
linphone_address_unref(peer);
|
linphone_address_unref(peer);
|
||||||
linphone_address_unref(local);
|
linphone_address_unref(local);
|
||||||
|
|
@ -610,14 +675,16 @@
|
||||||
LinphoneAddress *local = linphone_address_new(local_address.UTF8String);
|
LinphoneAddress *local = linphone_address_new(local_address.UTF8String);
|
||||||
LinphoneChatRoom *room = linphone_core_find_chat_room(LC, peer, local);
|
LinphoneChatRoom *room = linphone_core_find_chat_room(LC, peer, local);
|
||||||
if (room) {
|
if (room) {
|
||||||
[PhoneMainView.instance goToChatRoom:room];
|
[PhoneMainView.instance resetBeforeGoToChatRoomSwift];
|
||||||
|
[PhoneMainView.instance changeCurrentView:ChatsListView.compositeViewDescription];
|
||||||
|
[PhoneMainView.instance goToChatRoomSwift:room];
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
[PhoneMainView.instance changeCurrentView:ChatsListView.compositeViewDescription];
|
||||||
}
|
}
|
||||||
[PhoneMainView.instance changeCurrentView:ChatsListView.compositeViewDescription];
|
|
||||||
}
|
}
|
||||||
} 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
|
||||||
|
|
@ -718,7 +785,7 @@
|
||||||
LinphoneAddress *local = linphone_address_new(local_address.UTF8String);
|
LinphoneAddress *local = linphone_address_new(local_address.UTF8String);
|
||||||
LinphoneChatRoom *room = linphone_core_find_chat_room(LC, peer, local);
|
LinphoneChatRoom *room = linphone_core_find_chat_room(LC, peer, local);
|
||||||
if (room)
|
if (room)
|
||||||
[ChatConversationView markAsRead:room];
|
[ChatConversationViewSwift markAsRead:room];
|
||||||
|
|
||||||
linphone_address_unref(peer);
|
linphone_address_unref(peer);
|
||||||
linphone_address_unref(local);
|
linphone_address_unref(local);
|
||||||
|
|
@ -799,23 +866,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)showWaitingIndicator {
|
|
||||||
_waitingIndicator = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Fetching remote configuration...", nil)
|
|
||||||
message:@""
|
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
|
|
||||||
UIActivityIndicatorView *progress = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(125, 60, 30, 30)];
|
|
||||||
progress.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
|
|
||||||
|
|
||||||
[_waitingIndicator setValue:progress forKey:@"accessoryView"];
|
|
||||||
[progress setColor:[UIColor blackColor]];
|
|
||||||
|
|
||||||
[progress startAnimating];
|
|
||||||
[PhoneMainView.instance presentViewController:_waitingIndicator animated:YES completion:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)attemptRemoteConfiguration {
|
- (void)attemptRemoteConfiguration {
|
||||||
|
|
||||||
[NSNotificationCenter.defaultCenter addObserver:self
|
[NSNotificationCenter.defaultCenter addObserver:self
|
||||||
selector:@selector(ConfigurationStateUpdateEvent:)
|
selector:@selector(ConfigurationStateUpdateEvent:)
|
||||||
name:kLinphoneConfiguringStateUpdate
|
name:kLinphoneConfiguringStateUpdate
|
||||||
|
|
@ -823,7 +874,7 @@
|
||||||
linphone_core_set_provisioning_uri(LC, [configURL UTF8String]);
|
linphone_core_set_provisioning_uri(LC, [configURL UTF8String]);
|
||||||
[LinphoneManager.instance destroyLinphoneCore];
|
[LinphoneManager.instance destroyLinphoneCore];
|
||||||
[LinphoneManager.instance launchLinphoneCore];
|
[LinphoneManager.instance launchLinphoneCore];
|
||||||
[LinphoneManager.instance.fastAddressBook fetchContactsInBackGroundThread];
|
[LinphoneManager.instance.fastAddressBook fetchContactsInBackGroundThread];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Prevent ImagePickerView from rotating
|
#pragma mark - Prevent ImagePickerView from rotating
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
@ -152,6 +155,7 @@
|
||||||
// default values
|
// default values
|
||||||
{
|
{
|
||||||
[self setBool:NO forKey:@"account_pushnotification_preference"];
|
[self setBool:NO forKey:@"account_pushnotification_preference"];
|
||||||
|
[self setBool:NO forKey:@"account_bundle_mode_preference"];
|
||||||
[self setObject:@"" forKey:@"account_mandatory_username_preference"];
|
[self setObject:@"" forKey:@"account_mandatory_username_preference"];
|
||||||
[self setObject:@"" forKey:@"account_mandatory_domain_preference"];
|
[self setObject:@"" forKey:@"account_mandatory_domain_preference"];
|
||||||
[self setCString:"" forKey:@"account_display_name_preference"];
|
[self setCString:"" forKey:@"account_display_name_preference"];
|
||||||
|
|
@ -168,6 +172,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"];
|
||||||
|
|
@ -180,10 +185,13 @@
|
||||||
{
|
{
|
||||||
BOOL pushEnabled = linphone_account_params_get_push_notification_allowed(accountParams);
|
BOOL pushEnabled = linphone_account_params_get_push_notification_allowed(accountParams);
|
||||||
[self setBool:pushEnabled forKey:@"account_pushnotification_preference"];
|
[self setBool:pushEnabled forKey:@"account_pushnotification_preference"];
|
||||||
|
|
||||||
|
BOOL bundleModeEnabled = linphone_account_params_rtp_bundle_enabled(accountParams);
|
||||||
|
[self setBool:bundleModeEnabled forKey:@"account_bundle_mode_preference"];
|
||||||
|
|
||||||
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 +242,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 +261,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 +356,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"];
|
||||||
|
|
@ -430,10 +445,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
|
||||||
|
|
@ -485,7 +500,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"];
|
||||||
|
|
@ -509,8 +524,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// contacts section
|
// contacts section
|
||||||
if (linphone_core_ldap_available(LC)) {
|
{
|
||||||
[self transformLdapToKeys:nil];
|
[self setInteger:[lm lpConfigBoolForKey:@"account_push_presence_preference" withDefault:YES] forKey:@"account_push_presence_preference"];
|
||||||
|
if (linphone_core_ldap_available(LC)) {
|
||||||
|
[self transformLdapToKeys:nil];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// advanced section
|
// advanced section
|
||||||
|
|
@ -519,6 +537,7 @@
|
||||||
[self setBool:ANIMATED forKey:@"animations_preference"];
|
[self setBool:ANIMATED forKey:@"animations_preference"];
|
||||||
[self setBool:[lm lpConfigBoolForKey:@"backgroundmode_preference"] forKey:@"backgroundmode_preference"];
|
[self setBool:[lm lpConfigBoolForKey:@"backgroundmode_preference"] forKey:@"backgroundmode_preference"];
|
||||||
[self setBool:[lm lpConfigBoolForKey:@"start_at_boot_preference"] forKey:@"start_at_boot_preference"];
|
[self setBool:[lm lpConfigBoolForKey:@"start_at_boot_preference"] forKey:@"start_at_boot_preference"];
|
||||||
|
[self setBool:[lm lpConfigBoolForKey:@"screenshot_preference" withDefault:NO] forKey:@"screenshot_preference"];
|
||||||
[self setBool:[lm lpConfigBoolForKey:@"autoanswer_notif_preference"] forKey:@"autoanswer_notif_preference"];
|
[self setBool:[lm lpConfigBoolForKey:@"autoanswer_notif_preference"] forKey:@"autoanswer_notif_preference"];
|
||||||
[self setBool:[lm lpConfigBoolForKey:@"show_msg_in_notif" withDefault:YES] forKey:@"show_msg_in_notif"];
|
[self setBool:[lm lpConfigBoolForKey:@"show_msg_in_notif" withDefault:YES] forKey:@"show_msg_in_notif"];
|
||||||
[self setBool:[lm lpConfigBoolForKey:@"use_rls_presence" withDefault:YES] forKey:@"use_rls_presence"];
|
[self setBool:[lm lpConfigBoolForKey:@"use_rls_presence" withDefault:YES] forKey:@"use_rls_presence"];
|
||||||
|
|
@ -603,7 +622,9 @@
|
||||||
if (username && [username length] > 0 && domain && [domain length] > 0) {
|
if (username && [username length] > 0 && domain && [domain length] > 0) {
|
||||||
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"];
|
||||||
|
BOOL bundlemode = [self boolForKey:@"account_bundle_mode_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 +635,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 +646,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 +693,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);
|
||||||
|
|
@ -681,8 +702,10 @@
|
||||||
|
|
||||||
// use empty string "" instead of NULL to avoid being overwritten by default proxy config values
|
// use empty string "" instead of NULL to avoid being overwritten by default proxy config values
|
||||||
linphone_account_params_set_push_notification_allowed(newAccountParams, pushnotification);
|
linphone_account_params_set_push_notification_allowed(newAccountParams, pushnotification);
|
||||||
|
linphone_account_params_enable_rtp_bundle(newAccountParams, bundlemode);
|
||||||
|
linphone_account_params_set_push_notification_allowed(newAccountParams, pushnotification);
|
||||||
linphone_account_params_set_remote_push_notification_allowed(newAccountParams, pushnotification);
|
linphone_account_params_set_remote_push_notification_allowed(newAccountParams, pushnotification);
|
||||||
|
|
||||||
linphone_account_params_set_register_enabled(newAccountParams, is_enabled);
|
linphone_account_params_set_register_enabled(newAccountParams, is_enabled);
|
||||||
linphone_account_params_set_avpf_mode(newAccountParams, use_avpf);
|
linphone_account_params_set_avpf_mode(newAccountParams, use_avpf);
|
||||||
linphone_account_params_set_expires(newAccountParams, expire);
|
linphone_account_params_set_expires(newAccountParams, expire);
|
||||||
|
|
@ -713,7 +736,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 +828,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 +852,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
|
||||||
|
|
@ -1018,7 +1041,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)
|
||||||
|
|
@ -1071,7 +1094,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// contacts section
|
// contacts section
|
||||||
|
BOOL push_presence = [self boolForKey:@"account_push_presence_preference"];
|
||||||
|
if (push_presence) {
|
||||||
|
linphone_core_set_consolidated_presence([LinphoneManager getLc], LinphoneConsolidatedPresenceOnline);
|
||||||
|
} else {
|
||||||
|
linphone_core_set_consolidated_presence([LinphoneManager getLc], LinphoneConsolidatedPresenceOffline);
|
||||||
|
}
|
||||||
|
[lm lpConfigSetInt:push_presence forKey:@"account_push_presence_preference"];
|
||||||
|
|
||||||
BOOL ldap_changed = NO;
|
BOOL ldap_changed = NO;
|
||||||
for (NSString *key in self->changedDict) {
|
for (NSString *key in self->changedDict) {
|
||||||
|
|
@ -1086,6 +1115,9 @@
|
||||||
// advanced section
|
// advanced section
|
||||||
BOOL animations = [self boolForKey:@"animations_preference"];
|
BOOL animations = [self boolForKey:@"animations_preference"];
|
||||||
[lm lpConfigSetInt:animations forKey:@"animations_preference"];
|
[lm lpConfigSetInt:animations forKey:@"animations_preference"];
|
||||||
|
|
||||||
|
BOOL screenshot = [self boolForKey:@"screenshot_preference"];
|
||||||
|
[lm lpConfigSetInt:screenshot forKey:@"screenshot_preference"];
|
||||||
|
|
||||||
UIDevice *device = [UIDevice currentDevice];
|
UIDevice *device = [UIDevice currentDevice];
|
||||||
BOOL backgroundSupported = [device respondsToSelector:@selector(isMultitaskingSupported)] && [device isMultitaskingSupported];
|
BOOL backgroundSupported = [device respondsToSelector:@selector(isMultitaskingSupported)] && [device isMultitaskingSupported];
|
||||||
|
|
@ -1100,7 +1132,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 {
|
||||||
|
|
@ -1114,6 +1148,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"];
|
||||||
|
|
@ -1155,9 +1190,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);
|
||||||
|
|
@ -1178,11 +1216,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;
|
||||||
|
|
@ -193,6 +196,8 @@ typedef struct _LinphoneManagerSounds {
|
||||||
- (void)checkLocalNetworkPermission;
|
- (void)checkLocalNetworkPermission;
|
||||||
- (void)setDnsServer;
|
- (void)setDnsServer;
|
||||||
|
|
||||||
|
+ (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,13 +81,14 @@ 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";
|
||||||
|
|
||||||
const int kLinphoneAudioVbrCodecDefaultBitrate = 36; /*you can override this from linphonerc or linphonerc-factory*/
|
const int kLinphoneAudioVbrCodecDefaultBitrate = 36; /*you can override this from linphonerc or linphonerc-factory*/
|
||||||
|
|
||||||
extern void libmsamr_init(MSFactory *factory);
|
extern void libmsamr_init(MSFactory *factory);
|
||||||
extern void libmsx264_init(MSFactory *factory);
|
|
||||||
extern void libmsopenh264_init(MSFactory *factory);
|
extern void libmsopenh264_init(MSFactory *factory);
|
||||||
extern void libmssilk_init(MSFactory *factory);
|
extern void libmssilk_init(MSFactory *factory);
|
||||||
extern void libmswebrtc_init(MSFactory *factory);
|
extern void libmswebrtc_init(MSFactory *factory);
|
||||||
|
|
@ -239,7 +240,7 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre
|
||||||
NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"];
|
NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"];
|
||||||
self.messagePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:nil];
|
self.messagePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:nil];
|
||||||
|
|
||||||
_sounds.vibrate = kSystemSoundID_Vibrate;
|
//_sounds.vibrate = kSystemSoundID_Vibrate;
|
||||||
|
|
||||||
_logs = [[NSMutableArray alloc] init];
|
_logs = [[NSMutableArray alloc] init];
|
||||||
_pushDict = [[NSMutableDictionary alloc] init];
|
_pushDict = [[NSMutableDictionary alloc] init];
|
||||||
|
|
@ -253,6 +254,11 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre
|
||||||
[self renameDefaultSettings];
|
[self renameDefaultSettings];
|
||||||
[self copyDefaultSettings];
|
[self copyDefaultSettings];
|
||||||
[self overrideDefaultSettings];
|
[self overrideDefaultSettings];
|
||||||
|
|
||||||
|
if (![self lpConfigBoolForKey:@"disable_chat_feature" withDefault:FALSE]) {
|
||||||
|
_sounds.vibrate = kSystemSoundID_Vibrate;
|
||||||
|
}
|
||||||
|
|
||||||
if (![self lpConfigBoolForKey:@"migration_images_done" withDefault:FALSE]) {
|
if (![self lpConfigBoolForKey:@"migration_images_done" withDefault:FALSE]) {
|
||||||
[self migrationAllImages];
|
[self migrationAllImages];
|
||||||
}
|
}
|
||||||
|
|
@ -276,6 +282,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];
|
||||||
|
|
@ -372,6 +386,10 @@ static int check_should_migrate_images(void *data, int argc, char **argv, char *
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)migrationLinphoneSettings {
|
- (void)migrationLinphoneSettings {
|
||||||
|
NSString *appDomain = [LinphoneManager.instance lpConfigStringForKey:@"domain_name"
|
||||||
|
inSection:@"app"
|
||||||
|
withDefault:@"sip.linphone.org"];
|
||||||
|
|
||||||
/* AVPF migration */
|
/* AVPF migration */
|
||||||
if ([self lpConfigBoolForKey:@"avpf_migration_done"] == FALSE) {
|
if ([self lpConfigBoolForKey:@"avpf_migration_done"] == FALSE) {
|
||||||
const MSList *accounts = linphone_core_get_account_list(theLinphoneCore);
|
const MSList *accounts = linphone_core_get_account_list(theLinphoneCore);
|
||||||
|
|
@ -464,6 +482,26 @@ static int check_should_migrate_images(void *data, int argc, char **argv, char *
|
||||||
}
|
}
|
||||||
[self lpConfigSetBool:TRUE forKey:@"push_notification_migration_done"];
|
[self lpConfigSetBool:TRUE forKey:@"push_notification_migration_done"];
|
||||||
}
|
}
|
||||||
|
if ([self lpConfigBoolForKey:@"publish_enabled_migration_done"] == FALSE) {
|
||||||
|
const MSList *accounts = linphone_core_get_account_list(theLinphoneCore);
|
||||||
|
linphone_core_set_log_collection_upload_server_url(LC, "https://www.linphone.org:444/lft.php");
|
||||||
|
[self lpConfigSetBool:TRUE forKey:@"update_presence_model_timestamp_before_publish_expires_refresh"];
|
||||||
|
|
||||||
|
while (accounts)
|
||||||
|
{
|
||||||
|
LinphoneAccount *account = (LinphoneAccount *)accounts->data;
|
||||||
|
LinphoneAccountParams *newAccountParams = linphone_account_params_clone(linphone_account_get_params(account));
|
||||||
|
|
||||||
|
if (strcmp(appDomain.UTF8String, linphone_account_params_get_domain(newAccountParams)) == 0) {
|
||||||
|
linphone_account_params_set_publish_enabled(newAccountParams, true);
|
||||||
|
linphone_account_params_set_publish_expires(newAccountParams, 120);
|
||||||
|
linphone_account_set_params(account, newAccountParams);
|
||||||
|
}
|
||||||
|
linphone_account_params_unref(newAccountParams);
|
||||||
|
accounts = accounts->next;
|
||||||
|
}
|
||||||
|
[self lpConfigSetBool:TRUE forKey:@"publish_enabled_migration_done"];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)migrationPerAccount {
|
- (void)migrationPerAccount {
|
||||||
|
|
@ -474,27 +512,33 @@ static int check_should_migrate_images(void *data, int argc, char **argv, char *
|
||||||
while (accounts) {
|
while (accounts) {
|
||||||
LinphoneAccount *account = accounts->data;
|
LinphoneAccount *account = accounts->data;
|
||||||
LinphoneAccountParams *newAccountParams = linphone_account_params_clone(linphone_account_get_params(account));
|
LinphoneAccountParams *newAccountParams = linphone_account_params_clone(linphone_account_get_params(account));
|
||||||
// can not create group chat without conference factory
|
|
||||||
if (!linphone_account_params_get_conference_factory_uri(newAccountParams)) {
|
if (strcmp(appDomain.UTF8String, linphone_account_params_get_domain(newAccountParams)) == 0) {
|
||||||
if (strcmp(appDomain.UTF8String, linphone_account_params_get_domain(newAccountParams)) == 0) {
|
// can not create group chat without conference factory
|
||||||
|
if (!linphone_account_params_get_conference_factory_uri(newAccountParams)) {
|
||||||
linphone_account_params_set_conference_factory_uri(newAccountParams, "sip:conference-factory@sip.linphone.org");
|
linphone_account_params_set_conference_factory_uri(newAccountParams, "sip:conference-factory@sip.linphone.org");
|
||||||
linphone_account_set_params(account, newAccountParams);
|
linphone_account_set_params(account, newAccountParams);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!linphone_account_params_get_audio_video_conference_factory_address(newAccountParams) && strcmp(appDomain.UTF8String, linphone_account_params_get_domain(newAccountParams)) == 0) {
|
if (!linphone_account_params_get_audio_video_conference_factory_address(newAccountParams)) {
|
||||||
NSString *uri = [self lpConfigStringForKey:@"default_audio_video_conference_factory_uri" withDefault:@"sip:videoconference-factory2@sip.linphone.org"];
|
NSString *uri = [self lpConfigStringForKey:@"default_audio_video_conference_factory_uri" withDefault:@"sip:videoconference-factory2@sip.linphone.org"];
|
||||||
LinphoneAddress *a = linphone_factory_create_address(linphone_factory_get(), uri.UTF8String);
|
LinphoneAddress *a = linphone_factory_create_address(linphone_factory_get(), uri.UTF8String);
|
||||||
if (a) {
|
if (a) {
|
||||||
linphone_account_params_set_audio_video_conference_factory_address(newAccountParams, a);
|
linphone_account_params_set_audio_video_conference_factory_address(newAccountParams, a);
|
||||||
linphone_account_set_params(account, newAccountParams);
|
linphone_account_set_params(account, newAccountParams);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (!linphone_account_params_rtp_bundle_enabled(newAccountParams)) {
|
||||||
|
linphone_account_params_enable_rtp_bundle(newAccountParams, true);
|
||||||
|
linphone_account_set_params(account,newAccountParams);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
LOGI(@"Setting the sip 'expires' parameters of existing account to 1 year (31536000 seconds)");
|
||||||
|
linphone_account_params_set_expires(newAccountParams, 31536000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(appDomain.UTF8String, linphone_account_params_get_domain(newAccountParams)) == 0 && !linphone_account_params_rtp_bundle_enabled(newAccountParams)) {
|
|
||||||
linphone_account_params_enable_rtp_bundle(newAccountParams, true);
|
|
||||||
linphone_account_set_params(account,newAccountParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
linphone_account_params_unref(newAccountParams);
|
linphone_account_params_unref(newAccountParams);
|
||||||
accounts = accounts->next;
|
accounts = accounts->next;
|
||||||
}
|
}
|
||||||
|
|
@ -637,6 +681,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 {
|
||||||
|
|
@ -865,9 +914,9 @@ static void linphone_iphone_popup_password_request(LinphoneCore *lc, LinphoneAut
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (hasFile) {
|
if (hasFile) {
|
||||||
if (PhoneMainView.instance.currentView == ChatConversationView.compositeViewDescription && room == PhoneMainView.instance.currentRoom)
|
if (PhoneMainView.instance.currentView == ChatConversationViewSwift.compositeViewDescription && room == PhoneMainView.instance.currentRoom)
|
||||||
return;
|
return;
|
||||||
[ChatConversationView autoDownload:msg];
|
[self autoDownload:msg];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post event
|
// Post event
|
||||||
|
|
@ -881,6 +930,21 @@ static void linphone_iphone_popup_password_request(LinphoneCore *lc, LinphoneAut
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:self userInfo:dict];
|
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:self userInfo:dict];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)autoDownload:(LinphoneChatMessage *)message {
|
||||||
|
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(message);
|
||||||
|
NSString *name = [NSString stringWithUTF8String:linphone_content_get_name(content)];
|
||||||
|
NSString *fileType = [NSString stringWithUTF8String:linphone_content_get_type(content)];
|
||||||
|
NSString *key = [ChatConversationViewSwift getKeyFromFileType:fileType fileName:name];
|
||||||
|
|
||||||
|
[LinphoneManager setValueInMessageAppData:name forKey:key inMessage:message];
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:VIEW(ChatConversationViewSwift)];
|
||||||
|
if (![VFSUtil vfsEnabledWithGroupName:kLinphoneMsgNotificationAppGroupId] && [ConfigManager.instance lpConfigBoolForKeyWithKey:@"auto_write_to_gallery_preference"]) {
|
||||||
|
[ChatConversationViewSwift writeMediaToGalleryFromName:name fileType:fileType];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static void linphone_iphone_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message) {
|
static void linphone_iphone_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message) {
|
||||||
[(__bridge LinphoneManager *)linphone_core_cbs_get_user_data(linphone_core_get_current_callbacks(lc)) onMessageReceived:lc room:room message:message];
|
[(__bridge LinphoneManager *)linphone_core_cbs_get_user_data(linphone_core_get_current_callbacks(lc)) onMessageReceived:lc room:room message:message];
|
||||||
}
|
}
|
||||||
|
|
@ -1264,7 +1328,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"
|
||||||
|
|
@ -1285,7 +1349,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];
|
||||||
|
|
@ -1304,7 +1375,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)));
|
||||||
|
|
@ -1344,22 +1415,37 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)activateBasicChatroomCPIMForLinphoneAccounts {
|
- (void)enableLinphoneAccountSpecificSettings {
|
||||||
const MSList *accountsList = linphone_core_get_account_list(theLinphoneCore);
|
const MSList *accountsList = linphone_core_get_account_list(theLinphoneCore);
|
||||||
while (accountsList) {
|
while (accountsList) {
|
||||||
LinphoneAccount * account = accountsList->data;
|
LinphoneAccount * account = accountsList->data;
|
||||||
LinphoneAccountParams const * currentParams = linphone_account_get_params(account);
|
LinphoneAccountParams const * currentParams = linphone_account_get_params(account);
|
||||||
LinphoneAddress const * currentAddress = linphone_account_params_get_identity_address(currentParams);
|
LinphoneAddress const * currentAddress = linphone_account_params_get_identity_address(currentParams);
|
||||||
|
char * addressIdentity = linphone_address_as_string(currentAddress);
|
||||||
|
|
||||||
if (strcmp(linphone_address_get_domain(currentAddress), "sip.linphone.org") == 0 && !linphone_account_params_cpim_in_basic_chat_room_enabled(currentParams) ) {
|
if (strcmp(linphone_address_get_domain(currentAddress), "sip.linphone.org") == 0) {
|
||||||
|
|
||||||
LOGI(@"Enabling CPIM in basic chatroom for user %s", linphone_address_get_username(currentAddress));
|
|
||||||
LinphoneAccountParams * newParams = linphone_account_params_clone(linphone_account_get_params(account));
|
LinphoneAccountParams * newParams = linphone_account_params_clone(linphone_account_get_params(account));
|
||||||
linphone_account_params_enable_cpim_in_basic_chat_room(newParams, true);
|
if (!linphone_account_params_cpim_in_basic_chat_room_enabled(currentParams) ) {
|
||||||
|
LOGI(@"Enabling CPIM in basic chatroom for account [%s]", addressIdentity);
|
||||||
|
linphone_account_params_enable_cpim_in_basic_chat_room(newParams, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* current_lime_url = linphone_account_params_get_lime_server_url(currentParams);
|
||||||
|
if (!current_lime_url){
|
||||||
|
const char* core_lime_url = linphone_core_get_lime_x3dh_server_url(LC);
|
||||||
|
if (core_lime_url) {
|
||||||
|
LOGI(@"Copying core's LIME X3DH server URL [%s] to account [%s]", core_lime_url, addressIdentity);
|
||||||
|
linphone_account_params_set_lime_server_url(newParams, core_lime_url);
|
||||||
|
} else {
|
||||||
|
LOGI(@"Account [%s] didn't have a LIME X3DH server URL, setting one: [%s]", addressIdentity, core_lime_url);
|
||||||
|
linphone_account_params_set_lime_server_url(newParams, "https://lime.linphone.org/lime-server/lime-server.php");
|
||||||
|
}
|
||||||
|
}
|
||||||
linphone_account_set_params(account, newParams);
|
linphone_account_set_params(account, newParams);
|
||||||
linphone_account_params_unref(newParams);
|
linphone_account_params_unref(newParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ms_free(addressIdentity);
|
||||||
accountsList = accountsList->next;
|
accountsList = accountsList->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1370,7 +1456,7 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
|
||||||
linphone_core_start([LinphoneManager getLc]);
|
linphone_core_start([LinphoneManager getLc]);
|
||||||
|
|
||||||
[self configurePushProviderForAccounts];
|
[self configurePushProviderForAccounts];
|
||||||
[self activateBasicChatroomCPIMForLinphoneAccounts];
|
[self enableLinphoneAccountSpecificSettings];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)createLinphoneCore {
|
- (void)createLinphoneCore {
|
||||||
|
|
@ -1439,7 +1525,6 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
|
||||||
MSFactory *f = linphone_core_get_ms_factory(theLinphoneCore);
|
MSFactory *f = linphone_core_get_ms_factory(theLinphoneCore);
|
||||||
libmssilk_init(f);
|
libmssilk_init(f);
|
||||||
libmsamr_init(f);
|
libmsamr_init(f);
|
||||||
libmsx264_init(f);
|
|
||||||
libmsopenh264_init(f);
|
libmsopenh264_init(f);
|
||||||
libmswebrtc_init(f);
|
libmswebrtc_init(f);
|
||||||
libmscodec2_init(f);
|
libmscodec2_init(f);
|
||||||
|
|
@ -1472,6 +1557,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
|
||||||
|
|
||||||
|
|
@ -1501,8 +1587,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) {
|
||||||
|
|
@ -1817,7 +1901,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
|
||||||
LinphoneChatMessage *msg = linphone_chat_room_create_message(room, replyText.UTF8String);
|
LinphoneChatMessage *msg = linphone_chat_room_create_message(room, replyText.UTF8String);
|
||||||
linphone_chat_message_send(msg);
|
linphone_chat_message_send(msg);
|
||||||
|
|
||||||
[ChatConversationView markAsRead:room];
|
[ChatConversationViewSwift markAsRead:room];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1900,7 +1984,10 @@ 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];
|
LinphoneVideoActivationPolicy *policy = linphone_core_get_video_activation_policy(LC);
|
||||||
|
BOOL initiateVideoCall = linphone_video_activation_policy_get_automatically_initiate(policy);
|
||||||
|
[CallManager.instance startCallWithAddr:iaddr isSas:FALSE isVideo:initiateVideoCall isConference:false];
|
||||||
|
linphone_video_activation_policy_unref(policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Misc Functions
|
#pragma mark - Misc Functions
|
||||||
|
|
@ -2226,6 +2313,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);
|
||||||
|
|
@ -2319,6 +2423,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="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="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>
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="189" height="64"/>
|
<rect key="frame" x="0.0" y="0.0" width="189" height="64"/>
|
||||||
<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"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="hBI-Xz-aEV" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="hBI-Xz-aEV" userLabel="avatarImage">
|
||||||
<rect key="frame" x="6" y="20" width="27" height="27"/>
|
<rect key="frame" x="6" y="20" width="27" height="27"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
|
@ -59,14 +59,14 @@
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<textView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" editable="NO" text="Lore ipsum..." translatesAutoresizingMaskIntoConstraints="NO" id="CYa-If-oB4" userLabel="messageText" customClass="UITextViewNoDefine">
|
<textView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" editable="NO" text="Lore ipsum..." translatesAutoresizingMaskIntoConstraints="NO" id="CYa-If-oB4" userLabel="messageText" customClass="UITextViewNoDefine">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="126" height="40"/>
|
<rect key="frame" x="4" y="0.0" width="118" height="40"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||||
<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>
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="86"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="86"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="19" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="19" userLabel="avatarImage" customClass="UIImageView">
|
||||||
<rect key="frame" x="10" y="11" width="42" height="42"/>
|
<rect key="frame" x="10" y="11" width="42" height="42"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
|
@ -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,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" useTraitCollections="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" 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="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>
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||||
<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">
|
||||||
<rect key="frame" x="0.0" y="8" 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>
|
||||||
|
|
|
||||||
|
|
@ -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="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||||
<device id="retina5_5" orientation="landscape" appearance="light"/>
|
<device id="retina5_5" orientation="landscape" 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="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>
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
<action selector="onDelete:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="gSd-t2-eDY"/>
|
<action selector="onDelete:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="gSd-t2-eDY"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="Zsv-H9-9Dv" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="Zsv-H9-9Dv" userLabel="avatarImage">
|
||||||
<rect key="frame" x="8" y="0.0" width="35" height="42"/>
|
<rect key="frame" x="8" y="0.0" width="35" height="42"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Linphone"/>
|
<accessibility key="accessibilityConfiguration" label="Linphone"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="ktO-jm-Ra6" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="ktO-jm-Ra6" userLabel="avatarImage">
|
||||||
<rect key="frame" x="10" y="10" width="40" height="40"/>
|
<rect key="frame" x="10" y="10" width="40" height="40"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
|
@ -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="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,11 +11,14 @@
|
||||||
<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"/>
|
||||||
|
<outlet property="subscribeLabel" destination="Xbl-Qs-GaE" id="Qnf-pA-nL0"/>
|
||||||
<outlet property="titleLabel" destination="jLz-g1-cTe" id="qaj-OB-2r1"/>
|
<outlet property="titleLabel" destination="jLz-g1-cTe" id="qaj-OB-2r1"/>
|
||||||
<outlet property="view" destination="2Vb-Xy-rci" id="nNw-EJ-AY3"/>
|
<outlet property="view" destination="2Vb-Xy-rci" id="nNw-EJ-AY3"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
|
@ -25,27 +28,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 +65,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 +78,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 +87,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,20 +99,34 @@
|
||||||
</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>
|
||||||
|
<label hidden="YES" opaque="NO" tag="13" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="https://subscribe.linphone.org" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Xbl-Qs-GaE" userLabel="subscribeLabel">
|
||||||
|
<rect key="frame" x="-42" y="291" width="414" height="29"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<color key="textColor" red="0.98766469960000003" green="0.27512490750000002" blue="0.029739789660000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
<connections>
|
||||||
|
<outletCollection property="gestureRecognizers" destination="tfG-O1-yfD" appends="YES" id="Jcg-KH-U5B"/>
|
||||||
|
</connections>
|
||||||
|
</label>
|
||||||
</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="548" y="34"/>
|
||||||
</view>
|
</view>
|
||||||
|
<tapGestureRecognizer id="tfG-O1-yfD" userLabel="onSubscribeTap">
|
||||||
|
<connections>
|
||||||
|
<action selector="onSubscribeTap:" destination="-1" id="Zq2-mP-ccM"/>
|
||||||
|
</connections>
|
||||||
|
</tapGestureRecognizer>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="checkbox_checked.png" width="27.200000762939453" height="27.200000762939453"/>
|
<image name="checkbox_checked.png" width="27.200000762939453" height="27.200000762939453"/>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +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="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" 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">
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<adaptation id="fullscreen"/>
|
|
||||||
</device>
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
|
<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>
|
||||||
|
|
@ -14,37 +12,47 @@
|
||||||
<outlet property="avatarImage" destination="23" id="24"/>
|
<outlet property="avatarImage" destination="23" id="24"/>
|
||||||
<outlet property="linphoneImage" destination="25" id="27"/>
|
<outlet property="linphoneImage" destination="25" id="27"/>
|
||||||
<outlet property="nameLabel" destination="6" id="26"/>
|
<outlet property="nameLabel" destination="6" id="26"/>
|
||||||
|
<outlet property="organizationLabel" destination="fva-Hf-er8" id="Ib6-rS-ybW"/>
|
||||||
</connections>
|
</connections>
|
||||||
</placeholder>
|
</placeholder>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
<view contentMode="scaleToFill" id="16">
|
<view contentMode="scaleToFill" id="16">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="360" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="360" height="49"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" image="avatar.png" id="23" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="23" userLabel="avatarImage">
|
||||||
<rect key="frame" x="6" y="6" width="32" height="32"/>
|
<rect key="frame" x="6" y="9" width="32" height="32"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="2" contentMode="left" text="John Doe" lineBreakMode="tailTruncation" minimumFontSize="10" id="6" userLabel="nameLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="2" contentMode="left" fixedFrame="YES" text="John Doe" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="6" userLabel="nameLabel">
|
||||||
<rect key="frame" x="46" y="0.0" width="256" height="44"/>
|
<rect key="frame" x="46" y="4" width="256" height="39"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
<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"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Firstname"/>
|
<accessibility key="accessibilityConfiguration" label="Firstname"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="21"/>
|
<fontDescription key="fontDescription" type="system" pointSize="21"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" misplaced="YES" image="linphone_user.png" id="25" userLabel="linphoneImage">
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" fixedFrame="YES" image="linphone_user.png" translatesAutoresizingMaskIntoConstraints="NO" id="25" userLabel="linphoneImage">
|
||||||
<rect key="frame" x="319" y="10" width="25" height="25"/>
|
<rect key="frame" x="319" y="13" width="25" height="25"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="2" contentMode="left" fixedFrame="YES" text="Organization" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="fva-Hf-er8" userLabel="organizationLabel">
|
||||||
|
<rect key="frame" x="46" y="29" width="256" height="18"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<accessibility key="accessibilityConfiguration" label="Firstname"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<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"/>
|
||||||
<nil key="simulatedStatusBarMetrics"/>
|
<nil key="simulatedStatusBarMetrics"/>
|
||||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||||
|
<point key="canvasLocation" x="137.59999999999999" y="-10.794602698650676"/>
|
||||||
</view>
|
</view>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="avatar.png" width="259" height="259"/>
|
<image name="avatar.png" width="414.39999389648438" height="414.39999389648438"/>
|
||||||
<image name="linphone_user.png" width="26" height="26"/>
|
<image name="linphone_user.png" width="41.599998474121094" height="42.400001525878906"/>
|
||||||
</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="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" 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="17125"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
|
||||||
<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 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="88"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="88"/>
|
||||||
<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"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="john.doe@sip.linphone.org" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="frB-ep-LWi" userLabel="addressLabel">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="john.doe@sip.linphone.org" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="frB-ep-LWi" userLabel="addressLabel" customClass="CopyableLabel" customModule="linphoneapp" customModuleProvider="target">
|
||||||
<rect key="frame" x="26" y="0.0" width="323" height="44"/>
|
<rect key="frame" x="26" y="0.0" width="323" height="44"/>
|
||||||
<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"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||||
|
<device id="retina6_12" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UIHistoryCell">
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UIHistoryCell">
|
||||||
|
|
@ -18,31 +20,27 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" image="avatar.png" id="J9B-Wl-Qgm" userLabel="avatarImage" customClass="UIRoundedImageView">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="avatar.png" translatesAutoresizingMaskIntoConstraints="NO" id="J9B-Wl-Qgm" userLabel="avatarImage">
|
||||||
<rect key="frame" x="6" y="6" width="32" height="32"/>
|
<rect key="frame" x="6" y="6" width="32" height="32"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<animations/>
|
|
||||||
</imageView>
|
</imageView>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="history_missed_default.png" id="Jpe-IK-xK1" userLabel="stateImage">
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="history_missed_default.png" translatesAutoresizingMaskIntoConstraints="NO" id="Jpe-IK-xK1" userLabel="stateImage">
|
||||||
<rect key="frame" x="46" y="6" width="32" height="32"/>
|
<rect key="frame" x="46" y="6" width="32" height="32"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<animations/>
|
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="2" contentMode="left" text="John Doe" lineBreakMode="tailTruncation" minimumFontSize="10" id="zG2-Kg-0jD" userLabel="displayNameLabel">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="2" contentMode="left" fixedFrame="YES" text="John Doe" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="zG2-Kg-0jD" userLabel="displayNameLabel">
|
||||||
<rect key="frame" x="86" y="0.0" width="237" height="44"/>
|
<rect key="frame" x="86" y="0.0" width="237" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<animations/>
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
|
||||||
<accessibility key="accessibilityConfiguration" label="Firstname"/>
|
<accessibility key="accessibilityConfiguration" label="Firstname"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="21"/>
|
<fontDescription key="fontDescription" type="system" pointSize="21"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="Lfl-dI-bSt" userLabel="detailsButton" customClass="UIIconButton">
|
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Lfl-dI-bSt" userLabel="detailsButton" customClass="UIIconButton">
|
||||||
<rect key="frame" x="331" y="0.0" width="44" height="44"/>
|
<rect key="frame" x="331" y="0.0" width="44" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
<animations/>
|
|
||||||
<state key="normal" image="list_details_default.png">
|
<state key="normal" image="list_details_default.png">
|
||||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</state>
|
</state>
|
||||||
<state key="highlighted" image="list_details_over.png"/>
|
<state key="highlighted" image="list_details_over.png"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
@ -50,17 +48,16 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<animations/>
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
|
||||||
<nil key="simulatedStatusBarMetrics"/>
|
<nil key="simulatedStatusBarMetrics"/>
|
||||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||||
<point key="canvasLocation" x="366.5" y="248"/>
|
<point key="canvasLocation" x="559.5419847328244" y="174.64788732394368"/>
|
||||||
</view>
|
</view>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="avatar.png" width="255" height="255"/>
|
<image name="avatar.png" width="414.39999389648438" height="414.39999389648438"/>
|
||||||
<image name="history_missed_default.png" width="32" height="32"/>
|
<image name="history_missed_default.png" width="52.799999237060547" height="52.799999237060547"/>
|
||||||
<image name="list_details_default.png" width="33" height="34"/>
|
<image name="list_details_default.png" width="54.400001525878906" height="55.200000762939453"/>
|
||||||
<image name="list_details_over.png" width="33" height="34"/>
|
<image name="list_details_over.png" width="54.400001525878906" height="55.200000762939453"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
||||||
|
|
@ -194,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);
|
||||||
|
|
@ -330,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];
|
||||||
|
|
@ -369,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);
|
||||||
|
|
@ -394,6 +391,7 @@
|
||||||
|
|
||||||
securityDialog.securityImage.hidden = FALSE;
|
securityDialog.securityImage.hidden = FALSE;
|
||||||
[securityDialog setSpecialColor];
|
[securityDialog setSpecialColor];
|
||||||
|
[securityDialog setWhiteCancel];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -405,7 +403,6 @@
|
||||||
[ControlsViewModelBridge toggleStatsVisibility];
|
[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)];
|
||||||
|
|
@ -415,10 +412,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,16 +76,20 @@
|
||||||
- (void)update:(BOOL)appear {
|
- (void)update:(BOOL)appear {
|
||||||
[self updateSelectedButton:[PhoneMainView.instance currentView]];
|
[self updateSelectedButton:[PhoneMainView.instance currentView]];
|
||||||
[self updateMissedCall:linphone_core_get_missed_calls_count(LC) appear:appear];
|
[self updateMissedCall:linphone_core_get_missed_calls_count(LC) appear:appear];
|
||||||
[self updateUnreadMessage:appear];
|
if (![LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"]) {
|
||||||
|
[self updateUnreadMessage:appear];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateUnreadMessage:(BOOL)appear {
|
- (void)updateUnreadMessage:(BOOL)appear {
|
||||||
int unreadMessage = [LinphoneManager unreadMessageCount];
|
int unreadMessage = [LinphoneManager unreadMessageCount];
|
||||||
if (unreadMessage > 0) {
|
if (![LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"]) {
|
||||||
_chatNotificationLabel.text = [NSString stringWithFormat:@"%i", unreadMessage];
|
if (unreadMessage > 0) {
|
||||||
[_chatNotificationView startAnimating:appear];
|
_chatNotificationLabel.text = [NSString stringWithFormat:@"%i", unreadMessage];
|
||||||
} else {
|
[_chatNotificationView startAnimating:appear];
|
||||||
[_chatNotificationView stopAnimating:appear];
|
} else {
|
||||||
|
[_chatNotificationView stopAnimating:appear];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +113,25 @@
|
||||||
[view equal:ChatConversationCreateView.compositeViewDescription] ||
|
[view equal:ChatConversationCreateView.compositeViewDescription] ||
|
||||||
[view equal:ChatConversationInfoView.compositeViewDescription] ||
|
[view equal:ChatConversationInfoView.compositeViewDescription] ||
|
||||||
[view equal:ChatConversationImdnView.compositeViewDescription] ||
|
[view equal:ChatConversationImdnView.compositeViewDescription] ||
|
||||||
[view equal:ChatConversationView.compositeViewDescription];
|
[view equal:ChatConversationViewSwift.compositeViewDescription];
|
||||||
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"] && [self viewIsCurrentlyPortrait]) {
|
||||||
|
CGFloat itemWidth = [UIScreen mainScreen].bounds.size.width/3;
|
||||||
|
[_chatButton setEnabled:false];
|
||||||
|
[_chatButton setHidden:true];
|
||||||
|
[_chatNotificationView setHidden:true];
|
||||||
|
_historyButton.frame = CGRectMake(0, 0, itemWidth, 66);
|
||||||
|
_contactsButton.frame = CGRectMake(itemWidth, 0, itemWidth, 66);
|
||||||
|
_dialerButton.frame = CGRectMake(itemWidth*2, 0, itemWidth, 66);
|
||||||
|
_selectedButtonImage.frame = CGRectMake(_selectedButtonImage.frame.origin.x, _selectedButtonImage.frame.origin.y, itemWidth, 3);
|
||||||
|
} else if ([LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"] && ![self viewIsCurrentlyPortrait]) {
|
||||||
|
[_chatButton setEnabled:false];
|
||||||
|
[_chatButton setHidden:true];
|
||||||
|
[_chatNotificationView setHidden:true];
|
||||||
|
_historyButton.frame = CGRectMake(0, 20, 90, 90);
|
||||||
|
_contactsButton.frame = CGRectMake(0, 120, 90, 90);
|
||||||
|
_dialerButton.frame = CGRectMake(0, 220, 90, 90);
|
||||||
|
_selectedButtonImage.frame = CGRectMake(_selectedButtonImage.frame.origin.x, _selectedButtonImage.frame.origin.y, 3, 90);
|
||||||
|
}
|
||||||
CGRect selectedNewFrame = _selectedButtonImage.frame;
|
CGRect selectedNewFrame = _selectedButtonImage.frame;
|
||||||
if ([self viewIsCurrentlyPortrait]) {
|
if ([self viewIsCurrentlyPortrait]) {
|
||||||
selectedNewFrame.origin.x =
|
selectedNewFrame.origin.x =
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
@property(readonly, nonatomic) LinphoneEventLog *event;
|
@property(readonly, nonatomic) LinphoneEventLog *event;
|
||||||
@property(readonly, nonatomic) LinphoneChatMessage *message;
|
@property(readonly, nonatomic) LinphoneChatMessage *message;
|
||||||
@property(nonatomic, weak) IBOutlet UIImageView *backgroundColorImage;
|
@property(nonatomic, weak) IBOutlet UIImageView *backgroundColorImage;
|
||||||
@property(nonatomic, weak) IBOutlet UIRoundedImageView *avatarImage;
|
@property(nonatomic, weak) IBOutlet UIImageView *avatarImage;
|
||||||
@property(nonatomic, weak) IBOutlet UILabel *contactDateLabel;
|
@property(nonatomic, weak) IBOutlet UILabel *contactDateLabel;
|
||||||
//@property(weak, nonatomic) IBOutlet UIActivityIndicatorView *statusInProgressSpinner;
|
//@property(weak, nonatomic) IBOutlet UIActivityIndicatorView *statusInProgressSpinner;
|
||||||
@property(nonatomic, weak) IBOutlet UITextViewNoDefine *messageText;
|
@property(nonatomic, weak) IBOutlet UITextViewNoDefine *messageText;
|
||||||
|
|
|
||||||
|
|
@ -119,16 +119,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setChatMessageForCbs:(LinphoneChatMessage *)amessage {
|
- (void)setChatMessageForCbs:(LinphoneChatMessage *)amessage {
|
||||||
if (!amessage || amessage == _message) {
|
if (amessage == _message) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (_message){
|
||||||
|
linphone_chat_message_unref(_message);
|
||||||
|
}
|
||||||
_message = amessage;
|
_message = amessage;
|
||||||
linphone_chat_message_set_user_data(_message, (void *)CFBridgingRetain(self));
|
if (amessage){
|
||||||
LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(_message);
|
linphone_chat_message_ref(amessage);
|
||||||
linphone_chat_message_cbs_set_msg_state_changed(cbs, message_status);
|
linphone_chat_message_set_user_data(_message, (void *)CFBridgingRetain(self));
|
||||||
linphone_chat_message_cbs_set_participant_imdn_state_changed(cbs, participant_imdn_status);
|
LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(_message);
|
||||||
linphone_chat_message_cbs_set_user_data(cbs, (void *)_event);
|
linphone_chat_message_cbs_set_msg_state_changed(cbs, message_status);
|
||||||
|
linphone_chat_message_cbs_set_participant_imdn_state_changed(cbs, participant_imdn_status);
|
||||||
|
linphone_chat_message_cbs_set_user_data(cbs, (void *)_event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *)TextMessageForChat:(LinphoneChatMessage *)message {
|
+ (NSString *)TextMessageForChat:(LinphoneChatMessage *)message {
|
||||||
|
|
@ -196,9 +201,7 @@
|
||||||
_avatarImage.hidden = TRUE;
|
_avatarImage.hidden = TRUE;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
[_avatarImage setImage:[FastAddressBook imageForAddress:linphone_chat_message_get_from_address(_message)]
|
[_avatarImage setImage:[FastAddressBook imageForAddress:linphone_chat_message_get_from_address(_message)]];
|
||||||
bordered:NO
|
|
||||||
withRoundedRadius:YES];
|
|
||||||
_contactDateLabel.text = [self.class ContactDateForChat:_message];
|
_contactDateLabel.text = [self.class ContactDateForChat:_message];
|
||||||
_contactDateLabel.textAlignment = NSTextAlignmentLeft;
|
_contactDateLabel.textAlignment = NSTextAlignmentLeft;
|
||||||
_avatarImage.hidden = !_isFirst;
|
_avatarImage.hidden = !_isFirst;
|
||||||
|
|
@ -321,11 +324,13 @@
|
||||||
|
|
||||||
- (void)onDelete {
|
- (void)onDelete {
|
||||||
if (_message != NULL) {
|
if (_message != NULL) {
|
||||||
UITableView *tableView = VIEW(ChatConversationView).tableController.tableView;
|
/*
|
||||||
|
UITableView *tableView = VIEW(ChatConversationViewSwift).tableController.tableView;
|
||||||
NSIndexPath *indexPath = [tableView indexPathForCell:self];
|
NSIndexPath *indexPath = [tableView indexPathForCell:self];
|
||||||
[tableView.dataSource tableView:tableView
|
[tableView.dataSource tableView:tableView
|
||||||
commitEditingStyle:UITableViewCellEditingStyleDelete
|
commitEditingStyle:UITableViewCellEditingStyleDelete
|
||||||
forRowAtIndexPath:indexPath];
|
forRowAtIndexPath:indexPath];
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,15 +342,17 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
|
||||||
|
|
||||||
if (!linphone_chat_message_is_outgoing(msg) || (state != LinphoneChatMessageStateFileTransferDone && state != LinphoneChatMessageStateFileTransferInProgress)) {
|
if (!linphone_chat_message_is_outgoing(msg) || (state != LinphoneChatMessageStateFileTransferDone && state != LinphoneChatMessageStateFileTransferInProgress)) {
|
||||||
LinphoneEventLog *event = (LinphoneEventLog *)linphone_chat_message_cbs_get_user_data(linphone_chat_message_get_callbacks(msg));
|
LinphoneEventLog *event = (LinphoneEventLog *)linphone_chat_message_cbs_get_user_data(linphone_chat_message_get_callbacks(msg));
|
||||||
ChatConversationView *view = VIEW(ChatConversationView);
|
ChatConversationViewSwift *view = VIEW(ChatConversationViewSwift);
|
||||||
[view.tableController updateEventEntry:event];
|
//[view.tableController updateEventEntry:event];
|
||||||
[view.tableController scrollToBottom:true];
|
//[view.tableController scrollToBottom:true];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
|
@ -762,7 +769,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
- (void)layoutSubviews {
|
- (void)layoutSubviews {
|
||||||
[super layoutSubviews];
|
[super layoutSubviews];
|
||||||
if (_message != nil) {
|
if (_message != nil) {
|
||||||
UITableView *tableView = VIEW(ChatConversationView).tableController.tableView;
|
//UITableView *tableView = VIEW(ChatConversationViewSwift).tableController.tableView;
|
||||||
BOOL is_outgoing = linphone_chat_message_is_outgoing(_message);
|
BOOL is_outgoing = linphone_chat_message_is_outgoing(_message);
|
||||||
CGRect bubbleFrame = _bubbleView.frame;
|
CGRect bubbleFrame = _bubbleView.frame;
|
||||||
int available_width = self.frame.size.width;
|
int available_width = self.frame.size.width;
|
||||||
|
|
@ -773,11 +780,13 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
bubbleFrame.size.width = MAX(bubbleFrame.size.width, 300);
|
bubbleFrame.size.width = MAX(bubbleFrame.size.width, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (tableView.isEditing) {
|
if (tableView.isEditing) {
|
||||||
origin_x = 0;
|
origin_x = 0;
|
||||||
} else {
|
} else {
|
||||||
origin_x = (is_outgoing ? self.frame.size.width - bubbleFrame.size.width : 0);
|
origin_x = (is_outgoing ? self.frame.size.width - bubbleFrame.size.width : 0);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
CGRect r = _messageText.frame;
|
CGRect r = _messageText.frame;
|
||||||
r.origin.y = linphone_chat_message_is_reply(_message) ? _replyView.view.frame.origin.y + _replyView.view.frame.size.height + 5 : 3;
|
r.origin.y = linphone_chat_message_is_reply(_message) ? _replyView.view.frame.origin.y + _replyView.view.frame.size.height + 5 : 3;
|
||||||
|
|
@ -848,10 +857,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);
|
||||||
|
|
@ -883,7 +895,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
[_messageActionsIcons addObject:@"menu_forward_default"];
|
[_messageActionsIcons addObject:@"menu_forward_default"];
|
||||||
[_messageActionsBlocks addObject:^{
|
[_messageActionsBlocks addObject:^{
|
||||||
[thiz dismissPopup];
|
[thiz dismissPopup];
|
||||||
VIEW(ChatConversationView).pendingForwardMessage = linphone_chat_message_ref(message);
|
VIEW(ChatConversationViewSwift).pendingForwardMessage = message;
|
||||||
[PhoneMainView.instance changeCurrentView:VIEW(ChatsListView).compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:VIEW(ChatsListView).compositeViewDescription];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
@ -893,26 +905,53 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
[_messageActionsIcons addObject:@"menu_reply_default"];
|
[_messageActionsIcons addObject:@"menu_reply_default"];
|
||||||
[_messageActionsBlocks addObject:^{
|
[_messageActionsBlocks addObject:^{
|
||||||
[thiz dismissPopup];
|
[thiz dismissPopup];
|
||||||
[VIEW(ChatConversationView) initiateReplyViewForMessage:message];
|
[VIEW(ChatConversationViewSwift) 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"];
|
||||||
[_messageActionsBlocks addObject:^{
|
[_messageActionsBlocks addObject:^{
|
||||||
[thiz dismissPopup];
|
[thiz dismissPopup];
|
||||||
linphone_chat_room_delete_message(linphone_chat_message_get_chat_room(message), message);
|
linphone_chat_room_delete_message(linphone_chat_message_get_chat_room(message), message);
|
||||||
[VIEW(ChatConversationView).tableController reloadData];
|
//[VIEW(ChatConversationViewSwift).tableController reloadData];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -924,7 +963,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
[VIEW(ChatConversationView).tableController dismissMessagesPopups];
|
//[VIEW(ChatConversationViewSwift).tableController dismissMessagesPopups];
|
||||||
[self buildActions];
|
[self buildActions];
|
||||||
int width = 250;
|
int width = 250;
|
||||||
int cellHeight = 45;
|
int cellHeight = 45;
|
||||||
|
|
@ -932,17 +971,19 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
CGRect screenRect = UIScreen.mainScreen.bounds;
|
CGRect screenRect = UIScreen.mainScreen.bounds;
|
||||||
int menuHeight = numberOfItems * cellHeight;
|
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,
|
||||||
(self.frame.origin.y + self.frame.size.height) - [VIEW(ChatConversationView).tableController .tableView contentOffset].y > screenRect.size.height /2 ? self.frame.origin.y - menuHeight - 10: self.frame.origin.y + self.frame.size.height,
|
(self.frame.origin.y + self.frame.size.height) - [VIEW(ChatConversationViewSwift).tableController .tableView contentOffset].y > screenRect.size.height /2 ? self.frame.origin.y - menuHeight - 10: self.frame.origin.y + self.frame.size.height,
|
||||||
width,
|
width,
|
||||||
menuHeight);
|
menuHeight);*/
|
||||||
|
|
||||||
_popupMenu = [[UITableView alloc]initWithFrame:frame];
|
//_popupMenu = [[UITableView alloc]initWithFrame:frame];
|
||||||
_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;
|
||||||
|
|
@ -955,11 +996,11 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
_popupMenu.editing = NO;
|
_popupMenu.editing = NO;
|
||||||
_popupMenu.userInteractionEnabled = true;
|
_popupMenu.userInteractionEnabled = true;
|
||||||
[_popupMenu reloadData];
|
[_popupMenu reloadData];
|
||||||
[VIEW(ChatConversationView).tableController.view addSubview:_popupMenu];
|
//[VIEW(ChatConversationViewSwift).tableController.view addSubview:_popupMenu];
|
||||||
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOutsideMenu:)];
|
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOutsideMenu:)];
|
||||||
tapGestureRecognizer.cancelsTouchesInView = NO;
|
tapGestureRecognizer.cancelsTouchesInView = NO;
|
||||||
tapGestureRecognizer.numberOfTapsRequired = 1;
|
tapGestureRecognizer.numberOfTapsRequired = 1;
|
||||||
[VIEW(ChatConversationView).tableController.view addGestureRecognizer:tapGestureRecognizer];
|
//[VIEW(ChatConversationViewSwift).tableController.view addGestureRecognizer:tapGestureRecognizer];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) dismissPopup {
|
-(void) dismissPopup {
|
||||||
|
|
@ -972,10 +1013,12 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18;
|
||||||
|
|
||||||
|
|
||||||
-(void) tapOutsideMenu:(UITapGestureRecognizer *) g {
|
-(void) tapOutsideMenu:(UITapGestureRecognizer *) g {
|
||||||
CGPoint p = [g locationInView:VIEW(ChatConversationView).tableController.view];
|
/*
|
||||||
|
CGPoint p = [g locationInView:VIEW(ChatConversationViewSwift).tableController.view];
|
||||||
if (!CGRectContainsPoint(_popupMenu.frame,p)) {
|
if (!CGRectContainsPoint(_popupMenu.frame,p)) {
|
||||||
[self dismissPopup];
|
[self dismissPopup];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,8 @@
|
||||||
LinphoneChatRoom *chatRoom;
|
LinphoneChatRoom *chatRoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property(nonatomic, strong) IBOutlet UIRoundedImageView *avatarImage;
|
@property(readonly, nonatomic) LinphoneEventLog *event;
|
||||||
|
@property(nonatomic, strong) IBOutlet UIImageView *avatarImage;
|
||||||
@property (weak, nonatomic) IBOutlet UIImageView *securityImage;
|
@property (weak, nonatomic) IBOutlet UIImageView *securityImage;
|
||||||
@property(nonatomic, strong) IBOutlet UILabel *addressLabel;
|
@property(nonatomic, strong) IBOutlet UILabel *addressLabel;
|
||||||
@property(nonatomic, strong) IBOutlet UILabel *chatContentLabel;
|
@property(nonatomic, strong) IBOutlet UILabel *chatContentLabel;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,14 +78,15 @@
|
||||||
const LinphoneAddress *addr = firstParticipant ? linphone_participant_get_address(firstParticipant) : linphone_chat_room_get_peer_address(chatRoom);
|
const LinphoneAddress *addr = firstParticipant ? linphone_participant_get_address(firstParticipant) : linphone_chat_room_get_peer_address(chatRoom);
|
||||||
if (addr) {
|
if (addr) {
|
||||||
[ContactDisplay setDisplayNameLabel:_addressLabel forAddress:addr];
|
[ContactDisplay setDisplayNameLabel:_addressLabel forAddress:addr];
|
||||||
[_avatarImage setImage:[FastAddressBook imageForAddress:addr] bordered:NO withRoundedRadius:YES];
|
[_avatarImage setImage:[FastAddressBook imageForAddress:addr]];
|
||||||
} else {
|
} else {
|
||||||
_addressLabel.text = [NSString stringWithUTF8String:LINPHONE_DUMMY_SUBJECT];
|
_addressLabel.text = [NSString stringWithUTF8String:LINPHONE_DUMMY_SUBJECT];
|
||||||
}
|
}
|
||||||
|
bctbx_list_free(participants);
|
||||||
} else {
|
} else {
|
||||||
const char *subject = linphone_chat_room_get_subject(chatRoom);
|
const char *subject = linphone_chat_room_get_subject(chatRoom);
|
||||||
_addressLabel.text = [NSString stringWithUTF8String:subject ?: LINPHONE_DUMMY_SUBJECT];
|
_addressLabel.text = [NSString stringWithUTF8String:subject ?: LINPHONE_DUMMY_SUBJECT];
|
||||||
[_avatarImage setImage:[UIImage imageNamed:@"chat_group_avatar.png"] bordered:NO withRoundedRadius:YES];
|
[_avatarImage setImage:[UIImage imageNamed:@"chat_group_avatar.png"]];
|
||||||
}
|
}
|
||||||
// TODO update security image when security level changed
|
// TODO update security image when security level changed
|
||||||
[_securityImage setImage:[FastAddressBook imageForSecurityLevel:linphone_chat_room_get_security_level(chatRoom)]];
|
[_securityImage setImage:[FastAddressBook imageForSecurityLevel:linphone_chat_room_get_security_level(chatRoom)]];
|
||||||
|
|
@ -89,11 +95,11 @@
|
||||||
|
|
||||||
LinphoneChatMessage *last_msg = linphone_chat_room_get_last_message_in_history(chatRoom);
|
LinphoneChatMessage *last_msg = linphone_chat_room_get_last_message_in_history(chatRoom);
|
||||||
if (last_msg) {
|
if (last_msg) {
|
||||||
BOOL imdnInSnap = FALSE;
|
BOOL imdnInSnap = TRUE;
|
||||||
if (imdnInSnap) {
|
if (imdnInSnap) {
|
||||||
BOOL outgoing = linphone_chat_message_is_outgoing(last_msg);
|
BOOL outgoing = linphone_chat_message_is_outgoing(last_msg);
|
||||||
NSString *text = [UIChatBubbleTextCell TextMessageForChat:last_msg];
|
NSString *text = [UIChatBubbleTextCell TextMessageForChat:last_msg];
|
||||||
if (outgoing) {
|
if (capabilities & LinphoneChatRoomCapabilitiesOneToOne) {
|
||||||
// shorten long messages
|
// shorten long messages
|
||||||
/*if ([text length] > 50)
|
/*if ([text length] > 50)
|
||||||
text = [[text substringToIndex:50] stringByAppendingString:@"[...]"];*/
|
text = [[text substringToIndex:50] stringByAppendingString:@"[...]"];*/
|
||||||
|
|
@ -117,6 +123,13 @@
|
||||||
_chatContentLabel.attributedText = boldText;
|
_chatContentLabel.attributedText = boldText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (outgoing){
|
||||||
|
linphone_chat_message_set_user_data(last_msg, (void *)CFBridgingRetain(self));
|
||||||
|
LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(last_msg);
|
||||||
|
linphone_chat_message_cbs_set_msg_state_changed(cbs, message_status);
|
||||||
|
linphone_chat_message_cbs_set_participant_imdn_state_changed(cbs, participant_imdn_status);
|
||||||
|
linphone_chat_message_cbs_set_user_data(cbs, (void *)_event);
|
||||||
|
}
|
||||||
|
|
||||||
LinphoneChatMessageState state = linphone_chat_message_get_state(last_msg);
|
LinphoneChatMessageState state = linphone_chat_message_get_state(last_msg);
|
||||||
if (outgoing && (state == LinphoneChatMessageStateDeliveredToUser || state == LinphoneChatMessageStateDisplayed || state == LinphoneChatMessageStateNotDelivered || state == LinphoneChatMessageStateFileTransferError)) {
|
if (outgoing && (state == LinphoneChatMessageStateDeliveredToUser || state == LinphoneChatMessageStateDisplayed || state == LinphoneChatMessageStateNotDelivered || state == LinphoneChatMessageStateFileTransferError)) {
|
||||||
|
|
@ -132,7 +145,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)
|
||||||
|
|
@ -214,4 +228,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
|
||||||
|
LOGI(@"State for message [%p] changed to %s", msg, linphone_chat_message_state_to_string(state));
|
||||||
|
if (state == LinphoneChatMessageStateFileTransferInProgress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!linphone_chat_message_is_outgoing(msg) || (state != LinphoneChatMessageStateFileTransferDone && state != LinphoneChatMessageStateFileTransferInProgress)) {
|
||||||
|
ChatsListView *view = VIEW(ChatsListView);
|
||||||
|
[view.tableController updateEventEntry:msg];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void participant_imdn_status(LinphoneChatMessage* msg, const LinphoneParticipantImdnState *state) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
ChatConversationImdnView *imdnView = VIEW(ChatConversationImdnView);
|
||||||
|
[imdnView updateImdnList];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
@interface UIChatConversationImdnTableViewCell : UITableViewCell
|
@interface UIChatConversationImdnTableViewCell : UITableViewCell
|
||||||
|
|
||||||
@property (weak, nonatomic) IBOutlet UIRoundedImageView *avatar;
|
@property (weak, nonatomic) IBOutlet UIImageView *avatar;
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *displayName;
|
@property (weak, nonatomic) IBOutlet UILabel *displayName;
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *dateLabel;
|
@property (weak, nonatomic) IBOutlet UILabel *dateLabel;
|
||||||
- (id)initWithIdentifier:(NSString *)identifier;
|
- (id)initWithIdentifier:(NSString *)identifier;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
@interface UIChatConversationInfoTableViewCell : UITableViewCell <UIGestureRecognizerDelegate>
|
@interface UIChatConversationInfoTableViewCell : UITableViewCell <UIGestureRecognizerDelegate>
|
||||||
|
|
||||||
@property (weak, nonatomic) IBOutlet UIRoundedImageView *avatarImage;
|
@property (weak, nonatomic) IBOutlet UIImageView *avatarImage;
|
||||||
@property (weak, nonatomic) IBOutlet UIIconButton *removeButton;
|
@property (weak, nonatomic) IBOutlet UIIconButton *removeButton;
|
||||||
@property (weak, nonatomic) IBOutlet UIView *adminButton;
|
@property (weak, nonatomic) IBOutlet UIView *adminButton;
|
||||||
@property (weak, nonatomic) IBOutlet UILabel *adminLabel;
|
@property (weak, nonatomic) IBOutlet UILabel *adminLabel;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
@property(weak, nonatomic) IBOutlet UILabel *addressLabel;
|
@property(weak, nonatomic) IBOutlet UILabel *addressLabel;
|
||||||
@property (weak, nonatomic) IBOutlet UIImageView *selectedImage;
|
@property (weak, nonatomic) IBOutlet UIImageView *selectedImage;
|
||||||
@property (weak, nonatomic) IBOutlet UIImageView *linphoneImage;
|
@property (weak, nonatomic) IBOutlet UIImageView *linphoneImage;
|
||||||
@property (weak, nonatomic) IBOutlet UIRoundedImageView *avatarImage;
|
@property (weak, nonatomic) IBOutlet UIImageView *avatarImage;
|
||||||
@property (weak, nonatomic) IBOutlet UIImageView *securityImage;
|
@property (weak, nonatomic) IBOutlet UIImageView *securityImage;
|
||||||
@property (weak, nonatomic) IBOutlet UIView *greyView;
|
@property (weak, nonatomic) IBOutlet UIView *greyView;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -657,6 +663,8 @@
|
||||||
// 4. side menu
|
// 4. side menu
|
||||||
self.sideMenuView.frame = sideMenuFrame;
|
self.sideMenuView.frame = sideMenuFrame;
|
||||||
self.sideMenuViewController.view.frame = self.sideMenuView.bounds;
|
self.sideMenuViewController.view.frame = self.sideMenuView.bounds;
|
||||||
|
[PhoneMainView.instance.mainViewController.view bringSubviewToFront:_sideMenuView];
|
||||||
|
[PhoneMainView.instance.mainViewController.view bringSubviewToFront:_sideMenuViewController.view];
|
||||||
|
|
||||||
// Commit animation
|
// Commit animation
|
||||||
if (tabBar != nil || statusBar != nil || sideMenu != nil || fullscreen != nil) {
|
if (tabBar != nil || statusBar != nil || sideMenu != nil || fullscreen != nil) {
|
||||||
|
|
|
||||||
|
|
@ -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,13 +52,18 @@ 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;
|
||||||
|
@property(weak, nonatomic) IBOutlet UILabel *subscribeLabel;
|
||||||
|
|
||||||
|
|
||||||
- (void)setSpecialColor;
|
- (void)setSpecialColor;
|
||||||
-(void) setWhiteCancel;
|
-(void) setWhiteCancel;
|
||||||
- (IBAction)onCancelClick:(id)sender;
|
- (IBAction)onCancelClick:(id)sender;
|
||||||
- (IBAction)onConfirmationClick:(id)sender;
|
- (IBAction)onConfirmationClick:(id)sender;
|
||||||
- (IBAction)onAuthClick:(id)sender;
|
- (IBAction)onAuthClick:(id)sender;
|
||||||
|
- (IBAction)onSubscribeTap:(id)sender;
|
||||||
- (void)dismiss;
|
- (void)dismiss;
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -131,4 +145,12 @@
|
||||||
- (void)dismiss {
|
- (void)dismiss {
|
||||||
[self onCancelClick:nil];
|
[self onCancelClick:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IBAction)onSubscribeTap:(id)sender {
|
||||||
|
UIGestureRecognizer *gest = sender;
|
||||||
|
NSString *url = ((UILabel *)gest.view).text;
|
||||||
|
if (![UIApplication.sharedApplication openURL:[NSURL URLWithString:url]]) {
|
||||||
|
LOGE(@"Failed to open %@, invalid URL", url);
|
||||||
|
}
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@
|
||||||
@interface UIContactCell : UITableViewCell
|
@interface UIContactCell : UITableViewCell
|
||||||
|
|
||||||
@property(nonatomic, strong) IBOutlet UILabel *nameLabel;
|
@property(nonatomic, strong) IBOutlet UILabel *nameLabel;
|
||||||
@property(nonatomic, strong) IBOutlet UIRoundedImageView *avatarImage;
|
@property(nonatomic, strong) IBOutlet UILabel *organizationLabel;
|
||||||
|
@property(nonatomic, strong) IBOutlet UIImageView *avatarImage;
|
||||||
@property(weak, nonatomic) IBOutlet UIImageView *linphoneImage;
|
@property(weak, nonatomic) IBOutlet UIImageView *linphoneImage;
|
||||||
@property(nonatomic, assign) Contact *contact;
|
@property(nonatomic, assign) Contact *contact;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@
|
||||||
_linphoneImage.hidden = TRUE;
|
_linphoneImage.hidden = TRUE;
|
||||||
if(_contact) {
|
if(_contact) {
|
||||||
[ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
|
[ContactDisplay setDisplayNameLabel:_nameLabel forContact:_contact];
|
||||||
|
_organizationLabel.text = [FastAddressBook ogrganizationForContact:_contact];
|
||||||
_linphoneImage.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"] ||
|
_linphoneImage.hidden = [LinphoneManager.instance lpConfigBoolForKey:@"hide_linphone_contacts" inSection:@"app"] ||
|
||||||
! ((_contact.friend && linphone_presence_model_get_basic_status(linphone_friend_get_presence_model(_contact.friend)) == LinphonePresenceBasicStatusOpen) || [FastAddressBook contactHasValidSipDomain:_contact]);
|
! ((_contact.friend && linphone_presence_model_get_basic_status(linphone_friend_get_presence_model(_contact.friend)) == LinphonePresenceBasicStatusOpen) || [FastAddressBook contactHasValidSipDomain:_contact]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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"] || [LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr) {
|
if (addr) {
|
||||||
|
|
@ -80,7 +86,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)shouldHideEncryptedChatView:(BOOL)hasLime {
|
- (void)shouldHideEncryptedChatView:(BOOL)hasLime {
|
||||||
_encryptedChatView.hidden = !hasLime;
|
_encryptedChatView.hidden = !hasLime || [LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"];
|
||||||
CGRect newFrame = _optionsView.frame;
|
CGRect newFrame = _optionsView.frame;
|
||||||
if (!hasLime) {
|
if (!hasLime) {
|
||||||
newFrame.origin.x = _addressLabel.frame.origin.x + _callButton.frame.size.width * 2/3;
|
newFrame.origin.x = _addressLabel.frame.origin.x + _callButton.frame.size.width * 2/3;
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
@property (nonatomic, assign) LinphoneCallLog *callLog;
|
@property (nonatomic, assign) LinphoneCallLog *callLog;
|
||||||
|
|
||||||
@property(weak, nonatomic) IBOutlet UIRoundedImageView *avatarImage;
|
@property(weak, nonatomic) IBOutlet UIImageView *avatarImage;
|
||||||
@property(nonatomic, strong) IBOutlet UILabel *displayNameLabel;
|
@property(nonatomic, strong) IBOutlet UILabel *displayNameLabel;
|
||||||
@property(weak, nonatomic) IBOutlet UIImageView *stateImage;
|
@property(weak, nonatomic) IBOutlet UIImageView *stateImage;
|
||||||
@property(weak, nonatomic) IBOutlet UIIconButton *detailsButton;
|
@property(weak, nonatomic) IBOutlet UIIconButton *detailsButton;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
@ -118,7 +118,7 @@
|
||||||
[displayNameLabel.text stringByAppendingString:[NSString stringWithFormat:@" (%lu)", count]];
|
[displayNameLabel.text stringByAppendingString:[NSString stringWithFormat:@" (%lu)", count]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[_avatarImage setImage:[FastAddressBook imageForAddress:addr] bordered:NO withRoundedRadius:YES];
|
[_avatarImage setImage:[FastAddressBook imageForAddress:addr]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,12 +92,6 @@
|
||||||
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal];
|
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal];
|
||||||
[_stopButton setTitle:@"" forState:UIControlStateNormal];
|
[_stopButton setTitle:@"" forState:UIControlStateNormal];
|
||||||
[_stopButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemRefresh:[UIColor blackColor]] forState:UIControlStateNormal];
|
[_stopButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemRefresh:[UIColor blackColor]] forState:UIControlStateNormal];
|
||||||
if (linphone_player_get_is_video_available(player)) {
|
|
||||||
linphone_player_set_window_id(player, (__bridge void *)VIEW(RecordingsListView).videoView);
|
|
||||||
VIEW(RecordingsListView).videoView.hidden = NO;
|
|
||||||
} else {
|
|
||||||
VIEW(RecordingsListView).videoView.hidden = YES;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isOpened {
|
- (BOOL)isOpened {
|
||||||
|
|
@ -195,6 +189,12 @@ void on_eof_reached(LinphonePlayer *pl) {
|
||||||
[_playButton setTitle:@"" forState:UIControlStateNormal];
|
[_playButton setTitle:@"" forState:UIControlStateNormal];
|
||||||
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPause:[UIColor blackColor]] forState:UIControlStateNormal];
|
[_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPause:[UIColor blackColor]] forState:UIControlStateNormal];
|
||||||
linphone_player_start(player);
|
linphone_player_start(player);
|
||||||
|
if (linphone_player_get_is_video_available(player)) {
|
||||||
|
linphone_player_set_window_id(player, (__bridge void *)VIEW(RecordingsListView).videoView);
|
||||||
|
VIEW(RecordingsListView).videoView.hidden = NO;
|
||||||
|
} else {
|
||||||
|
VIEW(RecordingsListView).videoView.hidden = YES;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case LinphonePlayerPlaying:
|
case LinphonePlayerPlaying:
|
||||||
NSLog(@"Pause");
|
NSLog(@"Pause");
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -90,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 {
|
||||||
|
|
@ -105,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];
|
||||||
}
|
}
|
||||||
|
|
@ -122,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.
|
|
@ -20,6 +20,7 @@ import linphonesw
|
||||||
var previousFilter : String?
|
var previousFilter : String?
|
||||||
var magicSearch : MagicSearch
|
var magicSearch : MagicSearch
|
||||||
var magicSearchDelegate : MagicSearchDelegate?
|
var magicSearchDelegate : MagicSearchDelegate?
|
||||||
|
var lastSearch : [SearchResult]?
|
||||||
|
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
|
|
@ -30,10 +31,12 @@ import linphonesw
|
||||||
magicSearchDelegate = MagicSearchDelegateStub(onSearchResultsReceived: { (magicSearch: MagicSearch) in
|
magicSearchDelegate = MagicSearchDelegateStub(onSearchResultsReceived: { (magicSearch: MagicSearch) in
|
||||||
self.needUpdateLastSearchContacts = true
|
self.needUpdateLastSearchContacts = true
|
||||||
self.ongoingSearch = false
|
self.ongoingSearch = false
|
||||||
|
self.lastSearch = magicSearch.lastSearch
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "Contact magic search -- filter = \(String(describing: self.previousFilter)) -- \(magicSearch.lastSearch.count) contact founds")
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "Contact magic search -- filter = \(String(describing: self.previousFilter)) -- \(magicSearch.lastSearch.count) contact founds")
|
||||||
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 +50,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 +78,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 +88,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,8 +103,10 @@ import linphonesw
|
||||||
@objc func getLastSearchResults() -> UnsafeMutablePointer<bctbx_list_t>? {
|
@objc func getLastSearchResults() -> UnsafeMutablePointer<bctbx_list_t>? {
|
||||||
|
|
||||||
var cList: UnsafeMutablePointer<bctbx_list_t>? = nil
|
var cList: UnsafeMutablePointer<bctbx_list_t>? = nil
|
||||||
for data in magicSearch.lastSearch {
|
if let search = lastSearch {
|
||||||
cList = bctbx_list_append(cList, UnsafeMutableRawPointer(data.getCobject))
|
for data in search {
|
||||||
|
cList = bctbx_list_append(cList, UnsafeMutableRawPointer(data.getCobject))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return cList
|
return cList
|
||||||
}
|
}
|
||||||
|
|
@ -100,13 +114,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
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@
|
||||||
- (void)getOrCreateOneToOneChatRoom:(const LinphoneAddress *)remoteAddress waitView:(UIView *)waitView isEncrypted:(BOOL)isEncrypted;
|
- (void)getOrCreateOneToOneChatRoom:(const LinphoneAddress *)remoteAddress waitView:(UIView *)waitView isEncrypted:(BOOL)isEncrypted;
|
||||||
- (LinphoneChatRoom *)createChatRoom:(const char *)subject addresses:(bctbx_list_t *)addresses andWaitView:(UIView *)waitView isEncrypted:(BOOL)isEncrypted isGroup:(BOOL)isGroup;
|
- (LinphoneChatRoom *)createChatRoom:(const char *)subject addresses:(bctbx_list_t *)addresses andWaitView:(UIView *)waitView isEncrypted:(BOOL)isEncrypted isGroup:(BOOL)isGroup;
|
||||||
- (void)goToChatRoom:(LinphoneChatRoom *)cr;
|
- (void)goToChatRoom:(LinphoneChatRoom *)cr;
|
||||||
|
- (void)goToChatRoomSwift:(LinphoneChatRoom *)cr;
|
||||||
|
- (void)resetBeforeGoToChatRoomSwift;
|
||||||
+ (PhoneMainView*) instance;
|
+ (PhoneMainView*) instance;
|
||||||
|
|
||||||
- (BOOL)isIphoneXDevice;
|
- (BOOL)isIphoneXDevice;
|
||||||
|
|
@ -123,3 +125,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);
|
||||||
|
|
|
||||||
|
|
@ -307,9 +307,9 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
if (linphone_chat_message_is_outgoing(msg))
|
if (linphone_chat_message_is_outgoing(msg))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatConversationView *view = VIEW(ChatConversationView);
|
ChatConversationViewSwift *view = VIEW(ChatConversationViewSwift);
|
||||||
// if we already are in the conversation, we should not ring/vibrate
|
// if we already are in the conversation, we should not ring/vibrate
|
||||||
if (view.chatRoom && _currentRoom == view.chatRoom)
|
if (view.linphoneChatRoom && _currentRoom == view.linphoneChatRoom)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive)
|
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive)
|
||||||
|
|
@ -375,7 +375,6 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LinphoneCallOutgoingInit:
|
|
||||||
case LinphoneCallOutgoingEarlyMedia:
|
case LinphoneCallOutgoingEarlyMedia:
|
||||||
case LinphoneCallOutgoingProgress:
|
case LinphoneCallOutgoingProgress:
|
||||||
case LinphoneCallOutgoingRinging: {
|
case LinphoneCallOutgoingRinging: {
|
||||||
|
|
@ -387,7 +386,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*/
|
||||||
|
|
@ -419,6 +418,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];
|
||||||
|
|
@ -454,9 +454,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:@"ChatConversationViewSwift"]) {
|
||||||
|
|
||||||
if (linphone_core_get_global_state(LC) != LinphoneGlobalOn) {
|
if (linphone_core_get_global_state(LC) != LinphoneGlobalOn) {
|
||||||
[self changeCurrentView:DialerView.compositeViewDescription];
|
[self changeCurrentView:DialerView.compositeViewDescription];
|
||||||
|
|
@ -608,7 +618,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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -622,18 +633,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)];
|
||||||
|
|
@ -654,7 +666,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{
|
||||||
|
|
@ -842,7 +855,7 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self goToChatRoom:room];
|
[self goToChatRoomSwift:room];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (LinphoneChatRoom *)createChatRoom:(const char *)subject addresses:(bctbx_list_t *)addresses andWaitView:(UIView *)waitView isEncrypted:(BOOL)isEncrypted isGroup:(BOOL)isGroup{
|
- (LinphoneChatRoom *)createChatRoom:(const char *)subject addresses:(bctbx_list_t *)addresses andWaitView:(UIView *)waitView isEncrypted:(BOOL)isEncrypted isGroup:(BOOL)isGroup{
|
||||||
|
|
@ -865,7 +878,7 @@ static RootViewManager *rootViewManagerInstance = nil;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
LinphoneChatRoom *basicRoom = linphone_core_get_chat_room(LC, addresses->data);
|
LinphoneChatRoom *basicRoom = linphone_core_get_chat_room(LC, addresses->data);
|
||||||
[self goToChatRoom:basicRoom];
|
[self goToChatRoomSwift:basicRoom];
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -888,6 +901,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;
|
||||||
|
|
@ -905,31 +919,50 @@ 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)goToChatRoomSwift:(LinphoneChatRoom *)cr {
|
||||||
|
_waitView.hidden = YES;
|
||||||
|
_waitView = NULL;
|
||||||
|
ChatConversationViewSwift *view = VIEW(ChatConversationViewSwift);
|
||||||
|
self.currentRoom = view.linphoneChatRoom;
|
||||||
|
[view initChatRoomWithCChatRoom:cr];
|
||||||
|
|
||||||
|
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)resetBeforeGoToChatRoomSwift{
|
||||||
|
ChatConversationViewSwift *view = VIEW(ChatConversationViewSwift);
|
||||||
|
[view resetView];
|
||||||
|
}
|
||||||
|
|
||||||
|
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 goToChatRoomSwift:cr];
|
||||||
|
if (!IPAD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (PhoneMainView.instance.currentView != ChatsListView.compositeViewDescription && PhoneMainView.instance.currentView != ChatConversationViewSwift.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));
|
||||||
|
|
@ -938,7 +971,7 @@ void main_view_chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomSta
|
||||||
break;
|
break;
|
||||||
case LinphoneChatRoomStateTerminated:
|
case LinphoneChatRoomStateTerminated:
|
||||||
LOGI(@"Chat room [%p] has been terminated.", cr);
|
LOGI(@"Chat room [%p] has been terminated.", cr);
|
||||||
[view goToChatRoom:cr];
|
[view goToChatRoomSwift:cr];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -962,4 +995,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,26 @@ 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 {
|
||||||
|
[LinphoneManager.instance lpConfigSetBool:FALSE forKey:@"auto_download_mode_is_never"];
|
||||||
|
[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"];
|
||||||
|
[LinphoneManager.instance lpConfigSetBool:FALSE forKey:@"auto_write_to_gallery_preference"];
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
[hiddenKeys addObject:@"vfs_enabled_mode"];
|
||||||
|
[keys addObject:@"vfs_enabled"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (NSString *key in keys) {
|
for (NSString *key in keys) {
|
||||||
if (removeFromHiddenKeys)
|
if (removeFromHiddenKeys)
|
||||||
|
|
@ -552,11 +570,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 +602,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 +610,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,23 +645,40 @@ 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)) {
|
||||||
[hiddenKeys addObject:@"contacts_menu"];
|
[hiddenKeys addObject:@"contacts_menu"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"disable_chat_feature"]){
|
||||||
|
[hiddenKeys addObject:@"message_menu"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([LinphoneManager.instance lpConfigBoolForKey:@"disable_video_feature"]) {
|
||||||
|
[hiddenKeys addObject:@"enable_video_preference"];
|
||||||
|
[hiddenKeys addObject:@"video_menu"];
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
[hiddenKeys addObject:@"debug_actions_group"];
|
[hiddenKeys addObject:@"debug_actions_group"];
|
||||||
[hiddenKeys addObject:@"release_button"];
|
[hiddenKeys addObject:@"release_button"];
|
||||||
|
|
@ -761,6 +798,13 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
if (![[lm lpConfigStringForKey:@"auto_download_mode"] isEqualToString:@"Customize"]) {
|
if (![[lm lpConfigStringForKey:@"auto_download_mode"] isEqualToString:@"Customize"]) {
|
||||||
[hiddenKeys addObject:@"auto_download_incoming_files_max_size"];
|
[hiddenKeys addObject:@"auto_download_incoming_files_max_size"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ([lm lpConfigBoolForKey:@"vfs_enabled_mode"]) {
|
||||||
|
[hiddenKeys addObject:@"auto_write_to_gallery_mode"];
|
||||||
|
[hiddenKeys addObject:@"vfs_enabled_mode"];
|
||||||
|
}else{
|
||||||
|
[hiddenKeys addObject:@"vfs_enabled"];
|
||||||
|
}
|
||||||
|
|
||||||
return hiddenKeys;
|
return hiddenKeys;
|
||||||
}
|
}
|
||||||
|
|
@ -851,25 +895,34 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
[PhoneMainView.instance changeCurrentView:AssistantView.compositeViewDescription];
|
[PhoneMainView.instance changeCurrentView:AssistantView.compositeViewDescription];
|
||||||
return;
|
return;
|
||||||
} else if ([key isEqual:@"account_mandatory_remove_button"]) {
|
} else if ([key isEqual:@"account_mandatory_remove_button"]) {
|
||||||
UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Warning", nil)
|
NSString *popUpText;
|
||||||
message:NSLocalizedString(@"Are you sure to want to remove your proxy setup?", nil)
|
NSString *appDomain = [LinphoneManager.instance lpConfigStringForKey:@"domain_name"
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
inSection:@"app"
|
||||||
|
withDefault:@"sip.linphone.org"];
|
||||||
|
|
||||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil)
|
MSList *accountList = [LinphoneManager.instance createAccountsNotHiddenList];
|
||||||
style:UIAlertActionStyleDefault
|
LinphoneAccount *account = bctbx_list_nth_data(accountList,
|
||||||
handler:^(UIAlertAction * action) {}];
|
[settingsStore integerForKey:@"current_proxy_config_preference"]);
|
||||||
|
|
||||||
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Yes", nil)
|
bool isLinphoneAccount = strcmp(appDomain.UTF8String, linphone_account_params_get_domain(linphone_account_get_params(account))) == 0;
|
||||||
style:UIAlertActionStyleDefault
|
if (isLinphoneAccount) {
|
||||||
handler:^(UIAlertAction * action) {
|
popUpText = NSLocalizedString(@"Your account will only be deleted locally.\nTo delete it permanently, go to our account management platform:", nil);
|
||||||
[settingsStore removeAccount];
|
} else {
|
||||||
[self recomputeAccountLabelsAndSync];
|
popUpText = NSLocalizedString(@"Your account will only be deleted locally.\nTo delete it permanently, go on your SIP provider website.", nil);
|
||||||
[_settingsController.navigationController popViewControllerAnimated:NO];
|
}
|
||||||
}];
|
bctbx_free(accountList);
|
||||||
|
|
||||||
[errView addAction:defaultAction];
|
UIConfirmationDialog *dialog = [UIConfirmationDialog ShowWithMessage:popUpText
|
||||||
[errView addAction:continueAction];
|
cancelMessage:nil
|
||||||
[self presentViewController:errView animated:YES completion:nil];
|
confirmMessage:nil
|
||||||
|
onCancelClick:nil
|
||||||
|
onConfirmationClick:^() {
|
||||||
|
[settingsStore removeAccount];
|
||||||
|
[self recomputeAccountLabelsAndSync];
|
||||||
|
[_settingsController.navigationController popViewControllerAnimated:NO];
|
||||||
|
}];
|
||||||
|
dialog.subscribeLabel.hidden = !isLinphoneAccount; // Only display link to https://subscribe.linphone.org for linphone accounts
|
||||||
|
|
||||||
} else if ([key isEqual:@"account_mandatory_change_password"]) {
|
} else if ([key isEqual:@"account_mandatory_change_password"]) {
|
||||||
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Change your password", nil)
|
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Change your password", nil)
|
||||||
message:NSLocalizedString(@"Please enter and confirm your new password", nil)
|
message:NSLocalizedString(@"Please enter and confirm your new password", nil)
|
||||||
|
|
@ -901,8 +954,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(
|
||||||
|
|
@ -1072,6 +1128,14 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
|
|
||||||
// retrieve linphone logs if available
|
// retrieve linphone logs if available
|
||||||
char *filepath = linphone_core_compress_log_collection();
|
char *filepath = linphone_core_compress_log_collection();
|
||||||
|
|
||||||
|
|
||||||
|
LinphoneCoreCbs *coreCbs = linphone_factory_create_core_cbs(linphone_factory_get());
|
||||||
|
linphone_core_cbs_set_log_collection_upload_state_changed(coreCbs, core_log_collection_upload_state_changed);
|
||||||
|
linphone_core_add_callbacks(LC, coreCbs);
|
||||||
|
|
||||||
|
linphone_core_upload_log_collection(LC);
|
||||||
|
|
||||||
if (filepath != NULL) {
|
if (filepath != NULL) {
|
||||||
NSString *filename = [[NSString stringWithUTF8String:filepath] componentsSeparatedByString:@"/"].lastObject;
|
NSString *filename = [[NSString stringWithUTF8String:filepath] componentsSeparatedByString:@"/"].lastObject;
|
||||||
NSString *mimeType = nil;
|
NSString *mimeType = nil;
|
||||||
|
|
@ -1119,6 +1183,17 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat
|
||||||
[self emailAttachments:attachments];
|
[self emailAttachments:attachments];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void core_log_collection_upload_state_changed(LinphoneCore *core, LinphoneCoreLogCollectionUploadState state , const char* info) {
|
||||||
|
|
||||||
|
LOGD(@"LinphoneCoreLogCollectionUploadStateDelivered core_log_collection_upload_state_changed %s", info);
|
||||||
|
if (state == LinphoneCoreLogCollectionUploadStateDelivered) {
|
||||||
|
LOGD(@"LinphoneCoreLogCollectionUploadStateDelivered %s", info);
|
||||||
|
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
|
||||||
|
|
||||||
|
pasteboard.string = [NSString stringWithUTF8String: info];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)sendEmailWithPrivacyAttachments {
|
- (void)sendEmailWithPrivacyAttachments {
|
||||||
NSMutableArray *attachments = [[NSMutableArray alloc] initWithCapacity:4];
|
NSMutableArray *attachments = [[NSMutableArray alloc] initWithCapacity:4];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"]
|
||||||
|
|
@ -103,13 +106,17 @@
|
||||||
}]];
|
}]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[_sideMenuEntries addObject:[[SideMenuEntry alloc] initWithTitle:VoipTexts.conference_scheduled
|
LinphoneAccount *defaultAccount = linphone_core_get_default_account(LC);
|
||||||
image:[UIImage imageNamed:@"menu_voip_meeting_schedule"]
|
if (defaultAccount && linphone_account_params_get_audio_video_conference_factory_address(linphone_account_get_params(defaultAccount))){
|
||||||
tapBlock:^() {
|
|
||||||
[PhoneMainView.instance
|
[_sideMenuEntries addObject:[[SideMenuEntry alloc] initWithTitle:VoipTexts.conference_scheduled
|
||||||
changeCurrentView:ScheduledConferencesView.compositeViewDescription];
|
image:[UIImage imageNamed:@"side_menu_voip_meeting_schedule"]
|
||||||
|
tapBlock:^() {
|
||||||
|
[PhoneMainView.instance
|
||||||
|
changeCurrentView:ScheduledConferencesView.compositeViewDescription];
|
||||||
|
|
||||||
}]];
|
}]];
|
||||||
|
}
|
||||||
|
|
||||||
[_sideMenuEntries addObject:[[SideMenuEntry alloc] initWithTitle:NSLocalizedString(@"About", nil)
|
[_sideMenuEntries addObject:[[SideMenuEntry alloc] initWithTitle:NSLocalizedString(@"About", nil)
|
||||||
image:[UIImage imageNamed:@"menu_about.png"]
|
image:[UIImage imageNamed:@"menu_about.png"]
|
||||||
|
|
@ -127,9 +134,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 +152,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) {
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ enum NetworkType: Int {
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "File :\(file) removed")
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "File :\(file) removed")
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
print("Could not remove file : \(file) \(error)")
|
Log.e("Could not remove file : \(file) \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||||
*
|
*
|
||||||
* This file is part of linphone-iphone
|
* This file is part of linphone-iphone
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import linphonesw
|
import linphonesw
|
||||||
|
|
@ -27,14 +27,14 @@ 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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CallManager is a class that manages application calls and supports callkit.
|
* CallManager is a class that manages application calls and supports callkit.
|
||||||
* There is only one CallManager by calling CallManager.instance().
|
* There is only one CallManager by calling CallManager.instance().
|
||||||
*/
|
*/
|
||||||
@objc class CallManager: NSObject, CoreDelegate {
|
@objc class CallManager: NSObject, CoreDelegate {
|
||||||
static var theCallManager: CallManager?
|
static var theCallManager: CallManager?
|
||||||
let providerDelegate: ProviderDelegate! // to support callkit
|
let providerDelegate: ProviderDelegate! // to support callkit
|
||||||
|
|
@ -49,28 +49,31 @@ 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 endCallKitReplacedCall: Bool = true
|
||||||
|
static var uuidReplacedCall: String?
|
||||||
|
|
||||||
var backgroundContextCall : Call?
|
var backgroundContextCall : Call?
|
||||||
@objc var backgroundContextCameraIsEnabled : Bool = false
|
@objc var backgroundContextCameraIsEnabled : Bool = false
|
||||||
|
|
||||||
fileprivate override init() {
|
fileprivate override init() {
|
||||||
providerDelegate = ProviderDelegate.shared
|
providerDelegate = ProviderDelegate.shared
|
||||||
callController = CXCallController()
|
callController = CXCallController()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc static func instance() -> CallManager {
|
@objc static func instance() -> CallManager {
|
||||||
if (theCallManager == nil) {
|
if (theCallManager == nil) {
|
||||||
theCallManager = CallManager()
|
theCallManager = CallManager()
|
||||||
}
|
}
|
||||||
return theCallManager!
|
return theCallManager!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@objc func setCore(core: OpaquePointer) {
|
@objc func setCore(core: OpaquePointer) {
|
||||||
lc = Core.getSwiftObject(cObject: core)
|
lc = Core.getSwiftObject(cObject: core)
|
||||||
lc?.addDelegate(delegate: self)
|
lc?.addDelegate(delegate: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc static func getAppData(call: OpaquePointer) -> CallAppData? {
|
@objc static func getAppData(call: OpaquePointer) -> CallAppData? {
|
||||||
let sCall = Call.getSwiftObject(cObject: call)
|
let sCall = Call.getSwiftObject(cObject: call)
|
||||||
return getAppData(sCall: sCall)
|
return getAppData(sCall: sCall)
|
||||||
|
|
@ -82,7 +85,7 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
return Unmanaged<CallAppData>.fromOpaque(sCall.userData!).takeUnretainedValue()
|
return Unmanaged<CallAppData>.fromOpaque(sCall.userData!).takeUnretainedValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc static func setAppData(call:OpaquePointer, appData: CallAppData) {
|
@objc static func setAppData(call:OpaquePointer, appData: CallAppData) {
|
||||||
let sCall = Call.getSwiftObject(cObject: call)
|
let sCall = Call.getSwiftObject(cObject: call)
|
||||||
setAppData(sCall: sCall, appData: appData)
|
setAppData(sCall: sCall, appData: appData)
|
||||||
|
|
@ -98,12 +101,12 @@ import AVFoundation
|
||||||
sCall.userData = UnsafeMutableRawPointer(Unmanaged.passRetained(appData!).toOpaque())
|
sCall.userData = UnsafeMutableRawPointer(Unmanaged.passRetained(appData!).toOpaque())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func findCall(callId: String?) -> OpaquePointer? {
|
@objc func findCall(callId: String?) -> OpaquePointer? {
|
||||||
let call = callByCallId(callId: callId)
|
let call = callByCallId(callId: callId)
|
||||||
return call?.getCobject
|
return call?.getCobject
|
||||||
}
|
}
|
||||||
|
|
||||||
func callByCallId(callId: String?) -> Call? {
|
func callByCallId(callId: String?) -> Call? {
|
||||||
if (callId == nil) {
|
if (callId == nil) {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -114,7 +117,7 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func stopLinphoneCore() {
|
@objc func stopLinphoneCore() {
|
||||||
if (lc?.callsNb == 0) {
|
if (lc?.callsNb == 0) {
|
||||||
lc?.stopAsync()
|
lc?.stopAsync()
|
||||||
|
|
@ -133,11 +136,11 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc static func callKitEnabled() -> Bool {
|
@objc static func callKitEnabled() -> Bool {
|
||||||
#if !targetEnvironment(simulator)
|
#if !targetEnvironment(simulator)
|
||||||
if ConfigManager.instance().lpConfigBoolForKey(key: "use_callkit", section: "app") {
|
if ConfigManager.instance().lpConfigBoolForKey(key: "use_callkit", section: "app") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,17 +211,17 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func displayIncomingCall(call:Call?, handle: String, hasVideo: Bool, callId: String, displayName:String) {
|
func displayIncomingCall(call:Call?, handle: String, hasVideo: Bool, callId: String, displayName:String) {
|
||||||
let uuid = UUID()
|
let uuid = UUID()
|
||||||
let callInfo = CallInfo.newIncomingCallInfo(callId: callId)
|
let callInfo = CallInfo.newIncomingCallInfo(callId: callId)
|
||||||
|
|
||||||
providerDelegate.callInfos.updateValue(callInfo, forKey: uuid)
|
providerDelegate.callInfos.updateValue(callInfo, forKey: uuid)
|
||||||
providerDelegate.uuids.updateValue(uuid, forKey: callId)
|
providerDelegate.uuids.updateValue(uuid, forKey: callId)
|
||||||
providerDelegate.reportIncomingCall(call:call, uuid: uuid, handle: handle, hasVideo: hasVideo, displayName: displayName)
|
providerDelegate.reportIncomingCall(call:call, uuid: uuid, handle: handle, hasVideo: hasVideo, displayName: displayName)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func acceptCall(call: OpaquePointer?, hasVideo:Bool) {
|
@objc func acceptCall(call: OpaquePointer?, hasVideo:Bool) {
|
||||||
if (call == nil) {
|
if (call == nil) {
|
||||||
Log.directLog(BCTBX_LOG_ERROR, text: "Can not accept null call!")
|
Log.directLog(BCTBX_LOG_ERROR, text: "Can not accept null call!")
|
||||||
|
|
@ -227,7 +230,7 @@ import AVFoundation
|
||||||
let call = Call.getSwiftObject(cObject: call!)
|
let call = Call.getSwiftObject(cObject: call!)
|
||||||
acceptCall(call: call, hasVideo: hasVideo)
|
acceptCall(call: call, hasVideo: hasVideo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func acceptCall(call: Call, hasVideo:Bool) {
|
func acceptCall(call: Call, hasVideo:Bool) {
|
||||||
do {
|
do {
|
||||||
let callParams = try lc!.createCallParams(call: call)
|
let callParams = try lc!.createCallParams(call: call)
|
||||||
|
|
@ -239,7 +242,7 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
callParams.lowBandwidthEnabled = low_bandwidth
|
callParams.lowBandwidthEnabled = low_bandwidth
|
||||||
}
|
}
|
||||||
|
|
||||||
//We set the record file name here because we can't do it after the call is started.
|
//We set the record file name here because we can't do it after the call is started.
|
||||||
let address = call.callLog?.fromAddress
|
let address = call.callLog?.fromAddress
|
||||||
let writablePath = AppManager.recordingFilePathFromCall(address: address?.username ?? "")
|
let writablePath = AppManager.recordingFilePathFromCall(address: address?.username ?? "")
|
||||||
|
|
@ -265,14 +268,14 @@ import AVFoundation
|
||||||
Log.directLog(BCTBX_LOG_ERROR, text: "accept call failed \(error)")
|
Log.directLog(BCTBX_LOG_ERROR, text: "accept call failed \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for outgoing call. There is not yet callId
|
// for outgoing call. There is not yet callId
|
||||||
@objc func startCall(addr: OpaquePointer?, isSas: Bool, isVideo: Bool, isConference: Bool = false) {
|
@objc func startCall(addr: OpaquePointer?, isSas: Bool, isVideo: Bool, isConference: Bool = false) {
|
||||||
if (addr == nil) {
|
if (addr == nil) {
|
||||||
print("Can not start a call with null address!")
|
Log.i("Can not start a call with null address!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let sAddr = Address.getSwiftObject(cObject: addr!)
|
let sAddr = Address.getSwiftObject(cObject: addr!)
|
||||||
if (CallManager.callKitEnabled() && !CallManager.instance().nextCallIsTransfer && lc?.conference?.isIn != true) {
|
if (CallManager.callKitEnabled() && !CallManager.instance().nextCallIsTransfer && lc?.conference?.isIn != true) {
|
||||||
let uuid = UUID()
|
let uuid = UUID()
|
||||||
|
|
@ -280,11 +283,11 @@ import AVFoundation
|
||||||
let handle = CXHandle(type: .generic, value: sAddr.asStringUriOnly())
|
let handle = CXHandle(type: .generic, value: sAddr.asStringUriOnly())
|
||||||
let startCallAction = CXStartCallAction(call: uuid, handle: handle)
|
let startCallAction = CXStartCallAction(call: uuid, handle: handle)
|
||||||
let transaction = CXTransaction(action: startCallAction)
|
let transaction = CXTransaction(action: startCallAction)
|
||||||
|
|
||||||
let callInfo = CallInfo.newOutgoingCallInfo(addr: sAddr, isSas: isSas, displayName: name, isVideo: isVideo, isConference:isConference)
|
let callInfo = CallInfo.newOutgoingCallInfo(addr: sAddr, isSas: isSas, displayName: name, isVideo: isVideo, isConference:isConference)
|
||||||
providerDelegate.callInfos.updateValue(callInfo, forKey: uuid)
|
providerDelegate.callInfos.updateValue(callInfo, forKey: uuid)
|
||||||
providerDelegate.uuids.updateValue(uuid, forKey: "")
|
providerDelegate.uuids.updateValue(uuid, forKey: "")
|
||||||
|
|
||||||
setHeldOtherCalls(exceptCallid: "")
|
setHeldOtherCalls(exceptCallid: "")
|
||||||
requestTransaction(transaction, action: "startCall")
|
requestTransaction(transaction, action: "startCall")
|
||||||
}else {
|
}else {
|
||||||
|
|
@ -294,30 +297,30 @@ import AVFoundation
|
||||||
|
|
||||||
func startCall(addr:String, isSas: Bool = false, isVideo: Bool, isConference: Bool = false) {
|
func startCall(addr:String, isSas: Bool = false, isVideo: Bool, isConference: Bool = false) {
|
||||||
do {
|
do {
|
||||||
let address = try Factory.Instance.createAddress(addr: addr)
|
let address = try Factory.Instance.createAddress(addr: addr)
|
||||||
startCall(addr: address.getCobject,isSas: isSas, isVideo: isVideo, isConference:isConference)
|
startCall(addr: address.getCobject,isSas: isSas, isVideo: isVideo, isConference:isConference)
|
||||||
} catch {
|
} catch {
|
||||||
Log.e("[CallManager] unable to create address for a new outgoing call : \(addr) \(error) ")
|
Log.e("[CallManager] unable to create address for a new outgoing call : \(addr) \(error) ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func doCall(addr: Address, isSas: Bool, isVideo: Bool, isConference:Bool = false) throws {
|
func doCall(addr: Address, isSas: Bool, isVideo: Bool, isConference:Bool = false) throws {
|
||||||
let displayName = FastAddressBook.displayName(for: addr.getCobject)
|
let displayName = FastAddressBook.displayName(for: addr.getCobject)
|
||||||
|
|
||||||
let lcallParams = try CallManager.instance().lc!.createCallParams(call: nil)
|
let lcallParams = try CallManager.instance().lc!.createCallParams(call: nil)
|
||||||
if ConfigManager.instance().lpConfigBoolForKey(key: "edge_opt_preference") && AppManager.network() == .network_2g {
|
if ConfigManager.instance().lpConfigBoolForKey(key: "edge_opt_preference") && AppManager.network() == .network_2g {
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "Enabling low bandwidth mode")
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "Enabling low bandwidth mode")
|
||||||
lcallParams.lowBandwidthEnabled = true
|
lcallParams.lowBandwidthEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayName != nil) {
|
if (displayName != nil) {
|
||||||
try addr.setDisplayname(newValue: displayName!)
|
try addr.setDisplayname(newValue: displayName!)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ConfigManager.instance().lpConfigBoolForKey(key: "override_domain_with_default_one")) {
|
if(ConfigManager.instance().lpConfigBoolForKey(key: "override_domain_with_default_one")) {
|
||||||
try addr.setDomain(newValue: ConfigManager.instance().lpConfigStringForKey(key: "domain", section: "assistant"))
|
try addr.setDomain(newValue: ConfigManager.instance().lpConfigStringForKey(key: "domain", section: "assistant"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CallManager.instance().nextCallIsTransfer) {
|
if (CallManager.instance().nextCallIsTransfer) {
|
||||||
let call = CallManager.instance().lc!.currentCall
|
let call = CallManager.instance().lc!.currentCall
|
||||||
try call?.transferTo(referTo: addr)
|
try call?.transferTo(referTo: addr)
|
||||||
|
|
@ -359,7 +362,7 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func groupCall() {
|
@objc func groupCall() {
|
||||||
if (CallManager.callKitEnabled()) {
|
if (CallManager.callKitEnabled()) {
|
||||||
let calls = lc?.calls
|
let calls = lc?.calls
|
||||||
|
|
@ -368,29 +371,29 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
let firstCall = calls!.first?.callLog?.callId ?? ""
|
let firstCall = calls!.first?.callLog?.callId ?? ""
|
||||||
let lastCall = (calls!.count > 1) ? calls!.last?.callLog?.callId ?? "" : ""
|
let lastCall = (calls!.count > 1) ? calls!.last?.callLog?.callId ?? "" : ""
|
||||||
|
|
||||||
let currentUuid = CallManager.instance().providerDelegate.uuids["\(firstCall)"]
|
let currentUuid = CallManager.instance().providerDelegate.uuids["\(firstCall)"]
|
||||||
if (currentUuid == nil) {
|
if (currentUuid == nil) {
|
||||||
Log.directLog(BCTBX_LOG_ERROR, text: "Can not find correspondant call to group.")
|
Log.directLog(BCTBX_LOG_ERROR, text: "Can not find correspondant call to group.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let newUuid = CallManager.instance().providerDelegate.uuids["\(lastCall)"]
|
let newUuid = CallManager.instance().providerDelegate.uuids["\(lastCall)"]
|
||||||
let groupAction = CXSetGroupCallAction(call: currentUuid!, callUUIDToGroupWith: newUuid)
|
let groupAction = CXSetGroupCallAction(call: currentUuid!, callUUIDToGroupWith: newUuid)
|
||||||
let transcation = CXTransaction(action: groupAction)
|
let transcation = CXTransaction(action: groupAction)
|
||||||
requestTransaction(transcation, action: "groupCall")
|
requestTransaction(transcation, action: "groupCall")
|
||||||
|
|
||||||
setResumeCalls()
|
setResumeCalls()
|
||||||
} else {
|
} else {
|
||||||
try? lc?.addAllToConference()
|
try? lc?.addAllToConference()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func removeAllCallInfos() {
|
@objc func removeAllCallInfos() {
|
||||||
providerDelegate.callInfos.removeAll()
|
providerDelegate.callInfos.removeAll()
|
||||||
providerDelegate.uuids.removeAll()
|
providerDelegate.uuids.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func terminateCall(call: OpaquePointer?) {
|
@objc func terminateCall(call: OpaquePointer?) {
|
||||||
if (call == nil) {
|
if (call == nil) {
|
||||||
Log.directLog(BCTBX_LOG_ERROR, text: "Can not terminate null call!")
|
Log.directLog(BCTBX_LOG_ERROR, text: "Can not terminate null call!")
|
||||||
|
|
@ -404,12 +407,12 @@ import AVFoundation
|
||||||
Log.directLog(BCTBX_LOG_ERROR, text: "Failed to terminate call failed because \(error)")
|
Log.directLog(BCTBX_LOG_ERROR, text: "Failed to terminate call failed because \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func markCallAsDeclined(callId: String) {
|
@objc func markCallAsDeclined(callId: String) {
|
||||||
if !CallManager.callKitEnabled() {
|
if !CallManager.callKitEnabled() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let uuid = providerDelegate.uuids["\(callId)"]
|
let uuid = providerDelegate.uuids["\(callId)"]
|
||||||
if (uuid == nil) {
|
if (uuid == nil) {
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "Mark call \(callId) as declined.")
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "Mark call \(callId) as declined.")
|
||||||
|
|
@ -423,7 +426,7 @@ import AVFoundation
|
||||||
providerDelegate.endCall(uuid: uuid!)
|
providerDelegate.endCall(uuid: uuid!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func setHeld(call: OpaquePointer, hold: Bool) {
|
@objc func setHeld(call: OpaquePointer, hold: Bool) {
|
||||||
let sCall = Call.getSwiftObject(cObject: call)
|
let sCall = Call.getSwiftObject(cObject: call)
|
||||||
if (!hold) {
|
if (!hold) {
|
||||||
|
|
@ -434,13 +437,13 @@ import AVFoundation
|
||||||
|
|
||||||
func setHeld(call: Call, hold: Bool) {
|
func setHeld(call: Call, hold: Bool) {
|
||||||
|
|
||||||
#if targetEnvironment(simulator)
|
#if targetEnvironment(simulator)
|
||||||
if (hold) {
|
if (hold) {
|
||||||
try?call.pause()
|
try?call.pause()
|
||||||
} else {
|
} else {
|
||||||
try?call.resume()
|
try?call.resume()
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
let callid = call.callLog?.callId ?? ""
|
let callid = call.callLog?.callId ?? ""
|
||||||
let uuid = providerDelegate.uuids["\(callid)"]
|
let uuid = providerDelegate.uuids["\(callid)"]
|
||||||
if (uuid == nil) {
|
if (uuid == nil) {
|
||||||
|
|
@ -450,9 +453,9 @@ import AVFoundation
|
||||||
let setHeldAction = CXSetHeldCallAction(call: uuid!, onHold: hold)
|
let setHeldAction = CXSetHeldCallAction(call: uuid!, onHold: hold)
|
||||||
let transaction = CXTransaction(action: setHeldAction)
|
let transaction = CXTransaction(action: setHeldAction)
|
||||||
requestTransaction(transaction, action: "setHeld")
|
requestTransaction(transaction, action: "setHeld")
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func setHeldOtherCalls(exceptCallid: String) {
|
@objc func setHeldOtherCalls(exceptCallid: String) {
|
||||||
for call in CallManager.instance().lc!.calls {
|
for call in CallManager.instance().lc!.calls {
|
||||||
if (call.callLog?.callId != exceptCallid && call.state != .Paused && call.state != .Pausing && call.state != .PausedByRemote) {
|
if (call.callLog?.callId != exceptCallid && call.state != .Paused && call.state != .Pausing && call.state != .PausedByRemote) {
|
||||||
|
|
@ -460,7 +463,7 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setResumeCalls() {
|
func setResumeCalls() {
|
||||||
for call in CallManager.instance().lc!.calls {
|
for call in CallManager.instance().lc!.calls {
|
||||||
if (call.state == .Paused || call.state == .Pausing || call.state == .PausedByRemote) {
|
if (call.state == .Paused || call.state == .Pausing || call.state == .PausedByRemote) {
|
||||||
|
|
@ -468,7 +471,7 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func performActionWhenCoreIsOn(action: @escaping ()->Void ) {
|
@objc func performActionWhenCoreIsOn(action: @escaping ()->Void ) {
|
||||||
if (globalState == .On) {
|
if (globalState == .On) {
|
||||||
action()
|
action()
|
||||||
|
|
@ -476,14 +479,14 @@ import AVFoundation
|
||||||
actionsToPerformOnceWhenCoreIsOn.append(action)
|
actionsToPerformOnceWhenCoreIsOn.append(action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func acceptVideo(call: OpaquePointer, confirm: Bool) {
|
@objc func acceptVideo(call: OpaquePointer, confirm: Bool) {
|
||||||
let sCall = Call.getSwiftObject(cObject: call)
|
let sCall = Call.getSwiftObject(cObject: call)
|
||||||
let params = try? lc?.createCallParams(call: sCall)
|
let params = try? lc?.createCallParams(call: sCall)
|
||||||
params?.videoEnabled = confirm
|
params?.videoEnabled = confirm
|
||||||
try? sCall.acceptUpdate(params: params)
|
try? sCall.acceptUpdate(params: params)
|
||||||
}
|
}
|
||||||
|
|
||||||
func onGlobalStateChanged(core: Core, state: GlobalState, message: String) {
|
func onGlobalStateChanged(core: Core, state: GlobalState, message: String) {
|
||||||
if (state == .On) {
|
if (state == .On) {
|
||||||
actionsToPerformOnceWhenCoreIsOn.forEach {
|
actionsToPerformOnceWhenCoreIsOn.forEach {
|
||||||
|
|
@ -493,7 +496,7 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
globalState = state
|
globalState = state
|
||||||
}
|
}
|
||||||
|
|
||||||
func onRegistrationStateChanged(core: Core, proxyConfig: ProxyConfig, state: RegistrationState, message: String) {
|
func onRegistrationStateChanged(core: Core, proxyConfig: ProxyConfig, state: RegistrationState, message: String) {
|
||||||
if core.proxyConfigList.count == 1 && (state == .Failed || state == .Cleared){
|
if core.proxyConfigList.count == 1 && (state == .Failed || state == .Cleared){
|
||||||
// terminate callkit immediately when registration failed or cleared, supporting single proxy configuration
|
// terminate callkit immediately when registration failed or cleared, supporting single proxy configuration
|
||||||
|
|
@ -506,7 +509,7 @@ import AVFoundation
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CallManager.instance().providerDelegate.endCall(uuid: call.value)
|
CallManager.instance().providerDelegate.endCall(uuid: call.value)
|
||||||
}
|
}
|
||||||
CallManager.instance().endCallkit = true
|
CallManager.instance().endCallkit = true
|
||||||
|
|
@ -533,7 +536,7 @@ import AVFoundation
|
||||||
return FastAddressBook.displayName(for: call.remoteAddress?.getCobject) ?? "Unknown"
|
return FastAddressBook.displayName(for: call.remoteAddress?.getCobject) ?? "Unknown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func onCallStateChanged(core: Core, call: Call, state cstate: Call.State, message: String) {
|
func onCallStateChanged(core: Core, call: Call, state cstate: Call.State, message: String) {
|
||||||
let callLog = call.callLog
|
let callLog = call.callLog
|
||||||
let callId = callLog?.callId
|
let callId = callLog?.callId
|
||||||
|
|
@ -541,7 +544,7 @@ import AVFoundation
|
||||||
displayIncomingCall(call: call, handle: "Calling", hasVideo: false, callId: callId!, displayName: "Calling")
|
displayIncomingCall(call: call, handle: "Calling", hasVideo: false, callId: callId!, displayName: "Calling")
|
||||||
} else {
|
} else {
|
||||||
let video = (core.videoActivationPolicy?.automaticallyAccept ?? false) && (call.remoteParams?.videoEnabled ?? false)
|
let video = (core.videoActivationPolicy?.automaticallyAccept ?? false) && (call.remoteParams?.videoEnabled ?? false)
|
||||||
|
|
||||||
if (call.userData == nil) {
|
if (call.userData == nil) {
|
||||||
let appData = CallAppData()
|
let appData = CallAppData()
|
||||||
CallManager.setAppData(sCall: call, appData: appData)
|
CallManager.setAppData(sCall: call, appData: appData)
|
||||||
|
|
@ -552,161 +555,194 @@ import AVFoundation
|
||||||
ConferenceViewModel.shared.initConference(conference)
|
ConferenceViewModel.shared.initConference(conference)
|
||||||
ConferenceViewModel.shared.configureConference(conference)
|
ConferenceViewModel.shared.configureConference(conference)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 call.replacedCall != nil {
|
||||||
let isConference = isConferenceCall(call: call)
|
endCallKitReplacedCall = false
|
||||||
let isEarlyConference = isConference && CallsViewModel.shared.currentCallData.value??.isConferenceCall.value != true // Conference info not be received yet.
|
|
||||||
if (isEarlyConference) {
|
let uuid = CallManager.instance().providerDelegate.uuids["\(CallManager.uuidReplacedCall)"]
|
||||||
CallsViewModel.shared.currentCallData.readCurrentAndObserve { _ in
|
let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
|
||||||
let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
|
callInfo!.callId = CallManager.instance().referedToCall ?? ""
|
||||||
if (uuid != nil) {
|
CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
|
||||||
displayName = "\(VoipTexts.conference_incoming_title): \(CallsViewModel.shared.currentCallData.value??.remoteConferenceSubject.value ?? "") (\(CallsViewModel.shared.currentCallData.value??.conferenceParticipantsCountLabel.value ?? ""))"
|
CallManager.instance().providerDelegate.uuids.removeValue(forKey: callId!)
|
||||||
CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: addr!.asStringUriOnly(), hasVideo: video, displayName: displayName)
|
CallManager.instance().providerDelegate.uuids.updateValue(uuid!, forKey: callInfo!.callId)
|
||||||
}
|
CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: addr!.asStringUriOnly(), hasVideo: video, displayName: displayName)
|
||||||
}
|
} else if (CallManager.callKitEnabled()) {
|
||||||
}
|
let isConference = isConferenceCall(call: call)
|
||||||
|
let isEarlyConference = isConference && CallsViewModel.shared.currentCallData.value??.isConferenceCall.value != true // Conference info not be received yet.
|
||||||
let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
|
if (isEarlyConference) {
|
||||||
if (uuid != nil) {
|
CallsViewModel.shared.currentCallData.readCurrentAndObserve { _ in
|
||||||
// Tha app is now registered, updated the call already existed.
|
let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
|
||||||
CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: addr!.asStringUriOnly(), hasVideo: video, displayName: displayName)
|
if (uuid != nil) {
|
||||||
} else {
|
displayName = "\(VoipTexts.conference_incoming_title): \(CallsViewModel.shared.currentCallData.value??.remoteConferenceSubject.value ?? "") (\(CallsViewModel.shared.currentCallData.value??.conferenceParticipantsCountLabel.value ?? ""))"
|
||||||
CallManager.instance().displayIncomingCall(call: call, handle: addr!.asStringUriOnly(), hasVideo: video, callId: callId!, displayName: displayName)
|
CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: addr!.asStringUriOnly(), hasVideo: video, displayName: displayName)
|
||||||
}
|
|
||||||
} else if (UIApplication.shared.applicationState != .active) {
|
|
||||||
// not support callkit , use notif
|
|
||||||
let content = UNMutableNotificationContent()
|
|
||||||
content.title = NSLocalizedString("Incoming call", comment: "")
|
|
||||||
content.body = displayName
|
|
||||||
content.sound = UNNotificationSound.init(named: UNNotificationSoundName.init("notes_of_the_optimistic.caf"))
|
|
||||||
content.categoryIdentifier = "call_cat"
|
|
||||||
content.userInfo = ["CallId" : callId!]
|
|
||||||
let req = UNNotificationRequest.init(identifier: "call_request", content: content, trigger: nil)
|
|
||||||
UNUserNotificationCenter.current().add(req, withCompletionHandler: nil)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case .StreamsRunning:
|
|
||||||
if (CallManager.callKitEnabled()) {
|
|
||||||
let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
|
|
||||||
if (uuid != nil) {
|
|
||||||
let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
|
|
||||||
if (callInfo != nil && callInfo!.isOutgoing && !callInfo!.connected) {
|
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "CallKit: outgoing call connected with uuid \(uuid!) and callId \(callId!)")
|
|
||||||
CallManager.instance().providerDelegate.reportOutgoingCallConnected(uuid: uuid!)
|
|
||||||
callInfo!.connected = true
|
|
||||||
CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CallManager.instance().speakerBeforePause) {
|
let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
|
||||||
CallManager.instance().speakerBeforePause = false
|
if call.replacedCall == nil {
|
||||||
CallManager.instance().changeRouteToSpeaker()
|
CallManager.uuidReplacedCall = callId
|
||||||
}
|
}
|
||||||
break
|
|
||||||
case .OutgoingInit,
|
if (uuid != nil) {
|
||||||
.OutgoingProgress,
|
// Tha app is now registered, updated the call already existed.
|
||||||
.OutgoingRinging,
|
CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: addr!.asStringUriOnly(), hasVideo: video, displayName: displayName)
|
||||||
.OutgoingEarlyMedia:
|
} else {
|
||||||
if (CallManager.callKitEnabled()) {
|
CallManager.instance().displayIncomingCall(call: call, handle: addr!.asStringUriOnly(), hasVideo: video, callId: callId!, displayName: displayName)
|
||||||
let uuid = CallManager.instance().providerDelegate.uuids[""]
|
}
|
||||||
if (uuid != nil) {
|
} else if (UIApplication.shared.applicationState != .active) {
|
||||||
let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
|
// not support callkit , use notif
|
||||||
callInfo!.callId = callId!
|
let content = UNMutableNotificationContent()
|
||||||
|
content.title = NSLocalizedString("Incoming call", comment: "")
|
||||||
|
content.body = displayName
|
||||||
|
content.sound = UNNotificationSound.init(named: UNNotificationSoundName.init("notes_of_the_optimistic.caf"))
|
||||||
|
content.categoryIdentifier = "call_cat"
|
||||||
|
content.userInfo = ["CallId" : callId!]
|
||||||
|
let req = UNNotificationRequest.init(identifier: "call_request", content: content, trigger: nil)
|
||||||
|
UNUserNotificationCenter.current().add(req, withCompletionHandler: nil)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case .StreamsRunning:
|
||||||
|
if (CallManager.callKitEnabled()) {
|
||||||
|
let uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
|
||||||
|
if (uuid != nil) {
|
||||||
|
let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
|
||||||
|
if (callInfo != nil && callInfo!.isOutgoing && !callInfo!.connected) {
|
||||||
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "CallKit: outgoing call connected with uuid \(uuid!) and callId \(callId!)")
|
||||||
|
CallManager.instance().providerDelegate.reportOutgoingCallConnected(uuid: uuid!)
|
||||||
|
callInfo!.connected = true
|
||||||
CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
|
CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
|
||||||
CallManager.instance().providerDelegate.uuids.removeValue(forKey: "")
|
}
|
||||||
CallManager.instance().providerDelegate.uuids.updateValue(uuid!, forKey: callId!)
|
}
|
||||||
|
}
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "CallKit: outgoing call started connecting with uuid \(uuid!) and callId \(callId!)")
|
|
||||||
CallManager.instance().providerDelegate.reportOutgoingCallStartedConnecting(uuid: uuid!)
|
if (CallManager.instance().speakerBeforePause) {
|
||||||
|
CallManager.instance().speakerBeforePause = false
|
||||||
|
CallManager.instance().changeRouteToSpeaker()
|
||||||
|
}
|
||||||
|
actionToFulFill?.fulfill()
|
||||||
|
actionToFulFill = nil
|
||||||
|
break
|
||||||
|
case .Paused:
|
||||||
|
actionToFulFill?.fulfill()
|
||||||
|
actionToFulFill = nil
|
||||||
|
break
|
||||||
|
case .OutgoingInit,
|
||||||
|
.OutgoingProgress,
|
||||||
|
.OutgoingRinging,
|
||||||
|
.OutgoingEarlyMedia:
|
||||||
|
if (CallManager.callKitEnabled()) {
|
||||||
|
let uuid = CallManager.instance().providerDelegate.uuids[""]
|
||||||
|
if (uuid != nil) {
|
||||||
|
let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
|
||||||
|
callInfo!.callId = callId!
|
||||||
|
CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
|
||||||
|
CallManager.instance().providerDelegate.uuids.removeValue(forKey: "")
|
||||||
|
CallManager.instance().providerDelegate.uuids.updateValue(uuid!, forKey: callId!)
|
||||||
|
|
||||||
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "CallKit: outgoing call started connecting with uuid \(uuid!) and callId \(callId!)")
|
||||||
|
CallManager.instance().providerDelegate.reportOutgoingCallStartedConnecting(uuid: uuid!)
|
||||||
|
} else {
|
||||||
|
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 {
|
} else {
|
||||||
CallManager.instance().referedToCall = callId
|
CallManager.instance().referedToCall = callId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
}
|
||||||
case .End,
|
break
|
||||||
.Error:
|
case .End,
|
||||||
var displayName = "Unknown"
|
.Error:
|
||||||
if (call.dir == .Incoming) {
|
var displayName = "Unknown"
|
||||||
displayName = incomingDisplayName(call: call)
|
if (call.dir == .Incoming) {
|
||||||
} else if let addr = call.remoteAddress, let contactName = FastAddressBook.displayName(for: addr.getCobject) {
|
displayName = incomingDisplayName(call: call)
|
||||||
displayName = contactName
|
} else if let addr = call.remoteAddress, let contactName = FastAddressBook.displayName(for: addr.getCobject) {
|
||||||
}
|
displayName = contactName
|
||||||
|
}
|
||||||
|
|
||||||
|
UIDevice.current.isProximityMonitoringEnabled = false
|
||||||
|
if (CallManager.instance().lc!.callsNb == 0) {
|
||||||
|
CallManager.instance().changeRouteToDefault()
|
||||||
|
// disable this because I don't find anygood reason for it: _bluetoothAvailable = FALSE;
|
||||||
|
// furthermore it introduces a bug when calling multiple times since route may not be
|
||||||
|
// reconfigured between cause leading to bluetooth being disabled while it should not
|
||||||
|
//CallManager.instance().bluetoothEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if UIApplication.shared.applicationState != .active && (callLog == nil || callLog?.status == .Missed || callLog?.status == .Aborted || callLog?.status == .EarlyAborted) {
|
||||||
|
// Configure the notification's payload.
|
||||||
|
let content = UNMutableNotificationContent()
|
||||||
|
content.title = NSString.localizedUserNotificationString(forKey: NSLocalizedString("Missed call", comment: ""), arguments: nil)
|
||||||
|
content.body = NSString.localizedUserNotificationString(forKey: displayName, arguments: nil)
|
||||||
|
|
||||||
UIDevice.current.isProximityMonitoringEnabled = false
|
// Deliver the notification.
|
||||||
if (CallManager.instance().lc!.callsNb == 0) {
|
let request = UNNotificationRequest(identifier: "call_request", content: content, trigger: nil) // Schedule the notification.
|
||||||
CallManager.instance().changeRouteToDefault()
|
let center = UNUserNotificationCenter.current()
|
||||||
// disable this because I don't find anygood reason for it: _bluetoothAvailable = FALSE;
|
center.add(request) { (error : Error?) in
|
||||||
// furthermore it introduces a bug when calling multiple times since route may not be
|
if error != nil {
|
||||||
// reconfigured between cause leading to bluetooth being disabled while it should not
|
|
||||||
//CallManager.instance().bluetoothEnabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if UIApplication.shared.applicationState != .active && (callLog == nil || callLog?.status == .Missed || callLog?.status == .Aborted || callLog?.status == .EarlyAborted) {
|
|
||||||
// Configure the notification's payload.
|
|
||||||
let content = UNMutableNotificationContent()
|
|
||||||
content.title = NSString.localizedUserNotificationString(forKey: NSLocalizedString("Missed call", comment: ""), arguments: nil)
|
|
||||||
content.body = NSString.localizedUserNotificationString(forKey: displayName, arguments: nil)
|
|
||||||
|
|
||||||
// Deliver the notification.
|
|
||||||
let request = UNNotificationRequest(identifier: "call_request", content: content, trigger: nil) // Schedule the notification.
|
|
||||||
let center = UNUserNotificationCenter.current()
|
|
||||||
center.add(request) { (error : Error?) in
|
|
||||||
if error != nil {
|
|
||||||
Log.directLog(BCTBX_LOG_ERROR, text: "Error while adding notification request : \(error!.localizedDescription)")
|
Log.directLog(BCTBX_LOG_ERROR, text: "Error while adding notification request : \(error!.localizedDescription)")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (CallManager.callKitEnabled()) {
|
|
||||||
var uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
|
if (CallManager.callKitEnabled()) {
|
||||||
if (callId == CallManager.instance().referedToCall) {
|
var uuid = CallManager.instance().providerDelegate.uuids["\(callId!)"]
|
||||||
// refered call ended before connecting
|
if (callId == CallManager.instance().referedToCall) {
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "Callkit: end refered to call : \(String(describing: CallManager.instance().referedToCall))")
|
// refered call ended before connecting
|
||||||
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "Callkit: end refered to call : \(String(describing: CallManager.instance().referedToCall))")
|
||||||
|
CallManager.instance().referedFromCall = nil
|
||||||
|
CallManager.instance().referedToCall = nil
|
||||||
|
}
|
||||||
|
if uuid == nil {
|
||||||
|
// the call not yet connected
|
||||||
|
uuid = CallManager.instance().providerDelegate.uuids[""]
|
||||||
|
}
|
||||||
|
if (uuid != nil) {
|
||||||
|
if (callId == CallManager.instance().referedFromCall) {
|
||||||
|
Log.directLog(BCTBX_LOG_MESSAGE, text: "Callkit: end refered from call : \(String(describing: CallManager.instance().referedFromCall))")
|
||||||
CallManager.instance().referedFromCall = nil
|
CallManager.instance().referedFromCall = nil
|
||||||
|
let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
|
||||||
|
callInfo!.callId = CallManager.instance().referedToCall ?? ""
|
||||||
|
CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
|
||||||
|
CallManager.instance().providerDelegate.uuids.removeValue(forKey: callId!)
|
||||||
|
CallManager.instance().providerDelegate.uuids.updateValue(uuid!, forKey: callInfo!.callId)
|
||||||
CallManager.instance().referedToCall = nil
|
CallManager.instance().referedToCall = nil
|
||||||
|
break
|
||||||
}
|
}
|
||||||
if uuid == nil {
|
if (endCallKitReplacedCall){
|
||||||
// the call not yet connected
|
|
||||||
uuid = CallManager.instance().providerDelegate.uuids[""]
|
|
||||||
}
|
|
||||||
if (uuid != nil) {
|
|
||||||
if (callId == CallManager.instance().referedFromCall) {
|
|
||||||
Log.directLog(BCTBX_LOG_MESSAGE, text: "Callkit: end refered from call : \(String(describing: CallManager.instance().referedFromCall))")
|
|
||||||
CallManager.instance().referedFromCall = nil
|
|
||||||
let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!]
|
|
||||||
callInfo!.callId = CallManager.instance().referedToCall ?? ""
|
|
||||||
CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!)
|
|
||||||
CallManager.instance().providerDelegate.uuids.removeValue(forKey: callId!)
|
|
||||||
CallManager.instance().providerDelegate.uuids.updateValue(uuid!, forKey: callInfo!.callId)
|
|
||||||
CallManager.instance().referedToCall = nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
let transaction = CXTransaction(action:
|
let transaction = CXTransaction(action:
|
||||||
CXEndCallAction(call: uuid!))
|
CXEndCallAction(call: uuid!))
|
||||||
CallManager.instance().requestTransaction(transaction, action: "endCall")
|
CallManager.instance().requestTransaction(transaction, action: "endCall")
|
||||||
|
}else{
|
||||||
|
endCallKitReplacedCall = true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
break
|
}
|
||||||
case .Released:
|
break
|
||||||
call.userData = nil
|
case .Released:
|
||||||
break
|
CallManager.setAppData(sCall : call, appData : nil);
|
||||||
case .Referred:
|
break
|
||||||
CallManager.instance().referedFromCall = call.callLog?.callId
|
case .Referred:
|
||||||
break
|
CallManager.instance().referedFromCall = call.callLog?.callId
|
||||||
default:
|
break
|
||||||
break
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -721,7 +757,7 @@ import AVFoundation
|
||||||
AnyHashable("message"): message
|
AnyHashable("message"): message
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio messages
|
// Audio messages
|
||||||
|
|
||||||
@objc func activateAudioSession() {
|
@objc func activateAudioSession() {
|
||||||
|
|
@ -742,7 +778,7 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
return speakerCard != nil ? speakerCard : earpieceCard
|
return speakerCard != nil ? speakerCard : earpieceCard
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local Conference
|
// Local Conference
|
||||||
|
|
||||||
@objc func startLocalConference() {
|
@objc func startLocalConference() {
|
||||||
|
|
@ -753,18 +789,18 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
let firstCall = calls!.first?.callLog?.callId ?? ""
|
let firstCall = calls!.first?.callLog?.callId ?? ""
|
||||||
let lastCall = (calls!.count > 1) ? calls!.last?.callLog?.callId ?? "" : ""
|
let lastCall = (calls!.count > 1) ? calls!.last?.callLog?.callId ?? "" : ""
|
||||||
|
|
||||||
let currentUuid = CallManager.instance().providerDelegate.uuids["\(firstCall)"]
|
let currentUuid = CallManager.instance().providerDelegate.uuids["\(firstCall)"]
|
||||||
if (currentUuid == nil) {
|
if (currentUuid == nil) {
|
||||||
Log.directLog(BCTBX_LOG_ERROR, text: "Can not find correspondant call to group.")
|
Log.directLog(BCTBX_LOG_ERROR, text: "Can not find correspondant call to group.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let newUuid = CallManager.instance().providerDelegate.uuids["\(lastCall)"]
|
let newUuid = CallManager.instance().providerDelegate.uuids["\(lastCall)"]
|
||||||
let groupAction = CXSetGroupCallAction(call: currentUuid!, callUUIDToGroupWith: newUuid)
|
let groupAction = CXSetGroupCallAction(call: currentUuid!, callUUIDToGroupWith: newUuid)
|
||||||
let transcation = CXTransaction(action: groupAction)
|
let transcation = CXTransaction(action: groupAction)
|
||||||
requestTransaction(transcation, action: "groupCall")
|
requestTransaction(transcation, action: "groupCall")
|
||||||
|
|
||||||
setResumeCalls()
|
setResumeCalls()
|
||||||
} else {
|
} else {
|
||||||
addAllToLocalConference()
|
addAllToLocalConference()
|
||||||
|
|
@ -775,6 +811,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 +820,12 @@ import AVFoundation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func applyInternationalPrefix() -> Bool {
|
||||||
|
if let account = lc?.defaultAccount, let params = account.params {
|
||||||
|
return params.useInternationalPrefixForCallsAndChats
|
||||||
|
}
|
||||||
|
return true; // Legacy behavior
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
106
Classes/Swift/Chat/Data/FileType.swift
Normal file
106
Classes/Swift/Chat/Data/FileType.swift
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* 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 Foundation
|
||||||
|
|
||||||
|
enum FileType : String {
|
||||||
|
case pdf = "pdf";
|
||||||
|
case png = "png";
|
||||||
|
case jpg = "jpg";
|
||||||
|
case jpeg = "jpeg";
|
||||||
|
case bmp = "bmp";
|
||||||
|
case heic = "heic";
|
||||||
|
case mkv = "mkv";
|
||||||
|
case avi = "avi";
|
||||||
|
case mov = "mov";
|
||||||
|
case mp4 = "mp4";
|
||||||
|
case wav = "wav";
|
||||||
|
case au = "au";
|
||||||
|
case m4a = "m4a";
|
||||||
|
case other = "other";
|
||||||
|
|
||||||
|
case file_pdf_default = "file_pdf_default";
|
||||||
|
case file_picture_default = "file_picture_default";
|
||||||
|
case file_video_default = "file_video_default";
|
||||||
|
case file_audio_default = "file_audio_default";
|
||||||
|
case file_default = "file_default";
|
||||||
|
|
||||||
|
func getGroupTypeFromFile() -> String? {
|
||||||
|
switch self {
|
||||||
|
case .pdf, .file_pdf_default:
|
||||||
|
return "file_pdf_default"
|
||||||
|
|
||||||
|
case .png, .jpg, .jpeg, .bmp, .heic, .file_picture_default:
|
||||||
|
return "file_picture_default"
|
||||||
|
|
||||||
|
case .mkv, .avi, .mov, .mp4, .file_video_default:
|
||||||
|
return "file_video_default"
|
||||||
|
|
||||||
|
case .wav, .au, .m4a, .file_audio_default:
|
||||||
|
return "file_audio_default"
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "file_default"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getImageFromFile() -> UIImage? {
|
||||||
|
switch self {
|
||||||
|
case .pdf, .file_pdf_default:
|
||||||
|
return UIImage(named:"file_pdf_default")
|
||||||
|
|
||||||
|
case .png, .jpg, .jpeg, .bmp, .heic, .file_picture_default:
|
||||||
|
return UIImage(named:"file_picture_default")
|
||||||
|
|
||||||
|
case .mkv, .avi, .mov, .mp4, .file_video_default:
|
||||||
|
return UIImage(named:"file_video_default")
|
||||||
|
|
||||||
|
case .wav, .au, .m4a, .file_audio_default:
|
||||||
|
return UIImage(named:"file_audio_default")
|
||||||
|
|
||||||
|
default:
|
||||||
|
return UIImage(named:"file_default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FileType {
|
||||||
|
init() {
|
||||||
|
self = .file_default
|
||||||
|
}
|
||||||
|
|
||||||
|
init?(_ value: String) {
|
||||||
|
switch value.lowercased() {
|
||||||
|
case "pdf", "file_pdf_default":
|
||||||
|
self = .file_pdf_default
|
||||||
|
|
||||||
|
case "png", "jpg", "jpeg", "bmp", "heic", "file_picture_default":
|
||||||
|
self = .file_picture_default
|
||||||
|
|
||||||
|
case "mkv", "avi", "mov", "mp4", "file_video_default":
|
||||||
|
self = .file_video_default
|
||||||
|
|
||||||
|
case "wav", "au", "m4a", "file_audio_default":
|
||||||
|
self = .file_audio_default
|
||||||
|
|
||||||
|
default:
|
||||||
|
self = .file_default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* 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 Foundation
|
||||||
|
import linphonesw
|
||||||
|
|
||||||
|
|
||||||
|
class ChatConversationTableViewModel {
|
||||||
|
|
||||||
|
static let sharedModel = ChatConversationTableViewModel()
|
||||||
|
|
||||||
|
var chatRoom: ChatRoom? = nil
|
||||||
|
|
||||||
|
var refreshIndexPath = MutableLiveData<Int>(0)
|
||||||
|
|
||||||
|
var onClickIndexPath = MutableLiveData<Int>(0)
|
||||||
|
var onClickMessageIndexPath = 0
|
||||||
|
|
||||||
|
|
||||||
|
var editModeOn = MutableLiveData<Bool>(false)
|
||||||
|
|
||||||
|
var messageSelected = MutableLiveData<Int>(0)
|
||||||
|
var messageListSelected = MutableLiveData<[Bool]>([])
|
||||||
|
|
||||||
|
var messageListToDelete : [EventLog] = []
|
||||||
|
|
||||||
|
func getMessage(index: Int) -> EventLog? {
|
||||||
|
if (chatRoom != nil) {
|
||||||
|
let chatRoomEvents = chatRoom?.getHistoryRangeEvents(begin: index, end: index+1)
|
||||||
|
return chatRoomEvents?.first
|
||||||
|
}else{
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIndexMessage(message: ChatMessage) -> Int {
|
||||||
|
var index = -1
|
||||||
|
if (chatRoom == nil) {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
var indexRange = 0
|
||||||
|
let msgId = message.messageId
|
||||||
|
|
||||||
|
while index == -1 {
|
||||||
|
let chatRoomEvents = chatRoom?.getHistoryRangeEvents(begin: indexRange, end: indexRange+20)
|
||||||
|
if chatRoomEvents?.count == 0 {
|
||||||
|
index = -2
|
||||||
|
}
|
||||||
|
chatRoomEvents?.reversed().forEach({ event in
|
||||||
|
let chat = event.chatMessage
|
||||||
|
if (chat != nil && msgId == chat?.messageId) {
|
||||||
|
index = indexRange
|
||||||
|
}
|
||||||
|
indexRange += 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNBMessages() -> Int {
|
||||||
|
if (chatRoom == nil) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return chatRoom!.historyEventsSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func eventTypeIsOfInterestForOne(toOneRoom type: EventLogType) -> Bool {
|
||||||
|
return type.rawValue == LinphoneEventLogTypeConferenceChatMessage.rawValue || type.rawValue == LinphoneEventLogTypeConferenceEphemeralMessageEnabled.rawValue || type.rawValue == LinphoneEventLogTypeConferenceEphemeralMessageDisabled.rawValue || type.rawValue == LinphoneEventLogTypeConferenceEphemeralMessageLifetimeChanged.rawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func reloadCollectionViewCell(){
|
||||||
|
refreshIndexPath.value! += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func onGridClick(indexMessage: Int, index :Int){
|
||||||
|
onClickMessageIndexPath = indexMessage
|
||||||
|
onClickIndexPath.value! = index
|
||||||
|
}
|
||||||
|
|
||||||
|
func changeEditMode(editMode :Bool){
|
||||||
|
editModeOn.value = editMode
|
||||||
|
}
|
||||||
|
|
||||||
|
func selectAllMessages(){
|
||||||
|
for i in 0...messageListSelected.value!.count - 1 {
|
||||||
|
messageListSelected.value![i] = true
|
||||||
|
messageSelected.value! += 1
|
||||||
|
}
|
||||||
|
refreshIndexPath.value! += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func unSelectAllMessages(){
|
||||||
|
for i in 0...messageListSelected.value!.count - 1 {
|
||||||
|
messageListSelected.value![i] = false
|
||||||
|
}
|
||||||
|
messageSelected.value! = 0
|
||||||
|
refreshIndexPath.value! += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteMessagesSelected(){
|
||||||
|
for i in 0...(messageListSelected.value!.count - 1) {
|
||||||
|
if messageListSelected.value![i] == true {
|
||||||
|
let messageEvent = getMessage(index: i)
|
||||||
|
//if messageEvent
|
||||||
|
messageListToDelete.append((messageEvent)!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messageListToDelete.forEach { chatMessage in
|
||||||
|
chatMessage.deleteFromDatabase()
|
||||||
|
}
|
||||||
|
messageSelected.value! = 0
|
||||||
|
refreshIndexPath.value! += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
584
Classes/Swift/Chat/ViewModels/ChatConversationViewModel.swift
Normal file
584
Classes/Swift/Chat/ViewModels/ChatConversationViewModel.swift
Normal file
|
|
@ -0,0 +1,584 @@
|
||||||
|
/*
|
||||||
|
* 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 Foundation
|
||||||
|
import linphonesw
|
||||||
|
|
||||||
|
|
||||||
|
class ChatConversationViewModel {
|
||||||
|
|
||||||
|
static let sharedModel = ChatConversationViewModel()
|
||||||
|
|
||||||
|
let APP_GROUP_ID = "group.belledonne-communications.linphone.widget"
|
||||||
|
|
||||||
|
var chatRoom: ChatRoom? = nil
|
||||||
|
var chatRoomDelegate: ChatRoomDelegate? = nil
|
||||||
|
|
||||||
|
var mediaCount : Int = 0
|
||||||
|
var newMediaCount : Int = 0
|
||||||
|
|
||||||
|
var address: String? = nil
|
||||||
|
var participants: String? = nil
|
||||||
|
var subject: String? = nil
|
||||||
|
var shareFileMessage: String? = nil
|
||||||
|
|
||||||
|
var debugEnabled = false
|
||||||
|
var isVoiceRecording = false
|
||||||
|
var showVoiceRecorderView = false
|
||||||
|
var isPendingVoiceRecord = false
|
||||||
|
var isPlayingVoiceRecording = false
|
||||||
|
var isOneToOneChat = false
|
||||||
|
|
||||||
|
var urlFile : [URL?] = []
|
||||||
|
var mediaURLCollection : [URL] = []
|
||||||
|
var replyURLCollection : [URL] = []
|
||||||
|
|
||||||
|
var data : [Data?] = []
|
||||||
|
var fileContext : [Data] = []
|
||||||
|
|
||||||
|
var progress : [Progress] = []
|
||||||
|
var workItem : DispatchWorkItem? = nil
|
||||||
|
|
||||||
|
var replyMessage : OpaquePointer? = nil
|
||||||
|
|
||||||
|
var vrRecordTimer = Timer()
|
||||||
|
|
||||||
|
var voiceRecorder : Recorder? = nil
|
||||||
|
|
||||||
|
var secureLevel : UIImage?
|
||||||
|
var imageT : [UIImage?] = []
|
||||||
|
var mediaCollectionView : [UIImage] = []
|
||||||
|
var replyCollectionView : [UIImage] = []
|
||||||
|
|
||||||
|
var isComposing = MutableLiveData<Bool>(false)
|
||||||
|
var messageReceived = MutableLiveData<EventLog>()
|
||||||
|
var stateChanged = MutableLiveData<ChatRoom>()
|
||||||
|
var secureLevelChanged = MutableLiveData<EventLog>()
|
||||||
|
var subjectChanged = MutableLiveData<EventLog>()
|
||||||
|
var eventLog = MutableLiveData<EventLog>()
|
||||||
|
var indexPathVM = MutableLiveData<Int>()
|
||||||
|
var shareFileURL = MutableLiveData<String>()
|
||||||
|
var shareFileName = MutableLiveData<String>()
|
||||||
|
|
||||||
|
func resetViewModel(){
|
||||||
|
chatRoom?.removeDelegate(delegate: chatRoomDelegate!)
|
||||||
|
mediaURLCollection = []
|
||||||
|
replyURLCollection.removeAll()
|
||||||
|
fileContext = []
|
||||||
|
urlFile = []
|
||||||
|
data = []
|
||||||
|
workItem?.cancel()
|
||||||
|
for progressItem in progress{
|
||||||
|
progressItem.cancel()
|
||||||
|
}
|
||||||
|
progress.removeAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
func createChatConversation(){
|
||||||
|
chatRoomDelegate = ChatRoomDelegateStub(
|
||||||
|
onIsComposingReceived: { (room: ChatRoom, remoteAddress: Address, isComposing: Bool) -> Void in
|
||||||
|
self.on_chat_room_is_composing_received(room, remoteAddress, isComposing)
|
||||||
|
}, onChatMessageReceived: { (room: ChatRoom, event: EventLog) -> Void in
|
||||||
|
self.on_chat_room_chat_message_received(room, event)
|
||||||
|
}, onChatMessageSending: { (room: ChatRoom, event: EventLog) -> Void in
|
||||||
|
self.on_chat_room_event_log(room, event)
|
||||||
|
}, onParticipantAdded: { (room: ChatRoom, event: EventLog) -> Void in
|
||||||
|
self.on_chat_room_secure_level(room, event)
|
||||||
|
}, onParticipantRemoved: { (room: ChatRoom, event: EventLog) -> Void in
|
||||||
|
self.on_chat_room_secure_level(room, event)
|
||||||
|
}, onParticipantAdminStatusChanged: { (room: ChatRoom, event: EventLog) -> Void in
|
||||||
|
self.on_chat_room_event_log(room, event)
|
||||||
|
}, onStateChanged: { (room: ChatRoom, state: ChatRoom.State) -> Void in
|
||||||
|
self.on_chat_room_state_changed(room)
|
||||||
|
}, onSecurityEvent: { (room: ChatRoom, event: EventLog) -> Void in
|
||||||
|
self.on_chat_room_secure_level(room, event)
|
||||||
|
}, onSubjectChanged: { (room: ChatRoom, event: EventLog) -> Void in
|
||||||
|
self.on_chat_room_subject_changed(room, event)
|
||||||
|
}, onConferenceJoined: { (room: ChatRoom, event: EventLog) -> Void in
|
||||||
|
self.on_chat_room_event_log(room, event)
|
||||||
|
}, onConferenceLeft: { (room: ChatRoom, event: EventLog) -> Void in
|
||||||
|
self.on_chat_room_event_log(room, event)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
chatRoom?.addDelegate(delegate: chatRoomDelegate!)
|
||||||
|
|
||||||
|
workItem = DispatchWorkItem {
|
||||||
|
let indexPath = IndexPath(row: self.mediaCollectionView.count, section: 0)
|
||||||
|
self.mediaURLCollection.append(self.urlFile[indexPath.row]!)
|
||||||
|
self.mediaCollectionView.append(self.imageT[indexPath.row]!)
|
||||||
|
|
||||||
|
self.fileContext.append(self.data[indexPath.row]!)
|
||||||
|
if(self.mediaCount + self.newMediaCount <= indexPath.row+1){
|
||||||
|
self.indexPathVM.value = indexPath.row
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func on_chat_room_is_composing_received(_ cr: ChatRoom?, _ remoteAddr: Address?, _ isComposingBool: Bool) {
|
||||||
|
isComposing.value = (linphone_chat_room_is_remote_composing(cr?.getCobject) != 0) || bctbx_list_size(linphone_chat_room_get_composing_addresses(cr?.getCobject)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func on_chat_room_chat_message_received(_ cr: ChatRoom?, _ event_log: EventLog?) {
|
||||||
|
let chat = event_log?.chatMessage
|
||||||
|
if chat == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasFile = false
|
||||||
|
// if auto_download is available and file is downloaded
|
||||||
|
if (linphone_core_get_max_size_for_auto_download_incoming_files(LinphoneManager.getLc()) > -1) && (chat?.fileTransferInformation != nil) {
|
||||||
|
hasFile = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var returnValue = false;
|
||||||
|
chat?.contents.forEach({ content in
|
||||||
|
if !content.isFileTransfer && !content.isText && !content.isVoiceRecording && !hasFile {
|
||||||
|
returnValue = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if returnValue {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let from = chat?.fromAddress
|
||||||
|
if from == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
messageReceived.value = event_log
|
||||||
|
}
|
||||||
|
|
||||||
|
func on_chat_room_state_changed(_ cr: ChatRoom?) {
|
||||||
|
isOneToOneChat = chatRoom!.hasCapability(mask: Int(LinphoneChatRoomCapabilitiesOneToOne.rawValue))
|
||||||
|
secureLevel = FastAddressBook.image(for: linphone_chat_room_get_security_level(cr?.getCobject))
|
||||||
|
stateChanged.value = cr
|
||||||
|
}
|
||||||
|
|
||||||
|
func on_chat_room_subject_changed(_ cr: ChatRoom?, _ event_log: EventLog?) {
|
||||||
|
subject = event_log?.subject != nil ? event_log?.subject : cr?.subject
|
||||||
|
subjectChanged.value = event_log
|
||||||
|
}
|
||||||
|
|
||||||
|
func on_chat_room_secure_level(_ cr: ChatRoom?, _ event_log: EventLog?) {
|
||||||
|
secureLevel = FastAddressBook.image(for: linphone_chat_room_get_security_level(cr?.getCobject))
|
||||||
|
secureLevelChanged.value = event_log
|
||||||
|
}
|
||||||
|
|
||||||
|
func on_chat_room_event_log(_ cr: ChatRoom?, _ event_log: EventLog?) {
|
||||||
|
eventLog.value = event_log
|
||||||
|
}
|
||||||
|
|
||||||
|
func nsDataRead() -> Data? {
|
||||||
|
let groupName = "group.\(Bundle.main.bundleIdentifier ?? "").linphoneExtension"
|
||||||
|
let path = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupName)?.path
|
||||||
|
let fullCacheFilePathPath = "\(path ?? "")/\("nsData")"
|
||||||
|
return NSData(contentsOfFile: fullCacheFilePathPath) as Data?
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendMessage(message: String?, withExterlBodyUrl externalUrl: URL?, rootMessage: ChatMessage?) -> Bool {
|
||||||
|
if chatRoom == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let msg = rootMessage
|
||||||
|
let basic = isBasicChatRoom(chatRoom?.getCobject)
|
||||||
|
let params = linphone_account_get_params(linphone_core_get_default_account(LinphoneManager.getLc()))
|
||||||
|
let cpimEnabled = linphone_account_params_cpim_in_basic_chat_room_enabled(params)
|
||||||
|
|
||||||
|
if (!basic || (cpimEnabled != 0)) && (message != nil) && message!.count > 0 {
|
||||||
|
linphone_chat_message_add_utf8_text_content(msg?.getCobject, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (externalUrl != nil) {
|
||||||
|
linphone_chat_message_set_external_body_url(msg?.getCobject, externalUrl!.absoluteString)
|
||||||
|
}
|
||||||
|
|
||||||
|
let contentList = linphone_chat_message_get_contents(msg?.getCobject)
|
||||||
|
if bctbx_list_size(contentList) > 0 {
|
||||||
|
linphone_chat_message_send(msg?.getCobject)
|
||||||
|
}
|
||||||
|
|
||||||
|
if basic && (cpimEnabled == 0) && (message != nil) && message!.count > 0 {
|
||||||
|
linphone_chat_message_send(linphone_chat_room_create_message_from_utf8(chatRoom?.getCobject, message))
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBasicChatRoom(_ room: OpaquePointer?) -> Bool {
|
||||||
|
if room == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
let charRoomBasic = ChatRoom.getSwiftObject(cObject: room!)
|
||||||
|
let isBasic = charRoomBasic.hasCapability(mask: Int(LinphoneChatRoomCapabilitiesBasic.rawValue))
|
||||||
|
return isBasic
|
||||||
|
}
|
||||||
|
|
||||||
|
func startUploadData(_ data: Data?, withType type: String?, withName name: String?, andMessage message: String?, rootMessage: ChatMessage?){
|
||||||
|
let fileTransfer = FileTransferDelegate.init()
|
||||||
|
if let msg = message {
|
||||||
|
fileTransfer.text = msg
|
||||||
|
}
|
||||||
|
var resultType = "file"
|
||||||
|
var key = "localfile"
|
||||||
|
if type == "file_video_default" {
|
||||||
|
resultType = "video"
|
||||||
|
key = "localvideo"
|
||||||
|
} else if type == "file_picture_default" {
|
||||||
|
resultType = "image"
|
||||||
|
key = "localimage"
|
||||||
|
}
|
||||||
|
fileTransfer.uploadData(data, for: chatRoom?.getCobject, type: resultType, subtype: resultType, name: name, key: key, rootMessage: rootMessage?.getCobject)
|
||||||
|
}
|
||||||
|
|
||||||
|
func startFileUpload(_ data: Data?, withName name: String?, rootMessage: ChatMessage?){
|
||||||
|
let fileTransfer = FileTransferDelegate()
|
||||||
|
fileTransfer.uploadFile(data, for: ChatConversationViewModel.sharedModel.chatRoom?.getCobject, withName: name, rootMessage: rootMessage?.getCobject)
|
||||||
|
}
|
||||||
|
|
||||||
|
func shareFile() {
|
||||||
|
let groupName = "group.\(Bundle.main.bundleIdentifier ?? "").linphoneExtension"
|
||||||
|
let defaults = UserDefaults(suiteName: groupName)
|
||||||
|
let dict = defaults?.value(forKey: "photoData") as? [AnyHashable : Any]
|
||||||
|
if let dict_notnil = dict {
|
||||||
|
//file shared from photo lib
|
||||||
|
shareFileMessage = dict_notnil["message"] as? String
|
||||||
|
shareFileName.value = dict_notnil["url"] as? String
|
||||||
|
defaults?.removeObject(forKey: "photoData")
|
||||||
|
} else if let dictFile = defaults?.value(forKey: "icloudData") as? [AnyHashable : Any] {
|
||||||
|
shareFileMessage = dict?["message"] as? String
|
||||||
|
shareFileName.value = dictFile["url"] as? String
|
||||||
|
defaults?.removeObject(forKey: "icloudData")
|
||||||
|
} else if let dictUrl = defaults?.value(forKey: "url") as? [AnyHashable : Any] {
|
||||||
|
shareFileMessage = dict?["message"] as? String
|
||||||
|
shareFileURL.value = dictUrl["url"] as? String
|
||||||
|
defaults?.removeObject(forKey: "url")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getImageFrom(_ content: OpaquePointer?, filePath: String?, forReplyBubble: Bool) -> UIImage? {
|
||||||
|
var filePath = filePath
|
||||||
|
let type = String(utf8String: linphone_content_get_type(content))
|
||||||
|
let name = String(utf8String: linphone_content_get_name(content))
|
||||||
|
if filePath == nil {
|
||||||
|
filePath = LinphoneManager.validFilePath(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
var image: UIImage? = nil
|
||||||
|
if type == "video" {
|
||||||
|
image = UIChatBubbleTextCell.getImageFromVideoUrl(URL(fileURLWithPath: filePath ?? ""))
|
||||||
|
} else if type == "image" {
|
||||||
|
image = UIImage(named: filePath ?? "")
|
||||||
|
}
|
||||||
|
|
||||||
|
if let img = image {
|
||||||
|
return img
|
||||||
|
} else {
|
||||||
|
return getImageFromFileName(name, forReplyBubble: forReplyBubble)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getImageFromFileName(_ fileName: String?, forReplyBubble forReplyBubbble: Bool) -> UIImage? {
|
||||||
|
let extensionFile = fileName?.lowercased().components(separatedBy: ".").last
|
||||||
|
var image: UIImage?
|
||||||
|
var text = fileName
|
||||||
|
if fileName?.contains("voice-recording") ?? false {
|
||||||
|
image = UIImage(named: "file_voice_default")
|
||||||
|
text = recordingDuration(LinphoneManager.validFilePath(fileName))
|
||||||
|
} else {
|
||||||
|
if extensionFile == "pdf" {
|
||||||
|
image = UIImage(named: "file_pdf_default")
|
||||||
|
} else if ["png", "jpg", "jpeg", "bmp", "heic"].contains(extensionFile ?? "") {
|
||||||
|
image = UIImage(named: "file_picture_default")
|
||||||
|
} else if ["mkv", "avi", "mov", "mp4"].contains(extensionFile ?? "") {
|
||||||
|
image = UIImage(named: "file_video_default")
|
||||||
|
} else if ["wav", "au", "m4a"].contains(extensionFile ?? "") {
|
||||||
|
image = UIImage(named: "file_audio_default")
|
||||||
|
} else {
|
||||||
|
image = UIImage(named: "file_default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SwiftUtil.textToImage(drawText: text!, inImage: image!, forReplyBubble: forReplyBubbble)
|
||||||
|
}
|
||||||
|
|
||||||
|
func recordingDuration(_ _voiceRecordingFile: String?) -> String? {
|
||||||
|
let core = Core.getSwiftObject(cObject: LinphoneManager.getLc())
|
||||||
|
var result = ""
|
||||||
|
do{
|
||||||
|
let linphonePlayer = try core.createLocalPlayer(soundCardName: nil, videoDisplayName: nil, windowId: nil)
|
||||||
|
try linphonePlayer.open(filename: _voiceRecordingFile!)
|
||||||
|
result = formattedDuration(linphonePlayer.duration)!
|
||||||
|
linphonePlayer.close()
|
||||||
|
}catch{
|
||||||
|
Log.e(error.localizedDescription)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func formattedDuration(_ valueMs: Int) -> String? {
|
||||||
|
return String(format: "%02ld:%02ld", valueMs / 60000, (valueMs % 60000) / 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeMediaToGalleryFromName(_ name: String?, fileType: String?) {
|
||||||
|
let filePath = LinphoneManager.validFilePath(name)
|
||||||
|
let fileManager = FileManager.default
|
||||||
|
if fileManager.fileExists(atPath: filePath!) {
|
||||||
|
let data = NSData(contentsOfFile: filePath!) as Data?
|
||||||
|
let block: (() -> Void)? = {
|
||||||
|
if fileType == "image" {
|
||||||
|
// we're finished, save the image and update the message
|
||||||
|
let image = UIImage(data: data!)
|
||||||
|
if image == nil {
|
||||||
|
ChatConversationViewSwift.showFileDownloadError()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var placeHolder: PHObjectPlaceholder? = nil
|
||||||
|
PHPhotoLibrary.shared().performChanges({
|
||||||
|
let request = PHAssetCreationRequest.creationRequestForAsset(from: image!)
|
||||||
|
placeHolder = request.placeholderForCreatedAsset
|
||||||
|
}) { success, error in
|
||||||
|
DispatchQueue.main.async(execute: {
|
||||||
|
if error != nil {
|
||||||
|
Log.e("Cannot save image data downloaded \(error!.localizedDescription)")
|
||||||
|
let errView = UIAlertController(
|
||||||
|
title: NSLocalizedString("Transfer error", comment: ""),
|
||||||
|
message: NSLocalizedString("Cannot write image to photo library", comment: ""),
|
||||||
|
preferredStyle: .alert)
|
||||||
|
|
||||||
|
let defaultAction = UIAlertAction(
|
||||||
|
title: "OK",
|
||||||
|
style: .default,
|
||||||
|
handler: { action in
|
||||||
|
})
|
||||||
|
|
||||||
|
errView.addAction(defaultAction)
|
||||||
|
PhoneMainView.instance()!.present(errView, animated: true)
|
||||||
|
} else {
|
||||||
|
Log.i("Image saved to \(placeHolder!.localIdentifier)")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if fileType == "video" {
|
||||||
|
var placeHolder: PHObjectPlaceholder?
|
||||||
|
PHPhotoLibrary.shared().performChanges({
|
||||||
|
let request = PHAssetCreationRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath!))
|
||||||
|
placeHolder = request?.placeholderForCreatedAsset
|
||||||
|
}) { success, error in
|
||||||
|
DispatchQueue.main.async(execute: {
|
||||||
|
if error != nil {
|
||||||
|
Log.e("Cannot save video data downloaded \(error!.localizedDescription)")
|
||||||
|
let errView = UIAlertController(
|
||||||
|
title: NSLocalizedString("Transfer error", comment: ""),
|
||||||
|
message: NSLocalizedString("Cannot write video to photo library", comment: ""),
|
||||||
|
preferredStyle: .alert)
|
||||||
|
let defaultAction = UIAlertAction(
|
||||||
|
title: "OK",
|
||||||
|
style: .default,
|
||||||
|
handler: { action in
|
||||||
|
})
|
||||||
|
|
||||||
|
errView.addAction(defaultAction)
|
||||||
|
PhoneMainView.instance()!.present(errView, animated: true)
|
||||||
|
} else {
|
||||||
|
Log.i("video saved to \(placeHolder!.localIdentifier)")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if PHPhotoLibrary.authorizationStatus() == .authorized {
|
||||||
|
block!()
|
||||||
|
} else {
|
||||||
|
PHPhotoLibrary.requestAuthorization({ status in
|
||||||
|
DispatchQueue.main.async(execute: {
|
||||||
|
if PHPhotoLibrary.authorizationStatus() == .authorized {
|
||||||
|
block!()
|
||||||
|
} else {
|
||||||
|
let alert = UIAlertController(title: NSLocalizedString("Photo's permission", comment: ""), message: NSLocalizedString("Photo not authorized", comment: ""), preferredStyle: .alert)
|
||||||
|
alert.addAction(UIAlertAction(title: NSLocalizedString("Continue", comment: ""), style: .default))
|
||||||
|
PhoneMainView.instance()!.present(alert, animated: true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createCollectionViewItem(urlFile: URL?, type: String) {
|
||||||
|
if let url = urlFile {
|
||||||
|
do {
|
||||||
|
if(type == "public.image"){
|
||||||
|
let dataResult = try Data(contentsOf: url)
|
||||||
|
ChatConversationViewModel.sharedModel.data.append(dataResult)
|
||||||
|
if let image = UIImage(data: dataResult) {
|
||||||
|
ChatConversationViewModel.sharedModel.imageT.append(image)
|
||||||
|
}else{
|
||||||
|
ChatConversationViewModel.sharedModel.imageT.append(UIImage(named: "chat_error"))
|
||||||
|
}
|
||||||
|
}else if(type == "public.movie"){
|
||||||
|
ChatConversationViewModel.sharedModel.data.append(try Data(contentsOf: url))
|
||||||
|
var tmpImage = ChatConversationViewModel.sharedModel.createThumbnailOfVideoFromFileURL(videoURL: url.relativeString)
|
||||||
|
if tmpImage == nil { tmpImage = UIImage(named: "chat_error")}
|
||||||
|
ChatConversationViewModel.sharedModel.imageT.append(tmpImage)
|
||||||
|
}else{
|
||||||
|
|
||||||
|
ChatConversationViewModel.sharedModel.data.append(try Data(contentsOf: url))
|
||||||
|
let otherFile = FileType.init(url.pathExtension)
|
||||||
|
let otherFileImage = otherFile!.getImageFromFile()
|
||||||
|
ChatConversationViewModel.sharedModel.imageT.append(otherFileImage)
|
||||||
|
}
|
||||||
|
ChatConversationViewModel.sharedModel.urlFile.append(url)
|
||||||
|
DispatchQueue.main.async(execute: ChatConversationViewModel.sharedModel.workItem!)
|
||||||
|
}catch let error{
|
||||||
|
Log.e(error.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func createCollectionViewItemForReply(urlFile: URL?, type: String) -> UIImage {
|
||||||
|
if urlFile != nil {
|
||||||
|
do {
|
||||||
|
if(type == "public.image"){
|
||||||
|
let dataResult = try Data(contentsOf: urlFile!)
|
||||||
|
if let image = UIImage(data: dataResult) {
|
||||||
|
return image
|
||||||
|
}else{
|
||||||
|
return UIImage(named: "chat_error")!
|
||||||
|
}
|
||||||
|
}else if(type == "public.movie"){
|
||||||
|
var tmpImage = ChatConversationViewModel.sharedModel.createThumbnailOfVideoFromFileURL(videoURL: urlFile!.relativeString)
|
||||||
|
if tmpImage == nil { tmpImage = UIImage(named: "chat_error")}
|
||||||
|
return tmpImage!
|
||||||
|
}else{
|
||||||
|
let otherFile = FileType.init(urlFile!.pathExtension)
|
||||||
|
let otherFileImage = otherFile!.getImageFromFile()
|
||||||
|
return otherFileImage!
|
||||||
|
}
|
||||||
|
}catch let error{
|
||||||
|
Log.e(error.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UIImage(named: "chat_error")!
|
||||||
|
}
|
||||||
|
|
||||||
|
func createThumbnailOfVideoFromFileURL(videoURL: String) -> UIImage? {
|
||||||
|
if let urlVideo = URL(string: videoURL){
|
||||||
|
let asset = AVAsset(url: urlVideo)
|
||||||
|
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
|
||||||
|
assetImgGenerate.appliesPreferredTrackTransform = true
|
||||||
|
do {
|
||||||
|
let img = try assetImgGenerate.copyCGImage(at: CMTimeMake(value: 1, timescale: 10), actualTime: nil)
|
||||||
|
let thumbnail = UIImage(cgImage: img)
|
||||||
|
return thumbnail
|
||||||
|
} catch _{
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Voice recoder and player
|
||||||
|
func createVoiceRecorder() {
|
||||||
|
let core = Core.getSwiftObject(cObject: LinphoneManager.getLc())
|
||||||
|
do{
|
||||||
|
let p = try core.createRecorderParams()
|
||||||
|
p.fileFormat = RecorderFileFormat.Mkv
|
||||||
|
ChatConversationViewModel.sharedModel.voiceRecorder = try core.createRecorder(params: p)
|
||||||
|
}catch{
|
||||||
|
Log.e(error.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func startVoiceRecording() {
|
||||||
|
if (voiceRecorder == nil) {
|
||||||
|
createVoiceRecorder()
|
||||||
|
}
|
||||||
|
CallManager.instance().activateAudioSession()
|
||||||
|
|
||||||
|
showVoiceRecorderView = true
|
||||||
|
isVoiceRecording = true
|
||||||
|
|
||||||
|
switch linphone_recorder_get_state(voiceRecorder?.getCobject) {
|
||||||
|
case LinphoneRecorderClosed:
|
||||||
|
let filename = "\(String(describing: LinphoneManager.imagesDirectory()))/voice-recording-\(UUID().uuidString).mkv"
|
||||||
|
linphone_recorder_open(voiceRecorder?.getCobject, filename)
|
||||||
|
linphone_recorder_start(voiceRecorder?.getCobject)
|
||||||
|
Log.i("[Chat Message Sending] Recorder is closed opening it with \(filename)")
|
||||||
|
case LinphoneRecorderRunning:
|
||||||
|
Log.i("[Chat Message Sending] Recorder is already recording")
|
||||||
|
case LinphoneRecorderPaused:
|
||||||
|
Log.i("[Chat Message Sending] Recorder isn't closed, resuming recording")
|
||||||
|
linphone_recorder_start(voiceRecorder?.getCobject)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopVoiceRecording() {
|
||||||
|
if (ChatConversationViewModel.sharedModel.voiceRecorder != nil) && linphone_recorder_get_state(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject) == LinphoneRecorderRunning {
|
||||||
|
Log.i("[Chat Message Sending] Pausing / closing voice recorder")
|
||||||
|
linphone_recorder_pause(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject)
|
||||||
|
linphone_recorder_close(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject)
|
||||||
|
}
|
||||||
|
isVoiceRecording = false
|
||||||
|
vrRecordTimer.invalidate()
|
||||||
|
isPendingVoiceRecord = linphone_recorder_get_duration(ChatConversationViewModel.sharedModel.voiceRecorder?.getCobject) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func initSharedPlayer() {
|
||||||
|
AudioPlayer.initSharedPlayer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func startSharedPlayer(_ path: String?) {
|
||||||
|
AudioPlayer.startSharedPlayer(path)
|
||||||
|
AudioPlayer.sharedModel.fileChanged.value = path
|
||||||
|
}
|
||||||
|
|
||||||
|
func cancelVoiceRecordingVM() {
|
||||||
|
showVoiceRecorderView = false
|
||||||
|
isPendingVoiceRecord = false
|
||||||
|
isVoiceRecording = false
|
||||||
|
if (voiceRecorder != nil) && linphone_recorder_get_state(voiceRecorder?.getCobject) != LinphoneRecorderClosed {
|
||||||
|
AudioPlayer.cancelVoiceRecordingVM(voiceRecorder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopSharedPlayer() {
|
||||||
|
AudioPlayer.stopSharedPlayer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeTmpFile(filePath: String?){
|
||||||
|
if (filePath != nil) {
|
||||||
|
if (filePath != "") {
|
||||||
|
do {
|
||||||
|
Log.i("[vfs] remove item at \(filePath)")
|
||||||
|
try FileManager.default.removeItem(atPath: filePath!)
|
||||||
|
}catch{
|
||||||
|
Log.e("[vfs] remove item error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
725
Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift
Normal file
725
Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift
Normal file
|
|
@ -0,0 +1,725 @@
|
||||||
|
/*
|
||||||
|
* 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 Foundation
|
||||||
|
import linphonesw
|
||||||
|
import DropDown
|
||||||
|
import QuickLook
|
||||||
|
import SwipeCellKit
|
||||||
|
|
||||||
|
class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, QLPreviewControllerDelegate, QLPreviewControllerDataSource, SwipeCollectionViewCellDelegate {
|
||||||
|
|
||||||
|
static let compositeDescription = UICompositeViewDescription(ChatConversationTableViewSwift.self, statusBar: StatusBarView.self, tabBar: nil, sideMenu: SideMenuView.self, fullscreen: false, isLeftFragment: false,fragmentWith: nil)
|
||||||
|
|
||||||
|
static func compositeViewDescription() -> UICompositeViewDescription! { return compositeDescription }
|
||||||
|
|
||||||
|
func compositeViewDescription() -> UICompositeViewDescription! { return type(of: self).compositeDescription }
|
||||||
|
|
||||||
|
lazy var collectionView: UICollectionView = {
|
||||||
|
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
|
||||||
|
return collectionView
|
||||||
|
}()
|
||||||
|
|
||||||
|
var menu: DropDown? = nil
|
||||||
|
|
||||||
|
var basic :Bool = false
|
||||||
|
|
||||||
|
var floatingScrollButton : UIButton?
|
||||||
|
var scrollBadge : UILabel?
|
||||||
|
var floatingScrollBackground : UIButton?
|
||||||
|
|
||||||
|
var previewItems : [QLPreviewItem?] = []
|
||||||
|
var afterPreviewIndex = -1
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
|
||||||
|
self.initView()
|
||||||
|
|
||||||
|
UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in
|
||||||
|
self.collectionView.backgroundColor = VoipTheme.backgroundWhiteBlack.get()
|
||||||
|
self.collectionView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatConversationTableViewModel.sharedModel.refreshIndexPath.observe { index in
|
||||||
|
self.collectionView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatConversationTableViewModel.sharedModel.onClickIndexPath.observe { index in
|
||||||
|
self.onGridClick(indexMessage: ChatConversationTableViewModel.sharedModel.onClickMessageIndexPath, index: index!)
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatConversationTableViewModel.sharedModel.editModeOn.observe { mode in
|
||||||
|
self.collectionView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
collectionView.isUserInteractionEnabled = true
|
||||||
|
collectionView.keyboardDismissMode = .interactive
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
NotificationCenter.default.removeObserver(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initView(){
|
||||||
|
basic = isBasicChatRoom(ChatConversationTableViewModel.sharedModel.chatRoom?.getCobject)
|
||||||
|
|
||||||
|
view.addSubview(collectionView)
|
||||||
|
collectionView.contentInsetAdjustmentBehavior = .always
|
||||||
|
collectionView.contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
|
||||||
|
|
||||||
|
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
|
||||||
|
collectionView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
|
||||||
|
collectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
|
||||||
|
collectionView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
|
||||||
|
|
||||||
|
collectionView.dataSource = self
|
||||||
|
collectionView.delegate = self
|
||||||
|
collectionView.register(MultilineMessageCell.self, forCellWithReuseIdentifier: MultilineMessageCell.reuseId)
|
||||||
|
|
||||||
|
(collectionView.collectionViewLayout as! UICollectionViewFlowLayout).estimatedItemSize = UICollectionViewFlowLayout.automaticSize
|
||||||
|
(collectionView.collectionViewLayout as! UICollectionViewFlowLayout).minimumLineSpacing = 2
|
||||||
|
|
||||||
|
collectionView.transform = CGAffineTransform(scaleX: 1, y: -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
createFloatingButton()
|
||||||
|
if ChatConversationTableViewModel.sharedModel.getNBMessages() > 0 {
|
||||||
|
scrollToBottom(animated: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(self.receivePresenceNotification(notification:)), name: Notification.Name("LinphoneFriendPresenceUpdate"), object: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
|
NotificationCenter.default.removeObserver(self, name: Notification.Name("LinphoneFriendPresenceUpdate"), object: nil)
|
||||||
|
NotificationCenter.default.removeObserver(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func receivePresenceNotification(notification: NSNotification) {
|
||||||
|
if (notification.name.rawValue == "LinphoneFriendPresenceUpdate"){
|
||||||
|
let userInfo = notification.userInfo
|
||||||
|
let friend = userInfo!["friend"]
|
||||||
|
|
||||||
|
let indexPathsVisible = self.collectionView.indexPathsForVisibleItems
|
||||||
|
if indexPathsVisible.count > 0 {
|
||||||
|
for i in 0...indexPathsVisible.count-1 {
|
||||||
|
let cell = self.collectionView.cellForItem(at: indexPathsVisible[i])
|
||||||
|
if cell != nil {
|
||||||
|
let multilineCell = cell as! MultilineMessageCell
|
||||||
|
if multilineCell.imageUser.isHidden == false {
|
||||||
|
let contact = ChatConversationTableViewModel.sharedModel.getMessage(index: indexPathsVisible[i].row)?.chatMessage?.fromAddress
|
||||||
|
if (contact != nil){
|
||||||
|
let uri = "sip:" + contact!.username + "@" + contact!.domain
|
||||||
|
if(uri == friend as! String){
|
||||||
|
let indexPath = indexPathsVisible[i]
|
||||||
|
collectionView.reloadItems(at: [indexPath])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func scrollToMessage(message: ChatMessage){
|
||||||
|
let messageIndex = ChatConversationTableViewModel.sharedModel.getIndexMessage(message: message)
|
||||||
|
self.collectionView.scrollToItem(at: IndexPath(row: messageIndex, section: 0), at: .bottom, animated: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func scrollToBottom(animated: Bool){
|
||||||
|
DispatchQueue.main.async{
|
||||||
|
self.collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .top, animated: animated)
|
||||||
|
}
|
||||||
|
ChatConversationViewSwift.markAsRead(ChatConversationViewModel.sharedModel.chatRoom?.getCobject)
|
||||||
|
self.floatingScrollButton?.isHidden = true
|
||||||
|
self.floatingScrollBackground?.isHidden = true
|
||||||
|
scrollBadge!.text = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
func refreshDataAfterForeground(){
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.collectionView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func refreshData(isOutgoing: Bool){
|
||||||
|
if (ChatConversationTableViewModel.sharedModel.getNBMessages() > 1){
|
||||||
|
let isDisplayingBottomOfTable = collectionView.contentOffset.y <= 20
|
||||||
|
|
||||||
|
if ChatConversationTableViewModel.sharedModel.getNBMessages() < 4 {
|
||||||
|
collectionView.reloadData()
|
||||||
|
ChatConversationViewSwift.markAsRead(ChatConversationViewModel.sharedModel.chatRoom?.getCobject)
|
||||||
|
} else if isDisplayingBottomOfTable {
|
||||||
|
if self.collectionView.numberOfItems(inSection: 0) > 2 {
|
||||||
|
self.collectionView.scrollToItem(at: IndexPath(item: 1, section: 0), at: .top, animated: false)
|
||||||
|
}
|
||||||
|
collectionView.reloadData()
|
||||||
|
self.scrollToBottom(animated: true)
|
||||||
|
} else if !isOutgoing {
|
||||||
|
if !collectionView.indexPathsForVisibleItems.isEmpty {
|
||||||
|
let selectedCellIndex = collectionView.indexPathsForVisibleItems.sorted().first!
|
||||||
|
let selectedCell = collectionView.cellForItem(at: selectedCellIndex)
|
||||||
|
let visibleRect = collectionView.convert(collectionView.bounds, to: selectedCell)
|
||||||
|
|
||||||
|
UIView.performWithoutAnimation {
|
||||||
|
collectionView.reloadData()
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2){
|
||||||
|
let newSelectedCell = self.collectionView.cellForItem(at: IndexPath(row: selectedCellIndex.row + 1, section: 0))
|
||||||
|
let updatedVisibleRect = self.collectionView.convert(self.collectionView.bounds, to: newSelectedCell)
|
||||||
|
|
||||||
|
var contentOffset = self.collectionView.contentOffset
|
||||||
|
contentOffset.y = contentOffset.y + (visibleRect.origin.y - updatedVisibleRect.origin.y)
|
||||||
|
self.collectionView.contentOffset = contentOffset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scrollBadge!.isHidden = false
|
||||||
|
scrollBadge!.text = "\(ChatConversationViewModel.sharedModel.chatRoom?.unreadMessagesCount ?? 0)"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
collectionView.reloadData()
|
||||||
|
self.scrollToBottom(animated: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ChatConversationTableViewModel.sharedModel.editModeOn.value! {
|
||||||
|
ChatConversationTableViewModel.sharedModel.messageListSelected.value!.insert(false, at: 0)
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
collectionView.reloadData()
|
||||||
|
if(ChatConversationViewModel.sharedModel.chatRoom != nil){
|
||||||
|
ChatConversationViewSwift.markAsRead(ChatConversationViewModel.sharedModel.chatRoom?.getCobject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
|
let contentOffsetY = scrollView.contentOffset.y
|
||||||
|
if contentOffsetY <= 20{
|
||||||
|
if floatingScrollButton != nil && floatingScrollBackground != nil {
|
||||||
|
floatingScrollButton?.isHidden = true
|
||||||
|
floatingScrollBackground?.isHidden = true
|
||||||
|
scrollBadge?.text = "0"
|
||||||
|
ChatConversationViewSwift.markAsRead(ChatConversationViewModel.sharedModel.chatRoom?.getCobject)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if floatingScrollButton != nil && floatingScrollBackground != nil {
|
||||||
|
floatingScrollButton?.isHidden = false
|
||||||
|
floatingScrollBackground?.isHidden = false;
|
||||||
|
if(scrollBadge?.text == "0"){
|
||||||
|
scrollBadge?.isHidden = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UICollectionViewDataSource -
|
||||||
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MultilineMessageCell.reuseId, for: indexPath) as! MultilineMessageCell
|
||||||
|
cell.delegate = self
|
||||||
|
if let event = ChatConversationTableViewModel.sharedModel.getMessage(index: indexPath.row){
|
||||||
|
if(ChatConversationTableViewModel.sharedModel.editModeOn.value! && indexPath.row >= ChatConversationTableViewModel.sharedModel.messageListSelected.value!.count){
|
||||||
|
for _ in ChatConversationTableViewModel.sharedModel.messageListSelected.value!.count...indexPath.row {
|
||||||
|
ChatConversationTableViewModel.sharedModel.messageListSelected.value!.append(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.configure(event: event, selfIndexPathConfigure: indexPath, editMode: ChatConversationTableViewModel.sharedModel.editModeOn.value!, selected: ChatConversationTableViewModel.sharedModel.editModeOn.value! ? ChatConversationTableViewModel.sharedModel.messageListSelected.value![indexPath.row] : false)
|
||||||
|
|
||||||
|
if (event.chatMessage != nil && ChatConversationViewModel.sharedModel.chatRoom != nil){
|
||||||
|
cell.onLongClickOneClick {
|
||||||
|
if(cell.chatMessage != nil && ChatConversationViewModel.sharedModel.chatRoom != nil){
|
||||||
|
self.initDataSource(message: cell.chatMessage!)
|
||||||
|
self.tapChooseMenuItemMessage(contentViewBubble: cell.contentViewBubble, event: cell.eventMessage!, preContentSize: cell.preContentViewBubble.frame.size.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cell.replyContent.isHidden && event.chatMessage?.replyMessage != nil){
|
||||||
|
cell.replyContent.onClick {
|
||||||
|
self.scrollToMessage(message: (cell.chatMessage?.replyMessage)!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cell.imageViewBubble.isHidden || !cell.imageVideoViewBubble.isHidden){
|
||||||
|
cell.imageViewBubble.onClick {
|
||||||
|
self.onImageClick(chatMessage: cell.chatMessage!, index: indexPath.row)
|
||||||
|
}
|
||||||
|
cell.imageVideoViewBubble.onClick {
|
||||||
|
self.onImageClick(chatMessage: cell.chatMessage!, index: indexPath.row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cell.contentView.transform = CGAffineTransform(scaleX: 1, y: -1)
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
|
||||||
|
let customCell = cell as! MultilineMessageCell
|
||||||
|
|
||||||
|
if customCell.isPlayingVoiceRecording {
|
||||||
|
AudioPlayer.stopSharedPlayer()
|
||||||
|
}
|
||||||
|
|
||||||
|
if customCell.ephemeralTimer != nil {
|
||||||
|
customCell.ephemeralTimer?.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
if customCell.chatMessageDelegate != nil {
|
||||||
|
customCell.chatMessage?.removeDelegate(delegate: customCell.chatMessageDelegate!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
|
return ChatConversationTableViewModel.sharedModel.getNBMessages()
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, editActionsForItemAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
|
||||||
|
let message = ChatConversationTableViewModel.sharedModel.getMessage(index: indexPath.row)
|
||||||
|
if orientation == .left {
|
||||||
|
if message?.chatMessage != nil {
|
||||||
|
let replyAction = SwipeAction(style: .default, title: "Reply") { action, indexPath in
|
||||||
|
self.replyMessage(message: (message?.chatMessage)!)
|
||||||
|
}
|
||||||
|
return [replyAction]
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
|
||||||
|
self.deleteMessage(message: message!)
|
||||||
|
}
|
||||||
|
return [deleteAction]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, editActionsOptionsForItemAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
|
||||||
|
var options = SwipeOptions()
|
||||||
|
if orientation == .left {
|
||||||
|
options.expansionStyle = .selection
|
||||||
|
}
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBasicChatRoom(_ room: OpaquePointer?) -> Bool {
|
||||||
|
if room == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
let charRoomBasic = ChatRoom.getSwiftObject(cObject: room!)
|
||||||
|
let isBasic = charRoomBasic.hasCapability(mask: Int(LinphoneChatRoomCapabilitiesBasic.rawValue))
|
||||||
|
return isBasic
|
||||||
|
}
|
||||||
|
|
||||||
|
func tapChooseMenuItemMessage(contentViewBubble: UIView, event: EventLog, preContentSize: CGFloat) {
|
||||||
|
|
||||||
|
menu!.anchorView = view
|
||||||
|
menu!.width = 200
|
||||||
|
|
||||||
|
let coordinateMin = contentViewBubble.convert(contentViewBubble.frame.origin, to: view)
|
||||||
|
let coordinateMax = contentViewBubble.convert(CGPoint(x: contentViewBubble.frame.maxX, y: contentViewBubble.frame.maxY), to: view)
|
||||||
|
|
||||||
|
if (coordinateMax.y + CGFloat(menu!.dataSource.count * 44) - preContentSize < view.frame.maxY) {
|
||||||
|
menu!.bottomOffset = CGPoint(x: event.chatMessage!.isOutgoing ? coordinateMax.x - 200 : coordinateMin.x, y: coordinateMax.y - preContentSize)
|
||||||
|
} else if ((coordinateMax.y + CGFloat(menu!.dataSource.count * 44) > view.frame.maxY) && coordinateMin.y > CGFloat(menu!.dataSource.count * 44) + (preContentSize * 2)) {
|
||||||
|
menu!.bottomOffset = CGPoint(x: event.chatMessage!.isOutgoing ? coordinateMax.x - 200 : coordinateMin.x, y: coordinateMin.y - (preContentSize * 2) - CGFloat(menu!.dataSource.count * 44))
|
||||||
|
} else {
|
||||||
|
menu!.bottomOffset = CGPoint(x: event.chatMessage!.isOutgoing ? coordinateMax.x - 200 : coordinateMin.x, y: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
let view: ChatConversationViewSwift = self.VIEW(ChatConversationViewSwift.compositeViewDescription())
|
||||||
|
view.messageView.endEditing(true)
|
||||||
|
|
||||||
|
menu!.show()
|
||||||
|
menu!.selectionAction = { [weak self] (index: Int, item: String) in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
switch item {
|
||||||
|
case VoipTexts.bubble_chat_dropDown_resend:
|
||||||
|
self!.resendMessage(message: event.chatMessage!)
|
||||||
|
case VoipTexts.bubble_chat_dropDown_copy_text:
|
||||||
|
self!.copyMessage(message: event.chatMessage!)
|
||||||
|
case VoipTexts.bubble_chat_dropDown_forward:
|
||||||
|
self!.forwardMessage(message: event.chatMessage!)
|
||||||
|
case VoipTexts.bubble_chat_dropDown_reply:
|
||||||
|
self!.replyMessage(message: event.chatMessage!)
|
||||||
|
case VoipTexts.bubble_chat_dropDown_infos:
|
||||||
|
self!.infoMessage(event: event)
|
||||||
|
case VoipTexts.bubble_chat_dropDown_add_to_contact:
|
||||||
|
self!.addToContacts(message: event.chatMessage!)
|
||||||
|
case VoipTexts.bubble_chat_dropDown_delete:
|
||||||
|
self!.deleteMessage(message: event)
|
||||||
|
default:
|
||||||
|
Log.e("Error Default tapChooseMenuItemMessage ChatConversationTableViewSwift")
|
||||||
|
}
|
||||||
|
self!.menu!.clearSelection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDataSource(message: ChatMessage) {
|
||||||
|
menu = {
|
||||||
|
let menu = DropDown()
|
||||||
|
menu.dataSource = [""]
|
||||||
|
let images = [
|
||||||
|
"menu_resend_default",
|
||||||
|
"menu_copy_text_default",
|
||||||
|
"menu_forward_default",
|
||||||
|
"menu_reply_default",
|
||||||
|
"menu_info",
|
||||||
|
"contact_add_default",
|
||||||
|
"menu_delete",
|
||||||
|
"menu_info"
|
||||||
|
]
|
||||||
|
menu.cellNib = UINib(nibName: "DropDownCell", bundle: nil)
|
||||||
|
menu.customCellConfiguration = { index, title, cell in
|
||||||
|
guard let cell = cell as? MyCell else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(index < images.count){
|
||||||
|
switch menu.dataSource[index] {
|
||||||
|
case VoipTexts.bubble_chat_dropDown_resend:
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
cell.myImageView.image = UIImage(named: images[0])!.withTintColor(.darkGray)
|
||||||
|
} else {
|
||||||
|
cell.myImageView.image = UIImage(named: images[0])
|
||||||
|
}
|
||||||
|
case VoipTexts.bubble_chat_dropDown_copy_text:
|
||||||
|
cell.myImageView.image = UIImage(named: images[1])
|
||||||
|
case VoipTexts.bubble_chat_dropDown_forward:
|
||||||
|
cell.myImageView.image = UIImage(named: images[2])
|
||||||
|
case VoipTexts.bubble_chat_dropDown_reply:
|
||||||
|
cell.myImageView.image = UIImage(named: images[3])
|
||||||
|
case VoipTexts.bubble_chat_dropDown_infos:
|
||||||
|
cell.myImageView.image = UIImage(named: images[4])
|
||||||
|
case VoipTexts.bubble_chat_dropDown_add_to_contact:
|
||||||
|
cell.myImageView.image = UIImage(named: images[5])
|
||||||
|
case VoipTexts.bubble_chat_dropDown_delete:
|
||||||
|
cell.myImageView.image = UIImage(named: images[6])
|
||||||
|
default:
|
||||||
|
cell.myImageView.image = UIImage(named: images[7])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return menu
|
||||||
|
}()
|
||||||
|
|
||||||
|
menu!.dataSource.removeAll()
|
||||||
|
let state = message.state
|
||||||
|
|
||||||
|
if (state.rawValue == LinphoneChatMessageStateNotDelivered.rawValue || state.rawValue == LinphoneChatMessageStateFileTransferError.rawValue) {
|
||||||
|
menu!.dataSource.append(VoipTexts.bubble_chat_dropDown_resend)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.utf8Text != "" && !ICSBubbleView.isConferenceInvitationMessage(cmessage: message.getCobject!)) {
|
||||||
|
menu!.dataSource.append(VoipTexts.bubble_chat_dropDown_copy_text)
|
||||||
|
}
|
||||||
|
|
||||||
|
menu!.dataSource.append(VoipTexts.bubble_chat_dropDown_forward)
|
||||||
|
|
||||||
|
menu!.dataSource.append(VoipTexts.bubble_chat_dropDown_reply)
|
||||||
|
|
||||||
|
let chatroom = ChatConversationViewModel.sharedModel.chatRoom
|
||||||
|
if chatroom != nil {
|
||||||
|
if (chatroom!.nbParticipants > 1) {
|
||||||
|
menu!.dataSource.append(VoipTexts.bubble_chat_dropDown_infos)
|
||||||
|
}
|
||||||
|
|
||||||
|
let isOneToOneChat = ChatConversationViewModel.sharedModel.chatRoom!.hasCapability(mask: Int(LinphoneChatRoomCapabilitiesOneToOne.rawValue))
|
||||||
|
if (!message.isOutgoing && FastAddressBook.getContactWith(message.fromAddress?.getCobject) == nil
|
||||||
|
&& !isOneToOneChat && !ConfigManager.instance().lpConfigBoolForKey(key: "read_only_native_address_book")) {
|
||||||
|
menu!.dataSource.append(VoipTexts.bubble_chat_dropDown_add_to_contact)
|
||||||
|
}
|
||||||
|
|
||||||
|
menu!.dataSource.append(VoipTexts.bubble_chat_dropDown_delete)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resendMessage(message: ChatMessage){
|
||||||
|
if ((linphone_core_is_network_reachable(LinphoneManager.getLc()) == 0)) {
|
||||||
|
PhoneMainView.instance().present(LinphoneUtils.networkErrorView("send a message"), animated: true)
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
message.send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyMessage(message: ChatMessage){
|
||||||
|
UIPasteboard.general.string = message.utf8Text
|
||||||
|
}
|
||||||
|
|
||||||
|
func forwardMessage(message: ChatMessage){
|
||||||
|
let view: ChatConversationViewSwift = self.VIEW(ChatConversationViewSwift.compositeViewDescription())
|
||||||
|
view.pendingForwardMessage = message.getCobject
|
||||||
|
let viewtoGo: ChatsListView = self.VIEW(ChatsListView.compositeViewDescription())
|
||||||
|
PhoneMainView.instance().changeCurrentView(viewtoGo.compositeViewDescription())
|
||||||
|
}
|
||||||
|
|
||||||
|
func replyMessage(message: ChatMessage){
|
||||||
|
let view: ChatConversationViewSwift = self.VIEW(ChatConversationViewSwift.compositeViewDescription())
|
||||||
|
if (view.messageView.messageText.text == "" && view.stackView.arrangedSubviews[3].isHidden && view.stackView.arrangedSubviews[4].isHidden){
|
||||||
|
view.messageView.messageText.becomeFirstResponder()
|
||||||
|
}
|
||||||
|
view.initiateReplyView(forMessage: message.getCobject)
|
||||||
|
}
|
||||||
|
|
||||||
|
func infoMessage(event: EventLog){
|
||||||
|
let view: ChatConversationImdnView = self.VIEW(ChatConversationImdnView.compositeViewDescription())
|
||||||
|
view.event = event.getCobject
|
||||||
|
PhoneMainView.instance().changeCurrentView(view.compositeViewDescription())
|
||||||
|
}
|
||||||
|
|
||||||
|
func addToContacts(message: ChatMessage) {
|
||||||
|
let addr = message.fromAddress
|
||||||
|
addr?.clean()
|
||||||
|
if let lAddress = addr?.asStringUriOnly() {
|
||||||
|
var normSip = String(utf8String: lAddress)
|
||||||
|
normSip = normSip?.hasPrefix("sip:") ?? false ? (normSip as NSString?)?.substring(from: 4) : normSip
|
||||||
|
normSip = normSip?.hasPrefix("sips:") ?? false ? (normSip as NSString?)?.substring(from: 5) : normSip
|
||||||
|
ContactSelection.setAddAddress(normSip)
|
||||||
|
ContactSelection.setSelectionMode(ContactSelectionModeEdit)
|
||||||
|
ContactSelection.enableSipFilter(false)
|
||||||
|
PhoneMainView.instance().changeCurrentView(ContactsListView.compositeViewDescription())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteMessage(message: EventLog){
|
||||||
|
let messageChat = message.chatMessage
|
||||||
|
if messageChat != nil {
|
||||||
|
if ChatConversationTableViewModel.sharedModel.editModeOn.value! {
|
||||||
|
let indexDeletedMessage = ChatConversationTableViewModel.sharedModel.getIndexMessage(message: messageChat!)
|
||||||
|
ChatConversationTableViewModel.sharedModel.messageListSelected.value!.remove(at: indexDeletedMessage)
|
||||||
|
ChatConversationTableViewModel.sharedModel.messageSelected.value! -= 1
|
||||||
|
}
|
||||||
|
let chatRoom = ChatConversationViewModel.sharedModel.chatRoom
|
||||||
|
if chatRoom != nil {
|
||||||
|
chatRoom!.deleteMessage(message: messageChat!)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.deleteFromDatabase()
|
||||||
|
}
|
||||||
|
collectionView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func reloadCollectionViewCell(indexPath: IndexPath){
|
||||||
|
collectionView.reloadItems(at: [indexPath])
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPreviewItem(filePath: String) -> NSURL{
|
||||||
|
let url = NSURL(fileURLWithPath: filePath)
|
||||||
|
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
|
||||||
|
return previewItems.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
|
||||||
|
return (previewItems[index] as QLPreviewItem?)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func previewControllerDidDismiss(_ controller: QLPreviewController) {
|
||||||
|
collectionView.scrollToItem(at: IndexPath(item: afterPreviewIndex, section: 0), at: .centeredVertically, animated: false)
|
||||||
|
afterPreviewIndex = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func onImageClick(chatMessage: ChatMessage, index: Int) {
|
||||||
|
|
||||||
|
let state = chatMessage.state
|
||||||
|
if (state.rawValue == LinphoneChatMessageStateNotDelivered.rawValue) {
|
||||||
|
Log.i("Messsage not delivered")
|
||||||
|
} else {
|
||||||
|
if (VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) || ConfigManager.instance().lpConfigBoolForKey(key: "use_in_app_file_viewer_for_non_encrypted_files", section: "app")){
|
||||||
|
|
||||||
|
var viewer: MediaViewer = VIEW(MediaViewer.compositeViewDescription())
|
||||||
|
|
||||||
|
var image = UIImage()
|
||||||
|
if chatMessage.contents.first!.type == "image" {
|
||||||
|
if VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) {
|
||||||
|
var plainFile = chatMessage.contents.first!.exportPlainFile()
|
||||||
|
|
||||||
|
image = UIImage(contentsOfFile: plainFile)!
|
||||||
|
|
||||||
|
ChatConversationViewModel.sharedModel.removeTmpFile(filePath: plainFile)
|
||||||
|
plainFile = ""
|
||||||
|
|
||||||
|
}else {
|
||||||
|
image = UIImage(contentsOfFile: chatMessage.contents.first!.filePath)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewer.imageViewer = image
|
||||||
|
viewer.imageNameViewer = chatMessage.contents.first!.name.isEmpty ? "" : chatMessage.contents.first!.name
|
||||||
|
viewer.imagePathViewer = chatMessage.contents.first!.exportPlainFile()
|
||||||
|
viewer.contentType = chatMessage.contents.first!.type
|
||||||
|
PhoneMainView.instance().changeCurrentView(viewer.compositeViewDescription())
|
||||||
|
|
||||||
|
} else {
|
||||||
|
let previewController = QLPreviewController()
|
||||||
|
self.previewItems = []
|
||||||
|
|
||||||
|
if VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) {
|
||||||
|
var plainFile = chatMessage.contents.first?.exportPlainFile()
|
||||||
|
|
||||||
|
self.previewItems.append(self.getPreviewItem(filePath: plainFile!))
|
||||||
|
|
||||||
|
ChatConversationViewModel.sharedModel.removeTmpFile(filePath: plainFile)
|
||||||
|
plainFile = ""
|
||||||
|
}else {
|
||||||
|
self.previewItems.append(self.getPreviewItem(filePath: (chatMessage.contents.first?.filePath)!))
|
||||||
|
}
|
||||||
|
|
||||||
|
afterPreviewIndex = index
|
||||||
|
|
||||||
|
previewController.currentPreviewItemIndex = 0
|
||||||
|
previewController.dataSource = self
|
||||||
|
previewController.delegate = self
|
||||||
|
previewController.reloadData()
|
||||||
|
PhoneMainView.instance().mainViewController.present(previewController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func onGridClick(indexMessage: Int, index: Int) {
|
||||||
|
let chatMessage = ChatConversationTableViewModel.sharedModel.getMessage(index: indexMessage)?.chatMessage
|
||||||
|
let state = chatMessage!.state
|
||||||
|
if (state.rawValue == LinphoneChatMessageStateNotDelivered.rawValue) {
|
||||||
|
Log.i("Messsage not delivered")
|
||||||
|
} else {
|
||||||
|
if (VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) || ConfigManager.instance().lpConfigBoolForKey(key: "use_in_app_file_viewer_for_non_encrypted_files", section: "app")){
|
||||||
|
|
||||||
|
var text = ""
|
||||||
|
var filePathString = VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) ? chatMessage!.contents[index].exportPlainFile() : chatMessage!.contents[index].filePath
|
||||||
|
if let urlEncoded = filePathString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed){
|
||||||
|
if !urlEncoded.isEmpty {
|
||||||
|
if let urlFile = URL(string: "file://" + urlEncoded){
|
||||||
|
do {
|
||||||
|
text = try String(contentsOf: urlFile, encoding: .utf8)
|
||||||
|
let viewer: TextViewer = VIEW(TextViewer.compositeViewDescription())
|
||||||
|
|
||||||
|
if chatMessage != nil {
|
||||||
|
|
||||||
|
viewer.textViewer = text
|
||||||
|
viewer.textNameViewer = chatMessage!.contents[index].name.isEmpty ? "" : chatMessage!.contents[index].name
|
||||||
|
PhoneMainView.instance().changeCurrentView(viewer.compositeViewDescription())
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
if text == "" && (chatMessage!.contents[index].type == "image" || chatMessage!.contents[index].type == "video" || chatMessage!.contents[index].name.lowercased().components(separatedBy: ".").last == "pdf"){
|
||||||
|
let viewer: MediaViewer = VIEW(MediaViewer.compositeViewDescription())
|
||||||
|
|
||||||
|
var image = UIImage()
|
||||||
|
if chatMessage != nil {
|
||||||
|
if chatMessage!.contents[index].type == "image" {
|
||||||
|
if VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) {
|
||||||
|
var plainFile = chatMessage!.contents[index].exportPlainFile()
|
||||||
|
|
||||||
|
image = UIImage(contentsOfFile: plainFile)!
|
||||||
|
|
||||||
|
ChatConversationViewModel.sharedModel.removeTmpFile(filePath: plainFile)
|
||||||
|
plainFile = ""
|
||||||
|
|
||||||
|
}else {
|
||||||
|
image = UIImage(contentsOfFile: chatMessage!.contents[index].filePath)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewer.imageViewer = image
|
||||||
|
viewer.imageNameViewer = chatMessage!.contents[index].name.isEmpty ? "" : chatMessage!.contents[index].name
|
||||||
|
viewer.imagePathViewer = chatMessage!.contents[index].exportPlainFile()
|
||||||
|
viewer.contentType = chatMessage!.contents[index].type
|
||||||
|
PhoneMainView.instance().changeCurrentView(viewer.compositeViewDescription())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let exportView = UIAlertController(
|
||||||
|
title: VoipTexts.chat_message_cant_open_file_in_app_dialog_title,
|
||||||
|
message: VoipTexts.chat_message_cant_open_file_in_app_dialog_message,
|
||||||
|
preferredStyle: .alert)
|
||||||
|
|
||||||
|
let cancelAction = UIAlertAction(
|
||||||
|
title: VoipTexts.cancel,
|
||||||
|
style: .default,
|
||||||
|
handler: { action in
|
||||||
|
})
|
||||||
|
|
||||||
|
let exportAction = UIAlertAction(
|
||||||
|
title: VoipTexts.chat_message_cant_open_file_in_app_dialog_export_button,
|
||||||
|
style: .destructive,
|
||||||
|
handler: { action in
|
||||||
|
let previewController = QLPreviewController()
|
||||||
|
self.previewItems = []
|
||||||
|
|
||||||
|
self.previewItems.append(self.getPreviewItem(filePath: filePathString))
|
||||||
|
|
||||||
|
|
||||||
|
self.afterPreviewIndex = indexMessage
|
||||||
|
|
||||||
|
previewController.dataSource = self
|
||||||
|
previewController.currentPreviewItemIndex = index
|
||||||
|
previewController.delegate = self
|
||||||
|
PhoneMainView.instance().mainViewController.present(previewController, animated: true, completion: nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
exportView.addAction(cancelAction)
|
||||||
|
exportView.addAction(exportAction)
|
||||||
|
PhoneMainView.instance()!.present(exportView, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) {
|
||||||
|
ChatConversationViewModel.sharedModel.removeTmpFile(filePath: filePathString)
|
||||||
|
filePathString = ""
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
let previewController = QLPreviewController()
|
||||||
|
self.previewItems = []
|
||||||
|
chatMessage?.contents.forEach({ content in
|
||||||
|
if(content.isFile){
|
||||||
|
if VFSUtil.vfsEnabled(groupName: kLinphoneMsgNotificationAppGroupId) {
|
||||||
|
var plainFile = content.exportPlainFile()
|
||||||
|
|
||||||
|
self.previewItems.append(self.getPreviewItem(filePath: plainFile))
|
||||||
|
|
||||||
|
ChatConversationViewModel.sharedModel.removeTmpFile(filePath: plainFile)
|
||||||
|
plainFile = ""
|
||||||
|
|
||||||
|
}else {
|
||||||
|
self.previewItems.append(self.getPreviewItem(filePath: (content.filePath)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterPreviewIndex = indexMessage
|
||||||
|
|
||||||
|
previewController.dataSource = self
|
||||||
|
previewController.currentPreviewItemIndex = index
|
||||||
|
previewController.delegate = self
|
||||||
|
PhoneMainView.instance().mainViewController.present(previewController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1592
Classes/Swift/Chat/Views/ChatConversationViewSwift.swift
Normal file
1592
Classes/Swift/Chat/Views/ChatConversationViewSwift.swift
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue