diff --git a/Classes/Swift/Util/BackActionsNavigationView.swift b/Classes/Swift/Util/BackActionsNavigationView.swift index 61d678993..3cee19984 100644 --- a/Classes/Swift/Util/BackActionsNavigationView.swift +++ b/Classes/Swift/Util/BackActionsNavigationView.swift @@ -49,6 +49,16 @@ import linphonesw let backButton = CallControlButton(buttonTheme:VoipTheme.nav_button("back_default")) let action1Button = CallControlButton(buttonTheme:VoipTheme.nav_button("call_audio_start_default")) let action2Button = CallControlButton(buttonTheme:VoipTheme.nav_button("more_menu_default")) + + let cancel_button_alert = UIButton() + let ok_button_alert = UIButton() + let checkBoxButton = CallControlButton(buttonTheme:VoipTheme.nav_button("checkbox_unchecked")) + var isChecked = false + let checkBoxText = UILabel() + + let isSecure : Bool = true + let levelMaxSecure : Bool = false + let floatingButton = CallControlButton(buttonTheme:VoipTheme.nav_button("")) func viewDidLoad(backAction : @escaping () -> Void, action1 : @escaping () -> Void, @@ -88,6 +98,16 @@ import linphonesw view.addSubview(messageView) messageView.alignParentBottom().height(top_bar_height).matchParentSideBorders().done() + + + if(isSecure){ + view.addSubview(floatingButton) + floatingButton.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -5).isActive = true + floatingButton.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor, constant: top_bar_height + 5).isActive = true + levelMaxSecure ? floatingButton.setImage(UIImage(named:"security_2_indicator.png"), for: .normal) : floatingButton.setImage(UIImage(named:"security_1_indicator.png"), for: .normal) + floatingButton.imageEdgeInsets = UIEdgeInsets(top: 45, left: 45, bottom: 45, right: 45) + floatingButton.onClickAction = alertAction + } } @@ -97,5 +117,89 @@ import linphonesw topBar.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() } + + func alertAction() { + + let alertController = UIAlertController(title: VoipTexts.alert_dialog_secure_badge_button_chat_conversation_title, message: nil, preferredStyle: .alert) + + alertController.setBackgroundColor(color: .darkGray) + alertController.setTitle(font: nil, color: .white) + alertController.setTint(color: .white) + alertController.setMaxWidth(alert: alertController) + + addButtonsAlertController(alertController: alertController) + + self.present(alertController, animated: true, completion:{ + alertController.view.superview?.isUserInteractionEnabled = true + alertController.view.superview?.subviews[0].addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dismissOnTapOutsideOrCancel))) + }) + + + } + + @objc func dismissOnTapOutsideOrCancel(){ + self.dismiss(animated: true, completion: nil) + } + + @objc func dismissOnTapOk(){ + self.dismiss(animated: true, completion: nil) + } + + @objc func switchCheckedValue(){ + isChecked = !isChecked + checkBoxButton.isSelected = isChecked + } + + func addButtonsAlertController(alertController: UIAlertController){ + + let buttonsView = UIView() + alertController.view.addSubview(buttonsView) + buttonsView.translatesAutoresizingMaskIntoConstraints = false + buttonsView.bottomAnchor.constraint(equalTo: alertController.view.bottomAnchor, constant: -10).isActive = true + buttonsView.rightAnchor.constraint(equalTo: alertController.view.rightAnchor, constant: -10).isActive = true + buttonsView.leftAnchor.constraint(equalTo: alertController.view.leftAnchor, constant: 10).isActive = true + buttonsView.heightAnchor.constraint(equalToConstant: 75).isActive = true + + alertController.view.translatesAutoresizingMaskIntoConstraints = false + alertController.view.heightAnchor.constraint(equalToConstant: 350).isActive = true + + cancel_button_alert.setTitle(VoipTexts.cancel.uppercased(), for: .normal) + cancel_button_alert.backgroundColor = .systemRed + cancel_button_alert.layer.cornerRadius = 5 + cancel_button_alert.addTarget(self, action: #selector(dismissOnTapOutsideOrCancel), for: .touchUpInside) + buttonsView.addSubview(cancel_button_alert) + + cancel_button_alert.alignParentLeft(withMargin: 40).size(w: 100, h: 50).done() + ok_button_alert.setTitle(VoipTexts.ok.uppercased(), for: .normal) + ok_button_alert.backgroundColor = .systemGreen + ok_button_alert.layer.cornerRadius = 5 + ok_button_alert.addTarget(self, action: #selector(dismissOnTapOk), for: .touchUpInside) + buttonsView.addSubview(ok_button_alert) + ok_button_alert.alignParentRight(withMargin: 40).size(w: 100, h: 50).done() + + + let checkboxView = UIView() + alertController.view.addSubview(checkboxView) + checkboxView.translatesAutoresizingMaskIntoConstraints = false + checkboxView.bottomAnchor.constraint(equalTo: buttonsView.topAnchor, constant: -10).isActive = true + checkboxView.centerXAnchor.constraint(equalTo: alertController.view.centerXAnchor).isActive = true + checkboxView.heightAnchor.constraint(equalToConstant: 50).isActive = true + checkboxView.width(180).done() + + checkBoxButton.setImage(UIImage(named:"checkbox_unchecked.png"), for: .normal) + checkBoxButton.setImage(UIImage(named:"checkbox_checked.png"), for: .selected) + checkBoxButton.addTarget(self, action: #selector(switchCheckedValue), for: .touchUpInside) + checkboxView.addSubview(checkBoxButton) + + + + checkBoxText.text = VoipTexts.alert_dialog_secure_badge_button_chat_conversation_checkboxtext + checkBoxText.textColor = .white + checkboxView.addSubview(checkBoxText) + checkBoxText.toRightOf(checkBoxButton, withLeftMargin: -5).size(w: 130, h: 50).done() + + + + } } diff --git a/Classes/Swift/Util/UIAlertController.swift b/Classes/Swift/Util/UIAlertController.swift new file mode 100644 index 000000000..f426028eb --- /dev/null +++ b/Classes/Swift/Util/UIAlertController.swift @@ -0,0 +1,109 @@ +/* + * 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 . + */ + +import Foundation +import UIKit + +extension UIAlertController { + + //Set background color of UIAlertController + func setBackgroundColor(color: UIColor) { + if let bgView = self.view.subviews.first, let groupView = bgView.subviews.first, let contentView = groupView.subviews.first { + contentView.backgroundColor = color + } + } + + func setMaxWidth(alert: UIAlertController) { + let widthConstraints = alert.view.constraints.filter({ return $0.firstAttribute == .width }) + alert.view.removeConstraints(widthConstraints) + // Here you can enter any width that you want + let newWidth = UIScreen.main.bounds.width * 0.90 + // Adding constraint for alert base view + let widthConstraint = NSLayoutConstraint(item: alert.view, + attribute: .width, + relatedBy: .equal, + toItem: nil, + attribute: .notAnAttribute, + multiplier: 1, + constant: newWidth) + alert.view.addConstraint(widthConstraint) + let firstContainer = alert.view.subviews[0] + // Finding first child width constraint + let constraint = firstContainer.constraints.filter({ return $0.firstAttribute == .width && $0.secondItem == nil }) + firstContainer.removeConstraints(constraint) + // And replacing with new constraint equal to alert.view width constraint that we setup earlier + alert.view.addConstraint(NSLayoutConstraint(item: firstContainer, + attribute: .width, + relatedBy: .equal, + toItem: alert.view, + attribute: .width, + multiplier: 1.0, + constant: 0)) + // Same for the second child with width constraint with 998 priority + let innerBackground = firstContainer.subviews[0] + let innerConstraints = innerBackground.constraints.filter({ return $0.firstAttribute == .width && $0.secondItem == nil }) + innerBackground.removeConstraints(innerConstraints) + firstContainer.addConstraint(NSLayoutConstraint(item: innerBackground, + attribute: .width, + relatedBy: .equal, + toItem: firstContainer, + attribute: .width, + multiplier: 1.0, + constant: 0)) + } + + //Set title font and title color + func setTitle(font: UIFont?, color: UIColor?) { + guard let title = self.title else { return } + let attributeString = NSMutableAttributedString(string: title)//1 + + if let titleFont = font { + attributeString.addAttributes([NSAttributedString.Key.font : titleFont],//2 + range: NSMakeRange(0, title.count)) + } + + if let titleColor = color { + attributeString.addAttributes([NSAttributedString.Key.foregroundColor : titleColor],//3 + range: NSMakeRange(0, title.count)) + } + + self.setValue(attributeString, forKey: "attributedTitle")//4 + } + + //Set message font and message color + func setMessage(font: UIFont?, color: UIColor?) { + guard let message = self.message else { return } + let attributeString = NSMutableAttributedString(string: message) + if let messageFont = font { + attributeString.addAttributes([NSAttributedString.Key.font : messageFont], + range: NSMakeRange(0, message.count)) + } + + if let messageColorColor = color { + attributeString.addAttributes([NSAttributedString.Key.foregroundColor : messageColorColor], + range: NSMakeRange(0, message.count)) + } + self.setValue(attributeString, forKey: "attributedMessage") + } + + //Set tint color of UIAlertController + func setTint(color: UIColor) { + self.view.tintColor = color + } +} diff --git a/Classes/Swift/Voip/Theme/VoipTexts.swift b/Classes/Swift/Voip/Theme/VoipTexts.swift index cfd4aa1c5..ef403e96f 100644 --- a/Classes/Swift/Voip/Theme/VoipTexts.swift +++ b/Classes/Swift/Voip/Theme/VoipTexts.swift @@ -154,6 +154,8 @@ import UIKit @objc static let image_picker_view_alert_action_camera = NSLocalizedString("Camera",comment:"") @objc static let image_picker_view_alert_action_photo_library = NSLocalizedString("Photo library",comment:"") @objc static let image_picker_view_alert_action_document = NSLocalizedString("Document",comment:"") + @objc static let alert_dialog_secure_badge_button_chat_conversation_title = NSLocalizedString("Instant messages are end-to-end encrypted in secured conversations. It is possible to upgrade the security level of a conversation by authenticating participants. To do so, call the contact and follow the authentification process.",comment:"") + @objc static let alert_dialog_secure_badge_button_chat_conversation_checkboxtext = NSLocalizedString("Do not show again",comment:"") // FROM ANDROID END diff --git a/linphone.xcodeproj/project.pbxproj b/linphone.xcodeproj/project.pbxproj index cb0338384..d8346aa42 100644 --- a/linphone.xcodeproj/project.pbxproj +++ b/linphone.xcodeproj/project.pbxproj @@ -947,6 +947,7 @@ D7421D9E29228A5200290CAB /* ChatConversationViewSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7421D9D29228A5200290CAB /* ChatConversationViewSwift.swift */; }; D74A44912923BAF90017D063 /* BackActionsNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74A44902923BAF90017D063 /* BackActionsNavigationView.swift */; }; D77057F1292E4A340031A970 /* ChatConversationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77057F0292E4A340031A970 /* ChatConversationViewModel.swift */; }; + D7C6DE7D2947331A00756E03 /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C6DE7C2947331A00756E03 /* UIAlertController.swift */; }; EA0007A62356008F003CC6BF /* msgNotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = EA5F25D9232BD3E200475F2E /* msgNotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; EA3650DB2330D2E30001148A /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5F25DB232BD3E200475F2E /* NotificationService.swift */; }; EA88A405242A6216007FEC61 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 63AADBC41B6A0FF200AA16FD /* Localizable.strings */; }; @@ -2182,6 +2183,7 @@ D7421D9D29228A5200290CAB /* ChatConversationViewSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatConversationViewSwift.swift; sourceTree = ""; }; D74A44902923BAF90017D063 /* BackActionsNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackActionsNavigationView.swift; sourceTree = ""; }; D77057F0292E4A340031A970 /* ChatConversationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatConversationViewModel.swift; sourceTree = ""; }; + D7C6DE7C2947331A00756E03 /* UIAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertController.swift; sourceTree = ""; }; DF241FDC6C7431777AB3BD58 /* Pods-msgNotificationContent.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-msgNotificationContent.debug.xcconfig"; path = "Target Support Files/Pods-msgNotificationContent/Pods-msgNotificationContent.debug.xcconfig"; sourceTree = ""; }; E19FC645A566E91D4EEB9C8F /* Pods-msgNotificationService.distributionadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-msgNotificationService.distributionadhoc.xcconfig"; path = "Target Support Files/Pods-msgNotificationService/Pods-msgNotificationService.distributionadhoc.xcconfig"; sourceTree = ""; }; EA5F25D9232BD3E200475F2E /* msgNotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = msgNotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -3445,6 +3447,7 @@ C63F71AF285A24B10066163B /* BackNextNavigationView.swift */, C63F71B0285A24B10066163B /* TimestampUtils.swift */, D74A44902923BAF90017D063 /* BackActionsNavigationView.swift */, + D7C6DE7C2947331A00756E03 /* UIAlertController.swift */, ); path = Util; sourceTree = ""; @@ -5034,6 +5037,7 @@ D3ED3E871586291E006C0DE4 /* TabBarView.m in Sources */, 617C242A263022690042FB4A /* UIChatContentView.m in Sources */, C63F7261285A24B10066163B /* CallControlButton.swift in Sources */, + D7C6DE7D2947331A00756E03 /* UIAlertController.swift in Sources */, D3ED3EA71587334E006C0DE4 /* HistoryListTableView.m in Sources */, C63F7220285A24B10066163B /* TimestampUtils.swift in Sources */, 61AEBEBD2191990A00F35E7F /* DevicesListView.m in Sources */,