improved clear notifications
This commit is contained in:
parent
63b56269ff
commit
ae6df32777
|
@ -922,8 +922,8 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
|||
}.fold(0L, Math::max)
|
||||
val count = DataStoreUtils.getInteractionsCount(context, spec.args,
|
||||
accountKeys, position, Activities.TIMESTAMP)
|
||||
publishProgress(TabBadge(i, count))
|
||||
result.put(i, count)
|
||||
publishProgress(TabBadge(i, count))
|
||||
}
|
||||
CustomTabType.DIRECT_MESSAGES -> {
|
||||
val accountKeys = Utils.getAccountKeys(context, spec.args) ?: activatedKeys
|
||||
|
@ -935,8 +935,8 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
|||
accountKeys, extraHaving = unreadHaving)?.useCursor { cur ->
|
||||
return@useCursor cur.count
|
||||
} ?: -1
|
||||
publishProgress(TabBadge(i, count))
|
||||
result.put(i, count)
|
||||
publishProgress(TabBadge(i, count))
|
||||
}
|
||||
else -> {
|
||||
publishProgress(TabBadge(i, -1))
|
||||
|
|
|
@ -28,8 +28,10 @@ import android.net.Uri
|
|||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.support.v4.content.Loader
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.widget.Toast
|
||||
import com.squareup.otto.Subscribe
|
||||
import kotlinx.android.synthetic.main.fragment_content_recyclerview.*
|
||||
import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe
|
||||
import org.mariotaku.ktextension.contains
|
||||
import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe
|
||||
|
@ -59,24 +61,65 @@ import org.mariotaku.twidere.util.Utils
|
|||
*/
|
||||
abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
||||
|
||||
override val accountKeys: Array<UserKey>
|
||||
get() = Utils.getAccountKeys(context, arguments) ?: DataStoreUtils.getActivatedAccountKeys(context)
|
||||
|
||||
abstract val contentUri: Uri
|
||||
|
||||
protected abstract val errorInfoKey: String
|
||||
|
||||
protected abstract val notificationType: Int
|
||||
|
||||
protected abstract val isFilterEnabled: Boolean
|
||||
|
||||
private var contentObserver: ContentObserver? = null
|
||||
|
||||
private val onScrollListener = object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
clearNotifications()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val accountListener: OnAccountsUpdateListener = OnAccountsUpdateListener {
|
||||
reloadActivities()
|
||||
}
|
||||
|
||||
override val accountKeys: Array<UserKey>
|
||||
get() = Utils.getAccountKeys(context, arguments) ?: DataStoreUtils.getActivatedAccountKeys(context)
|
||||
|
||||
protected abstract val errorInfoKey: String
|
||||
|
||||
private val sortOrder: String
|
||||
get() = Activities.DEFAULT_SORT_ORDER
|
||||
|
||||
abstract val contentUri: Uri
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (contentObserver == null) {
|
||||
contentObserver = object : ContentObserver(Handler()) {
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
reloadActivities()
|
||||
}
|
||||
}
|
||||
context.contentResolver.registerContentObserver(Filters.CONTENT_URI, true, contentObserver)
|
||||
}
|
||||
AccountManager.get(context).addOnAccountsUpdatedListenerSafe(accountListener, updateImmediately = false)
|
||||
recyclerView.addOnScrollListener(onScrollListener)
|
||||
updateRefreshState()
|
||||
reloadActivities()
|
||||
}
|
||||
|
||||
override fun onContentLoaded(loader: Loader<List<ParcelableActivity>>, data: List<ParcelableActivity>?) {
|
||||
showContentOrError()
|
||||
override fun onStop() {
|
||||
recyclerView.removeOnScrollListener(onScrollListener)
|
||||
if (contentObserver != null) {
|
||||
context.contentResolver.unregisterContentObserver(contentObserver)
|
||||
contentObserver = null
|
||||
}
|
||||
AccountManager.get(context).removeOnAccountsUpdatedListenerSafe(accountListener)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||
super.setUserVisibleHint(isVisibleToUser)
|
||||
if (isVisibleToUser) {
|
||||
clearNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateActivitiesLoader(context: Context, args: Bundle, fromUser: Boolean): Loader<List<ParcelableActivity>> {
|
||||
|
@ -104,34 +147,14 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
|||
sortOrder, fromUser)
|
||||
}
|
||||
|
||||
override fun onContentLoaded(loader: Loader<List<ParcelableActivity>>, data: List<ParcelableActivity>?) {
|
||||
showContentOrError()
|
||||
}
|
||||
|
||||
override fun createMessageBusCallback(): Any {
|
||||
return CursorActivitiesBusCallback()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (contentObserver == null) {
|
||||
contentObserver = object : ContentObserver(Handler()) {
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
reloadActivities()
|
||||
}
|
||||
}
|
||||
context.contentResolver.registerContentObserver(Filters.CONTENT_URI, true, contentObserver)
|
||||
}
|
||||
AccountManager.get(context).addOnAccountsUpdatedListenerSafe(accountListener, updateImmediately = false)
|
||||
updateRefreshState()
|
||||
reloadActivities()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
if (contentObserver != null) {
|
||||
context.contentResolver.unregisterContentObserver(contentObserver)
|
||||
contentObserver = null
|
||||
}
|
||||
AccountManager.get(context).removeOnAccountsUpdatedListenerSafe(accountListener)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun hasMoreData(data: List<ParcelableActivity>?): Boolean {
|
||||
return data?.size != 0
|
||||
}
|
||||
|
@ -167,7 +190,6 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
override fun triggerRefresh(): Boolean {
|
||||
super.triggerRefresh()
|
||||
val contentUri = this.contentUri
|
||||
|
@ -198,28 +220,12 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
|||
return DataStoreUtils.buildActivityFilterWhereClause(table, null)
|
||||
}
|
||||
|
||||
protected abstract val notificationType: Int
|
||||
|
||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||
super.setUserVisibleHint(isVisibleToUser)
|
||||
val context = context
|
||||
if (context != null && isVisibleToUser) {
|
||||
val accountKeys = accountKeys
|
||||
for (accountKey in accountKeys) {
|
||||
twitterWrapper.clearNotificationAsync(notificationType, accountKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract val isFilterEnabled: Boolean
|
||||
|
||||
protected open fun processWhere(where: Expression, whereArgs: Array<String>): ParameterizedExpression {
|
||||
return ParameterizedExpression(where, whereArgs)
|
||||
}
|
||||
|
||||
protected abstract fun updateRefreshState()
|
||||
|
||||
|
||||
protected fun reloadActivities() {
|
||||
if (activity == null || isDetached) return
|
||||
val args = Bundle()
|
||||
|
@ -231,30 +237,6 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
|||
loaderManager.restartLoader(loaderId, args, this)
|
||||
}
|
||||
|
||||
private fun showContentOrError() {
|
||||
val accountKeys = accountKeys
|
||||
if (adapter.itemCount > 0) {
|
||||
showContent()
|
||||
} else if (accountKeys.isNotEmpty()) {
|
||||
val errorInfo = ErrorInfoStore.getErrorInfo(context,
|
||||
errorInfoStore[errorInfoKey, accountKeys[0]])
|
||||
if (errorInfo != null) {
|
||||
showEmpty(errorInfo.icon, errorInfo.message)
|
||||
} else {
|
||||
showEmpty(R.drawable.ic_info_refresh, getString(R.string.swipe_down_to_refresh))
|
||||
}
|
||||
} else {
|
||||
showError(R.drawable.ic_info_accounts, getString(R.string.message_toast_no_account_selected))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun updateFavoritedStatus(status: ParcelableStatus) {
|
||||
activity ?: return
|
||||
replaceStatusStates(status)
|
||||
}
|
||||
|
||||
|
||||
fun replaceStatusStates(result: ParcelableStatus?) {
|
||||
if (result == null) return
|
||||
val lm = layoutManager
|
||||
|
@ -283,6 +265,36 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
|
|||
adapter.notifyItemRangeChanged(rangeStart, rangeEnd)
|
||||
}
|
||||
|
||||
private fun showContentOrError() {
|
||||
val accountKeys = accountKeys
|
||||
if (adapter.itemCount > 0) {
|
||||
showContent()
|
||||
} else if (accountKeys.isNotEmpty()) {
|
||||
val errorInfo = ErrorInfoStore.getErrorInfo(context,
|
||||
errorInfoStore[errorInfoKey, accountKeys[0]])
|
||||
if (errorInfo != null) {
|
||||
showEmpty(errorInfo.icon, errorInfo.message)
|
||||
} else {
|
||||
showEmpty(R.drawable.ic_info_refresh, getString(R.string.swipe_down_to_refresh))
|
||||
}
|
||||
} else {
|
||||
showError(R.drawable.ic_info_accounts, getString(R.string.message_toast_no_account_selected))
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFavoritedStatus(status: ParcelableStatus) {
|
||||
activity ?: return
|
||||
replaceStatusStates(status)
|
||||
}
|
||||
|
||||
private fun clearNotifications() {
|
||||
if (context != null && userVisibleHint) {
|
||||
for (accountKey in accountKeys) {
|
||||
twitterWrapper.clearNotificationAsync(notificationType, accountKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected inner class CursorActivitiesBusCallback {
|
||||
|
||||
@Subscribe
|
||||
|
|
|
@ -27,6 +27,7 @@ import android.net.Uri
|
|||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.support.v4.content.Loader
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.widget.Toast
|
||||
import com.bumptech.glide.Glide
|
||||
import com.squareup.otto.Subscribe
|
||||
|
@ -62,23 +63,63 @@ import org.mariotaku.twidere.util.buildStatusFilterWhereClause
|
|||
*/
|
||||
abstract class CursorStatusesFragment : AbsStatusesFragment() {
|
||||
|
||||
private var contentObserver: ContentObserver? = null
|
||||
private val accountListener: OnAccountsUpdateListener = OnAccountsUpdateListener {
|
||||
reloadStatuses()
|
||||
}
|
||||
|
||||
abstract val errorInfoKey: String
|
||||
abstract val isFilterEnabled: Boolean
|
||||
abstract val notificationType: Int
|
||||
abstract val contentUri: Uri
|
||||
override var refreshing: Boolean
|
||||
get() = swipeLayout.isRefreshing
|
||||
set(value) {
|
||||
super.refreshing = value
|
||||
}
|
||||
|
||||
override val useSortIdAsReadPosition: Boolean
|
||||
get() = false
|
||||
|
||||
override val accountKeys: Array<UserKey>
|
||||
get() = Utils.getAccountKeys(context, arguments) ?: DataStoreUtils.getActivatedAccountKeys(context)
|
||||
|
||||
abstract val errorInfoKey: String
|
||||
abstract val isFilterEnabled: Boolean
|
||||
abstract val notificationType: Int
|
||||
abstract val contentUri: Uri
|
||||
|
||||
private var contentObserver: ContentObserver? = null
|
||||
private val accountListener: OnAccountsUpdateListener = OnAccountsUpdateListener {
|
||||
reloadStatuses()
|
||||
}
|
||||
|
||||
private val onScrollListener = object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
clearNotifications()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (contentObserver == null) {
|
||||
contentObserver = object : ContentObserver(Handler()) {
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
reloadStatuses()
|
||||
}
|
||||
}
|
||||
context.contentResolver.registerContentObserver(Filters.CONTENT_URI, true, contentObserver)
|
||||
}
|
||||
AccountManager.get(context).addOnAccountsUpdatedListenerSafe(accountListener, updateImmediately = false)
|
||||
recyclerView.addOnScrollListener(onScrollListener)
|
||||
updateRefreshState()
|
||||
reloadStatuses()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
recyclerView.removeOnScrollListener(onScrollListener)
|
||||
if (contentObserver != null) {
|
||||
context.contentResolver.unregisterContentObserver(contentObserver)
|
||||
contentObserver = null
|
||||
}
|
||||
AccountManager.get(context).removeOnAccountsUpdatedListenerSafe(accountListener)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
|
||||
override fun onStatusesLoaded(loader: Loader<List<ParcelableStatus>?>, data: List<ParcelableStatus>?) {
|
||||
showContentOrError()
|
||||
}
|
||||
|
@ -110,61 +151,6 @@ abstract class CursorStatusesFragment : AbsStatusesFragment() {
|
|||
return CursorStatusesBusCallback()
|
||||
}
|
||||
|
||||
private fun showContentOrError() {
|
||||
val accountKeys = this.accountKeys
|
||||
if (adapter.itemCount > 0) {
|
||||
showContent()
|
||||
} else if (accountKeys.isNotEmpty()) {
|
||||
val errorInfo = ErrorInfoStore.getErrorInfo(context,
|
||||
errorInfoStore[errorInfoKey, accountKeys[0]])
|
||||
if (errorInfo != null) {
|
||||
showEmpty(errorInfo.icon, errorInfo.message)
|
||||
} else {
|
||||
showEmpty(R.drawable.ic_info_refresh, getString(R.string.swipe_down_to_refresh))
|
||||
}
|
||||
} else {
|
||||
showError(R.drawable.ic_info_accounts, getString(R.string.message_toast_no_account_selected))
|
||||
}
|
||||
}
|
||||
|
||||
override val accountKeys: Array<UserKey>
|
||||
get() = Utils.getAccountKeys(context, arguments) ?: DataStoreUtils.getActivatedAccountKeys(context)
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (contentObserver == null) {
|
||||
contentObserver = object : ContentObserver(Handler()) {
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
reloadStatuses()
|
||||
}
|
||||
}
|
||||
context.contentResolver.registerContentObserver(Filters.CONTENT_URI, true, contentObserver)
|
||||
}
|
||||
AccountManager.get(context).addOnAccountsUpdatedListenerSafe(accountListener, updateImmediately = false)
|
||||
updateRefreshState()
|
||||
reloadStatuses()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
if (contentObserver != null) {
|
||||
context.contentResolver.unregisterContentObserver(contentObserver)
|
||||
contentObserver = null
|
||||
}
|
||||
AccountManager.get(context).removeOnAccountsUpdatedListenerSafe(accountListener)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
protected fun reloadStatuses() {
|
||||
if (context == null || isDetached) return
|
||||
val args = Bundle()
|
||||
val fragmentArgs = arguments
|
||||
if (fragmentArgs != null) {
|
||||
args.putAll(fragmentArgs)
|
||||
args.putBoolean(EXTRA_FROM_USER, true)
|
||||
}
|
||||
loaderManager.restartLoader(loaderId, args, this)
|
||||
}
|
||||
|
||||
override fun hasMoreData(data: List<ParcelableStatus>?): Boolean {
|
||||
return data?.size != 0
|
||||
}
|
||||
|
@ -221,27 +207,60 @@ abstract class CursorStatusesFragment : AbsStatusesFragment() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||
super.setUserVisibleHint(isVisibleToUser)
|
||||
if (isVisibleToUser) {
|
||||
clearNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun getFiltersWhere(table: String): Expression? {
|
||||
if (!isFilterEnabled) return null
|
||||
return buildStatusFilterWhereClause(preferences, table, null)
|
||||
}
|
||||
|
||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||
super.setUserVisibleHint(isVisibleToUser)
|
||||
val context = context
|
||||
if (context != null && isVisibleToUser) {
|
||||
for (accountKey in accountKeys) {
|
||||
twitterWrapper.clearNotificationAsync(notificationType, accountKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun processWhere(where: Expression, whereArgs: Array<String>): ParameterizedExpression {
|
||||
return ParameterizedExpression(where, whereArgs)
|
||||
}
|
||||
|
||||
protected abstract fun updateRefreshState()
|
||||
|
||||
protected fun reloadStatuses() {
|
||||
if (context == null || isDetached) return
|
||||
val args = Bundle()
|
||||
val fragmentArgs = arguments
|
||||
if (fragmentArgs != null) {
|
||||
args.putAll(fragmentArgs)
|
||||
args.putBoolean(EXTRA_FROM_USER, true)
|
||||
}
|
||||
loaderManager.restartLoader(loaderId, args, this)
|
||||
}
|
||||
|
||||
private fun showContentOrError() {
|
||||
val accountKeys = this.accountKeys
|
||||
if (adapter.itemCount > 0) {
|
||||
showContent()
|
||||
} else if (accountKeys.isNotEmpty()) {
|
||||
val errorInfo = ErrorInfoStore.getErrorInfo(context,
|
||||
errorInfoStore[errorInfoKey, accountKeys[0]])
|
||||
if (errorInfo != null) {
|
||||
showEmpty(errorInfo.icon, errorInfo.message)
|
||||
} else {
|
||||
showEmpty(R.drawable.ic_info_refresh, getString(R.string.swipe_down_to_refresh))
|
||||
}
|
||||
} else {
|
||||
showError(R.drawable.ic_info_accounts, getString(R.string.message_toast_no_account_selected))
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearNotifications() {
|
||||
if (context != null && userVisibleHint) {
|
||||
for (accountKey in accountKeys) {
|
||||
twitterWrapper.clearNotificationAsync(notificationType, accountKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected inner class CursorStatusesBusCallback {
|
||||
|
||||
@Subscribe
|
||||
|
|
|
@ -81,7 +81,9 @@ class ContentNotificationManager(
|
|||
val accountKey = pref.accountKey
|
||||
val resources = context.resources
|
||||
val selection = Expression.and(Expression.equalsArgs(Statuses.ACCOUNT_KEY),
|
||||
Expression.greaterThan(Statuses.POSITION_KEY, minPositionKey))
|
||||
Expression.greaterThan(Statuses.POSITION_KEY, minPositionKey),
|
||||
Expression.notEquals(Statuses.IS_GAP, 1)
|
||||
)
|
||||
val selectionArgs = arrayOf(accountKey.toString())
|
||||
val filteredSelection = buildStatusFilterWhereClause(preferences, Statuses.TABLE_NAME,
|
||||
selection)
|
||||
|
@ -164,7 +166,8 @@ class ContentNotificationManager(
|
|||
val accountKey = pref.accountKey
|
||||
val where = Expression.and(
|
||||
Expression.equalsArgs(Activities.ACCOUNT_KEY),
|
||||
Expression.greaterThan(Activities.POSITION_KEY, position)
|
||||
Expression.greaterThan(Activities.POSITION_KEY, position),
|
||||
Expression.notEquals(Activities.IS_GAP, 1)
|
||||
).sql
|
||||
val whereArgs = arrayOf(accountKey.toString())
|
||||
@SuppressLint("Recycle")
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
<item>de</item>
|
||||
<item>el</item>
|
||||
<item>en_GB</item>
|
||||
<item>en_US</item>
|
||||
<item>es</item>
|
||||
<item>fa</item>
|
||||
<item>fi</item>
|
||||
|
@ -77,7 +78,8 @@
|
|||
<item>Danish</item>
|
||||
<item>German</item>
|
||||
<item>Greek</item>
|
||||
<item>English (UK)</item>
|
||||
<item>English (GB)</item>
|
||||
<item>English (United States)</item>
|
||||
<item>Spanish</item>
|
||||
<item>Persian</item>
|
||||
<item>Finnish</item>
|
||||
|
|
Loading…
Reference in New Issue