diff --git a/Ring/Ring.xcodeproj/project.pbxproj b/Ring/Ring.xcodeproj/project.pbxproj index 6d0f5babe6f293aa08045cbddac6e84dd0cbf97b..09342247596ac79c4a1260d9a6b6513a14335d03 100644 --- a/Ring/Ring.xcodeproj/project.pbxproj +++ b/Ring/Ring.xcodeproj/project.pbxproj @@ -89,8 +89,6 @@ 0ECB4E2A22B2D4BB0097CD7B /* CallKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0ECB4E2922B2D4BB0097CD7B /* CallKit.framework */; }; 0ECEE9A3220D1935000E1CF4 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0ECEE9A2220D1935000E1CF4 /* VideoToolbox.framework */; }; 0EDCC8601F98150500B121D7 /* UIView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDCC85F1F98150500B121D7 /* UIView+Rx.swift */; }; - 0EDE34C71F868E1200FFA15C /* EditProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE34C61F868E1200FFA15C /* EditProfileViewController.swift */; }; - 0EDE34C91F8691BB00FFA15C /* EditProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE34C81F8691BB00FFA15C /* EditProfileViewModel.swift */; }; 0EE1B5501F75AD4700BA98EE /* VCardUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EE1B54F1F75AD4700BA98EE /* VCardUtils.swift */; }; 0EF49AA123828CBC0064CD98 /* ParticipantProfileInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF49AA023828CBC0064CD98 /* ParticipantProfileInfo.swift */; }; 0EF78DE31FD0AE3000FC6966 /* ConversationsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF78DE21FD0AE3000FC6966 /* ConversationsManager.swift */; }; @@ -727,8 +725,6 @@ 0ECEE9A2220D1935000E1CF4 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; }; 0ED6660F1F9FED1C00743D42 /* AMPopTip.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AMPopTip.framework; path = Carthage/Build/iOS/AMPopTip.framework; sourceTree = "<group>"; }; 0EDCC85F1F98150500B121D7 /* UIView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Rx.swift"; sourceTree = "<group>"; }; - 0EDE34C61F868E1200FFA15C /* EditProfileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditProfileViewController.swift; sourceTree = "<group>"; }; - 0EDE34C81F8691BB00FFA15C /* EditProfileViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditProfileViewModel.swift; sourceTree = "<group>"; }; 0EE1B54F1F75AD4700BA98EE /* VCardUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VCardUtils.swift; sourceTree = "<group>"; }; 0EEFBA3B1F83DA21000EDBAD /* libsecp256k1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecp256k1.a; path = ../DEPS/arm64/lib/libsecp256k1.a; sourceTree = "<group>"; }; 0EF49AA023828CBC0064CD98 /* ParticipantProfileInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParticipantProfileInfo.swift; sourceTree = "<group>"; }; @@ -1875,8 +1871,6 @@ 0EDE34C51F868D2D00FFA15C /* Shared */ = { isa = PBXGroup; children = ( - 0EDE34C61F868E1200FFA15C /* EditProfileViewController.swift */, - 0EDE34C81F8691BB00FFA15C /* EditProfileViewModel.swift */, 26C6A25F2927EC4E007786B8 /* SwarmInfo.swift */, ); name = Shared; @@ -2992,7 +2986,6 @@ 26454F7C2B7E770900CFF06C /* TestEnvironment.swift in Sources */, 62AA15CA1FFD3D7E0064A063 /* VideoService.swift in Sources */, 26D08AB9269628F400E37574 /* RequestsService.swift in Sources */, - 0EDE34C71F868E1200FFA15C /* EditProfileViewController.swift in Sources */, 1DE93596291B119900E426CF /* SwarmCreationViewModel.swift in Sources */, 2679E42C29328352007E4639 /* ConcurrentDictionary.swift in Sources */, 26A072F92959F461006D8163 /* ContextMenuView.swift in Sources */, @@ -3135,7 +3128,6 @@ 66266FC4215C18F8002757A6 /* Emoji+Helpers.swift in Sources */, 0E0FF1B71FC398B3003898C2 /* ConversationDataHepler.swift in Sources */, 62DFAB2E1F9FF0D0002D6F9C /* NetworkService.swift in Sources */, - 0EDE34C91F8691BB00FFA15C /* EditProfileViewModel.swift in Sources */, 267B958A2C2478F100353B01 /* SipAccountDetailModel.swift in Sources */, 04399AAD1D1C304300E99CD9 /* DRingAdapter.mm in Sources */, 1A2D18D11F29182500B2C785 /* ConversationViewController.swift in Sources */, diff --git a/Ring/Ring/EditProfileViewController.swift b/Ring/Ring/EditProfileViewController.swift deleted file mode 100644 index 93a6e7ca0a5c2140ec9019b0c019fe956e3abc34..0000000000000000000000000000000000000000 --- a/Ring/Ring/EditProfileViewController.swift +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2017-2019 Savoir-faire Linux Inc. - * - * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> - * Author: Quentin Muret <quentin.muret@savoirfairelinux.com> - * Author: Alireza Toghiani Khorasgani <alireza.toghiani@savoirfairelinux.com> - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -import UIKit -import Reusable -import RxSwift - -class EditProfileViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate { - - // MARK: - outlets - @IBOutlet weak var profileImageView: UIImageView! - @IBOutlet weak var profileName: UITextField! - - // MARK: - members - var model: EditProfileViewModel! - private let disposeBag = DisposeBag() - - // MARK: - functions - - override func viewDidLoad() { - super.viewDidLoad() - self.model.profileImage - .bind(to: self.profileImageView.rx.image) - .disposed(by: disposeBag) - - self.model.profileName - .bind(to: self.profileName.rx.text) - .disposed(by: disposeBag) - - // Binds the keyboard Send button action to the ViewModel - self.profileName.rx.controlEvent(.editingDidEndOnExit) - .subscribe(onNext: { [weak self] _ in - guard let self = self else { return } - self.model.updateName(self.profileName.text!) - }) - .disposed(by: disposeBag) - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - self.setupUI() - } - - func setupUI() { - - profileName.returnKeyType = .done - profileName.autocorrectionType = .no - - let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:))) - profileImageView.isUserInteractionEnabled = true - profileImageView.addGestureRecognizer(tapGestureRecognizer) - } - - func resetProfileName() { - self.profileName.text = self.model.name - } - - @objc - func imageTapped(tapGestureRecognizer: UITapGestureRecognizer) { - - let alert = UIAlertController.init(title: nil, - message: nil, - preferredStyle: .actionSheet) - - let cameraAction = UIAlertAction(title: L10n.Alerts.profileTakePhoto, style: UIAlertAction.Style.default) { _ in - self.takePicture() - } - - let pictureAction = UIAlertAction(title: L10n.Alerts.profileUploadPhoto, style: UIAlertAction.Style.default) { _ in - self.importPicture() - } - - let cancelAction = UIAlertAction(title: L10n.Global.cancel, style: UIAlertAction.Style.cancel) - - alert.addAction(cameraAction) - alert.addAction(pictureAction) - alert.addAction(cancelAction) - alert.popoverPresentationController?.sourceView = self.view - alert.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection() - alert.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.maxX, width: 0, height: 0) - self.present(alert, animated: true, completion: nil) - } - - func takePicture() { - if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) { - let imagePicker = UIImagePickerController() - imagePicker.delegate = self - imagePicker.sourceType = UIImagePickerController.SourceType.camera - imagePicker.cameraDevice = UIImagePickerController.CameraDevice.front - imagePicker.allowsEditing = true - imagePicker.modalPresentationStyle = .overFullScreen - self.present(imagePicker, animated: true, completion: nil) - } - } - - func importPicture() { - let imagePicker = UIImagePickerController() - imagePicker.delegate = self - imagePicker.allowsEditing = true - imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary - imagePicker.modalPresentationStyle = .overFullScreen - self.present(imagePicker, animated: true, completion: nil) - } - - // MARK: - Delegates - internal func imagePickerController(_ picker: UIImagePickerController, - didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { - var image: UIImage? - - if let img = info[.editedImage] as? UIImage { - image = img - - } else if let img = info[.originalImage] as? UIImage { - image = img - } - - guard let avatar = image?.resizeProfileImage() else { return } - self.model.updateImage(avatar) - self.profileImageView.image = avatar - dismiss(animated: true, completion: nil) - } -} diff --git a/Ring/Ring/EditProfileViewModel.swift b/Ring/Ring/EditProfileViewModel.swift deleted file mode 100644 index 85c9ab7b9a46dd5852738528ced6736c3e246c93..0000000000000000000000000000000000000000 --- a/Ring/Ring/EditProfileViewModel.swift +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2017-2019 Savoir-faire Linux Inc. - * - * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> - * Author: Alireza Toghiani Khorasgani <alireza.toghiani@savoirfairelinux.com> - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -import Foundation -import RxSwift -import Contacts - -class EditProfileViewModel { - - let disposeBag = DisposeBag() - let defaultImage = UIImage(named: "add_avatar") - var image: UIImage? - var name: String = "" - let profileService: ProfilesService - let accountService: AccountsService - - lazy var profileImage: Observable<UIImage?> = { [weak self] in - DispatchQueue.main.asyncAfter(deadline: .now() + 0.01, execute: { - if let self = self, let account = self.accountService.currentAccount { - self.profileService.getAccountProfile(accountId: account.id) - .take(1) - .subscribe(onNext: { profile in - self.profileForCurrentAccount.onNext(profile) - }) - .disposed(by: self.disposeBag) - } - }) - return profileForCurrentAccount.share() - .map({ profile in - if let photo = profile.photo, - let data = NSData(base64Encoded: photo, - options: NSData.Base64DecodingOptions - .ignoreUnknownCharacters) as Data?, - let image = UIImage(data: data) { - self?.image = image - return image - } - return UIImage.defaultJamiAvatarFor(profileName: profile.alias, account: self?.accountService.currentAccount, size: 70, withFontSize: 26, inset: 16) - }) - }() - - var profileForCurrentAccount = PublishSubject<Profile>() - - lazy var profileName: Observable<String?> = { [weak self] in - return profileForCurrentAccount.share() - .map({ profile in - guard let self = self else { return "" } - if let name = profile.alias, !name.isEmpty { - self.name = name - return name - } - if let account = self.accountService.currentAccount { - guard var details = account.details else { return "" } - let name = details.get(withConfigKeyModel: ConfigKeyModel.init(withKey: .displayName)) - if !name.isEmpty { - self.name = name - return name - } - } - return "" - }) - }() - - init(profileService: ProfilesService, accountService: AccountsService) { - self.profileService = profileService - self.accountService = accountService - self.accountService.currentAccountChanged - .subscribe(onNext: { [weak self] account in - if let self = self, let selectedAccount = account { - self.updateProfileInfoFor(accountId: selectedAccount.id) - } - }) - .disposed(by: self.disposeBag) - } - - func updateProfileInfoFor(accountId: String) { - self.profileService.getAccountProfile(accountId: accountId) - .subscribe(onNext: { [weak self] profile in - self?.profileForCurrentAccount.onNext(profile) - }) - .disposed(by: self.disposeBag) - } - - func saveProfile() { - guard let account = self.accountService.currentAccount else { return } - var photo: String? - if let image = self.image, !image.isEqual(defaultImage), - let imageData = image.convertToData(ofMaxSize: 40000) { - photo = imageData.base64EncodedString() - } - guard let details = account.details else { return } - details.set(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.displayName), withValue: self.name) - account.details = details - self.accountService.setAccountDetails(forAccountId: account.id, withDetails: details) - let accountUri = AccountModelHelper.init(withAccount: account).uri ?? "" - self.profileService.updateAccountProfile(accountId: account.id, - alias: self.name, - photo: photo, accountURI: accountUri) - - } - - func updateImage(_ image: UIImage) { - self.image = image - self.saveProfile() - } - - func updateName(_ name: String) { - self.name = name - self.saveProfile() - } -}