Refactor notifications to Kotlin & paging (#4026)
This refactors the NotificationsFragment and related classes to Kotlin & paging. While trying to preserve as much of the original behavior as possible, this adds the following improvements as well: - The "show notifications filter" preference was added again - The "load more" button now has a background ripple effect when clicked - The "legal" report category of Mastodon 4.2 is now supported in report notifications - Unknown notifications now display "unknown notification type" instead of an empty line Other code quality improvements: - All views from xml layouts are now referenced via ViewBindings - the classes responsible for showing system notifications were moved to a new package `systemnotifications` while the classes from this refactoring are in `notifications` - the id of the local Tusky account is now called `tuskyAccountId` in all places I could find closes https://github.com/tuskyapp/Tusky/issues/3429 --------- Co-authored-by: Zongle Wang <wangzongler@gmail.com>
This commit is contained in:
parent
3bbf96b057
commit
b2c0b18c8e
121 changed files with 6992 additions and 4654 deletions
|
|
@ -2,6 +2,9 @@ package com.keylesspalace.tusky.appstore
|
|||
|
||||
import com.keylesspalace.tusky.db.AccountManager
|
||||
import com.keylesspalace.tusky.db.AppDatabase
|
||||
import com.keylesspalace.tusky.entity.Poll
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.adapter
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -9,40 +12,64 @@ import kotlinx.coroutines.SupervisorJob
|
|||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Updates the database cache in response to events.
|
||||
* This is important for the home timeline and notifications to be up to date.
|
||||
*/
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
class CacheUpdater @Inject constructor(
|
||||
eventHub: EventHub,
|
||||
accountManager: AccountManager,
|
||||
appDatabase: AppDatabase
|
||||
appDatabase: AppDatabase,
|
||||
moshi: Moshi
|
||||
) {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
|
||||
init {
|
||||
val timelineDao = appDatabase.timelineDao()
|
||||
private val timelineDao = appDatabase.timelineDao()
|
||||
private val statusDao = appDatabase.timelineStatusDao()
|
||||
private val notificationsDao = appDatabase.notificationsDao()
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
eventHub.events.collect { event ->
|
||||
val accountId = accountManager.activeAccount?.id ?: return@collect
|
||||
val tuskyAccountId = accountManager.activeAccount?.id ?: return@collect
|
||||
when (event) {
|
||||
is StatusChangedEvent -> {
|
||||
val status = event.status
|
||||
timelineDao.update(
|
||||
accountId = accountId,
|
||||
status = status
|
||||
)
|
||||
is StatusChangedEvent -> statusDao.update(
|
||||
tuskyAccountId = tuskyAccountId,
|
||||
status = event.status,
|
||||
moshi = moshi
|
||||
)
|
||||
|
||||
is UnfollowEvent -> timelineDao.removeStatusesAndReblogsByUser(tuskyAccountId, event.accountId)
|
||||
|
||||
is BlockEvent -> removeAllByUser(tuskyAccountId, event.accountId)
|
||||
is MuteEvent -> removeAllByUser(tuskyAccountId, event.accountId)
|
||||
|
||||
is DomainMuteEvent -> {
|
||||
timelineDao.deleteAllFromInstance(tuskyAccountId, event.instance)
|
||||
notificationsDao.deleteAllFromInstance(tuskyAccountId, event.instance)
|
||||
}
|
||||
is UnfollowEvent ->
|
||||
timelineDao.removeAllByUser(accountId, event.accountId)
|
||||
is StatusDeletedEvent ->
|
||||
timelineDao.delete(accountId, event.statusId)
|
||||
|
||||
is StatusDeletedEvent -> {
|
||||
timelineDao.deleteAllWithStatus(tuskyAccountId, event.statusId)
|
||||
notificationsDao.deleteAllWithStatus(tuskyAccountId, event.statusId)
|
||||
}
|
||||
|
||||
is PollVoteEvent -> {
|
||||
timelineDao.setVoted(accountId, event.statusId, event.poll)
|
||||
val pollString = moshi.adapter<Poll>().toJson(event.poll)
|
||||
statusDao.setVoted(tuskyAccountId, event.statusId, pollString)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun removeAllByUser(tuskyAccountId: Long, accountId: String) {
|
||||
timelineDao.removeAllByUser(tuskyAccountId, accountId)
|
||||
notificationsDao.removeAllByUser(tuskyAccountId, accountId)
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
this.scope.cancel()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
package com.keylesspalace.tusky.appstore
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import java.util.function.Consumer
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
interface Event
|
||||
|
||||
|
|
@ -21,13 +17,4 @@ class EventHub @Inject constructor() {
|
|||
suspend fun dispatch(event: Event) {
|
||||
_events.emit(event)
|
||||
}
|
||||
|
||||
// TODO remove as soon as NotificationsFragment is Kotlin
|
||||
fun subscribe(lifecycleOwner: LifecycleOwner, consumer: Consumer<Event>) {
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
events.collect { event ->
|
||||
consumer.accept(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue