mirror of https://github.com/nextcloud/android
363 lines
13 KiB
Kotlin
363 lines
13 KiB
Kotlin
/*
|
|
* Nextcloud - Android Client
|
|
*
|
|
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
|
|
* SPDX-FileCopyrightText: 2017 Mario Danic <mario@lovelyhq.com>
|
|
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
package com.owncloud.android.ui.activity
|
|
|
|
import android.os.Bundle
|
|
import android.view.Menu
|
|
import android.view.MenuItem
|
|
import android.view.View
|
|
import androidx.annotation.VisibleForTesting
|
|
import androidx.recyclerview.widget.LinearLayoutManager
|
|
import com.google.android.material.snackbar.Snackbar
|
|
import com.nextcloud.client.account.User
|
|
import com.nextcloud.client.account.UserAccountManager
|
|
import com.nextcloud.client.jobs.NotificationWork
|
|
import com.nextcloud.client.network.ClientFactory.CreationException
|
|
import com.owncloud.android.R
|
|
import com.owncloud.android.databinding.NotificationsLayoutBinding
|
|
import com.owncloud.android.datamodel.ArbitraryDataProvider
|
|
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl
|
|
import com.owncloud.android.lib.common.OwnCloudClient
|
|
import com.owncloud.android.lib.common.utils.Log_OC
|
|
import com.owncloud.android.lib.resources.notifications.GetNotificationsRemoteOperation
|
|
import com.owncloud.android.lib.resources.notifications.models.Notification
|
|
import com.owncloud.android.ui.adapter.NotificationListAdapter
|
|
import com.owncloud.android.ui.adapter.NotificationListAdapter.NotificationViewHolder
|
|
import com.owncloud.android.ui.asynctasks.DeleteAllNotificationsTask
|
|
import com.owncloud.android.ui.notifications.NotificationsContract
|
|
import com.owncloud.android.utils.DisplayUtils
|
|
import com.owncloud.android.utils.PushUtils
|
|
import java.util.Optional
|
|
|
|
/**
|
|
* Activity displaying all server side stored notification items.
|
|
*/
|
|
class NotificationsActivity : DrawerActivity(), NotificationsContract.View {
|
|
|
|
lateinit var binding: NotificationsLayoutBinding
|
|
|
|
private var adapter: NotificationListAdapter? = null
|
|
private var snackbar: Snackbar? = null
|
|
private var client: OwnCloudClient? = null
|
|
private var optionalUser: Optional<User>? = null
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
Log_OC.v(TAG, "onCreate() start")
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
binding = NotificationsLayoutBinding.inflate(layoutInflater)
|
|
setContentView(binding.root)
|
|
|
|
optionalUser = user
|
|
|
|
intent?.let {
|
|
it.extras?.let { bundle ->
|
|
setupUser(bundle)
|
|
}
|
|
}
|
|
|
|
setupToolbar()
|
|
updateActionBarTitleAndHomeButtonByString(getString(R.string.drawer_item_notifications))
|
|
setupDrawer(R.id.nav_notifications)
|
|
|
|
if (optionalUser?.isPresent == false) {
|
|
showError()
|
|
}
|
|
|
|
setupContainingList()
|
|
setupPushWarning()
|
|
setupContent()
|
|
}
|
|
|
|
private fun setupContainingList() {
|
|
viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.swipeContainingList)
|
|
viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.swipeContainingEmpty)
|
|
binding.swipeContainingList.setOnRefreshListener {
|
|
setLoadingMessage()
|
|
binding.swipeContainingList.isRefreshing = true
|
|
fetchAndSetData()
|
|
}
|
|
binding.swipeContainingEmpty.setOnRefreshListener {
|
|
setLoadingMessageEmpty()
|
|
fetchAndSetData()
|
|
}
|
|
}
|
|
|
|
private fun setupUser(bundle: Bundle) {
|
|
val accountName = bundle.getString(NotificationWork.KEY_NOTIFICATION_ACCOUNT)
|
|
|
|
if (accountName != null && optionalUser?.isPresent == true) {
|
|
val user = optionalUser?.get()
|
|
if (user?.accountName.equals(accountName, ignoreCase = true)) {
|
|
accountManager.setCurrentOwnCloudAccount(accountName)
|
|
setUser(userAccountManager.user)
|
|
optionalUser = getUser()
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun showError() {
|
|
runOnUiThread {
|
|
setEmptyContent(
|
|
getString(R.string.notifications_no_results_headline),
|
|
getString(R.string.account_not_found)
|
|
)
|
|
}
|
|
return
|
|
}
|
|
|
|
@Suppress("NestedBlockDepth")
|
|
private fun setupPushWarning() {
|
|
if (!resources.getBoolean(R.bool.show_push_warning)) {
|
|
return
|
|
}
|
|
|
|
if (snackbar != null) {
|
|
if (snackbar?.isShown == false) {
|
|
snackbar?.show()
|
|
}
|
|
} else {
|
|
val pushUrl = resources.getString(R.string.push_server_url)
|
|
if (pushUrl.isEmpty()) {
|
|
snackbar = Snackbar.make(
|
|
binding.emptyList.emptyListView,
|
|
R.string.push_notifications_not_implemented,
|
|
Snackbar.LENGTH_INDEFINITE
|
|
)
|
|
} else {
|
|
val arbitraryDataProvider: ArbitraryDataProvider = ArbitraryDataProviderImpl(this)
|
|
val accountName: String = if (optionalUser?.isPresent == true) {
|
|
optionalUser?.get()?.accountName ?: ""
|
|
} else {
|
|
""
|
|
}
|
|
val usesOldLogin = arbitraryDataProvider.getBooleanValue(
|
|
accountName,
|
|
UserAccountManager.ACCOUNT_USES_STANDARD_PASSWORD
|
|
)
|
|
|
|
if (usesOldLogin) {
|
|
snackbar = Snackbar.make(
|
|
binding.emptyList.emptyListView,
|
|
R.string.push_notifications_old_login,
|
|
Snackbar.LENGTH_INDEFINITE
|
|
)
|
|
} else {
|
|
val pushValue = arbitraryDataProvider.getValue(accountName, PushUtils.KEY_PUSH)
|
|
if (pushValue.isEmpty()) {
|
|
snackbar = Snackbar.make(
|
|
binding.emptyList.emptyListView,
|
|
R.string.push_notifications_temp_error,
|
|
Snackbar.LENGTH_INDEFINITE
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
if (snackbar != null && snackbar?.isShown == false) {
|
|
snackbar?.show()
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun openDrawer() {
|
|
super.openDrawer()
|
|
if (snackbar != null && snackbar?.isShown == true) {
|
|
snackbar?.dismiss()
|
|
}
|
|
}
|
|
|
|
override fun closeDrawer() {
|
|
super.closeDrawer()
|
|
setupPushWarning()
|
|
}
|
|
|
|
/**
|
|
* sets up the UI elements and loads all notification items.
|
|
*/
|
|
private fun setupContent() {
|
|
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_notification)
|
|
setLoadingMessageEmpty()
|
|
val layoutManager = LinearLayoutManager(this)
|
|
binding.list.layoutManager = layoutManager
|
|
fetchAndSetData()
|
|
}
|
|
|
|
@VisibleForTesting
|
|
fun populateList(notifications: List<Notification>?) {
|
|
initializeAdapter()
|
|
adapter?.setNotificationItems(notifications)
|
|
binding.loadingContent.visibility = View.GONE
|
|
|
|
if (notifications?.isNotEmpty() == true) {
|
|
binding.swipeContainingEmpty.visibility = View.GONE
|
|
binding.swipeContainingList.visibility = View.VISIBLE
|
|
} else {
|
|
setEmptyContent(
|
|
getString(R.string.notifications_no_results_headline),
|
|
getString(R.string.notifications_no_results_message)
|
|
)
|
|
binding.swipeContainingList.visibility = View.GONE
|
|
binding.swipeContainingEmpty.visibility = View.VISIBLE
|
|
}
|
|
}
|
|
|
|
private fun fetchAndSetData() {
|
|
val t = Thread {
|
|
initializeAdapter()
|
|
val getRemoteNotificationOperation = GetNotificationsRemoteOperation()
|
|
val result = getRemoteNotificationOperation.execute(client)
|
|
if (result.isSuccess && result.resultData != null) {
|
|
runOnUiThread { populateList(result.resultData) }
|
|
} else {
|
|
Log_OC.d(TAG, result.logMessage)
|
|
// show error
|
|
runOnUiThread {
|
|
setEmptyContent(
|
|
getString(R.string.notifications_no_results_headline),
|
|
result.logMessage
|
|
)
|
|
}
|
|
}
|
|
hideRefreshLayoutLoader()
|
|
}
|
|
t.start()
|
|
}
|
|
|
|
private fun initializeClient() {
|
|
if (client == null && optionalUser?.isPresent == true) {
|
|
try {
|
|
val user = optionalUser?.get()
|
|
client = clientFactory.create(user)
|
|
} catch (e: CreationException) {
|
|
Log_OC.e(TAG, "Error initializing client", e)
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun initializeAdapter() {
|
|
initializeClient()
|
|
if (adapter == null) {
|
|
adapter = NotificationListAdapter(client, this, viewThemeUtils)
|
|
binding.list.adapter = adapter
|
|
}
|
|
}
|
|
|
|
private fun hideRefreshLayoutLoader() {
|
|
runOnUiThread {
|
|
binding.swipeContainingList.isRefreshing = false
|
|
binding.swipeContainingEmpty.isRefreshing = false
|
|
}
|
|
}
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
menuInflater.inflate(R.menu.activity_notifications, menu)
|
|
return true
|
|
}
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
var retval = true
|
|
val itemId = item.itemId
|
|
if (itemId == android.R.id.home) {
|
|
if (isDrawerOpen) {
|
|
closeDrawer()
|
|
} else {
|
|
openDrawer()
|
|
}
|
|
} else if (itemId == R.id.action_empty_notifications) {
|
|
DeleteAllNotificationsTask(client, this).execute()
|
|
} else {
|
|
retval = super.onOptionsItemSelected(item)
|
|
}
|
|
return retval
|
|
}
|
|
|
|
private fun setLoadingMessage() {
|
|
binding.swipeContainingEmpty.visibility = View.GONE
|
|
}
|
|
|
|
@VisibleForTesting
|
|
fun setLoadingMessageEmpty() {
|
|
binding.swipeContainingList.visibility = View.GONE
|
|
binding.emptyList.emptyListView.visibility = View.GONE
|
|
binding.loadingContent.visibility = View.VISIBLE
|
|
}
|
|
|
|
@VisibleForTesting
|
|
fun setEmptyContent(headline: String?, message: String?) {
|
|
binding.swipeContainingList.visibility = View.GONE
|
|
binding.loadingContent.visibility = View.GONE
|
|
binding.swipeContainingEmpty.visibility = View.VISIBLE
|
|
binding.emptyList.emptyListView.visibility = View.VISIBLE
|
|
binding.emptyList.emptyListViewHeadline.text = headline
|
|
binding.emptyList.emptyListViewText.text = message
|
|
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_notification)
|
|
binding.emptyList.emptyListViewText.visibility = View.VISIBLE
|
|
binding.emptyList.emptyListIcon.visibility = View.VISIBLE
|
|
}
|
|
|
|
override fun onResume() {
|
|
super.onResume()
|
|
setDrawerMenuItemChecked(R.id.nav_notifications)
|
|
}
|
|
|
|
override fun onRemovedNotification(isSuccess: Boolean) {
|
|
if (!isSuccess) {
|
|
DisplayUtils.showSnackMessage(this, getString(R.string.remove_notification_failed))
|
|
fetchAndSetData()
|
|
}
|
|
}
|
|
|
|
override fun removeNotification(holder: NotificationViewHolder) {
|
|
adapter?.removeNotification(holder)
|
|
if (adapter?.itemCount == 0) {
|
|
setEmptyContent(
|
|
getString(R.string.notifications_no_results_headline),
|
|
getString(R.string.notifications_no_results_message)
|
|
)
|
|
binding.swipeContainingList.visibility = View.GONE
|
|
binding.loadingContent.visibility = View.GONE
|
|
binding.swipeContainingEmpty.visibility = View.VISIBLE
|
|
}
|
|
}
|
|
|
|
override fun onRemovedAllNotifications(isSuccess: Boolean) {
|
|
if (isSuccess) {
|
|
adapter?.removeAllNotifications()
|
|
setEmptyContent(
|
|
getString(R.string.notifications_no_results_headline),
|
|
getString(R.string.notifications_no_results_message)
|
|
)
|
|
binding.loadingContent.visibility = View.GONE
|
|
binding.swipeContainingList.visibility = View.GONE
|
|
binding.swipeContainingEmpty.visibility = View.VISIBLE
|
|
} else {
|
|
DisplayUtils.showSnackMessage(this, getString(R.string.clear_notifications_failed))
|
|
}
|
|
}
|
|
|
|
override fun onActionCallback(
|
|
isSuccess: Boolean,
|
|
notification: Notification,
|
|
holder: NotificationViewHolder
|
|
) {
|
|
if (isSuccess) {
|
|
adapter?.removeNotification(holder)
|
|
} else {
|
|
adapter?.setButtons(holder, notification)
|
|
DisplayUtils.showSnackMessage(this, getString(R.string.notification_action_failed))
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
private val TAG = NotificationsActivity::class.java.simpleName
|
|
}
|
|
}
|