/* * Copyright (C) 2004-2021 Savoir-faire Linux Inc. * * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> * Author: Adrien BĂ©raud <adrien.beraud@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, see <http://www.gnu.org/licenses/>. */ package net.jami.account import ezvcard.VCard import ezvcard.property.Photo import ezvcard.property.RawProperty import ezvcard.property.Uid import io.reactivex.rxjava3.core.Scheduler import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.schedulers.Schedulers import net.jami.model.Account import net.jami.mvp.RootPresenter import net.jami.services.AccountService import net.jami.services.DeviceRuntimeService import net.jami.services.VCardService import net.jami.utils.Log import net.jami.utils.StringUtils import net.jami.utils.VCardUtils import java.io.File import java.net.SocketException import javax.inject.Inject import javax.inject.Named class JamiAccountSummaryPresenter @Inject constructor( private val mAccountService: AccountService, private val mDeviceRuntimeService: DeviceRuntimeService, private val mVcardService: VCardService, @param:Named("UiScheduler") private val mUiScheduler: Scheduler ) : RootPresenter<JamiAccountSummaryView>() { private var mAccountID: String? = null fun registerName(name: String, password: String?) { val account = mAccountService.getAccount(mAccountID) ?: return mAccountService.registerName(account, password, name) //view?.accountChanged(account, a.second) } fun startAccountExport(password: String?) { if (view == null || mAccountID == null) { return } view?.showExportingProgressDialog() mCompositeDisposable.add(mAccountService .exportOnRing(mAccountID!!, password!!) .observeOn(mUiScheduler) .subscribe({ pin: String -> view?.showPIN(pin) }) { error: Throwable -> when (error) { is IllegalArgumentException -> view?.showPasswordError() is SocketException -> view?.showNetworkError() else -> view?.showGenericError() } }) } fun setAccountId(accountId: String) { mCompositeDisposable.clear() mAccountID = accountId mCompositeDisposable.add(mAccountService.getObservableAccountProfile(accountId) .observeOn(mUiScheduler) .subscribe { a -> view?.accountChanged(a.first, a.second) }) } fun enableAccount(newValue: Boolean) { val account = mAccountService.getAccount(mAccountID) if (account == null) { Log.w(TAG, "account not found!") return } account.isEnabled = newValue mAccountService.setAccountEnabled(account.accountId, newValue) } fun changePassword(oldPassword: String, newPassword: String) { view?.showPasswordProgressDialog() mCompositeDisposable.add(mAccountService.setAccountPassword(mAccountID!!, oldPassword, newPassword) .observeOn(mUiScheduler) .subscribe({ view?.passwordChangeEnded(true) }) { view?.passwordChangeEnded(false) }) } val deviceName: String? get() { val account = mAccountService.getAccount(mAccountID) if (account == null) { Log.w(TAG, "account not found!") return null } return account.deviceName } fun downloadAccountsArchive(dest: File, password: String?) { view?.showExportingProgressDialog() mCompositeDisposable.add( mAccountService.exportToFile(mAccountID!!, dest.absolutePath, password!!) .observeOn(mUiScheduler) .subscribe({ view?.displayCompleteArchive(dest) }) { view?.passwordChangeEnded(false) }) } fun saveVCardFormattedName(username: String?) { val accountId = mAccountID ?: return val account = mAccountService.getAccount(accountId) val filesDir = mDeviceRuntimeService.provideFilesDir() mCompositeDisposable.add(VCardUtils.loadLocalProfileFromDiskWithDefault(filesDir, accountId) .doOnSuccess { vcard: VCard -> val previousName = vcard.formattedName?.value if ( (StringUtils.isEmpty(previousName) && StringUtils.isEmpty(username)) || previousName == username) throw IllegalArgumentException("Name didn't change") vcard.setFormattedName(username) vcard.removeProperties(RawProperty::class.java) account?.loadedProfile = mVcardService.loadVCardProfile(vcard).cache() } .flatMap { vcard: VCard -> VCardUtils.saveLocalProfileToDisk(vcard, accountId, filesDir) } .subscribeOn(Schedulers.io()) .subscribe({}) { e: Throwable -> Log.e(TAG, "Error saving vCard " + e.message) }) } fun saveVCard(username: String?, photo: Single<Photo>) { val accountId = mAccountID ?: return val account = mAccountService.getAccount(accountId)!! val ringId = account.username val filesDir = mDeviceRuntimeService.provideFilesDir() mCompositeDisposable.add(Single.zip( VCardUtils.loadLocalProfileFromDiskWithDefault(filesDir, accountId).subscribeOn(Schedulers.io()), photo ) { vcard: VCard, pic: Photo -> vcard.uid = Uid(ringId) if (!StringUtils.isEmpty(username)) { vcard.setFormattedName(username) } vcard.removeProperties(Photo::class.java) vcard.addPhoto(pic) vcard.removeProperties(RawProperty::class.java) vcard } .flatMap { vcard: VCard -> VCardUtils.saveLocalProfileToDisk(vcard, accountId, filesDir) } .subscribeOn(Schedulers.io()) .subscribe({ vcard: VCard -> account.loadedProfile = mVcardService.loadVCardProfile(vcard).cache() }) { e: Throwable -> Log.e(TAG, "Error saving vCard !", e) }) } fun cameraClicked() { val hasPermission = mDeviceRuntimeService.hasVideoPermission() && mDeviceRuntimeService.hasWriteExternalStoragePermission() val view = view if (view != null) { if (hasPermission) { view.gotToImageCapture() } else { view.askCameraPermission() } } } fun galleryClicked() { val hasPermission = mDeviceRuntimeService.hasGalleryPermission() if (hasPermission) { view!!.goToGallery() } else { view!!.askGalleryPermission() } } fun goToAccount() { view?.goToAccount(mAccountID!!) } fun goToMedia() { view?.goToMedia(mAccountID!!) } fun goToSystem() { view?.goToSystem(mAccountID!!) } fun goToAdvanced() { view?.goToAdvanced(mAccountID!!) } fun revokeDevice(deviceId: String?, password: String?) { view?.showRevokingProgressDialog() mCompositeDisposable.add(mAccountService .revokeDevice(mAccountID!!, password!!, deviceId!!) .observeOn(mUiScheduler) .subscribe { result: Int -> val account = mAccountService.getAccount(mAccountID)!! view?.deviceRevocationEnded(deviceId, result) view?.updateDeviceList(account.devices, account.deviceId) }) } fun renameDevice(newName: String) { mAccountService.renameDevice(mAccountID!!, newName) } val account: Account? get() = mAccountService.getAccount(mAccountID) companion object { private val TAG = JamiAccountSummaryPresenter::class.simpleName!! } }