mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-22 04:55:29 +03:00
remove conductor
- replace remaining controllers with activities - remove conductor lib - modify some code related to account management and conductor Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
074fc301d6
commit
591d6dc3e8
49 changed files with 840 additions and 1410 deletions
|
@ -289,7 +289,6 @@ We are using [Dagger 2](https://dagger.dev/) to inject dependencies into major A
|
||||||
|
|
||||||
* `Activity`
|
* `Activity`
|
||||||
* `Fragment`
|
* `Fragment`
|
||||||
* `Controller`
|
|
||||||
* `Service`
|
* `Service`
|
||||||
* `BroadcastReceiver`
|
* `BroadcastReceiver`
|
||||||
* `ContentProvider`
|
* `ContentProvider`
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* @author Tim Krüger
|
* @author Tim Krüger
|
||||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||||
* Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
* Copyright (C) 2021-2023 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -210,8 +210,6 @@ dependencies {
|
||||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||||
implementation "io.reactivex.rxjava2:rxjava:2.2.21"
|
implementation "io.reactivex.rxjava2:rxjava:2.2.21"
|
||||||
|
|
||||||
implementation 'com.bluelinelabs:conductor:3.2.0'
|
|
||||||
|
|
||||||
implementation "com.squareup.okhttp3:okhttp:${okhttpVersion}"
|
implementation "com.squareup.okhttp3:okhttp:${okhttpVersion}"
|
||||||
implementation "com.squareup.okhttp3:okhttp-urlconnection:${okhttpVersion}"
|
implementation "com.squareup.okhttp3:okhttp-urlconnection:${okhttpVersion}"
|
||||||
implementation "com.squareup.okhttp3:logging-interceptor:${okhttpVersion}"
|
implementation "com.squareup.okhttp3:logging-interceptor:${okhttpVersion}"
|
||||||
|
|
|
@ -32,6 +32,5 @@
|
||||||
|
|
||||||
<issue id="ObsoleteLintCustomCheck" severity="warning">
|
<issue id="ObsoleteLintCustomCheck" severity="warning">
|
||||||
<ignore path="**/jetified-annotation-experimental-1.**/**/lint.jar" />
|
<ignore path="**/jetified-annotation-experimental-1.**/**/lint.jar" />
|
||||||
<ignore path="**/jetified-conductor-2.**/**/lint.jar" />
|
|
||||||
</issue>
|
</issue>
|
||||||
</lint>
|
</lint>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
~ @author Mario Danic
|
~ @author Mario Danic
|
||||||
~ @author Marcel Hibbe
|
~ @author Marcel Hibbe
|
||||||
~ Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
~ Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||||
~ Copyright (C) 2021-2022 Marcel Hibbe <dev@mhibbe.de>
|
~ Copyright (C) 2021-2023 Marcel Hibbe <dev@mhibbe.de>
|
||||||
~
|
~
|
||||||
~ 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
|
||||||
|
@ -131,6 +131,44 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".account.ServerSelectionActivity"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".account.WebViewLoginActivity"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".account.AccountVerificationActivity"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".account.SwitchAccountActivity"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".conversationlist.ConversationsListActivity"
|
||||||
|
android:theme="@style/AppTheme"
|
||||||
|
android:exported="true">
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".chat.ChatActivity"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.CallActivity"
|
android:name=".activities.CallActivity"
|
||||||
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
|
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
|
||||||
|
@ -215,32 +253,10 @@
|
||||||
android:name=".contacts.ContactsActivity"
|
android:name=".contacts.ContactsActivity"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".chat.ChatActivity"
|
|
||||||
android:theme="@style/AppTheme" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".openconversations.ListOpenConversationsActivity"
|
android:name=".openconversations.ListOpenConversationsActivity"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".conversationlist.ConversationsListActivity"
|
|
||||||
android:theme="@style/AppTheme"
|
|
||||||
android:exported="true">
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".lock.LockedActivity"
|
android:name=".lock.LockedActivity"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
*
|
*
|
||||||
* @author Mario Danic
|
* @author Mario Danic
|
||||||
* @author Andy Scherzinger
|
* @author Andy Scherzinger
|
||||||
|
* @author Marcel Hibbe
|
||||||
|
* Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
|
* Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
|
||||||
*
|
*
|
||||||
|
@ -19,7 +21,7 @@
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
package com.nextcloud.talk.controllers
|
package com.nextcloud.talk.account
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
@ -28,25 +30,24 @@ import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.widget.Toast
|
||||||
import androidx.work.Data
|
import androidx.work.Data
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
|
import androidx.work.WorkInfo
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.controllers.base.BaseController
|
|
||||||
import com.nextcloud.talk.controllers.util.viewBinding
|
|
||||||
import com.nextcloud.talk.conversationlist.ConversationsListActivity
|
import com.nextcloud.talk.conversationlist.ConversationsListActivity
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ControllerAccountVerificationBinding
|
import com.nextcloud.talk.databinding.ActivityAccountVerificationBinding
|
||||||
import com.nextcloud.talk.events.EventStatus
|
import com.nextcloud.talk.events.EventStatus
|
||||||
|
import com.nextcloud.talk.jobs.AccountRemovalWorker
|
||||||
import com.nextcloud.talk.jobs.CapabilitiesWorker
|
import com.nextcloud.talk.jobs.CapabilitiesWorker
|
||||||
import com.nextcloud.talk.jobs.PushRegistrationWorker
|
import com.nextcloud.talk.jobs.PushRegistrationWorker
|
||||||
import com.nextcloud.talk.jobs.SignalingSettingsWorker
|
import com.nextcloud.talk.jobs.SignalingSettingsWorker
|
||||||
|
@ -63,6 +64,7 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_BASE_URL
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_ACCOUNT_IMPORT
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_ACCOUNT_IMPORT
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_PASSWORD
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
|
||||||
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
||||||
|
@ -71,20 +73,15 @@ import io.reactivex.Observer
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class AccountVerificationController(args: Bundle? = null) : BaseController(
|
class AccountVerificationActivity : BaseActivity() {
|
||||||
R.layout.controller_account_verification,
|
|
||||||
args
|
private lateinit var binding: ActivityAccountVerificationBinding
|
||||||
) {
|
|
||||||
private val binding: ControllerAccountVerificationBinding? by viewBinding(
|
|
||||||
ControllerAccountVerificationBinding::bind
|
|
||||||
)
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var ncApi: NcApi
|
lateinit var ncApi: NcApi
|
||||||
|
@ -95,9 +92,6 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var cookieManager: CookieManager
|
lateinit var cookieManager: CookieManager
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var eventBus: EventBus
|
|
||||||
|
|
||||||
private var internalAccountId: Long = -1
|
private var internalAccountId: Long = -1
|
||||||
private val disposables: MutableList<Disposable> = ArrayList()
|
private val disposables: MutableList<Disposable> = ArrayList()
|
||||||
private var baseUrl: String? = null
|
private var baseUrl: String? = null
|
||||||
|
@ -106,43 +100,53 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
private var isAccountImport = false
|
private var isAccountImport = false
|
||||||
private var originalProtocol: String? = null
|
private var originalProtocol: String? = null
|
||||||
|
|
||||||
override fun onAttach(view: View) {
|
@SuppressLint("SourceLockedOrientationActivity")
|
||||||
super.onAttach(view)
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
eventBus.register(this)
|
super.onCreate(savedInstanceState)
|
||||||
}
|
sharedApplication!!.componentApplication.inject(this)
|
||||||
|
binding = ActivityAccountVerificationBinding.inflate(layoutInflater)
|
||||||
override fun onDetach(view: View) {
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
super.onDetach(view)
|
setContentView(binding.root)
|
||||||
eventBus.unregister(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewBound(view: View) {
|
|
||||||
super.onViewBound(view)
|
|
||||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
|
||||||
|
|
||||||
actionBar?.hide()
|
actionBar?.hide()
|
||||||
|
setupPrimaryColors()
|
||||||
|
|
||||||
|
handleIntent()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntent() {
|
||||||
|
val extras = intent.extras!!
|
||||||
|
baseUrl = extras.getString(KEY_BASE_URL)
|
||||||
|
username = extras.getString(KEY_USERNAME)
|
||||||
|
token = extras.getString(KEY_TOKEN)
|
||||||
|
if (extras.containsKey(KEY_IS_ACCOUNT_IMPORT)) {
|
||||||
|
isAccountImport = true
|
||||||
|
}
|
||||||
|
if (extras.containsKey(KEY_ORIGINAL_PROTOCOL)) {
|
||||||
|
originalProtocol = extras.getString(KEY_ORIGINAL_PROTOCOL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isAccountImport &&
|
isAccountImport &&
|
||||||
!UriUtils.hasHttpProtocolPrefixed(baseUrl!!) ||
|
!UriUtils.hasHttpProtocolPrefixed(baseUrl!!) ||
|
||||||
isSameProtocol(baseUrl!!, originalProtocol!!)
|
isNotSameProtocol(baseUrl!!, originalProtocol)
|
||||||
) {
|
) {
|
||||||
determineBaseUrlProtocol(true)
|
determineBaseUrlProtocol(true)
|
||||||
} else {
|
} else {
|
||||||
checkEverything()
|
findServerTalkApp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSameProtocol(baseUrl: String, originalProtocol: String): Boolean {
|
private fun isNotSameProtocol(baseUrl: String, originalProtocol: String?): Boolean {
|
||||||
|
if (originalProtocol == null) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return !TextUtils.isEmpty(originalProtocol) && !baseUrl.startsWith(originalProtocol)
|
return !TextUtils.isEmpty(originalProtocol) && !baseUrl.startsWith(originalProtocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkEverything() {
|
|
||||||
val credentials = ApiUtils.getCredentials(username, token)
|
|
||||||
cookieManager.cookieStore.removeAll()
|
|
||||||
findServerTalkApp(credentials)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun determineBaseUrlProtocol(checkForcedHttps: Boolean) {
|
private fun determineBaseUrlProtocol(checkForcedHttps: Boolean) {
|
||||||
cookieManager.cookieStore.removeAll()
|
cookieManager.cookieStore.removeAll()
|
||||||
baseUrl = baseUrl!!.replace("http://", "").replace("https://", "")
|
baseUrl = baseUrl!!.replace("http://", "").replace("https://", "")
|
||||||
|
@ -166,20 +170,16 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
"http://$baseUrl"
|
"http://$baseUrl"
|
||||||
}
|
}
|
||||||
if (isAccountImport) {
|
if (isAccountImport) {
|
||||||
router.replaceTopController(
|
val bundle = Bundle()
|
||||||
RouterTransaction.with(
|
bundle.putString(KEY_BASE_URL, baseUrl)
|
||||||
WebViewLoginController(
|
bundle.putString(KEY_USERNAME, username)
|
||||||
baseUrl,
|
bundle.putString(KEY_PASSWORD, "")
|
||||||
false,
|
|
||||||
username,
|
val intent = Intent(context, WebViewLoginActivity::class.java)
|
||||||
""
|
intent.putExtras(bundle)
|
||||||
)
|
startActivity(intent)
|
||||||
)
|
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(HorizontalChangeHandler())
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
checkEverything()
|
findServerTalkApp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +197,10 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findServerTalkApp(credentials: String) {
|
private fun findServerTalkApp() {
|
||||||
|
val credentials = ApiUtils.getCredentials(username, token)
|
||||||
|
cookieManager.cookieStore.removeAll()
|
||||||
|
|
||||||
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
|
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe(object : Observer<CapabilitiesOverall> {
|
.subscribe(object : Observer<CapabilitiesOverall> {
|
||||||
|
@ -214,27 +217,24 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
if (hasTalk) {
|
if (hasTalk) {
|
||||||
fetchProfile(credentials, capabilitiesOverall)
|
fetchProfile(credentials, capabilitiesOverall)
|
||||||
} else {
|
} else {
|
||||||
if (activity != null && resources != null) {
|
if (resources != null) {
|
||||||
activity!!.runOnUiThread {
|
runOnUiThread {
|
||||||
binding?.progressText?.setText(
|
binding.progressText.text = String.format(
|
||||||
String.format(
|
|
||||||
resources!!.getString(R.string.nc_nextcloud_talk_app_not_installed),
|
resources!!.getString(R.string.nc_nextcloud_talk_app_not_installed),
|
||||||
resources!!.getString(R.string.nc_app_product_name)
|
resources!!.getString(R.string.nc_app_product_name)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ApplicationWideMessageHolder.getInstance().setMessageType(
|
ApplicationWideMessageHolder.getInstance().messageType =
|
||||||
ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK
|
ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK
|
||||||
)
|
|
||||||
abortVerification()
|
abortVerification()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (activity != null && resources != null) {
|
if (resources != null) {
|
||||||
activity!!.runOnUiThread {
|
runOnUiThread {
|
||||||
binding?.progressText?.text = String.format(
|
binding.progressText.text = String.format(
|
||||||
resources!!.getString(R.string.nc_nextcloud_talk_app_not_installed),
|
resources!!.getString(R.string.nc_nextcloud_talk_app_not_installed),
|
||||||
resources!!.getString(R.string.nc_app_product_name)
|
resources!!.getString(R.string.nc_app_product_name)
|
||||||
)
|
)
|
||||||
|
@ -263,7 +263,7 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
displayName = displayName,
|
displayName = displayName,
|
||||||
pushConfigurationState = null,
|
pushConfigurationState = null,
|
||||||
capabilities = LoganSquare.serialize(capabilities),
|
capabilities = LoganSquare.serialize(capabilities),
|
||||||
certificateAlias = appPreferences!!.temporaryClientCertAlias,
|
certificateAlias = appPreferences.temporaryClientCertAlias,
|
||||||
externalSignalingServer = null
|
externalSignalingServer = null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -279,9 +279,9 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) {
|
if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) {
|
||||||
registerForPush()
|
registerForPush()
|
||||||
} else {
|
} else {
|
||||||
activity!!.runOnUiThread {
|
runOnUiThread {
|
||||||
binding?.progressText?.text =
|
binding.progressText.text =
|
||||||
""" ${binding?.progressText?.text}
|
""" ${binding.progressText.text}
|
||||||
${resources!!.getString(R.string.nc_push_disabled)}
|
${resources!!.getString(R.string.nc_push_disabled)}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
|
@ -291,7 +291,7 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
binding?.progressText?.text = """ ${binding?.progressText?.text}""".trimIndent() +
|
binding.progressText.text = """ ${binding.progressText.text}""".trimIndent() +
|
||||||
resources!!.getString(R.string.nc_display_name_not_stored)
|
resources!!.getString(R.string.nc_display_name_not_stored)
|
||||||
abortVerification()
|
abortVerification()
|
||||||
}
|
}
|
||||||
|
@ -328,30 +328,26 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
capabilities.ocs!!.data!!.capabilities!!
|
capabilities.ocs!!.data!!.capabilities!!
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (activity != null) {
|
runOnUiThread {
|
||||||
activity!!.runOnUiThread {
|
binding.progressText.text =
|
||||||
binding?.progressText?.text =
|
|
||||||
"""
|
"""
|
||||||
${binding?.progressText?.text}
|
${binding.progressText.text}
|
||||||
${resources!!.getString(R.string.nc_display_name_not_fetched)}
|
${resources!!.getString(R.string.nc_display_name_not_fetched)}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
abortVerification()
|
abortVerification()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (activity != null) {
|
runOnUiThread {
|
||||||
activity!!.runOnUiThread {
|
binding.progressText.text =
|
||||||
binding?.progressText?.text =
|
|
||||||
"""
|
"""
|
||||||
${binding?.progressText?.text}
|
${binding.progressText.text}
|
||||||
${resources!!.getString(R.string.nc_display_name_not_fetched)}
|
${resources!!.getString(R.string.nc_display_name_not_fetched)}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
abortVerification()
|
abortVerification()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +360,7 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
private fun registerForPush() {
|
private fun registerForPush() {
|
||||||
val data =
|
val data =
|
||||||
Data.Builder()
|
Data.Builder()
|
||||||
.putString(PushRegistrationWorker.ORIGIN, "AccountVerificationController#registerForPush")
|
.putString(PushRegistrationWorker.ORIGIN, "AccountVerificationActivity#registerForPush")
|
||||||
.build()
|
.build()
|
||||||
val pushRegistrationWork =
|
val pushRegistrationWork =
|
||||||
OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java)
|
OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java)
|
||||||
|
@ -377,11 +373,11 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
||||||
fun onMessageEvent(eventStatus: EventStatus) {
|
fun onMessageEvent(eventStatus: EventStatus) {
|
||||||
if (eventStatus.eventType == EventStatus.EventType.PUSH_REGISTRATION) {
|
if (eventStatus.eventType == EventStatus.EventType.PUSH_REGISTRATION) {
|
||||||
if (internalAccountId == eventStatus.userId && !eventStatus.isAllGood && activity != null) {
|
if (internalAccountId == eventStatus.userId && !eventStatus.isAllGood) {
|
||||||
activity!!.runOnUiThread {
|
runOnUiThread {
|
||||||
binding?.progressText?.text =
|
binding.progressText.text =
|
||||||
"""
|
"""
|
||||||
${binding?.progressText?.text}
|
${binding.progressText.text}
|
||||||
${resources!!.getString(R.string.nc_push_disabled)}
|
${resources!!.getString(R.string.nc_push_disabled)}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
|
@ -389,31 +385,27 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
fetchAndStoreCapabilities()
|
fetchAndStoreCapabilities()
|
||||||
} else if (eventStatus.eventType == EventStatus.EventType.CAPABILITIES_FETCH) {
|
} else if (eventStatus.eventType == EventStatus.EventType.CAPABILITIES_FETCH) {
|
||||||
if (internalAccountId == eventStatus.userId && !eventStatus.isAllGood) {
|
if (internalAccountId == eventStatus.userId && !eventStatus.isAllGood) {
|
||||||
if (activity != null) {
|
runOnUiThread {
|
||||||
activity!!.runOnUiThread {
|
binding.progressText.text =
|
||||||
binding?.progressText?.text =
|
|
||||||
"""
|
"""
|
||||||
${binding?.progressText?.text}
|
${binding.progressText.text}
|
||||||
${resources!!.getString(R.string.nc_capabilities_failed)}
|
${resources!!.getString(R.string.nc_capabilities_failed)}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
abortVerification()
|
abortVerification()
|
||||||
} else if (internalAccountId == eventStatus.userId && eventStatus.isAllGood) {
|
} else if (internalAccountId == eventStatus.userId && eventStatus.isAllGood) {
|
||||||
fetchAndStoreExternalSignalingSettings()
|
fetchAndStoreExternalSignalingSettings()
|
||||||
}
|
}
|
||||||
} else if (eventStatus.eventType == EventStatus.EventType.SIGNALING_SETTINGS) {
|
} else if (eventStatus.eventType == EventStatus.EventType.SIGNALING_SETTINGS) {
|
||||||
if (internalAccountId == eventStatus.userId && !eventStatus.isAllGood) {
|
if (internalAccountId == eventStatus.userId && !eventStatus.isAllGood) {
|
||||||
if (activity != null) {
|
runOnUiThread {
|
||||||
activity!!.runOnUiThread {
|
binding.progressText.text =
|
||||||
binding?.progressText?.text =
|
|
||||||
"""
|
"""
|
||||||
${binding?.progressText?.text}
|
${binding.progressText.text}
|
||||||
${resources!!.getString(R.string.nc_external_server_failed)}
|
${resources!!.getString(R.string.nc_external_server_failed)}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
proceedWithLogin()
|
proceedWithLogin()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,8 +449,7 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
Log.d(TAG, "userToSetAsActive: " + userToSetAsActive.username)
|
Log.d(TAG, "userToSetAsActive: " + userToSetAsActive.username)
|
||||||
|
|
||||||
if (userManager.setUserAsActive(userToSetAsActive).blockingGet()) {
|
if (userManager.setUserAsActive(userToSetAsActive).blockingGet()) {
|
||||||
if (activity != null) {
|
runOnUiThread {
|
||||||
activity!!.runOnUiThread {
|
|
||||||
if (userManager.users.blockingGet().size == 1) {
|
if (userManager.users.blockingGet().size == 1) {
|
||||||
val intent = Intent(context, ConversationsListActivity::class.java)
|
val intent = Intent(context, ConversationsListActivity::class.java)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
@ -471,10 +462,9 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "failed to set active user")
|
Log.e(TAG, "failed to set active user")
|
||||||
Snackbar.make(binding!!.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
|
Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,70 +477,70 @@ class AccountVerificationController(args: Bundle? = null) : BaseController(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
|
||||||
super.onDestroyView(view)
|
|
||||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onDestroy() {
|
public override fun onDestroy() {
|
||||||
dispose()
|
dispose()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun abortVerification() {
|
private fun abortVerification() {
|
||||||
if (!isAccountImport) {
|
if (isAccountImport) {
|
||||||
if (internalAccountId != -1L) {
|
ApplicationWideMessageHolder.getInstance().messageType = ApplicationWideMessageHolder.MessageType
|
||||||
val count = userManager.deleteUser(internalAccountId)
|
.FAILED_TO_IMPORT_ACCOUNT
|
||||||
if (count > 0) {
|
runOnUiThread {
|
||||||
activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ApplicationWideMessageHolder.getInstance().setMessageType(
|
|
||||||
ApplicationWideMessageHolder.MessageType.FAILED_TO_IMPORT_ACCOUNT
|
|
||||||
)
|
|
||||||
activity?.runOnUiThread {
|
|
||||||
Handler().postDelayed({
|
Handler().postDelayed({
|
||||||
if (router.hasRootController()) {
|
val intent = Intent(this, ServerSelectionActivity::class.java)
|
||||||
if (activity != null) {
|
|
||||||
router.popToRoot()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (userManager.users.blockingGet().isNotEmpty()) {
|
|
||||||
val intent = Intent(context, ConversationsListActivity::class.java)
|
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
} else {
|
|
||||||
router.setRoot(
|
|
||||||
RouterTransaction.with(ServerSelectionController())
|
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(HorizontalChangeHandler())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, DELAY_IN_MILLIS)
|
}, DELAY_IN_MILLIS)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (internalAccountId != -1L) {
|
||||||
|
runOnUiThread {
|
||||||
|
deleteUserAndStartServerSelection(internalAccountId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runOnUiThread {
|
||||||
|
Handler().postDelayed({
|
||||||
|
val intent = Intent(this, ServerSelectionActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
}, DELAY_IN_MILLIS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private fun deleteUserAndStartServerSelection(userId: Long) {
|
||||||
|
userManager.scheduleUserForDeletionWithId(userId).blockingGet()
|
||||||
|
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
|
||||||
|
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
||||||
|
|
||||||
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
||||||
|
.observeForever { workInfo: WorkInfo ->
|
||||||
|
|
||||||
|
when (workInfo.state) {
|
||||||
|
WorkInfo.State.SUCCEEDED -> {
|
||||||
|
val intent = Intent(this, ServerSelectionActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkInfo.State.FAILED, WorkInfo.State.CANCELLED -> {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context.resources.getString(R.string.nc_common_error_sorry),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
Log.e(TAG, "something went wrong when deleting user with id $userId")
|
||||||
|
val intent = Intent(this, ServerSelectionActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "AccountVerification"
|
private val TAG = AccountVerificationActivity::class.java.simpleName
|
||||||
const val DELAY_IN_MILLIS: Long = 7500
|
const val DELAY_IN_MILLIS: Long = 7500
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
sharedApplication!!.componentApplication.inject(this)
|
|
||||||
if (args != null) {
|
|
||||||
baseUrl = args.getString(KEY_BASE_URL)
|
|
||||||
username = args.getString(KEY_USERNAME)
|
|
||||||
token = args.getString(KEY_TOKEN)
|
|
||||||
if (args.containsKey(KEY_IS_ACCOUNT_IMPORT)) {
|
|
||||||
isAccountImport = true
|
|
||||||
}
|
|
||||||
if (args.containsKey(KEY_ORIGINAL_PROTOCOL)) {
|
|
||||||
originalProtocol = args.getString(KEY_ORIGINAL_PROTOCOL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
*
|
*
|
||||||
* @author Andy Scherzinger
|
* @author Andy Scherzinger
|
||||||
* @author Mario Danic
|
* @author Mario Danic
|
||||||
|
* @author Marcel Hibbe
|
||||||
|
* Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
||||||
*
|
*
|
||||||
|
@ -19,7 +21,7 @@
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
package com.nextcloud.talk.controllers
|
package com.nextcloud.talk.account
|
||||||
|
|
||||||
import android.accounts.Account
|
import android.accounts.Account
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
@ -34,24 +36,21 @@ import android.view.KeyEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.activity.OnBackPressedCallback
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.databinding.ActivityServerSelectionBinding
|
||||||
import com.nextcloud.talk.controllers.base.BaseController
|
|
||||||
import com.nextcloud.talk.controllers.util.viewBinding
|
|
||||||
import com.nextcloud.talk.databinding.ControllerServerSelectionBinding
|
|
||||||
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
|
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
|
||||||
import com.nextcloud.talk.models.json.generic.Status
|
import com.nextcloud.talk.models.json.generic.Status
|
||||||
import com.nextcloud.talk.users.UserManager
|
import com.nextcloud.talk.users.UserManager
|
||||||
import com.nextcloud.talk.utils.AccountUtils
|
import com.nextcloud.talk.utils.AccountUtils
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import com.nextcloud.talk.utils.UriUtils
|
import com.nextcloud.talk.utils.UriUtils
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys.ADD_ADDITIONAL_ACCOUNT
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_ACCOUNT_IMPORT
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_ACCOUNT_IMPORT
|
||||||
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
|
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
|
||||||
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
||||||
|
@ -61,12 +60,12 @@ import io.reactivex.disposables.Disposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import java.security.cert.CertificateException
|
import java.security.cert.CertificateException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class ServerSelectionController :
|
class ServerSelectionActivity : BaseActivity() {
|
||||||
BaseController(R.layout.controller_server_selection) {
|
|
||||||
|
|
||||||
private val binding: ControllerServerSelectionBinding? by viewBinding(ControllerServerSelectionBinding::bind)
|
private lateinit var binding: ActivityServerSelectionBinding
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var ncApi: NcApi
|
lateinit var ncApi: NcApi
|
||||||
|
@ -76,44 +75,40 @@ class ServerSelectionController :
|
||||||
|
|
||||||
private var statusQueryDisposable: Disposable? = null
|
private var statusQueryDisposable: Disposable? = null
|
||||||
|
|
||||||
fun onCertClick() {
|
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||||
if (activity != null) {
|
override fun handleOnBackPressed() {
|
||||||
KeyChain.choosePrivateKeyAlias(
|
if (intent.hasExtra(ADD_ADDITIONAL_ACCOUNT) && intent.getBooleanExtra(ADD_ADDITIONAL_ACCOUNT, false)) {
|
||||||
activity!!,
|
finish()
|
||||||
{ alias: String? ->
|
|
||||||
if (alias != null) {
|
|
||||||
appPreferences!!.temporaryClientCertAlias = alias
|
|
||||||
} else {
|
} else {
|
||||||
appPreferences!!.removeTemporaryClientCertAlias()
|
finishAffinity()
|
||||||
}
|
}
|
||||||
setCertTextView()
|
|
||||||
},
|
|
||||||
arrayOf("RSA", "EC"),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
-1,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewBound(view: View) {
|
@SuppressLint("SourceLockedOrientationActivity")
|
||||||
super.onViewBound(view)
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
sharedApplication!!.componentApplication.inject(this)
|
sharedApplication!!.componentApplication.inject(this)
|
||||||
if (activity != null) {
|
binding = ActivityServerSelectionBinding.inflate(layoutInflater)
|
||||||
activity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
setContentView(binding.root)
|
||||||
|
actionBar?.hide()
|
||||||
|
setupPrimaryColors()
|
||||||
|
|
||||||
|
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
actionBar?.hide()
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
binding?.hostUrlInputHelperText?.text = String.format(
|
binding.hostUrlInputHelperText.text = String.format(
|
||||||
resources!!.getString(R.string.nc_server_helper_text),
|
resources!!.getString(R.string.nc_server_helper_text),
|
||||||
resources!!.getString(R.string.nc_server_product_name)
|
resources!!.getString(R.string.nc_server_product_name)
|
||||||
)
|
)
|
||||||
binding?.serverEntryTextInputLayout?.setEndIconOnClickListener { checkServerAndProceed() }
|
binding.serverEntryTextInputLayout.setEndIconOnClickListener { checkServerAndProceed() }
|
||||||
|
|
||||||
if (resources!!.getBoolean(R.bool.hide_auth_cert)) {
|
if (resources!!.getBoolean(R.bool.hide_auth_cert)) {
|
||||||
binding?.certTextView?.visibility = View.GONE
|
binding.certTextView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
val loggedInUsers = userManager.users.blockingGet()
|
val loggedInUsers = userManager.users.blockingGet()
|
||||||
|
@ -124,21 +119,54 @@ class ServerSelectionController :
|
||||||
} else if (isAbleToShowProviderLink() && loggedInUsers.isEmpty()) {
|
} else if (isAbleToShowProviderLink() && loggedInUsers.isEmpty()) {
|
||||||
showVisitProvidersInfo()
|
showVisitProvidersInfo()
|
||||||
} else {
|
} else {
|
||||||
binding?.importOrChooseProviderText?.visibility = View.INVISIBLE
|
binding.importOrChooseProviderText.visibility = View.INVISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
binding?.serverEntryTextInputEditText?.requestFocus()
|
binding.serverEntryTextInputEditText.requestFocus()
|
||||||
if (!TextUtils.isEmpty(resources!!.getString(R.string.weblogin_url))) {
|
if (!TextUtils.isEmpty(resources!!.getString(R.string.weblogin_url))) {
|
||||||
binding?.serverEntryTextInputEditText?.setText(resources!!.getString(R.string.weblogin_url))
|
binding.serverEntryTextInputEditText.setText(resources!!.getString(R.string.weblogin_url))
|
||||||
checkServerAndProceed()
|
checkServerAndProceed()
|
||||||
}
|
}
|
||||||
binding?.serverEntryTextInputEditText?.setOnEditorActionListener { _: TextView?, i: Int, _: KeyEvent? ->
|
binding.serverEntryTextInputEditText.setOnEditorActionListener { _: TextView?, i: Int, _: KeyEvent? ->
|
||||||
if (i == EditorInfo.IME_ACTION_DONE) {
|
if (i == EditorInfo.IME_ACTION_DONE) {
|
||||||
checkServerAndProceed()
|
checkServerAndProceed()
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
binding?.certTextView?.setOnClickListener { onCertClick() }
|
binding.certTextView.setOnClickListener { onCertClick() }
|
||||||
|
|
||||||
|
if (ApplicationWideMessageHolder.getInstance().messageType != null) {
|
||||||
|
if (ApplicationWideMessageHolder.getInstance().messageType
|
||||||
|
== ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK
|
||||||
|
) {
|
||||||
|
setErrorText(resources!!.getString(R.string.nc_settings_no_talk_installed))
|
||||||
|
} else if (ApplicationWideMessageHolder.getInstance().messageType
|
||||||
|
== ApplicationWideMessageHolder.MessageType.FAILED_TO_IMPORT_ACCOUNT
|
||||||
|
) {
|
||||||
|
setErrorText(resources!!.getString(R.string.nc_server_failed_to_import_account))
|
||||||
|
}
|
||||||
|
ApplicationWideMessageHolder.getInstance().messageType = null
|
||||||
|
}
|
||||||
|
setCertTextView()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onCertClick() {
|
||||||
|
KeyChain.choosePrivateKeyAlias(
|
||||||
|
this,
|
||||||
|
{ alias: String? ->
|
||||||
|
if (alias != null) {
|
||||||
|
appPreferences.temporaryClientCertAlias = alias
|
||||||
|
} else {
|
||||||
|
appPreferences.removeTemporaryClientCertAlias()
|
||||||
|
}
|
||||||
|
setCertTextView()
|
||||||
|
},
|
||||||
|
arrayOf("RSA", "EC"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
-1,
|
||||||
|
null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isAbleToShowProviderLink(): Boolean {
|
private fun isAbleToShowProviderLink(): Boolean {
|
||||||
|
@ -152,41 +180,37 @@ class ServerSelectionController :
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (availableAccounts.size > 1) {
|
if (availableAccounts.size > 1) {
|
||||||
binding?.importOrChooseProviderText?.text = String.format(
|
binding.importOrChooseProviderText.text = String.format(
|
||||||
resources!!.getString(R.string.nc_server_import_accounts),
|
resources!!.getString(R.string.nc_server_import_accounts),
|
||||||
AccountUtils.getAppNameBasedOnPackage(resources!!.getString(R.string.nc_import_accounts_from))
|
AccountUtils.getAppNameBasedOnPackage(resources!!.getString(R.string.nc_import_accounts_from))
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
binding?.importOrChooseProviderText?.text = String.format(
|
binding.importOrChooseProviderText.text = String.format(
|
||||||
resources!!.getString(R.string.nc_server_import_account),
|
resources!!.getString(R.string.nc_server_import_account),
|
||||||
AccountUtils.getAppNameBasedOnPackage(resources!!.getString(R.string.nc_import_accounts_from))
|
AccountUtils.getAppNameBasedOnPackage(resources!!.getString(R.string.nc_import_accounts_from))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (availableAccounts.size > 1) {
|
if (availableAccounts.size > 1) {
|
||||||
binding?.importOrChooseProviderText?.text =
|
binding.importOrChooseProviderText.text =
|
||||||
resources!!.getString(R.string.nc_server_import_accounts_plain)
|
resources!!.getString(R.string.nc_server_import_accounts_plain)
|
||||||
} else {
|
} else {
|
||||||
binding?.importOrChooseProviderText?.text =
|
binding.importOrChooseProviderText.text =
|
||||||
resources!!.getString(R.string.nc_server_import_account_plain)
|
resources!!.getString(R.string.nc_server_import_account_plain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding?.importOrChooseProviderText?.setOnClickListener {
|
binding.importOrChooseProviderText.setOnClickListener {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putBoolean(KEY_IS_ACCOUNT_IMPORT, true)
|
bundle.putBoolean(KEY_IS_ACCOUNT_IMPORT, true)
|
||||||
router.pushController(
|
val intent = Intent(context, SwitchAccountActivity::class.java)
|
||||||
RouterTransaction.with(
|
intent.putExtras(bundle)
|
||||||
SwitchAccountController(bundle)
|
startActivity(intent)
|
||||||
)
|
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(HorizontalChangeHandler())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showVisitProvidersInfo() {
|
private fun showVisitProvidersInfo() {
|
||||||
binding?.importOrChooseProviderText?.setText(R.string.nc_get_from_provider)
|
binding.importOrChooseProviderText.setText(R.string.nc_get_from_provider)
|
||||||
binding?.importOrChooseProviderText?.setOnClickListener {
|
binding.importOrChooseProviderText.setOnClickListener {
|
||||||
val browserIntent = Intent(
|
val browserIntent = Intent(
|
||||||
Intent.ACTION_VIEW,
|
Intent.ACTION_VIEW,
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
|
@ -206,11 +230,11 @@ class ServerSelectionController :
|
||||||
@Suppress("Detekt.TooGenericExceptionCaught")
|
@Suppress("Detekt.TooGenericExceptionCaught")
|
||||||
private fun checkServerAndProceed() {
|
private fun checkServerAndProceed() {
|
||||||
dispose()
|
dispose()
|
||||||
var url: String = binding?.serverEntryTextInputEditText?.text.toString().trim { it <= ' ' }
|
var url: String = binding.serverEntryTextInputEditText.text.toString().trim { it <= ' ' }
|
||||||
showserverEntryProgressBar()
|
showserverEntryProgressBar()
|
||||||
if (binding?.importOrChooseProviderText?.visibility != View.INVISIBLE) {
|
if (binding.importOrChooseProviderText.visibility != View.INVISIBLE) {
|
||||||
binding?.importOrChooseProviderText?.visibility = View.INVISIBLE
|
binding.importOrChooseProviderText.visibility = View.INVISIBLE
|
||||||
binding?.certTextView?.visibility = View.INVISIBLE
|
binding.certTextView.visibility = View.INVISIBLE
|
||||||
}
|
}
|
||||||
if (url.endsWith("/")) {
|
if (url.endsWith("/")) {
|
||||||
url = url.substring(0, url.length - 1)
|
url = url.substring(0, url.length - 1)
|
||||||
|
@ -278,17 +302,17 @@ class ServerSelectionController :
|
||||||
hideserverEntryProgressBar()
|
hideserverEntryProgressBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (binding?.importOrChooseProviderText?.visibility != View.INVISIBLE) {
|
if (binding.importOrChooseProviderText.visibility != View.INVISIBLE) {
|
||||||
binding?.importOrChooseProviderText?.visibility = View.VISIBLE
|
binding.importOrChooseProviderText.visibility = View.VISIBLE
|
||||||
binding?.certTextView?.visibility = View.VISIBLE
|
binding.certTextView.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
dispose()
|
dispose()
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
hideserverEntryProgressBar()
|
hideserverEntryProgressBar()
|
||||||
if (binding?.importOrChooseProviderText?.visibility != View.INVISIBLE) {
|
if (binding.importOrChooseProviderText.visibility != View.INVISIBLE) {
|
||||||
binding?.importOrChooseProviderText?.visibility = View.VISIBLE
|
binding.importOrChooseProviderText.visibility = View.VISIBLE
|
||||||
binding?.certTextView?.visibility = View.VISIBLE
|
binding.certTextView.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
dispose()
|
dispose()
|
||||||
}
|
}
|
||||||
|
@ -311,29 +335,25 @@ class ServerSelectionController :
|
||||||
capabilities.spreedCapability?.features?.isNotEmpty() == true
|
capabilities.spreedCapability?.features?.isNotEmpty() == true
|
||||||
|
|
||||||
if (hasTalk) {
|
if (hasTalk) {
|
||||||
activity?.runOnUiThread {
|
runOnUiThread {
|
||||||
if (CapabilitiesUtilNew.isServerEOL(capabilities)) {
|
if (CapabilitiesUtilNew.isServerEOL(capabilities)) {
|
||||||
if (resources != null) {
|
if (resources != null) {
|
||||||
activity!!.runOnUiThread {
|
runOnUiThread {
|
||||||
setErrorText(resources!!.getString(R.string.nc_settings_server_eol))
|
setErrorText(resources!!.getString(R.string.nc_settings_server_eol))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
router.pushController(
|
val bundle = Bundle()
|
||||||
RouterTransaction.with(
|
bundle.putString(BundleKeys.KEY_BASE_URL, queryUrl.replace("/status.php", ""))
|
||||||
WebViewLoginController(
|
|
||||||
queryUrl.replace("/status.php", ""),
|
val intent = Intent(context, WebViewLoginActivity::class.java)
|
||||||
false
|
intent.putExtras(bundle)
|
||||||
)
|
startActivity(intent)
|
||||||
)
|
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(HorizontalChangeHandler())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (activity != null && resources != null) {
|
if (resources != null) {
|
||||||
activity!!.runOnUiThread {
|
runOnUiThread {
|
||||||
setErrorText(resources!!.getString(R.string.nc_server_unsupported))
|
setErrorText(resources!!.getString(R.string.nc_server_unsupported))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,8 +362,8 @@ class ServerSelectionController :
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
Log.e(TAG, "Error while checking capabilities", e)
|
Log.e(TAG, "Error while checking capabilities", e)
|
||||||
if (activity != null && resources != null) {
|
if (resources != null) {
|
||||||
activity!!.runOnUiThread {
|
runOnUiThread {
|
||||||
setErrorText(resources!!.getString(R.string.nc_common_error_sorry))
|
setErrorText(resources!!.getString(R.string.nc_common_error_sorry))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,72 +380,31 @@ class ServerSelectionController :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setErrorText(text: String) {
|
private fun setErrorText(text: String) {
|
||||||
binding?.errorWrapper?.visibility = View.VISIBLE
|
binding.errorWrapper.visibility = View.VISIBLE
|
||||||
binding?.errorText?.text = text
|
binding.errorText.text = text
|
||||||
hideserverEntryProgressBar()
|
hideserverEntryProgressBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showserverEntryProgressBar() {
|
private fun showserverEntryProgressBar() {
|
||||||
binding?.errorWrapper?.visibility = View.INVISIBLE
|
binding.errorWrapper.visibility = View.INVISIBLE
|
||||||
binding?.serverEntryProgressBar?.visibility = View.VISIBLE
|
binding.serverEntryProgressBar.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideserverEntryProgressBar() {
|
private fun hideserverEntryProgressBar() {
|
||||||
binding?.serverEntryProgressBar?.visibility = View.INVISIBLE
|
binding.serverEntryProgressBar.visibility = View.INVISIBLE
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAttach(view: View) {
|
|
||||||
super.onAttach(view)
|
|
||||||
if (ApplicationWideMessageHolder.getInstance().messageType != null) {
|
|
||||||
if (ApplicationWideMessageHolder.getInstance().messageType
|
|
||||||
== ApplicationWideMessageHolder.MessageType.ACCOUNT_SCHEDULED_FOR_DELETION
|
|
||||||
) {
|
|
||||||
setErrorText(resources!!.getString(R.string.nc_account_scheduled_for_deletion))
|
|
||||||
ApplicationWideMessageHolder.getInstance().messageType = null
|
|
||||||
} else if (ApplicationWideMessageHolder.getInstance().messageType
|
|
||||||
== ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK
|
|
||||||
) {
|
|
||||||
setErrorText(resources!!.getString(R.string.nc_settings_no_talk_installed))
|
|
||||||
} else if (ApplicationWideMessageHolder.getInstance().messageType
|
|
||||||
== ApplicationWideMessageHolder.MessageType.FAILED_TO_IMPORT_ACCOUNT
|
|
||||||
) {
|
|
||||||
setErrorText(resources!!.getString(R.string.nc_server_failed_to_import_account))
|
|
||||||
}
|
|
||||||
ApplicationWideMessageHolder.getInstance().messageType = null
|
|
||||||
}
|
|
||||||
if (activity != null && resources != null) {
|
|
||||||
DisplayUtils.applyColorToStatusBar(
|
|
||||||
activity,
|
|
||||||
ResourcesCompat.getColor(resources!!, R.color.colorPrimary, null)
|
|
||||||
)
|
|
||||||
DisplayUtils.applyColorToNavigationBar(
|
|
||||||
activity!!.window,
|
|
||||||
ResourcesCompat.getColor(resources!!, R.color.colorPrimary, null)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
setCertTextView()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("LongLogTag")
|
@SuppressLint("LongLogTag")
|
||||||
private fun setCertTextView() {
|
private fun setCertTextView() {
|
||||||
if (activity != null) {
|
runOnUiThread {
|
||||||
activity!!.runOnUiThread {
|
if (!TextUtils.isEmpty(appPreferences.temporaryClientCertAlias)) {
|
||||||
if (!TextUtils.isEmpty(appPreferences!!.temporaryClientCertAlias)) {
|
binding.certTextView.setText(R.string.nc_change_cert_auth)
|
||||||
binding?.certTextView?.setText(R.string.nc_change_cert_auth)
|
|
||||||
} else {
|
} else {
|
||||||
binding?.certTextView?.setText(R.string.nc_configure_cert_auth)
|
binding.certTextView.setText(R.string.nc_configure_cert_auth)
|
||||||
}
|
}
|
||||||
hideserverEntryProgressBar()
|
hideserverEntryProgressBar()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
|
||||||
super.onDestroyView(view)
|
|
||||||
if (activity != null) {
|
|
||||||
activity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onDestroy() {
|
public override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
@ -443,7 +422,7 @@ class ServerSelectionController :
|
||||||
get() = AppBarLayoutType.EMPTY
|
get() = AppBarLayoutType.EMPTY
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "ServerSelectionController"
|
private val TAG = ServerSelectionActivity::class.java.simpleName
|
||||||
const val MIN_SERVER_MAJOR_VERSION = 13
|
const val MIN_SERVER_MAJOR_VERSION = 13
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
*
|
*
|
||||||
* @author Mario Danic
|
* @author Mario Danic
|
||||||
* @author Andy Scherzinger
|
* @author Andy Scherzinger
|
||||||
|
* @author Marcel Hibbe
|
||||||
|
* Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
||||||
*
|
*
|
||||||
|
@ -22,25 +24,23 @@
|
||||||
* Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
|
* Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
|
||||||
* https://github.com/nextcloud/ownCloud-Account-Importer
|
* https://github.com/nextcloud/ownCloud-Account-Importer
|
||||||
*/
|
*/
|
||||||
package com.nextcloud.talk.controllers
|
package com.nextcloud.talk.account
|
||||||
|
|
||||||
import android.accounts.Account
|
import android.accounts.Account
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.View
|
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
import com.nextcloud.talk.adapters.items.AdvancedUserItem
|
import com.nextcloud.talk.adapters.items.AdvancedUserItem
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
|
||||||
import com.nextcloud.talk.controllers.base.BaseController
|
|
||||||
import com.nextcloud.talk.controllers.util.viewBinding
|
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ControllerGenericRvBinding
|
import com.nextcloud.talk.databinding.ActivitySwitchAccountBinding
|
||||||
import com.nextcloud.talk.models.ImportAccount
|
import com.nextcloud.talk.models.ImportAccount
|
||||||
import com.nextcloud.talk.models.json.participants.Participant
|
import com.nextcloud.talk.models.json.participants.Participant
|
||||||
import com.nextcloud.talk.users.UserManager
|
import com.nextcloud.talk.users.UserManager
|
||||||
|
@ -56,14 +56,11 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import org.osmdroid.config.Configuration
|
import org.osmdroid.config.Configuration
|
||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class SwitchAccountController(args: Bundle? = null) :
|
class SwitchAccountActivity : BaseActivity() {
|
||||||
BaseController(
|
private lateinit var binding: ActivitySwitchAccountBinding
|
||||||
R.layout.controller_generic_rv,
|
|
||||||
args
|
|
||||||
) {
|
|
||||||
private val binding: ControllerGenericRvBinding? by viewBinding(ControllerGenericRvBinding::bind)
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var userManager: UserManager
|
lateinit var userManager: UserManager
|
||||||
|
@ -89,41 +86,52 @@ class SwitchAccountController(args: Bundle? = null) :
|
||||||
|
|
||||||
if (userManager.setUserAsActive(user).blockingGet()) {
|
if (userManager.setUserAsActive(user).blockingGet()) {
|
||||||
cookieManager.cookieStore.removeAll()
|
cookieManager.cookieStore.removeAll()
|
||||||
if (activity != null) {
|
finish()
|
||||||
activity!!.runOnUiThread { router.popCurrentController() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
@SuppressLint("SourceLockedOrientationActivity")
|
||||||
setHasOptionsMenu(true)
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
sharedApplication!!.componentApplication.inject(this)
|
sharedApplication!!.componentApplication.inject(this)
|
||||||
|
binding = ActivitySwitchAccountBinding.inflate(layoutInflater)
|
||||||
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
setContentView(binding.root)
|
||||||
|
setupActionBar()
|
||||||
|
setupPrimaryColors()
|
||||||
|
|
||||||
Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))
|
Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))
|
||||||
if (args?.containsKey(KEY_IS_ACCOUNT_IMPORT) == true) {
|
|
||||||
|
handleIntent()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntent() {
|
||||||
|
intent.extras?.let {
|
||||||
|
if (it.containsKey(KEY_IS_ACCOUNT_IMPORT)) {
|
||||||
isAccountImport = true
|
isAccountImport = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
return when (item.itemId) {
|
|
||||||
android.R.id.home -> {
|
|
||||||
router.popCurrentController()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewBound(view: View) {
|
private fun setupActionBar() {
|
||||||
super.onViewBound(view)
|
setSupportActionBar(binding.toolbar)
|
||||||
binding?.swipeRefreshLayout?.isEnabled = false
|
binding.toolbar.setNavigationOnClickListener {
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
supportActionBar?.setIcon(ColorDrawable(resources!!.getColor(R.color.transparent, null)))
|
||||||
|
supportActionBar?.title = resources!!.getString(R.string.nc_select_an_account)
|
||||||
|
}
|
||||||
|
|
||||||
actionBar?.show()
|
@Suppress("Detekt.NestedBlockDepth")
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
if (adapter == null) {
|
if (adapter == null) {
|
||||||
adapter = FlexibleAdapter(userItems, activity, false)
|
adapter = FlexibleAdapter(userItems, this, false)
|
||||||
var participant: Participant
|
var participant: Participant
|
||||||
|
|
||||||
if (!isAccountImport) {
|
if (!isAccountImport) {
|
||||||
|
@ -166,11 +174,10 @@ class SwitchAccountController(args: Bundle? = null) :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prepareViews() {
|
private fun prepareViews() {
|
||||||
val layoutManager: LinearLayoutManager = SmoothScrollLinearLayoutManager(activity)
|
val layoutManager: LinearLayoutManager = SmoothScrollLinearLayoutManager(this)
|
||||||
binding?.recyclerView?.layoutManager = layoutManager
|
binding.recyclerView.layoutManager = layoutManager
|
||||||
binding?.recyclerView?.setHasFixedSize(true)
|
binding.recyclerView.setHasFixedSize(true)
|
||||||
binding?.recyclerView?.adapter = adapter
|
binding.recyclerView.adapter = adapter
|
||||||
binding?.swipeRefreshLayout?.isEnabled = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun reauthorizeFromImport(account: Account?) {
|
private fun reauthorizeFromImport(account: Account?) {
|
||||||
|
@ -180,14 +187,9 @@ class SwitchAccountController(args: Bundle? = null) :
|
||||||
bundle.putString(KEY_USERNAME, importAccount.getUsername())
|
bundle.putString(KEY_USERNAME, importAccount.getUsername())
|
||||||
bundle.putString(KEY_TOKEN, importAccount.getToken())
|
bundle.putString(KEY_TOKEN, importAccount.getToken())
|
||||||
bundle.putBoolean(KEY_IS_ACCOUNT_IMPORT, true)
|
bundle.putBoolean(KEY_IS_ACCOUNT_IMPORT, true)
|
||||||
router.pushController(
|
|
||||||
RouterTransaction.with(AccountVerificationController(bundle))
|
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(HorizontalChangeHandler())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val title: String
|
val intent = Intent(context, AccountVerificationActivity::class.java)
|
||||||
get() =
|
intent.putExtras(bundle)
|
||||||
resources!!.getString(R.string.nc_select_an_account)
|
startActivity(intent)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
*
|
*
|
||||||
* @author Mario Danic
|
* @author Mario Danic
|
||||||
* @author Andy Scherzinger
|
* @author Andy Scherzinger
|
||||||
|
* @author Marcel Hibbe
|
||||||
|
* Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
|
* Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
|
||||||
*
|
*
|
||||||
|
@ -19,9 +21,10 @@
|
||||||
* 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/>.
|
||||||
*/
|
*/
|
||||||
package com.nextcloud.talk.controllers
|
package com.nextcloud.talk.account
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.net.http.SslError
|
import android.net.http.SslError
|
||||||
|
@ -40,34 +43,30 @@ import android.webkit.WebResourceResponse
|
||||||
import android.webkit.WebSettings
|
import android.webkit.WebSettings
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import androidx.work.Data
|
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
|
import androidx.work.WorkInfo
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.controllers.base.BaseController
|
import com.nextcloud.talk.databinding.ActivityWebViewLoginBinding
|
||||||
import com.nextcloud.talk.controllers.util.viewBinding
|
|
||||||
import com.nextcloud.talk.databinding.ControllerWebViewLoginBinding
|
|
||||||
import com.nextcloud.talk.events.CertificateEvent
|
import com.nextcloud.talk.events.CertificateEvent
|
||||||
import com.nextcloud.talk.jobs.PushRegistrationWorker
|
import com.nextcloud.talk.jobs.AccountRemovalWorker
|
||||||
import com.nextcloud.talk.models.LoginData
|
import com.nextcloud.talk.models.LoginData
|
||||||
import com.nextcloud.talk.users.UserManager
|
import com.nextcloud.talk.users.UserManager
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_BASE_URL
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_BASE_URL
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
|
||||||
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
|
||||||
import com.nextcloud.talk.utils.ssl.TrustManager
|
import com.nextcloud.talk.utils.ssl.TrustManager
|
||||||
import de.cotech.hw.fido.WebViewFidoBridge
|
import de.cotech.hw.fido.WebViewFidoBridge
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
|
@ -78,11 +77,9 @@ import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class WebViewLoginController(args: Bundle? = null) : BaseController(
|
class WebViewLoginActivity : BaseActivity() {
|
||||||
R.layout.controller_web_view_login,
|
|
||||||
args
|
private lateinit var binding: ActivityWebViewLoginBinding
|
||||||
) {
|
|
||||||
private val binding: ControllerWebViewLoginBinding? by viewBinding(ControllerWebViewLoginBinding::bind)
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var userManager: UserManager
|
lateinit var userManager: UserManager
|
||||||
|
@ -90,34 +87,26 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var trustManager: TrustManager
|
lateinit var trustManager: TrustManager
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var eventBus: EventBus
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var cookieManager: CookieManager
|
lateinit var cookieManager: CookieManager
|
||||||
|
|
||||||
private var assembledPrefix: String? = null
|
private var assembledPrefix: String? = null
|
||||||
private var userQueryDisposable: Disposable? = null
|
private var userQueryDisposable: Disposable? = null
|
||||||
private var baseUrl: String? = null
|
private var baseUrl: String? = null
|
||||||
private var isPasswordUpdate = false
|
private var reauthorizeAccount = false
|
||||||
private var username: String? = null
|
private var username: String? = null
|
||||||
private var password: String? = null
|
private var password: String? = null
|
||||||
private var loginStep = 0
|
private var loginStep = 0
|
||||||
private var automatedLoginAttempted = false
|
private var automatedLoginAttempted = false
|
||||||
private var webViewFidoBridge: WebViewFidoBridge? = null
|
private var webViewFidoBridge: WebViewFidoBridge? = null
|
||||||
|
|
||||||
constructor(baseUrl: String?, isPasswordUpdate: Boolean) : this() {
|
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||||
this.baseUrl = baseUrl
|
override fun handleOnBackPressed() {
|
||||||
this.isPasswordUpdate = isPasswordUpdate
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(baseUrl: String?, isPasswordUpdate: Boolean, username: String?, password: String?) : this() {
|
|
||||||
this.baseUrl = baseUrl
|
|
||||||
this.isPasswordUpdate = isPasswordUpdate
|
|
||||||
this.username = username
|
|
||||||
this.password = password
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val webLoginUserAgent: String
|
private val webLoginUserAgent: String
|
||||||
get() = (
|
get() = (
|
||||||
Build.MANUFACTURER.substring(0, 1).toUpperCase(Locale.getDefault()) +
|
Build.MANUFACTURER.substring(0, 1).toUpperCase(Locale.getDefault()) +
|
||||||
|
@ -129,33 +118,57 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
")"
|
")"
|
||||||
)
|
)
|
||||||
|
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SourceLockedOrientationActivity")
|
||||||
override fun onViewBound(view: View) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onViewBound(view)
|
super.onCreate(savedInstanceState)
|
||||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
sharedApplication!!.componentApplication.inject(this)
|
||||||
|
binding = ActivityWebViewLoginBinding.inflate(layoutInflater)
|
||||||
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
setContentView(binding.root)
|
||||||
actionBar?.hide()
|
actionBar?.hide()
|
||||||
|
setupPrimaryColors()
|
||||||
|
|
||||||
|
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
||||||
|
handleIntent()
|
||||||
|
setupWebView()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntent() {
|
||||||
|
val extras = intent.extras!!
|
||||||
|
baseUrl = extras.getString(KEY_BASE_URL)
|
||||||
|
username = extras.getString(KEY_USERNAME)
|
||||||
|
|
||||||
|
if (extras.containsKey(BundleKeys.KEY_REAUTHORIZE_ACCOUNT)) {
|
||||||
|
reauthorizeAccount = extras.getBoolean(BundleKeys.KEY_REAUTHORIZE_ACCOUNT)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extras.containsKey(BundleKeys.KEY_PASSWORD)) {
|
||||||
|
password = extras.getString(BundleKeys.KEY_PASSWORD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
|
private fun setupWebView() {
|
||||||
assembledPrefix = resources!!.getString(R.string.nc_talk_login_scheme) + PROTOCOL_SUFFIX + "login/"
|
assembledPrefix = resources!!.getString(R.string.nc_talk_login_scheme) + PROTOCOL_SUFFIX + "login/"
|
||||||
binding?.webview?.settings?.allowFileAccess = false
|
binding.webview.settings.allowFileAccess = false
|
||||||
binding?.webview?.settings?.allowFileAccessFromFileURLs = false
|
binding.webview.settings.allowFileAccessFromFileURLs = false
|
||||||
binding?.webview?.settings?.javaScriptEnabled = true
|
binding.webview.settings.javaScriptEnabled = true
|
||||||
binding?.webview?.settings?.javaScriptCanOpenWindowsAutomatically = false
|
binding.webview.settings.javaScriptCanOpenWindowsAutomatically = false
|
||||||
binding?.webview?.settings?.domStorageEnabled = true
|
binding.webview.settings.domStorageEnabled = true
|
||||||
binding?.webview?.settings?.setUserAgentString(webLoginUserAgent)
|
binding.webview.settings.userAgentString = webLoginUserAgent
|
||||||
binding?.webview?.settings?.saveFormData = false
|
binding.webview.settings.saveFormData = false
|
||||||
binding?.webview?.settings?.savePassword = false
|
binding.webview.settings.savePassword = false
|
||||||
binding?.webview?.settings?.setRenderPriority(WebSettings.RenderPriority.HIGH)
|
binding.webview.settings.setRenderPriority(WebSettings.RenderPriority.HIGH)
|
||||||
binding?.webview?.clearCache(true)
|
binding.webview.clearCache(true)
|
||||||
binding?.webview?.clearFormData()
|
binding.webview.clearFormData()
|
||||||
binding?.webview?.clearHistory()
|
binding.webview.clearHistory()
|
||||||
WebView.clearClientCertPreferences(null)
|
WebView.clearClientCertPreferences(null)
|
||||||
webViewFidoBridge = WebViewFidoBridge.createInstanceForWebView(activity as AppCompatActivity?, binding?.webview)
|
webViewFidoBridge = WebViewFidoBridge.createInstanceForWebView(this, binding.webview)
|
||||||
CookieSyncManager.createInstance(activity)
|
CookieSyncManager.createInstance(this)
|
||||||
android.webkit.CookieManager.getInstance().removeAllCookies(null)
|
android.webkit.CookieManager.getInstance().removeAllCookies(null)
|
||||||
val headers: MutableMap<String, String> = HashMap()
|
val headers: MutableMap<String, String> = HashMap()
|
||||||
headers.put("OCS-APIRequest", "true")
|
headers["OCS-APIRequest"] = "true"
|
||||||
binding?.webview?.webViewClient = object : WebViewClient() {
|
binding.webview.webViewClient = object : WebViewClient() {
|
||||||
private var basePageLoaded = false
|
private var basePageLoaded = false
|
||||||
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
||||||
webViewFidoBridge?.delegateShouldInterceptRequest(view, request)
|
webViewFidoBridge?.delegateShouldInterceptRequest(view, request)
|
||||||
|
@ -180,24 +193,24 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
override fun onPageFinished(view: WebView, url: String) {
|
override fun onPageFinished(view: WebView, url: String) {
|
||||||
loginStep++
|
loginStep++
|
||||||
if (!basePageLoaded) {
|
if (!basePageLoaded) {
|
||||||
binding?.progressBar?.visibility = View.GONE
|
binding.progressBar.visibility = View.GONE
|
||||||
binding?.webview?.visibility = View.VISIBLE
|
binding.webview.visibility = View.VISIBLE
|
||||||
|
|
||||||
basePageLoaded = true
|
basePageLoaded = true
|
||||||
}
|
}
|
||||||
if (!TextUtils.isEmpty(username)) {
|
if (!TextUtils.isEmpty(username)) {
|
||||||
if (loginStep == 1) {
|
if (loginStep == 1) {
|
||||||
binding?.webview?.loadUrl(
|
binding.webview.loadUrl(
|
||||||
"javascript: {document.getElementsByClassName('login')[0].click(); };"
|
"javascript: {document.getElementsByClassName('login')[0].click(); };"
|
||||||
)
|
)
|
||||||
} else if (!automatedLoginAttempted) {
|
} else if (!automatedLoginAttempted) {
|
||||||
automatedLoginAttempted = true
|
automatedLoginAttempted = true
|
||||||
if (TextUtils.isEmpty(password)) {
|
if (TextUtils.isEmpty(password)) {
|
||||||
binding?.webview?.loadUrl(
|
binding.webview.loadUrl(
|
||||||
"javascript:var justStore = document.getElementById('user').value = '$username';"
|
"javascript:var justStore = document.getElementById('user').value = '$username';"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
binding?.webview?.loadUrl(
|
binding.webview.loadUrl(
|
||||||
"javascript: {" +
|
"javascript: {" +
|
||||||
"document.getElementById('user').value = '" + username + "';" +
|
"document.getElementById('user').value = '" + username + "';" +
|
||||||
"document.getElementById('password').value = '" + password + "';" +
|
"document.getElementById('password').value = '" + password + "';" +
|
||||||
|
@ -213,8 +226,8 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
override fun onReceivedClientCertRequest(view: WebView, request: ClientCertRequest) {
|
override fun onReceivedClientCertRequest(view: WebView, request: ClientCertRequest) {
|
||||||
val user = userManager.currentUser.blockingGet()
|
val user = userManager.currentUser.blockingGet()
|
||||||
var alias: String? = null
|
var alias: String? = null
|
||||||
if (!isPasswordUpdate) {
|
if (!reauthorizeAccount) {
|
||||||
alias = appPreferences!!.temporaryClientCertAlias
|
alias = appPreferences.temporaryClientCertAlias
|
||||||
}
|
}
|
||||||
if (TextUtils.isEmpty(alias) && user != null) {
|
if (TextUtils.isEmpty(alias) && user != null) {
|
||||||
alias = user.clientCertificate
|
alias = user.clientCertificate
|
||||||
|
@ -223,9 +236,9 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
val finalAlias = alias
|
val finalAlias = alias
|
||||||
Thread {
|
Thread {
|
||||||
try {
|
try {
|
||||||
val privateKey = KeyChain.getPrivateKey(activity!!, finalAlias!!)
|
val privateKey = KeyChain.getPrivateKey(applicationContext, finalAlias!!)
|
||||||
val certificates = KeyChain.getCertificateChain(
|
val certificates = KeyChain.getCertificateChain(
|
||||||
activity!!,
|
applicationContext,
|
||||||
finalAlias
|
finalAlias
|
||||||
)
|
)
|
||||||
if (privateKey != null && certificates != null) {
|
if (privateKey != null && certificates != null) {
|
||||||
|
@ -241,16 +254,16 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
}.start()
|
}.start()
|
||||||
} else {
|
} else {
|
||||||
KeyChain.choosePrivateKeyAlias(
|
KeyChain.choosePrivateKeyAlias(
|
||||||
activity!!,
|
this@WebViewLoginActivity,
|
||||||
{ chosenAlias: String? ->
|
{ chosenAlias: String? ->
|
||||||
if (chosenAlias != null) {
|
if (chosenAlias != null) {
|
||||||
appPreferences!!.temporaryClientCertAlias = chosenAlias
|
appPreferences!!.temporaryClientCertAlias = chosenAlias
|
||||||
Thread {
|
Thread {
|
||||||
var privateKey: PrivateKey? = null
|
var privateKey: PrivateKey? = null
|
||||||
try {
|
try {
|
||||||
privateKey = KeyChain.getPrivateKey(activity!!, chosenAlias)
|
privateKey = KeyChain.getPrivateKey(applicationContext, chosenAlias)
|
||||||
val certificates = KeyChain.getCertificateChain(
|
val certificates = KeyChain.getCertificateChain(
|
||||||
activity!!,
|
applicationContext,
|
||||||
chosenAlias
|
chosenAlias
|
||||||
)
|
)
|
||||||
if (privateKey != null && certificates != null) {
|
if (privateKey != null && certificates != null) {
|
||||||
|
@ -304,7 +317,7 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
super.onReceivedError(view, errorCode, description, failingUrl)
|
super.onReceivedError(view, errorCode, description, failingUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding?.webview?.loadUrl("$baseUrl/index.php/login/flow", headers)
|
binding.webview.loadUrl("$baseUrl/index.php/login/flow", headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dispose() {
|
private fun dispose() {
|
||||||
|
@ -318,25 +331,27 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
val loginData = parseLoginData(assembledPrefix, dataString)
|
val loginData = parseLoginData(assembledPrefix, dataString)
|
||||||
if (loginData != null) {
|
if (loginData != null) {
|
||||||
dispose()
|
dispose()
|
||||||
val currentUser = userManager.currentUser.blockingGet()
|
|
||||||
var messageType: ApplicationWideMessageHolder.MessageType? = null
|
|
||||||
if (!isPasswordUpdate &&
|
|
||||||
userManager.checkIfUserExists(loginData.username!!, baseUrl!!).blockingGet()
|
|
||||||
) {
|
|
||||||
messageType = ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED
|
|
||||||
}
|
|
||||||
if (userManager.checkIfUserIsScheduledForDeletion(loginData.username!!, baseUrl!!).blockingGet()) {
|
|
||||||
ApplicationWideMessageHolder.getInstance().messageType =
|
|
||||||
ApplicationWideMessageHolder.MessageType.ACCOUNT_SCHEDULED_FOR_DELETION
|
|
||||||
if (!isPasswordUpdate) {
|
|
||||||
router.popToRoot()
|
|
||||||
} else {
|
|
||||||
router.popCurrentController()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val finalMessageType = messageType
|
|
||||||
cookieManager.cookieStore.removeAll()
|
cookieManager.cookieStore.removeAll()
|
||||||
if (!isPasswordUpdate && finalMessageType == null) {
|
|
||||||
|
if (userManager.checkIfUserIsScheduledForDeletion(loginData.username!!, baseUrl!!).blockingGet()) {
|
||||||
|
Log.e(TAG, "Tried to add already existing user who is scheduled for deletion.")
|
||||||
|
Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
|
||||||
|
// however the user is not yet deleted, just start AccountRemovalWorker again to make sure to delete it.
|
||||||
|
startAccountRemovalWorkerAndRestartApp()
|
||||||
|
} else if (userManager.checkIfUserExists(loginData.username!!, baseUrl!!).blockingGet()) {
|
||||||
|
if (reauthorizeAccount) {
|
||||||
|
updateUserAndRestartApp(loginData)
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "It was tried to add an account that account already exists. Skipped user creation.")
|
||||||
|
restartApp()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startAccountVerification(loginData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startAccountVerification(loginData: LoginData) {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString(KEY_USERNAME, loginData.username)
|
bundle.putString(KEY_USERNAME, loginData.username)
|
||||||
bundle.putString(KEY_TOKEN, loginData.token)
|
bundle.putString(KEY_TOKEN, loginData.token)
|
||||||
|
@ -350,46 +365,41 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
if (!TextUtils.isEmpty(protocol)) {
|
if (!TextUtils.isEmpty(protocol)) {
|
||||||
bundle.putString(KEY_ORIGINAL_PROTOCOL, protocol)
|
bundle.putString(KEY_ORIGINAL_PROTOCOL, protocol)
|
||||||
}
|
}
|
||||||
router.pushController(
|
val intent = Intent(context, AccountVerificationActivity::class.java)
|
||||||
RouterTransaction.with(AccountVerificationController(bundle))
|
intent.putExtras(bundle)
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
startActivity(intent)
|
||||||
.popChangeHandler(HorizontalChangeHandler())
|
}
|
||||||
)
|
|
||||||
} else {
|
private fun restartApp() {
|
||||||
if (isPasswordUpdate) {
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateUserAndRestartApp(loginData: LoginData) {
|
||||||
|
val currentUser = userManager.currentUser.blockingGet()
|
||||||
if (currentUser != null) {
|
if (currentUser != null) {
|
||||||
currentUser.clientCertificate = appPreferences!!.temporaryClientCertAlias
|
currentUser.clientCertificate = appPreferences.temporaryClientCertAlias
|
||||||
currentUser.token = loginData.token
|
currentUser.token = loginData.token
|
||||||
val rowsUpdated = userManager.updateOrCreateUser(currentUser).blockingGet()
|
val rowsUpdated = userManager.updateOrCreateUser(currentUser).blockingGet()
|
||||||
Log.d(TAG, "User rows updated: $rowsUpdated")
|
Log.d(TAG, "User rows updated: $rowsUpdated")
|
||||||
|
restartApp()
|
||||||
if (finalMessageType != null) {
|
}
|
||||||
ApplicationWideMessageHolder.getInstance().messageType = finalMessageType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val data = Data.Builder().putString(
|
private fun startAccountRemovalWorkerAndRestartApp() {
|
||||||
PushRegistrationWorker.ORIGIN,
|
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
|
||||||
"WebViewLoginController#parseAndLoginFromWebView"
|
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
||||||
).build()
|
|
||||||
|
|
||||||
val pushRegistrationWork = OneTimeWorkRequest.Builder(
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
||||||
PushRegistrationWorker::class.java
|
.observeForever { workInfo: WorkInfo ->
|
||||||
)
|
|
||||||
.setInputData(data)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
WorkManager.getInstance().enqueue(pushRegistrationWork)
|
when (workInfo.state) {
|
||||||
router.popCurrentController()
|
WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED -> {
|
||||||
}
|
restartApp()
|
||||||
} else {
|
|
||||||
if (finalMessageType != null) {
|
|
||||||
// FIXME when the user registers a new account that was setup before (aka
|
|
||||||
// ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED)
|
|
||||||
// The token is not updated in the database and therefore the account not visible/usable
|
|
||||||
ApplicationWideMessageHolder.getInstance().messageType = finalMessageType
|
|
||||||
}
|
|
||||||
router.popToRoot()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -432,30 +442,11 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttach(view: View) {
|
|
||||||
super.onAttach(view)
|
|
||||||
if (activity != null && resources != null) {
|
|
||||||
DisplayUtils.applyColorToStatusBar(
|
|
||||||
activity,
|
|
||||||
ResourcesCompat.getColor(resources!!, R.color.colorPrimary, null)
|
|
||||||
)
|
|
||||||
DisplayUtils.applyColorToNavigationBar(
|
|
||||||
activity!!.window,
|
|
||||||
ResourcesCompat.getColor(resources!!, R.color.colorPrimary, null)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onDestroy() {
|
public override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
dispose()
|
dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
|
||||||
super.onDestroyView(view)
|
|
||||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
sharedApplication!!.componentApplication.inject(this)
|
sharedApplication!!.componentApplication.inject(this)
|
||||||
}
|
}
|
||||||
|
@ -464,7 +455,7 @@ class WebViewLoginController(args: Bundle? = null) : BaseController(
|
||||||
get() = AppBarLayoutType.EMPTY
|
get() = AppBarLayoutType.EMPTY
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "WebViewLoginController"
|
private val TAG = WebViewLoginActivity::class.java.simpleName
|
||||||
private const val PROTOCOL_SUFFIX = "://"
|
private const val PROTOCOL_SUFFIX = "://"
|
||||||
private const val LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":"
|
private const val LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":"
|
||||||
private const val PARAMETER_COUNT = 3
|
private const val PARAMETER_COUNT = 3
|
|
@ -16,7 +16,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.nextcloud.talk.controllers.base.providers;
|
package com.nextcloud.talk.activities;
|
||||||
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
|
|
@ -24,17 +24,26 @@ package com.nextcloud.talk.activities
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.webkit.SslErrorHandler
|
import android.webkit.SslErrorHandler
|
||||||
|
import android.widget.EditText
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.account.AccountVerificationActivity
|
||||||
|
import com.nextcloud.talk.account.ServerSelectionActivity
|
||||||
|
import com.nextcloud.talk.account.SwitchAccountActivity
|
||||||
|
import com.nextcloud.talk.account.WebViewLoginActivity
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.events.CertificateEvent
|
import com.nextcloud.talk.events.CertificateEvent
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
|
@ -77,6 +86,8 @@ open class BaseActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
cleanTempCertPreference()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun onStart() {
|
public override fun onStart() {
|
||||||
|
@ -87,6 +98,11 @@ open class BaseActivity : AppCompatActivity() {
|
||||||
public override fun onResume() {
|
public override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.isKeyboardIncognito) {
|
||||||
|
val viewGroup = (findViewById<View>(android.R.id.content) as ViewGroup).getChildAt(0) as ViewGroup
|
||||||
|
disableKeyboardPersonalisedLearning(viewGroup)
|
||||||
|
}
|
||||||
|
|
||||||
if (appPreferences.isScreenSecured) {
|
if (appPreferences.isScreenSecured) {
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,6 +120,19 @@ open class BaseActivity : AppCompatActivity() {
|
||||||
colorizeNavigationBar()
|
colorizeNavigationBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setupPrimaryColors() {
|
||||||
|
if (resources != null) {
|
||||||
|
DisplayUtils.applyColorToStatusBar(
|
||||||
|
this,
|
||||||
|
ResourcesCompat.getColor(resources!!, R.color.colorPrimary, null)
|
||||||
|
)
|
||||||
|
DisplayUtils.applyColorToNavigationBar(
|
||||||
|
window,
|
||||||
|
ResourcesCompat.getColor(resources!!, R.color.colorPrimary, null)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open fun colorizeStatusBar() {
|
open fun colorizeStatusBar() {
|
||||||
if (resources != null) {
|
if (resources != null) {
|
||||||
if (appBarLayoutType == AppBarLayoutType.SEARCH_BAR) {
|
if (appBarLayoutType == AppBarLayoutType.SEARCH_BAR) {
|
||||||
|
@ -123,7 +152,23 @@ open class BaseActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showCertificateDialog(
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
private fun disableKeyboardPersonalisedLearning(viewGroup: ViewGroup) {
|
||||||
|
var view: View?
|
||||||
|
var editText: EditText
|
||||||
|
for (i in 0 until viewGroup.childCount) {
|
||||||
|
view = viewGroup.getChildAt(i)
|
||||||
|
if (view is EditText) {
|
||||||
|
editText = view
|
||||||
|
editText.imeOptions = editText.imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
|
||||||
|
} else if (view is ViewGroup) {
|
||||||
|
disableKeyboardPersonalisedLearning(view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("Detekt.NestedBlockDepth")
|
||||||
|
private fun showCertificateDialog(
|
||||||
cert: X509Certificate,
|
cert: X509Certificate,
|
||||||
trustManager: TrustManager,
|
trustManager: TrustManager,
|
||||||
sslErrorHandler: SslErrorHandler?
|
sslErrorHandler: SslErrorHandler?
|
||||||
|
@ -160,15 +205,17 @@ open class BaseActivity : AppCompatActivity() {
|
||||||
validUntil
|
validUntil
|
||||||
)
|
)
|
||||||
|
|
||||||
val dialogBuilder = MaterialAlertDialogBuilder(this)
|
val dialogBuilder = MaterialAlertDialogBuilder(this).setIcon(
|
||||||
.setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_security_white_24dp))
|
viewThemeUtils.dialog.colorMaterialAlertDialogIcon(
|
||||||
.setTitle(R.string.nc_certificate_dialog_title)
|
context,
|
||||||
|
R.drawable.ic_security_white_24dp
|
||||||
|
)
|
||||||
|
).setTitle(R.string.nc_certificate_dialog_title)
|
||||||
.setMessage(dialogText)
|
.setMessage(dialogText)
|
||||||
.setPositiveButton(R.string.nc_yes) { _, _ ->
|
.setPositiveButton(R.string.nc_yes) { _, _ ->
|
||||||
trustManager.addCertInTrustStore(cert)
|
trustManager.addCertInTrustStore(cert)
|
||||||
sslErrorHandler?.proceed()
|
sslErrorHandler?.proceed()
|
||||||
}
|
}.setNegativeButton(R.string.nc_no) { _, _ ->
|
||||||
.setNegativeButton(R.string.nc_no) { _, _ ->
|
|
||||||
sslErrorHandler?.cancel()
|
sslErrorHandler?.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,12 +232,23 @@ open class BaseActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun cleanTempCertPreference() {
|
||||||
|
val temporaryClassNames: MutableList<String> = ArrayList()
|
||||||
|
temporaryClassNames.add(ServerSelectionActivity::class.java.name)
|
||||||
|
temporaryClassNames.add(AccountVerificationActivity::class.java.name)
|
||||||
|
temporaryClassNames.add(WebViewLoginActivity::class.java.name)
|
||||||
|
temporaryClassNames.add(SwitchAccountActivity::class.java.name)
|
||||||
|
if (!temporaryClassNames.contains(javaClass.name)) {
|
||||||
|
appPreferences.removeTemporaryClientCertAlias()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onMessageEvent(event: CertificateEvent) {
|
fun onMessageEvent(event: CertificateEvent) {
|
||||||
showCertificateDialog(event.x509Certificate, event.magicTrustManager, event.sslErrorHandler)
|
showCertificateDialog(event.x509Certificate, event.magicTrustManager, event.sslErrorHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = "BaseActivity"
|
private val TAG = BaseActivity::class.java.simpleName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3096,7 +3096,7 @@ class CallActivity : CallBaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun suppressFitsSystemWindows() {
|
override fun suppressFitsSystemWindows() {
|
||||||
binding!!.controllerCallLayout.fitsSystemWindows = false
|
binding!!.callLayout.fitsSystemWindows = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
|
|
|
@ -37,21 +37,14 @@ import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.bluelinelabs.conductor.Conductor
|
|
||||||
import com.bluelinelabs.conductor.Router
|
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
|
||||||
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.nextcloud.talk.BuildConfig
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.account.ServerSelectionActivity
|
||||||
|
import com.nextcloud.talk.account.WebViewLoginActivity
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.callnotification.CallNotificationActivity
|
import com.nextcloud.talk.callnotification.CallNotificationActivity
|
||||||
import com.nextcloud.talk.chat.ChatActivity
|
import com.nextcloud.talk.chat.ChatActivity
|
||||||
import com.nextcloud.talk.controllers.ServerSelectionController
|
|
||||||
import com.nextcloud.talk.controllers.WebViewLoginController
|
|
||||||
import com.nextcloud.talk.controllers.base.providers.ActionBarProvider
|
|
||||||
import com.nextcloud.talk.conversationlist.ConversationsListActivity
|
import com.nextcloud.talk.conversationlist.ConversationsListActivity
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ActivityMainBinding
|
import com.nextcloud.talk.databinding.ActivityMainBinding
|
||||||
|
@ -61,7 +54,6 @@ import com.nextcloud.talk.users.UserManager
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.SecurityUtils
|
import com.nextcloud.talk.utils.SecurityUtils
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.ADD_ACCOUNT
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
||||||
import io.reactivex.Observer
|
import io.reactivex.Observer
|
||||||
import io.reactivex.SingleObserver
|
import io.reactivex.SingleObserver
|
||||||
|
@ -80,15 +72,11 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var userManager: UserManager
|
lateinit var userManager: UserManager
|
||||||
|
|
||||||
private var router: Router? = null
|
|
||||||
|
|
||||||
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||||
override fun handleOnBackPressed() {
|
override fun handleOnBackPressed() {
|
||||||
if (!router!!.handleBack()) {
|
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("Detekt.TooGenericExceptionCaught")
|
@Suppress("Detekt.TooGenericExceptionCaught")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -111,8 +99,6 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||||
|
|
||||||
setSupportActionBar(binding.toolbar)
|
setSupportActionBar(binding.toolbar)
|
||||||
|
|
||||||
router = Conductor.attachRouter(this, binding.controllerContainer, savedInstanceState)
|
|
||||||
|
|
||||||
handleIntent(intent)
|
handleIntent(intent)
|
||||||
|
|
||||||
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
||||||
|
@ -128,28 +114,24 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun launchLoginScreen() {
|
private fun launchServerSelection() {
|
||||||
if (!TextUtils.isEmpty(resources.getString(R.string.weblogin_url))) {
|
if (isBrandingUrlSet()) {
|
||||||
router!!.pushController(
|
val intent = Intent(context, WebViewLoginActivity::class.java)
|
||||||
RouterTransaction.with(
|
val bundle = Bundle()
|
||||||
WebViewLoginController(resources.getString(R.string.weblogin_url), false)
|
bundle.putString(BundleKeys.KEY_BASE_URL, resources.getString(R.string.weblogin_url))
|
||||||
)
|
intent.putExtras(bundle)
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
startActivity(intent)
|
||||||
.popChangeHandler(HorizontalChangeHandler())
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
router!!.setRoot(
|
val intent = Intent(context, ServerSelectionActivity::class.java)
|
||||||
RouterTransaction.with(ServerSelectionController())
|
startActivity(intent)
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(HorizontalChangeHandler())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isBrandingUrlSet() = !TextUtils.isEmpty(resources.getString(R.string.weblogin_url))
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
Log.d(TAG, "onStart: Activity: " + System.identityHashCode(this).toString())
|
Log.d(TAG, "onStart: Activity: " + System.identityHashCode(this).toString())
|
||||||
super.onStart()
|
super.onStart()
|
||||||
logRouterBackStack(router!!)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
@ -178,14 +160,6 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addAccount() {
|
|
||||||
router!!.pushController(
|
|
||||||
RouterTransaction.with(ServerSelectionController())
|
|
||||||
.pushChangeHandler(VerticalChangeHandler())
|
|
||||||
.popChangeHandler(VerticalChangeHandler())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleActionFromContact(intent: Intent) {
|
private fun handleActionFromContact(intent: Intent) {
|
||||||
if (intent.action == Intent.ACTION_VIEW && intent.data != null) {
|
if (intent.action == Intent.ACTION_VIEW && intent.data != null) {
|
||||||
val cursor = contentResolver.query(intent.data!!, null, null, null, null)
|
val cursor = contentResolver.query(intent.data!!, null, null, null, null)
|
||||||
|
@ -209,7 +183,7 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||||
startConversation(user)
|
startConversation(user)
|
||||||
} else {
|
} else {
|
||||||
Snackbar.make(
|
Snackbar.make(
|
||||||
binding.controllerContainer,
|
binding.root,
|
||||||
R.string.nc_phone_book_integration_account_not_found,
|
R.string.nc_phone_book_integration_account_not_found,
|
||||||
Snackbar.LENGTH_LONG
|
Snackbar.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
|
@ -283,28 +257,18 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user != null && userManager.setUserAsActive(user).blockingGet()) {
|
if (user != null && userManager.setUserAsActive(user).blockingGet()) {
|
||||||
// this should be avoided (it's still from conductor architecture). activities should be opened directly.
|
|
||||||
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
|
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
|
||||||
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
|
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
|
||||||
if (!router!!.hasRootController()) {
|
|
||||||
openConversationList()
|
|
||||||
}
|
|
||||||
val callNotificationIntent = Intent(this, CallNotificationActivity::class.java)
|
val callNotificationIntent = Intent(this, CallNotificationActivity::class.java)
|
||||||
intent.extras?.let { callNotificationIntent.putExtras(it) }
|
intent.extras?.let { callNotificationIntent.putExtras(it) }
|
||||||
startActivity(callNotificationIntent)
|
startActivity(callNotificationIntent)
|
||||||
} else {
|
} else {
|
||||||
logRouterBackStack(router!!)
|
|
||||||
|
|
||||||
val chatIntent = Intent(context, ChatActivity::class.java)
|
val chatIntent = Intent(context, ChatActivity::class.java)
|
||||||
chatIntent.putExtras(intent.extras!!)
|
chatIntent.putExtras(intent.extras!!)
|
||||||
startActivity(chatIntent)
|
startActivity(chatIntent)
|
||||||
|
|
||||||
logRouterBackStack(router!!)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (intent.hasExtra(ADD_ACCOUNT) && intent.getBooleanExtra(ADD_ACCOUNT, false)) {
|
} else {
|
||||||
addAccount()
|
|
||||||
} else if (!router!!.hasRootController()) {
|
|
||||||
if (!appPreferences.isDbRoomMigrated) {
|
if (!appPreferences.isDbRoomMigrated) {
|
||||||
appPreferences.isDbRoomMigrated = true
|
appPreferences.isDbRoomMigrated = true
|
||||||
}
|
}
|
||||||
|
@ -321,7 +285,7 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
launchLoginScreen()
|
launchServerSelection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,19 +297,7 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logRouterBackStack(router: Router) {
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
val backstack = router.backstack
|
|
||||||
var routerTransaction: RouterTransaction?
|
|
||||||
Log.d(TAG, " backstack size: " + router.backstackSize)
|
|
||||||
for (i in 0 until router.backstackSize) {
|
|
||||||
routerTransaction = backstack[i]
|
|
||||||
Log.d(TAG, " controller: " + routerTransaction.controller)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MainActivity"
|
private val TAG = MainActivity::class.java.simpleName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,6 +231,6 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) :
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = NextcloudTalkApplication::class.java.simpleName
|
private val TAG = IncomingPollMessageViewHolder::class.java.simpleName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,6 +209,6 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) :
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = NextcloudTalkApplication::class.java.simpleName
|
private val TAG = OutcomingPollMessageViewHolder::class.java.simpleName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.nextcloud.talk.controllers.bottomsheet.items
|
package com.nextcloud.talk.bottomsheet.items
|
||||||
|
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
|
@ -18,7 +18,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.nextcloud.talk.controllers.bottomsheet.items
|
package com.nextcloud.talk.bottomsheet.items
|
||||||
|
|
||||||
import androidx.annotation.CheckResult
|
import androidx.annotation.CheckResult
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
|
@ -18,7 +18,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.nextcloud.talk.controllers.bottomsheet.items
|
package com.nextcloud.talk.bottomsheet.items
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
|
@ -317,7 +317,7 @@ class CallNotificationActivity : CallBaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun suppressFitsSystemWindows() {
|
override fun suppressFitsSystemWindows() {
|
||||||
binding!!.controllerCallNotificationLayout.fitsSystemWindows = false
|
binding!!.callNotificationLayout.fitsSystemWindows = false
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -1605,7 +1605,7 @@ class ChatActivity :
|
||||||
participantPermissions.hasChatPermission() &&
|
participantPermissions.hasChatPermission() &&
|
||||||
!isReadOnlyConversation()
|
!isReadOnlyConversation()
|
||||||
) {
|
) {
|
||||||
val messageSwipeController = MessageSwipeCallback(
|
val messageSwipeCallback = MessageSwipeCallback(
|
||||||
this,
|
this,
|
||||||
object : MessageSwipeActions {
|
object : MessageSwipeActions {
|
||||||
override fun showReplyUI(position: Int) {
|
override fun showReplyUI(position: Int) {
|
||||||
|
@ -1617,7 +1617,7 @@ class ChatActivity :
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
val itemTouchHelper = ItemTouchHelper(messageSwipeController)
|
val itemTouchHelper = ItemTouchHelper(messageSwipeCallback)
|
||||||
itemTouchHelper.attachToRecyclerView(binding.messagesListView)
|
itemTouchHelper.attachToRecyclerView(binding.messagesListView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2561,7 +2561,7 @@ class ChatActivity :
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
if (requestCode == UploadAndShareFilesWorker.REQUEST_PERMISSION) {
|
if (requestCode == UploadAndShareFilesWorker.REQUEST_PERMISSION) {
|
||||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
Log.d(ConversationsListActivity.TAG, "upload starting after permissions were granted")
|
Log.d(TAG, "upload starting after permissions were granted")
|
||||||
if (filesToUpload.isNotEmpty()) {
|
if (filesToUpload.isNotEmpty()) {
|
||||||
uploadFiles(filesToUpload)
|
uploadFiles(filesToUpload)
|
||||||
}
|
}
|
||||||
|
|
|
@ -488,17 +488,13 @@ class ContactsActivity :
|
||||||
} else {
|
} else {
|
||||||
adapter?.filterItems()
|
adapter?.filterItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.controllerGenericRv.swipeRefreshLayout.isRefreshing = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
binding.controllerGenericRv.swipeRefreshLayout.isRefreshing = false
|
|
||||||
dispose(contactsQueryDisposable)
|
dispose(contactsQueryDisposable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onComplete() {
|
override fun onComplete() {
|
||||||
binding.controllerGenericRv.swipeRefreshLayout.isRefreshing = false
|
|
||||||
dispose(contactsQueryDisposable)
|
dispose(contactsQueryDisposable)
|
||||||
alreadyFetching = false
|
alreadyFetching = false
|
||||||
disengageProgressBar()
|
disengageProgressBar()
|
||||||
|
@ -656,12 +652,9 @@ class ContactsActivity :
|
||||||
|
|
||||||
private fun prepareViews() {
|
private fun prepareViews() {
|
||||||
layoutManager = SmoothScrollLinearLayoutManager(this)
|
layoutManager = SmoothScrollLinearLayoutManager(this)
|
||||||
binding.controllerGenericRv.recyclerView.layoutManager = layoutManager
|
binding.contactsRv.layoutManager = layoutManager
|
||||||
binding.controllerGenericRv.recyclerView.setHasFixedSize(true)
|
binding.contactsRv.setHasFixedSize(true)
|
||||||
binding.controllerGenericRv.recyclerView.adapter = adapter
|
binding.contactsRv.adapter = adapter
|
||||||
binding.controllerGenericRv.swipeRefreshLayout.setOnRefreshListener { fetchData() }
|
|
||||||
|
|
||||||
binding.controllerGenericRv.let { viewThemeUtils.androidx.themeSwipeRefreshLayout(it.swipeRefreshLayout) }
|
|
||||||
|
|
||||||
binding.listOpenConversationsImage.background?.setColorFilter(
|
binding.listOpenConversationsImage.background?.setColorFilter(
|
||||||
ResourcesCompat.getColor(resources!!, R.color.colorBackgroundDarker, null),
|
ResourcesCompat.getColor(resources!!, R.color.colorBackgroundDarker, null),
|
||||||
|
@ -677,7 +670,7 @@ class ContactsActivity :
|
||||||
private fun disengageProgressBar() {
|
private fun disengageProgressBar() {
|
||||||
if (!alreadyFetching) {
|
if (!alreadyFetching) {
|
||||||
binding.loadingContent.visibility = View.GONE
|
binding.loadingContent.visibility = View.GONE
|
||||||
binding.controllerGenericRv.root.visibility = View.VISIBLE
|
binding.root.visibility = View.VISIBLE
|
||||||
if (isNewConversationView) {
|
if (isNewConversationView) {
|
||||||
binding.callHeaderLayout.visibility = View.VISIBLE
|
binding.callHeaderLayout.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
@ -713,8 +706,6 @@ class ContactsActivity :
|
||||||
adapter?.updateDataSet(contactItems as List<Nothing>?)
|
adapter?.updateDataSet(contactItems as List<Nothing>?)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.controllerGenericRv?.swipeRefreshLayout?.isEnabled = !adapter!!.hasFilter()
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,256 +0,0 @@
|
||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Mario Danic
|
|
||||||
* @author Andy Scherzinger
|
|
||||||
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
|
||||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.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 com.nextcloud.talk.controllers
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.media.MediaPlayer
|
|
||||||
import android.media.RingtoneManager
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Handler
|
|
||||||
import android.text.TextUtils
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.View
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
|
||||||
import com.nextcloud.talk.R
|
|
||||||
import com.nextcloud.talk.adapters.items.NotificationSoundItem
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
|
||||||
import com.nextcloud.talk.controllers.base.BaseController
|
|
||||||
import com.nextcloud.talk.controllers.util.viewBinding
|
|
||||||
import com.nextcloud.talk.databinding.ControllerGenericRvBinding
|
|
||||||
import com.nextcloud.talk.models.RingtoneSettings
|
|
||||||
import com.nextcloud.talk.utils.NotificationUtils
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ARE_CALL_SOUNDS
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
|
||||||
import eu.davidea.flexibleadapter.SelectableAdapter
|
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class RingtoneSelectionController(args: Bundle) :
|
|
||||||
BaseController(
|
|
||||||
R.layout.controller_generic_rv,
|
|
||||||
args
|
|
||||||
),
|
|
||||||
FlexibleAdapter.OnItemClickListener {
|
|
||||||
private val binding: ControllerGenericRvBinding? by viewBinding(ControllerGenericRvBinding::bind)
|
|
||||||
|
|
||||||
private var adapter: FlexibleAdapter<*>? = null
|
|
||||||
private var adapterDataObserver: RecyclerView.AdapterDataObserver? = null
|
|
||||||
private val abstractFlexibleItemList: MutableList<AbstractFlexibleItem<*>> = ArrayList()
|
|
||||||
private val callNotificationSounds: Boolean
|
|
||||||
private var mediaPlayer: MediaPlayer? = null
|
|
||||||
private var cancelMediaPlayerHandler: Handler? = null
|
|
||||||
|
|
||||||
override fun onViewBound(view: View) {
|
|
||||||
super.onViewBound(view)
|
|
||||||
if (adapter == null) {
|
|
||||||
adapter = FlexibleAdapter(abstractFlexibleItemList, activity, false)
|
|
||||||
adapter!!.setNotifyChangeOfUnfilteredItems(true).mode = SelectableAdapter.Mode.SINGLE
|
|
||||||
adapter!!.addListener(this)
|
|
||||||
cancelMediaPlayerHandler = Handler()
|
|
||||||
}
|
|
||||||
adapter!!.addListener(this)
|
|
||||||
prepareViews()
|
|
||||||
fetchNotificationSounds()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
return if (item.itemId == android.R.id.home) {
|
|
||||||
router.popCurrentController()
|
|
||||||
} else {
|
|
||||||
super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareViews() {
|
|
||||||
val layoutManager: RecyclerView.LayoutManager = SmoothScrollLinearLayoutManager(activity)
|
|
||||||
binding?.recyclerView?.layoutManager = layoutManager
|
|
||||||
binding?.recyclerView?.setHasFixedSize(true)
|
|
||||||
binding?.recyclerView?.adapter = adapter
|
|
||||||
adapterDataObserver = object : RecyclerView.AdapterDataObserver() {
|
|
||||||
override fun onChanged() {
|
|
||||||
super.onChanged()
|
|
||||||
findSelectedSound()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adapter!!.registerAdapterDataObserver(adapterDataObserver!!)
|
|
||||||
binding?.swipeRefreshLayout?.isEnabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("LongLogTag")
|
|
||||||
private fun findSelectedSound() {
|
|
||||||
var foundDefault = false
|
|
||||||
var preferencesString: String? = null
|
|
||||||
val callsEnabledButNoRingtone = callNotificationSounds &&
|
|
||||||
TextUtils.isEmpty(appPreferences.callRingtoneUri.also { preferencesString = it })
|
|
||||||
val noCallsAndNoMessageTone = !callNotificationSounds &&
|
|
||||||
TextUtils.isEmpty(appPreferences.messageRingtoneUri.also { preferencesString = it })
|
|
||||||
if (callsEnabledButNoRingtone || noCallsAndNoMessageTone) {
|
|
||||||
adapter!!.toggleSelection(1)
|
|
||||||
foundDefault = true
|
|
||||||
}
|
|
||||||
if (!TextUtils.isEmpty(preferencesString) && !foundDefault) {
|
|
||||||
try {
|
|
||||||
val ringtoneSettings: RingtoneSettings =
|
|
||||||
LoganSquare.parse<RingtoneSettings>(preferencesString, RingtoneSettings::class.java)
|
|
||||||
if (ringtoneSettings.ringtoneUri == null) {
|
|
||||||
adapter!!.toggleSelection(0)
|
|
||||||
} else if (ringtoneSettings.ringtoneUri!!.toString() == ringtoneString) {
|
|
||||||
adapter!!.toggleSelection(1)
|
|
||||||
} else {
|
|
||||||
var notificationSoundItem: NotificationSoundItem?
|
|
||||||
for (i in 2 until adapter!!.itemCount) {
|
|
||||||
notificationSoundItem = adapter!!.getItem(i) as NotificationSoundItem?
|
|
||||||
if (
|
|
||||||
notificationSoundItem!!.notificationSoundUri == ringtoneSettings.ringtoneUri!!.toString()
|
|
||||||
) {
|
|
||||||
adapter!!.toggleSelection(i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
|
||||||
Log.e(TAG, "Failed to parse ringtone settings")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adapter!!.unregisterAdapterDataObserver(adapterDataObserver!!)
|
|
||||||
adapterDataObserver = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private val ringtoneString: String
|
|
||||||
get() = if (callNotificationSounds) {
|
|
||||||
NotificationUtils.DEFAULT_CALL_RINGTONE_URI
|
|
||||||
} else {
|
|
||||||
NotificationUtils.DEFAULT_MESSAGE_RINGTONE_URI
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fetchNotificationSounds() {
|
|
||||||
abstractFlexibleItemList.add(
|
|
||||||
NotificationSoundItem(
|
|
||||||
resources!!.getString(R.string.nc_settings_no_ringtone),
|
|
||||||
null
|
|
||||||
)
|
|
||||||
)
|
|
||||||
abstractFlexibleItemList.add(
|
|
||||||
NotificationSoundItem(
|
|
||||||
resources!!.getString(R.string.nc_settings_default_ringtone),
|
|
||||||
ringtoneString
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if (activity != null) {
|
|
||||||
val manager = RingtoneManager(activity)
|
|
||||||
if (callNotificationSounds) {
|
|
||||||
manager.setType(RingtoneManager.TYPE_RINGTONE)
|
|
||||||
} else {
|
|
||||||
manager.setType(RingtoneManager.TYPE_NOTIFICATION)
|
|
||||||
}
|
|
||||||
val cursor = manager.cursor
|
|
||||||
var notificationSoundItem: NotificationSoundItem
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
val notificationTitle = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX)
|
|
||||||
val notificationUri = cursor.getString(RingtoneManager.URI_COLUMN_INDEX)
|
|
||||||
val completeNotificationUri = notificationUri + "/" + cursor.getString(RingtoneManager.ID_COLUMN_INDEX)
|
|
||||||
notificationSoundItem = NotificationSoundItem(notificationTitle, completeNotificationUri)
|
|
||||||
abstractFlexibleItemList.add(notificationSoundItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adapter!!.updateDataSet(abstractFlexibleItemList as List<Nothing>?, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemClick(view: View, position: Int): Boolean {
|
|
||||||
val notificationSoundItem = adapter!!.getItem(position) as NotificationSoundItem?
|
|
||||||
var ringtoneUri: Uri? = null
|
|
||||||
if (!TextUtils.isEmpty(notificationSoundItem!!.notificationSoundUri)) {
|
|
||||||
ringtoneUri = Uri.parse(notificationSoundItem.notificationSoundUri)
|
|
||||||
endMediaPlayer()
|
|
||||||
mediaPlayer = MediaPlayer.create(activity, ringtoneUri)
|
|
||||||
cancelMediaPlayerHandler = Handler()
|
|
||||||
cancelMediaPlayerHandler!!.postDelayed(
|
|
||||||
{ endMediaPlayer() },
|
|
||||||
(mediaPlayer!!.duration + DURATION_EXTENSION).toLong()
|
|
||||||
)
|
|
||||||
mediaPlayer!!.start()
|
|
||||||
}
|
|
||||||
if (adapter!!.selectedPositions.size == 0 || adapter!!.selectedPositions[0] != position) {
|
|
||||||
val ringtoneSettings = RingtoneSettings()
|
|
||||||
ringtoneSettings.ringtoneName = notificationSoundItem.notificationSoundName
|
|
||||||
ringtoneSettings.ringtoneUri = ringtoneUri
|
|
||||||
if (callNotificationSounds) {
|
|
||||||
try {
|
|
||||||
appPreferences!!.callRingtoneUri = LoganSquare.serialize(ringtoneSettings)
|
|
||||||
adapter!!.toggleSelection(position)
|
|
||||||
adapter!!.notifyDataSetChanged()
|
|
||||||
} catch (e: IOException) {
|
|
||||||
Log.e(TAG, "Failed to store selected ringtone for calls")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
appPreferences!!.messageRingtoneUri = LoganSquare.serialize(ringtoneSettings)
|
|
||||||
adapter!!.toggleSelection(position)
|
|
||||||
adapter!!.notifyDataSetChanged()
|
|
||||||
} catch (e: IOException) {
|
|
||||||
Log.e(TAG, "Failed to store selected ringtone for calls")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun endMediaPlayer() {
|
|
||||||
if (cancelMediaPlayerHandler != null) {
|
|
||||||
cancelMediaPlayerHandler!!.removeCallbacksAndMessages(null)
|
|
||||||
}
|
|
||||||
if (mediaPlayer != null) {
|
|
||||||
if (mediaPlayer!!.isPlaying) {
|
|
||||||
mediaPlayer!!.stop()
|
|
||||||
}
|
|
||||||
mediaPlayer!!.release()
|
|
||||||
mediaPlayer = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onDestroy() {
|
|
||||||
endMediaPlayer()
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "RingtoneSelection"
|
|
||||||
private const val DURATION_EXTENSION = 25
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
setHasOptionsMenu(true)
|
|
||||||
sharedApplication!!.componentApplication.inject(this)
|
|
||||||
callNotificationSounds = args.getBoolean(KEY_ARE_CALL_SOUNDS, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val title: String
|
|
||||||
get() =
|
|
||||||
resources!!.getString(R.string.nc_settings_notification_sounds)
|
|
||||||
}
|
|
|
@ -1,309 +0,0 @@
|
||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Andy Scherzinger
|
|
||||||
* @author BlueLine Labs, Inc.
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2021 Andy Scherzinger (info@andy-scherzinger.de)
|
|
||||||
* Copyright (C) 2021 BlueLine Labs, Inc.
|
|
||||||
* Copyright (C) 2020 Mario Danic (mario@lovelyhq.com)
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.nextcloud.talk.controllers.base
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.inputmethod.EditorInfo
|
|
||||||
import android.view.inputmethod.InputMethodManager
|
|
||||||
import android.widget.EditText
|
|
||||||
import androidx.annotation.LayoutRes
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.appcompat.app.ActionBar
|
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.bluelinelabs.conductor.Controller
|
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
|
||||||
import com.bluelinelabs.conductor.ControllerChangeType
|
|
||||||
import com.nextcloud.talk.R
|
|
||||||
import com.nextcloud.talk.activities.MainActivity
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
|
||||||
import com.nextcloud.talk.controllers.AccountVerificationController
|
|
||||||
import com.nextcloud.talk.controllers.ServerSelectionController
|
|
||||||
import com.nextcloud.talk.controllers.SwitchAccountController
|
|
||||||
import com.nextcloud.talk.controllers.WebViewLoginController
|
|
||||||
import com.nextcloud.talk.controllers.base.providers.ActionBarProvider
|
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
|
||||||
import javax.inject.Inject
|
|
||||||
import kotlin.jvm.internal.Intrinsics
|
|
||||||
|
|
||||||
// TODO: check what needs to be migrated from this class to BaseActivity etc when conductor is removed
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
abstract class BaseController(@LayoutRes var layoutRes: Int, args: Bundle? = null) : Controller(args) {
|
|
||||||
enum class AppBarLayoutType {
|
|
||||||
TOOLBAR, SEARCH_BAR, EMPTY
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var appPreferences: AppPreferences
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var context: Context
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var viewThemeUtils: ViewThemeUtils
|
|
||||||
|
|
||||||
protected open val title: String?
|
|
||||||
get() = null
|
|
||||||
|
|
||||||
@Suppress("Detekt.TooGenericExceptionCaught")
|
|
||||||
protected val actionBar: ActionBar?
|
|
||||||
get() {
|
|
||||||
var actionBarProvider: ActionBarProvider? = null
|
|
||||||
if (this.activity is ActionBarProvider) {
|
|
||||||
try {
|
|
||||||
actionBarProvider = this.activity as ActionBarProvider?
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.d(TAG, "Failed to fetch the action bar provider", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return actionBarProvider?.supportActionBar
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
@Suppress("LeakingThis")
|
|
||||||
sharedApplication!!.componentApplication.inject(this)
|
|
||||||
addLifecycleListener(object : LifecycleListener() {
|
|
||||||
override fun postCreateView(controller: Controller, view: View) {
|
|
||||||
onViewBound(view)
|
|
||||||
actionBar?.let { setTitle() }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
cleanTempCertPreference()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isAlive(): Boolean {
|
|
||||||
return !isDestroyed && !isBeingDestroyed
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup,
|
|
||||||
savedViewState: Bundle?
|
|
||||||
): View {
|
|
||||||
return inflater.inflate(layoutRes, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected open fun onViewBound(view: View) {
|
|
||||||
var activity: MainActivity? = null
|
|
||||||
|
|
||||||
// if (getActivity() != null && getActivity() is MainActivity) {
|
|
||||||
// activity = getActivity() as MainActivity?
|
|
||||||
// viewThemeUtils.material.themeCardView(activity!!.binding.searchToolbar)
|
|
||||||
// viewThemeUtils.material.themeToolbar(activity.binding.toolbar)
|
|
||||||
// viewThemeUtils.material.themeSearchBarText(activity.binding.searchText)
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.isKeyboardIncognito) {
|
|
||||||
disableKeyboardPersonalisedLearning((view as ViewGroup))
|
|
||||||
if (activity != null) {
|
|
||||||
disableKeyboardPersonalisedLearning(activity.binding.appBar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAttach(view: View) {
|
|
||||||
// showSearchOrToolbar()
|
|
||||||
setTitle()
|
|
||||||
if (actionBar != null) {
|
|
||||||
actionBar!!.setDisplayHomeAsUpEnabled(parentController != null || router.backstackSize >= 1)
|
|
||||||
}
|
|
||||||
super.onAttach(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
// open fun showSearchOrToolbar() {
|
|
||||||
// if (isValidActivity(activity)) {
|
|
||||||
// val showSearchBar = appBarLayoutType == AppBarLayoutType.SEARCH_BAR
|
|
||||||
// val activity = activity as MainActivity
|
|
||||||
//
|
|
||||||
// if (appBarLayoutType == AppBarLayoutType.EMPTY) {
|
|
||||||
// hideBars(activity.binding)
|
|
||||||
// } else {
|
|
||||||
// if (showSearchBar) {
|
|
||||||
// showSearchBar(activity.binding)
|
|
||||||
// } else {
|
|
||||||
// showToolbar(activity.binding)
|
|
||||||
// }
|
|
||||||
// colorizeStatusBar(showSearchBar, activity, resources)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// colorizeNavigationBar(activity, resources)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private fun isValidActivity(activity: Activity?): Boolean {
|
|
||||||
// return activity != null && activity is MainActivity
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private fun showSearchBar(binding: ActivityMainBinding) {
|
|
||||||
// val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams
|
|
||||||
// binding.searchToolbar.visibility = View.VISIBLE
|
|
||||||
// binding.searchText.hint = searchHint
|
|
||||||
// binding.toolbar.visibility = View.GONE
|
|
||||||
// // layoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout
|
|
||||||
// // .LayoutParams.SCROLL_FLAG_SNAP | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
|
|
||||||
// layoutParams.scrollFlags = 0
|
|
||||||
// binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator(
|
|
||||||
// binding.appBar.context,
|
|
||||||
// R.animator.appbar_elevation_off
|
|
||||||
// )
|
|
||||||
// binding.searchToolbar.layoutParams = layoutParams
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private fun showToolbar(binding: ActivityMainBinding) {
|
|
||||||
// val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams
|
|
||||||
// binding.searchToolbar.visibility = View.GONE
|
|
||||||
// binding.toolbar.visibility = View.VISIBLE
|
|
||||||
// viewThemeUtils.material.colorToolbarOverflowIcon(binding.toolbar)
|
|
||||||
// layoutParams.scrollFlags = 0
|
|
||||||
// binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator(
|
|
||||||
// binding.appBar.context,
|
|
||||||
// R.animator.appbar_elevation_on
|
|
||||||
// )
|
|
||||||
// binding.searchToolbar.layoutParams = layoutParams
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private fun hideBars(binding: ActivityMainBinding) {
|
|
||||||
// binding.toolbar.visibility = View.GONE
|
|
||||||
// binding.searchToolbar.visibility = View.GONE
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun hideSearchBar() {
|
|
||||||
// val activity = activity as MainActivity?
|
|
||||||
// val layoutParams = activity!!.binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams
|
|
||||||
// activity.binding.searchToolbar.visibility = View.GONE
|
|
||||||
// activity.binding.toolbar.visibility = View.VISIBLE
|
|
||||||
// layoutParams.scrollFlags = 0
|
|
||||||
// activity.binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator(
|
|
||||||
// activity.binding.appBar.context,
|
|
||||||
// R.animator.appbar_elevation_on
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private fun colorizeStatusBar(showSearchBar: Boolean, activity: Activity?, resources: Resources?) {
|
|
||||||
// if (activity != null && resources != null) {
|
|
||||||
// if (showSearchBar) {
|
|
||||||
// view?.let { viewThemeUtils.platform.resetStatusBar(activity) }
|
|
||||||
// } else {
|
|
||||||
// view?.let { viewThemeUtils.platform.themeStatusBar(activity, it) }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private fun colorizeNavigationBar(activity: Activity?, resources: Resources?) {
|
|
||||||
// if (activity != null && resources != null) {
|
|
||||||
// DisplayUtils.applyColorToNavigationBar(
|
|
||||||
// activity.window,
|
|
||||||
// ResourcesCompat.getColor(resources, R.color.bg_default, null)
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
override fun onDetach(view: View) {
|
|
||||||
super.onDetach(view)
|
|
||||||
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
|
||||||
imm.hideSoftInputFromWindow(view.windowToken, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun setTitle() {
|
|
||||||
if (isTitleSetable()) {
|
|
||||||
run {
|
|
||||||
calculateValidParentController()
|
|
||||||
}
|
|
||||||
actionBar!!.title = title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun calculateValidParentController() {
|
|
||||||
var parentController = parentController
|
|
||||||
while (parentController != null) {
|
|
||||||
parentController = parentController.parentController
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isTitleSetable(): Boolean {
|
|
||||||
return title != null && actionBar != null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
if (item.itemId == android.R.id.home) {
|
|
||||||
router.popCurrentController()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onChangeStarted(changeHandler: ControllerChangeHandler, changeType: ControllerChangeType) {
|
|
||||||
super.onChangeStarted(changeHandler, changeType)
|
|
||||||
if (changeType.isEnter && actionBar != null) {
|
|
||||||
configureMenu(actionBar!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun configureMenu(toolbar: ActionBar) {
|
|
||||||
Intrinsics.checkNotNullParameter(toolbar, "toolbar")
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check if this must be migrated when using activities instead of conductor
|
|
||||||
private fun cleanTempCertPreference() {
|
|
||||||
val temporaryClassNames: MutableList<String> = ArrayList()
|
|
||||||
temporaryClassNames.add(ServerSelectionController::class.java.name)
|
|
||||||
temporaryClassNames.add(AccountVerificationController::class.java.name)
|
|
||||||
temporaryClassNames.add(WebViewLoginController::class.java.name)
|
|
||||||
temporaryClassNames.add(SwitchAccountController::class.java.name)
|
|
||||||
if (!temporaryClassNames.contains(javaClass.name)) {
|
|
||||||
appPreferences.removeTemporaryClientCertAlias()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
||||||
private fun disableKeyboardPersonalisedLearning(viewGroup: ViewGroup) {
|
|
||||||
var view: View?
|
|
||||||
var editText: EditText
|
|
||||||
for (i in 0 until viewGroup.childCount) {
|
|
||||||
view = viewGroup.getChildAt(i)
|
|
||||||
if (view is EditText) {
|
|
||||||
editText = view
|
|
||||||
editText.imeOptions = editText.imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
|
|
||||||
} else if (view is ViewGroup) {
|
|
||||||
disableKeyboardPersonalisedLearning(view)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open val appBarLayoutType: AppBarLayoutType
|
|
||||||
get() = AppBarLayoutType.TOOLBAR
|
|
||||||
val searchHint: String
|
|
||||||
get() = context.getString(R.string.appbar_search_in, context.getString(R.string.nc_app_product_name))
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val TAG = BaseController::class.java.simpleName
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author BlueLine Labs, Inc.
|
|
||||||
* Copyright (C) 2016 BlueLine Labs, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.nextcloud.talk.controllers.util
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import androidx.lifecycle.LifecycleObserver
|
|
||||||
import androidx.viewbinding.ViewBinding
|
|
||||||
import com.bluelinelabs.conductor.Controller
|
|
||||||
import kotlin.properties.ReadOnlyProperty
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
fun <T : ViewBinding> Controller.viewBinding(bindingFactory: (View) -> T) =
|
|
||||||
ControllerViewBindingDelegate(this, bindingFactory)
|
|
||||||
|
|
||||||
class ControllerViewBindingDelegate<T : ViewBinding>(
|
|
||||||
controller: Controller,
|
|
||||||
private val viewBinder: (View) -> T
|
|
||||||
) : ReadOnlyProperty<Controller, T?>, LifecycleObserver {
|
|
||||||
|
|
||||||
private var binding: T? = null
|
|
||||||
|
|
||||||
init {
|
|
||||||
controller.addLifecycleListener(object : Controller.LifecycleListener() {
|
|
||||||
override fun postDestroyView(controller: Controller) {
|
|
||||||
binding = null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getValue(thisRef: Controller, property: KProperty<*>): T? {
|
|
||||||
if (binding == null) {
|
|
||||||
binding = thisRef.view?.let { viewBinder(it) }
|
|
||||||
}
|
|
||||||
return binding
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -58,8 +58,8 @@ import com.nextcloud.talk.adapters.items.ParticipantItem
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.contacts.ContactsActivity
|
import com.nextcloud.talk.contacts.ContactsActivity
|
||||||
import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
|
import com.nextcloud.talk.bottomsheet.items.BasicListItemWithImage
|
||||||
import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
|
import com.nextcloud.talk.bottomsheet.items.listItemsWithImage
|
||||||
import com.nextcloud.talk.conversationinfoedit.ConversationInfoEditActivity
|
import com.nextcloud.talk.conversationinfoedit.ConversationInfoEditActivity
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ActivityConversationInfoBinding
|
import com.nextcloud.talk.databinding.ActivityConversationInfoBinding
|
||||||
|
|
|
@ -50,6 +50,7 @@ import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
|
@ -71,8 +72,11 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.nextcloud.android.common.ui.theme.utils.ColorRole
|
import com.nextcloud.android.common.ui.theme.utils.ColorRole
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.account.ServerSelectionActivity
|
||||||
|
import com.nextcloud.talk.account.WebViewLoginActivity
|
||||||
import com.nextcloud.talk.activities.BaseActivity
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
import com.nextcloud.talk.activities.CallActivity
|
import com.nextcloud.talk.activities.CallActivity
|
||||||
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
import com.nextcloud.talk.adapters.items.ConversationItem
|
import com.nextcloud.talk.adapters.items.ConversationItem
|
||||||
import com.nextcloud.talk.adapters.items.GenericTextHeaderItem
|
import com.nextcloud.talk.adapters.items.GenericTextHeaderItem
|
||||||
import com.nextcloud.talk.adapters.items.LoadMoreResultsItem
|
import com.nextcloud.talk.adapters.items.LoadMoreResultsItem
|
||||||
|
@ -84,7 +88,7 @@ import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
||||||
import com.nextcloud.talk.chat.ChatActivity
|
import com.nextcloud.talk.chat.ChatActivity
|
||||||
import com.nextcloud.talk.contacts.ContactsActivity
|
import com.nextcloud.talk.contacts.ContactsActivity
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ControllerConversationsRvBinding
|
import com.nextcloud.talk.databinding.ActivityConversationsBinding
|
||||||
import com.nextcloud.talk.events.ConversationsListFetchDataEvent
|
import com.nextcloud.talk.events.ConversationsListFetchDataEvent
|
||||||
import com.nextcloud.talk.events.EventStatus
|
import com.nextcloud.talk.events.EventStatus
|
||||||
import com.nextcloud.talk.jobs.AccountRemovalWorker
|
import com.nextcloud.talk.jobs.AccountRemovalWorker
|
||||||
|
@ -109,6 +113,7 @@ import com.nextcloud.talk.utils.Mimetype
|
||||||
import com.nextcloud.talk.utils.ParticipantPermissions
|
import com.nextcloud.talk.utils.ParticipantPermissions
|
||||||
import com.nextcloud.talk.utils.UserIdUtils
|
import com.nextcloud.talk.utils.UserIdUtils
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys.ADD_ADDITIONAL_ACCOUNT
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FORWARD_HIDE_SOURCE_ROOM
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FORWARD_HIDE_SOURCE_ROOM
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FORWARD_MSG_FLAG
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FORWARD_MSG_FLAG
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FORWARD_MSG_TEXT
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FORWARD_MSG_TEXT
|
||||||
|
@ -146,7 +151,7 @@ class ConversationsListActivity :
|
||||||
FlexibleAdapter.OnItemClickListener,
|
FlexibleAdapter.OnItemClickListener,
|
||||||
FlexibleAdapter.OnItemLongClickListener {
|
FlexibleAdapter.OnItemLongClickListener {
|
||||||
|
|
||||||
private lateinit var binding: ControllerConversationsRvBinding
|
private lateinit var binding: ActivityConversationsBinding
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var userManager: UserManager
|
lateinit var userManager: UserManager
|
||||||
|
@ -202,7 +207,6 @@ class ConversationsListActivity :
|
||||||
|
|
||||||
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||||
override fun handleOnBackPressed() {
|
override fun handleOnBackPressed() {
|
||||||
// TODO: replace this when conductor is removed. For now it avoids to load the MainActiviy which has no UI.
|
|
||||||
finishAffinity()
|
finishAffinity()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,7 +215,7 @@ class ConversationsListActivity :
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||||
|
|
||||||
binding = ControllerConversationsRvBinding.inflate(layoutInflater)
|
binding = ActivityConversationsBinding.inflate(layoutInflater)
|
||||||
setupActionBar()
|
setupActionBar()
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setupSystemColors()
|
setupSystemColors()
|
||||||
|
@ -740,11 +744,20 @@ class ConversationsListActivity :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resources!!.getBoolean(R.bool.multiaccount_support)) {
|
||||||
|
dialogBuilder.setNeutralButton(R.string.nc_account_chooser_add_account) { _, _ ->
|
||||||
|
val intent = Intent(this, ServerSelectionActivity::class.java)
|
||||||
|
intent.putExtra(ADD_ADDITIONAL_ACCOUNT, true)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder)
|
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder)
|
||||||
val dialog = dialogBuilder.show()
|
val dialog = dialogBuilder.show()
|
||||||
viewThemeUtils.platform.colorTextButtons(
|
viewThemeUtils.platform.colorTextButtons(
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||||
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
|
dialog.getButton(AlertDialog.BUTTON_NEGATIVE),
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -819,10 +832,10 @@ class ConversationsListActivity :
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private fun prepareViews() {
|
private fun prepareViews() {
|
||||||
layoutManager = SmoothScrollLinearLayoutManager(this)
|
layoutManager = SmoothScrollLinearLayoutManager(this)
|
||||||
binding?.recyclerView?.layoutManager = layoutManager
|
binding.recyclerView.layoutManager = layoutManager
|
||||||
binding?.recyclerView?.setHasFixedSize(true)
|
binding.recyclerView.setHasFixedSize(true)
|
||||||
binding?.recyclerView?.adapter = adapter
|
binding.recyclerView.adapter = adapter
|
||||||
binding?.recyclerView?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||||
super.onScrollStateChanged(recyclerView, newState)
|
super.onScrollStateChanged(recyclerView, newState)
|
||||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||||
|
@ -1131,7 +1144,7 @@ class ConversationsListActivity :
|
||||||
selectedConversation!!.displayName
|
selectedConversation!!.displayName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
binding?.floatingActionButton?.let {
|
binding.floatingActionButton.let {
|
||||||
val dialogBuilder = MaterialAlertDialogBuilder(it.context)
|
val dialogBuilder = MaterialAlertDialogBuilder(it.context)
|
||||||
.setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.upload))
|
.setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.upload))
|
||||||
.setTitle(confirmationQuestion)
|
.setTitle(confirmationQuestion)
|
||||||
|
@ -1358,30 +1371,17 @@ class ConversationsListActivity :
|
||||||
.setTitle(R.string.nc_dialog_invalid_password)
|
.setTitle(R.string.nc_dialog_invalid_password)
|
||||||
.setMessage(R.string.nc_dialog_reauth_or_delete)
|
.setMessage(R.string.nc_dialog_reauth_or_delete)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(R.string.nc_delete) { _, _ ->
|
.setPositiveButton(R.string.nc_settings_remove_account) { _, _ ->
|
||||||
val otherUserExists = userManager
|
deleteUserAndRestartApp()
|
||||||
.scheduleUserForDeletionWithId(currentUser!!.id!!)
|
}
|
||||||
.blockingGet()
|
.setNegativeButton(R.string.nc_settings_reauthorize) { _, _ ->
|
||||||
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
|
val intent = Intent(context, WebViewLoginActivity::class.java)
|
||||||
WorkManager.getInstance().enqueue(accountRemovalWork)
|
val bundle = Bundle()
|
||||||
if (otherUserExists) {
|
bundle.putString(BundleKeys.KEY_BASE_URL, currentUser!!.baseUrl)
|
||||||
finish()
|
bundle.putBoolean(BundleKeys.KEY_REAUTHORIZE_ACCOUNT, true)
|
||||||
|
intent.putExtras(bundle)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
} else if (!otherUserExists) {
|
|
||||||
Log.d(TAG, "No other users found. AccountRemovalWorker will restart the app.")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: show negative button again when conductor is removed
|
|
||||||
// .setNegativeButton(R.string.nc_settings_reauthorize) { _, _ ->
|
|
||||||
// // router.pushController(
|
|
||||||
// // RouterTransaction.with(
|
|
||||||
// // WebViewLoginController(currentUser!!.baseUrl, true)
|
|
||||||
// // )
|
|
||||||
// // .pushChangeHandler(VerticalChangeHandler())
|
|
||||||
// // .popChangeHandler(VerticalChangeHandler())
|
|
||||||
// // )
|
|
||||||
// }
|
|
||||||
|
|
||||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder)
|
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder)
|
||||||
val dialog = dialogBuilder.show()
|
val dialog = dialogBuilder.show()
|
||||||
|
@ -1392,6 +1392,50 @@ class ConversationsListActivity :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private fun deleteUserAndRestartApp() {
|
||||||
|
userManager.scheduleUserForDeletionWithId(currentUser!!.id!!).blockingGet()
|
||||||
|
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
|
||||||
|
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
||||||
|
|
||||||
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
||||||
|
.observeForever { workInfo: WorkInfo ->
|
||||||
|
|
||||||
|
when (workInfo.state) {
|
||||||
|
WorkInfo.State.SUCCEEDED -> {
|
||||||
|
val text = String.format(
|
||||||
|
context.resources.getString(R.string.nc_deleted_user),
|
||||||
|
currentUser!!.displayName
|
||||||
|
)
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
text,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
restartApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkInfo.State.FAILED, WorkInfo.State.CANCELLED -> {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context.resources.getString(R.string.nc_common_error_sorry),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
Log.e(TAG, "something went wrong when deleting user with id " + currentUser!!.userId)
|
||||||
|
restartApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun restartApp() {
|
||||||
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
private fun showOutdatedClientDialog() {
|
private fun showOutdatedClientDialog() {
|
||||||
binding.floatingActionButton.let {
|
binding.floatingActionButton.let {
|
||||||
val dialogBuilder = MaterialAlertDialogBuilder(it.context)
|
val dialogBuilder = MaterialAlertDialogBuilder(it.context)
|
||||||
|
@ -1423,11 +1467,20 @@ class ConversationsListActivity :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resources!!.getBoolean(R.bool.multiaccount_support)) {
|
||||||
|
dialogBuilder.setNeutralButton(R.string.nc_account_chooser_add_account) { _, _ ->
|
||||||
|
val intent = Intent(this, ServerSelectionActivity::class.java)
|
||||||
|
intent.putExtra(ADD_ADDITIONAL_ACCOUNT, true)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder)
|
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder)
|
||||||
val dialog = dialogBuilder.show()
|
val dialog = dialogBuilder.show()
|
||||||
viewThemeUtils.platform.colorTextButtons(
|
viewThemeUtils.platform.colorTextButtons(
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||||
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
|
dialog.getButton(AlertDialog.BUTTON_NEGATIVE),
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1445,23 +1498,31 @@ class ConversationsListActivity :
|
||||||
.setTitle(R.string.nc_dialog_maintenance_mode)
|
.setTitle(R.string.nc_dialog_maintenance_mode)
|
||||||
.setMessage(R.string.nc_dialog_maintenance_mode_description)
|
.setMessage(R.string.nc_dialog_maintenance_mode_description)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
|
.setNegativeButton(R.string.nc_settings_remove_account) { _, _ ->
|
||||||
|
deleteUserAndRestartApp()
|
||||||
|
}
|
||||||
|
|
||||||
if (resources!!.getBoolean(R.bool.multiaccount_support) && userManager.users.blockingGet().size > 1) {
|
if (resources!!.getBoolean(R.bool.multiaccount_support) && userManager.users.blockingGet().size > 1) {
|
||||||
dialogBuilder.setPositiveButton(R.string.nc_switch_account) { _, _ ->
|
dialogBuilder.setPositiveButton(R.string.nc_switch_account) { _, _ ->
|
||||||
val newFragment: DialogFragment = ChooseAccountDialogFragment.newInstance()
|
val newFragment: DialogFragment = ChooseAccountDialogFragment.newInstance()
|
||||||
newFragment.show(supportFragmentManager, ChooseAccountDialogFragment.TAG)
|
newFragment.show(supportFragmentManager, ChooseAccountDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
dialogBuilder.setPositiveButton(R.string.nc_close_app) { _, _ ->
|
|
||||||
finishAffinity()
|
if (resources!!.getBoolean(R.bool.multiaccount_support)) {
|
||||||
finish()
|
dialogBuilder.setNeutralButton(R.string.nc_account_chooser_add_account) { _, _ ->
|
||||||
|
val intent = Intent(this, ServerSelectionActivity::class.java)
|
||||||
|
intent.putExtra(ADD_ADDITIONAL_ACCOUNT, true)
|
||||||
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder)
|
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder)
|
||||||
val dialog = dialogBuilder.show()
|
val dialog = dialogBuilder.show()
|
||||||
viewThemeUtils.platform.colorTextButtons(
|
viewThemeUtils.platform.colorTextButtons(
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE)
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_NEGATIVE),
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1470,34 +1531,28 @@ class ConversationsListActivity :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showServerEOLDialog() {
|
private fun showServerEOLDialog() {
|
||||||
binding?.floatingActionButton?.let {
|
binding.floatingActionButton.let {
|
||||||
val dialogBuilder = MaterialAlertDialogBuilder(it.context)
|
val dialogBuilder = MaterialAlertDialogBuilder(it.context)
|
||||||
.setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_warning_white))
|
.setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_warning_white))
|
||||||
.setTitle(R.string.nc_settings_server_eol_title)
|
.setTitle(R.string.nc_settings_server_eol_title)
|
||||||
.setMessage(R.string.nc_settings_server_eol)
|
.setMessage(R.string.nc_settings_server_eol)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(R.string.nc_settings_remove_account) { _, _ ->
|
.setPositiveButton(R.string.nc_settings_remove_account) { _, _ ->
|
||||||
val otherUserExists = userManager
|
deleteUserAndRestartApp()
|
||||||
.scheduleUserForDeletionWithId(currentUser!!.id!!)
|
}
|
||||||
.blockingGet()
|
|
||||||
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
|
if (resources!!.getBoolean(R.bool.multiaccount_support) && userManager.users.blockingGet().size > 1) {
|
||||||
WorkManager.getInstance().enqueue(accountRemovalWork)
|
dialogBuilder.setNegativeButton(R.string.nc_switch_account) { _, _ ->
|
||||||
if (otherUserExists) {
|
val newFragment: DialogFragment = ChooseAccountDialogFragment.newInstance()
|
||||||
finish()
|
newFragment.show(supportFragmentManager, ChooseAccountDialogFragment.TAG)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resources!!.getBoolean(R.bool.multiaccount_support)) {
|
||||||
|
dialogBuilder.setNeutralButton(R.string.nc_account_chooser_add_account) { _, _ ->
|
||||||
|
val intent = Intent(this, ServerSelectionActivity::class.java)
|
||||||
|
intent.putExtra(ADD_ADDITIONAL_ACCOUNT, true)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
} else if (!otherUserExists) {
|
|
||||||
restartApp(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.setNegativeButton(R.string.nc_cancel) { _, _ ->
|
|
||||||
if (userManager.users.blockingGet().isNotEmpty()) {
|
|
||||||
// TODO show SwitchAccount screen again when conductor is removed instead to close app
|
|
||||||
// router.pushController(RouterTransaction.with(SwitchAccountController()))
|
|
||||||
finishAffinity()
|
|
||||||
finish()
|
|
||||||
} else {
|
|
||||||
finishAffinity()
|
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1505,20 +1560,12 @@ class ConversationsListActivity :
|
||||||
val dialog = dialogBuilder.show()
|
val dialog = dialogBuilder.show()
|
||||||
viewThemeUtils.platform.colorTextButtons(
|
viewThemeUtils.platform.colorTextButtons(
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||||
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
|
dialog.getButton(AlertDialog.BUTTON_NEGATIVE),
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun restartApp(context: Context) {
|
|
||||||
val packageManager = context.packageManager
|
|
||||||
val intent = packageManager.getLaunchIntentForPackage(context.packageName)
|
|
||||||
val componentName = intent!!.component
|
|
||||||
val mainIntent = Intent.makeRestartActivityTask(componentName)
|
|
||||||
context.startActivity(mainIntent)
|
|
||||||
Runtime.getRuntime().exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deleteConversation(conversation: Conversation) {
|
private fun deleteConversation(conversation: Conversation) {
|
||||||
val data = Data.Builder()
|
val data = Data.Builder()
|
||||||
data.putLong(
|
data.putLong(
|
||||||
|
@ -1613,10 +1660,10 @@ class ConversationsListActivity :
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "ConvListController"
|
private val TAG = ConversationsListActivity::class.java.simpleName
|
||||||
const val UNREAD_BUBBLE_DELAY = 2500
|
const val UNREAD_BUBBLE_DELAY = 2500
|
||||||
const val BOTTOM_SHEET_DELAY: Long = 2500
|
const val BOTTOM_SHEET_DELAY: Long = 2500
|
||||||
private const val KEY_SEARCH_QUERY = "ContactsController.searchQuery"
|
private const val KEY_SEARCH_QUERY = "ConversationsListActivity.searchQuery"
|
||||||
const val SEARCH_DEBOUNCE_INTERVAL_MS = 300
|
const val SEARCH_DEBOUNCE_INTERVAL_MS = 300
|
||||||
const val SEARCH_MIN_CHARS = 2
|
const val SEARCH_MIN_CHARS = 2
|
||||||
const val HTTP_UNAUTHORIZED = 401
|
const val HTTP_UNAUTHORIZED = 401
|
||||||
|
|
|
@ -23,10 +23,7 @@
|
||||||
package com.nextcloud.talk.jobs;
|
package com.nextcloud.talk.jobs;
|
||||||
|
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
@ -212,17 +209,5 @@ public class AccountRemovalWorker extends Worker {
|
||||||
Log.e(TAG, "error while trying to delete user", e);
|
Log.e(TAG, "error while trying to delete user", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (userManager.getUsers().blockingGet().isEmpty()) {
|
|
||||||
restartApp(getApplicationContext());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void restartApp(Context context) {
|
|
||||||
PackageManager packageManager = context.getPackageManager();
|
|
||||||
Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
|
|
||||||
ComponentName componentName = intent.getComponent();
|
|
||||||
Intent mainIntent = Intent.makeRestartActivityTask(componentName);
|
|
||||||
context.startActivity(mainIntent);
|
|
||||||
Runtime.getRuntime().exit(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ class GeocodingActivity :
|
||||||
if (viewModel.getQuery().isNotEmpty() && adapter.itemCount == 0) {
|
if (viewModel.getQuery().isNotEmpty() && adapter.itemCount == 0) {
|
||||||
viewModel.searchLocation()
|
viewModel.searchLocation()
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "search string that was passed to GeocodingController was null or empty")
|
Log.e(TAG, "search string that was passed to GeocodingActivity was null or empty")
|
||||||
}
|
}
|
||||||
adapter.setOnItemClickListener(object : GeocodingAdapter.OnItemClickListener {
|
adapter.setOnItemClickListener(object : GeocodingAdapter.OnItemClickListener {
|
||||||
override fun onItemClick(position: Int) {
|
override fun onItemClick(position: Int) {
|
||||||
|
|
|
@ -608,7 +608,7 @@ class ProfileActivity : BaseActivity() {
|
||||||
class UserInfoAdapter(
|
class UserInfoAdapter(
|
||||||
displayList: List<UserInfoDetailsItem>?,
|
displayList: List<UserInfoDetailsItem>?,
|
||||||
private val viewThemeUtils: ViewThemeUtils,
|
private val viewThemeUtils: ViewThemeUtils,
|
||||||
private val controller: ProfileActivity
|
private val profileActivity: ProfileActivity
|
||||||
) : RecyclerView.Adapter<UserInfoAdapter.ViewHolder>() {
|
) : RecyclerView.Adapter<UserInfoAdapter.ViewHolder>() {
|
||||||
var displayList: List<UserInfoDetailsItem>?
|
var displayList: List<UserInfoDetailsItem>?
|
||||||
var filteredDisplayList: MutableList<UserInfoDetailsItem> = LinkedList()
|
var filteredDisplayList: MutableList<UserInfoDetailsItem> = LinkedList()
|
||||||
|
@ -643,7 +643,7 @@ class ProfileActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val item: UserInfoDetailsItem = if (controller.edit) {
|
val item: UserInfoDetailsItem = if (profileActivity.edit) {
|
||||||
displayList!![position]
|
displayList!![position]
|
||||||
} else {
|
} else {
|
||||||
filteredDisplayList[position]
|
filteredDisplayList[position]
|
||||||
|
@ -656,11 +656,11 @@ class ProfileActivity : BaseActivity() {
|
||||||
|
|
||||||
holder.binding.icon.contentDescription = item.hint
|
holder.binding.icon.contentDescription = item.hint
|
||||||
viewThemeUtils.platform.colorImageView(holder.binding.icon, ColorRole.PRIMARY)
|
viewThemeUtils.platform.colorImageView(holder.binding.icon, ColorRole.PRIMARY)
|
||||||
if (!TextUtils.isEmpty(item.text) || controller.edit) {
|
if (!TextUtils.isEmpty(item.text) || profileActivity.edit) {
|
||||||
holder.binding.userInfoDetailContainer.visibility = View.VISIBLE
|
holder.binding.userInfoDetailContainer.visibility = View.VISIBLE
|
||||||
controller.viewThemeUtils.material.colorTextInputLayout(holder.binding.userInfoInputLayout)
|
profileActivity.viewThemeUtils.material.colorTextInputLayout(holder.binding.userInfoInputLayout)
|
||||||
if (controller.edit &&
|
if (profileActivity.edit &&
|
||||||
controller.editableFields.contains(item.field.toString().lowercase())
|
profileActivity.editableFields.contains(item.field.toString().lowercase())
|
||||||
) {
|
) {
|
||||||
holder.binding.userInfoEditTextEdit.isEnabled = true
|
holder.binding.userInfoEditTextEdit.isEnabled = true
|
||||||
holder.binding.userInfoEditTextEdit.isFocusableInTouchMode = true
|
holder.binding.userInfoEditTextEdit.isFocusableInTouchMode = true
|
||||||
|
@ -700,7 +700,7 @@ class ProfileActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
if (controller.edit) {
|
if (profileActivity.edit) {
|
||||||
displayList!![holder.adapterPosition].text = holder.binding.userInfoEditTextEdit.text.toString()
|
displayList!![holder.adapterPosition].text = holder.binding.userInfoEditTextEdit.text.toString()
|
||||||
} else {
|
} else {
|
||||||
filteredDisplayList[holder.adapterPosition].text =
|
filteredDisplayList[holder.adapterPosition].text =
|
||||||
|
@ -739,7 +739,7 @@ class ProfileActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
return if (controller.edit) {
|
return if (profileActivity.edit) {
|
||||||
displayList!!.size
|
displayList!!.size
|
||||||
} else {
|
} else {
|
||||||
filteredDisplayList.size
|
filteredDisplayList.size
|
||||||
|
@ -762,7 +762,7 @@ class ProfileActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG: String = "ProfileController"
|
private val TAG = ProfileActivity::class.java.simpleName
|
||||||
private const val DEFAULT_CACHE_SIZE: Int = 20
|
private const val DEFAULT_CACHE_SIZE: Int = 20
|
||||||
private const val DEFAULT_RETRIES: Long = 3
|
private const val DEFAULT_RETRIES: Long = 3
|
||||||
private const val HIGH_EMPHASIS_ALPHA: Float = 0.87f
|
private const val HIGH_EMPHASIS_ALPHA: Float = 0.87f
|
||||||
|
|
|
@ -91,8 +91,6 @@ class ShareRecordingToChatReceiver : BroadcastReceiver() {
|
||||||
// However, as we are in a broadcast receiver, this needs a TaskStackBuilder
|
// However, as we are in a broadcast receiver, this needs a TaskStackBuilder
|
||||||
// combined with addNextIntentWithParentStack. For further reading, see
|
// combined with addNextIntentWithParentStack. For further reading, see
|
||||||
// https://developer.android.com/develop/ui/views/notifications/navigation#DirectEntry
|
// https://developer.android.com/develop/ui/views/notifications/navigation#DirectEntry
|
||||||
// As we are using the conductor framework it might be hard the combine this or to keep an overview.
|
|
||||||
// For this reason there is only a Snackbar for now until we got rid of conductor.
|
|
||||||
|
|
||||||
Snackbar.make(
|
Snackbar.make(
|
||||||
View(context),
|
View(context),
|
||||||
|
|
|
@ -27,6 +27,7 @@ package com.nextcloud.talk.settings
|
||||||
|
|
||||||
import android.animation.Animator
|
import android.animation.Animator
|
||||||
import android.animation.AnimatorListenerAdapter
|
import android.animation.AnimatorListenerAdapter
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.KeyguardManager
|
import android.app.KeyguardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
|
@ -51,6 +52,7 @@ import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
@ -66,6 +68,7 @@ import com.nextcloud.android.common.ui.theme.utils.ColorRole
|
||||||
import com.nextcloud.talk.BuildConfig
|
import com.nextcloud.talk.BuildConfig
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.activities.BaseActivity
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.setAppTheme
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.setAppTheme
|
||||||
|
@ -465,17 +468,47 @@ class SettingsActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
private fun removeCurrentAccount() {
|
private fun removeCurrentAccount() {
|
||||||
val otherUserExists = userManager.scheduleUserForDeletionWithId(currentUser!!.id!!).blockingGet()
|
userManager.scheduleUserForDeletionWithId(currentUser!!.id!!).blockingGet()
|
||||||
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
|
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
|
||||||
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
WorkManager.getInstance(applicationContext).enqueue(accountRemovalWork)
|
||||||
if (otherUserExists) {
|
|
||||||
// TODO: find better solution once Conductor is removed
|
WorkManager.getInstance(context).getWorkInfoByIdLiveData(accountRemovalWork.id)
|
||||||
finish()
|
.observeForever { workInfo: WorkInfo ->
|
||||||
startActivity(intent)
|
|
||||||
} else if (!otherUserExists) {
|
when (workInfo.state) {
|
||||||
Log.d(TAG, "No other users found. AccountRemovalWorker will restart the app.")
|
WorkInfo.State.SUCCEEDED -> {
|
||||||
|
val text = String.format(
|
||||||
|
context.resources.getString(R.string.nc_deleted_user),
|
||||||
|
currentUser!!.displayName
|
||||||
|
)
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
text,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
restartApp()
|
||||||
}
|
}
|
||||||
|
WorkInfo.State.FAILED, WorkInfo.State.CANCELLED -> {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context.resources.getString(R.string.nc_common_error_sorry),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
Log.e(TAG, "something went wrong when deleting user with id " + currentUser!!.userId)
|
||||||
|
restartApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun restartApp() {
|
||||||
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRingtoneName(context: Context, ringtoneUri: Uri?): String {
|
private fun getRingtoneName(context: Context, ringtoneUri: Uri?): String {
|
||||||
|
@ -1205,7 +1238,7 @@ class SettingsActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "SettingsController"
|
private val TAG = SettingsActivity::class.java.simpleName
|
||||||
private const val DURATION: Long = 2500
|
private const val DURATION: Long = 2500
|
||||||
private const val START_DELAY: Long = 5000
|
private const val START_DELAY: Long = 5000
|
||||||
private const val DISABLED_ALPHA: Float = 0.38f
|
private const val DISABLED_ALPHA: Float = 0.38f
|
||||||
|
|
|
@ -31,8 +31,8 @@ import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.chat.ChatActivity
|
import com.nextcloud.talk.chat.ChatActivity
|
||||||
import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
|
import com.nextcloud.talk.bottomsheet.items.BasicListItemWithImage
|
||||||
import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
|
import com.nextcloud.talk.bottomsheet.items.listItemsWithImage
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||||
import com.nextcloud.talk.models.json.hovercard.HoverCardAction
|
import com.nextcloud.talk.models.json.hovercard.HoverCardAction
|
||||||
|
|
|
@ -35,7 +35,7 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
import com.nextcloud.talk.activities.MainActivity;
|
import com.nextcloud.talk.account.ServerSelectionActivity;
|
||||||
import com.nextcloud.talk.adapters.items.AdvancedUserItem;
|
import com.nextcloud.talk.adapters.items.AdvancedUserItem;
|
||||||
import com.nextcloud.talk.api.NcApi;
|
import com.nextcloud.talk.api.NcApi;
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||||
|
@ -71,7 +71,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
import static com.nextcloud.talk.utils.bundle.BundleKeys.ADD_ACCOUNT;
|
import static com.nextcloud.talk.utils.bundle.BundleKeys.ADD_ADDITIONAL_ACCOUNT;
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication.class)
|
@AutoInjector(NextcloudTalkApplication.class)
|
||||||
public class ChooseAccountDialogFragment extends DialogFragment {
|
public class ChooseAccountDialogFragment extends DialogFragment {
|
||||||
|
@ -185,11 +185,9 @@ public class ChooseAccountDialogFragment extends DialogFragment {
|
||||||
// Creating listeners for quick-actions
|
// Creating listeners for quick-actions
|
||||||
binding.currentAccount.getRoot().setOnClickListener(v -> dismiss());
|
binding.currentAccount.getRoot().setOnClickListener(v -> dismiss());
|
||||||
|
|
||||||
|
|
||||||
binding.addAccount.setOnClickListener(v -> {
|
binding.addAccount.setOnClickListener(v -> {
|
||||||
// TODO: change this when conductor is removed
|
Intent intent = new Intent(getContext(), ServerSelectionActivity.class);
|
||||||
Intent intent = new Intent(getContext(), MainActivity.class);
|
intent.putExtra(ADD_ADDITIONAL_ACCOUNT, true);
|
||||||
intent.putExtra(ADD_ACCOUNT, true);
|
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
dismiss();
|
dismiss();
|
||||||
});
|
});
|
||||||
|
|
|
@ -84,6 +84,8 @@ object BundleKeys {
|
||||||
const val KEY_DISMISS_RECORDING_URL = "KEY_DISMISS_RECORDING_URL"
|
const val KEY_DISMISS_RECORDING_URL = "KEY_DISMISS_RECORDING_URL"
|
||||||
const val KEY_SHARE_RECORDING_TO_CHAT_URL = "KEY_SHARE_RECORDING_TO_CHAT_URL"
|
const val KEY_SHARE_RECORDING_TO_CHAT_URL = "KEY_SHARE_RECORDING_TO_CHAT_URL"
|
||||||
const val KEY_GEOCODING_RESULT = "KEY_GEOCODING_RESULT"
|
const val KEY_GEOCODING_RESULT = "KEY_GEOCODING_RESULT"
|
||||||
const val ADD_ACCOUNT = "ADD_ACCOUNT" // temp workaround until conductor is removed
|
const val ADD_ADDITIONAL_ACCOUNT = "ADD_ADDITIONAL_ACCOUNT"
|
||||||
const val SAVED_TRANSLATED_MESSAGE = "SAVED_TRANSLATED_MESSAGE"
|
const val SAVED_TRANSLATED_MESSAGE = "SAVED_TRANSLATED_MESSAGE"
|
||||||
|
const val KEY_REAUTHORIZE_ACCOUNT = "KEY_REAUTHORIZE_ACCOUNT"
|
||||||
|
const val KEY_PASSWORD = "KEY_PASSWORD"
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class ApplicationWideMessageHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum MessageType {
|
public enum MessageType {
|
||||||
WRONG_ACCOUNT, ACCOUNT_UPDATED_NOT_ADDED, ACCOUNT_SCHEDULED_FOR_DELETION, SERVER_WITHOUT_TALK,
|
WRONG_ACCOUNT, ACCOUNT_UPDATED_NOT_ADDED, SERVER_WITHOUT_TALK,
|
||||||
FAILED_TO_IMPORT_ACCOUNT, ACCOUNT_WAS_IMPORTED, CALL_PASSWORD_WRONG
|
FAILED_TO_IMPORT_ACCOUNT, ACCOUNT_WAS_IMPORTED, CALL_PASSWORD_WRONG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -234,7 +234,7 @@
|
||||||
android:id="@+id/separator_1"
|
android:id="@+id/separator_1"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="@color/controller_chat_separator" />
|
android:background="@color/chat_separator" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/typing_indicator"
|
android:id="@+id/typing_indicator"
|
||||||
|
|
|
@ -178,7 +178,15 @@
|
||||||
android:textAppearance="@style/ListItem" />
|
android:textAppearance="@style/ListItem" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<include
|
<RelativeLayout
|
||||||
android:id="@+id/controller_generic_rv"
|
android:layout_width="match_parent"
|
||||||
layout="@layout/controller_generic_rv" />
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/contacts_rv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_anchorGravity="center" />
|
||||||
|
</RelativeLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -40,8 +40,6 @@
|
||||||
android:windowContentOverlay="@null"
|
android:windowContentOverlay="@null"
|
||||||
app:elevation="0dp">
|
app:elevation="0dp">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -58,11 +56,4 @@
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<com.bluelinelabs.conductor.ChangeHandlerFrameLayout
|
|
||||||
android:id="@+id/controller_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/bg_default"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
|
@ -18,25 +18,34 @@
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/generic_rv_layout"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:animateLayoutChanges="true">
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/swipe_refresh_layout"
|
android:id="@+id/appBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<FrameLayout
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="@color/appbar"
|
||||||
|
android:theme="?attr/actionBarPopupTheme"
|
||||||
|
app:layout_scrollFlags="enterAlwaysCollapsed|noScroll"
|
||||||
|
app:navigationIconTint="@color/fontAppbar"
|
||||||
|
app:popupTheme="@style/appActionBarPopupMenu"
|
||||||
|
app:titleTextColor="@color/fontAppbar"
|
||||||
|
tools:title="@string/nc_select_an_account">
|
||||||
|
|
||||||
</FrameLayout>
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recycler_view"
|
android:id="@+id/recycler_view"
|
||||||
|
@ -44,4 +53,4 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:layout_anchor="@+id/swipe_refresh_layout"
|
app:layout_anchor="@+id/swipe_refresh_layout"
|
||||||
app:layout_anchorGravity="center" />
|
app:layout_anchorGravity="center" />
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</LinearLayout>
|
|
@ -28,7 +28,7 @@
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/controllerCallLayout"
|
android:id="@+id/callLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
|
@ -128,7 +128,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/controller_call_incomingCallTextView"
|
android:textColor="@color/call_incomingCallTextView"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/controllerCallNotificationLayout"
|
android:id="@+id/callNotificationLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/grey950">
|
android:background="@color/grey950">
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="@string/nc_call_unknown"
|
android:text="@string/nc_call_unknown"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/controller_call_incomingCallTextView"
|
android:textColor="@color/call_incomingCallTextView"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
android:layout_below="@+id/conversationNameTextView"
|
android:layout_below="@+id/conversationNameTextView"
|
||||||
android:text="@string/nc_call_incoming"
|
android:text="@string/nc_call_incoming"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/controller_call_incomingCallTextView"
|
android:textColor="@color/call_incomingCallTextView"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
<color name="conversation_unread_bubble">#373737</color>
|
<color name="conversation_unread_bubble">#373737</color>
|
||||||
<color name="conversation_unread_bubble_text">#D8D8D8</color>
|
<color name="conversation_unread_bubble_text">#D8D8D8</color>
|
||||||
|
|
||||||
<color name="controller_chat_separator">#484848</color>
|
<color name="chat_separator">#484848</color>
|
||||||
|
|
||||||
<color name="colorBackgroundDarker">#2C2C2C</color>
|
<color name="colorBackgroundDarker">#2C2C2C</color>
|
||||||
|
|
||||||
|
|
|
@ -61,10 +61,10 @@
|
||||||
<color name="nc_darkRed">#D32F2F</color>
|
<color name="nc_darkRed">#D32F2F</color>
|
||||||
<color name="nc_darkYellow">#FF9800</color>
|
<color name="nc_darkYellow">#FF9800</color>
|
||||||
<color name="nc_darkGreen">#006400</color>
|
<color name="nc_darkGreen">#006400</color>
|
||||||
<color name="controller_chat_separator">#E8E8E8</color>
|
<color name="chat_separator">#E8E8E8</color>
|
||||||
<color name="grey_600">#757575</color>
|
<color name="grey_600">#757575</color>
|
||||||
<color name="nc_grey">#D5D5D5</color>
|
<color name="nc_grey">#D5D5D5</color>
|
||||||
<color name="controller_call_incomingCallTextView">#E9FFFFFF</color>
|
<color name="call_incomingCallTextView">#E9FFFFFF</color>
|
||||||
<color name="grey950">#111111</color>
|
<color name="grey950">#111111</color>
|
||||||
<color name="textColorMaxContrast">#767676</color>
|
<color name="textColorMaxContrast">#767676</color>
|
||||||
<color name="colorBackgroundDarker">#DBDBDB</color>
|
<color name="colorBackgroundDarker">#DBDBDB</color>
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
<!-- Branding -->
|
<!-- Branding -->
|
||||||
<bool name="hide_provider">false</bool>
|
<bool name="hide_provider">false</bool>
|
||||||
<bool name="hide_auth_cert">false</bool>
|
<bool name="hide_auth_cert">true</bool>
|
||||||
<bool name="multiaccount_support">true</bool>
|
<bool name="multiaccount_support">true</bool>
|
||||||
<string name="weblogin_url" translatable="false"></string>
|
<string name="weblogin_url" translatable="false"></string>
|
||||||
|
|
||||||
|
|
|
@ -574,6 +574,7 @@ How to translate with transifex:
|
||||||
<string name="filename_progress">%1$s (%2$d)</string>
|
<string name="filename_progress">%1$s (%2$d)</string>
|
||||||
<string name="nc_dialog_invalid_password">Invalid password</string>
|
<string name="nc_dialog_invalid_password">Invalid password</string>
|
||||||
<string name="nc_dialog_reauth_or_delete">Do you want to reauthorize or delete this account?</string>
|
<string name="nc_dialog_reauth_or_delete">Do you want to reauthorize or delete this account?</string>
|
||||||
|
<string name="nc_deleted_user">User %1$s was removed</string>
|
||||||
|
|
||||||
<string name="nc_dialog_outdated_client">App is outdated</string>
|
<string name="nc_dialog_outdated_client">App is outdated</string>
|
||||||
<string name="nc_dialog_outdated_client_description">The app is too old and no longer supported by this server. Please update.</string>
|
<string name="nc_dialog_outdated_client_description">The app is too old and no longer supported by this server. Please update.</string>
|
||||||
|
|
|
@ -97,7 +97,7 @@ class BundleKeysTest {
|
||||||
assertEquals("KEY_DISMISS_RECORDING_URL", BundleKeys.KEY_DISMISS_RECORDING_URL)
|
assertEquals("KEY_DISMISS_RECORDING_URL", BundleKeys.KEY_DISMISS_RECORDING_URL)
|
||||||
assertEquals("KEY_SHARE_RECORDING_TO_CHAT_URL", BundleKeys.KEY_SHARE_RECORDING_TO_CHAT_URL)
|
assertEquals("KEY_SHARE_RECORDING_TO_CHAT_URL", BundleKeys.KEY_SHARE_RECORDING_TO_CHAT_URL)
|
||||||
assertEquals("KEY_GEOCODING_RESULT", BundleKeys.KEY_GEOCODING_RESULT)
|
assertEquals("KEY_GEOCODING_RESULT", BundleKeys.KEY_GEOCODING_RESULT)
|
||||||
assertEquals("ADD_ACCOUNT", BundleKeys.ADD_ACCOUNT)
|
assertEquals("ADD_ADDITIONAL_ACCOUNT", BundleKeys.ADD_ADDITIONAL_ACCOUNT)
|
||||||
assertEquals("SAVED_TRANSLATED_MESSAGE", BundleKeys.SAVED_TRANSLATED_MESSAGE)
|
assertEquals("SAVED_TRANSLATED_MESSAGE", BundleKeys.SAVED_TRANSLATED_MESSAGE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue