@ -21,10 +21,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import at.connyduck.calladapter.networkresult.NetworkResult
import at.connyduck.calladapter.networkresult.fold
import at.connyduck.calladapter.networkresult.getOrElse
import at.connyduck.calladapter.networkresult.getOrThrow
import com.keylesspalace.tusky.appstore.Event
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.FilterUpdatedEvent
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
@ -32,13 +29,11 @@ import com.keylesspalace.tusky.components.preference.PreferencesFragment.Reading
import com.keylesspalace.tusky.components.timeline.util.ifExpected
import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.entity.FilterV1
import com.keylesspalace.tusky.entity.Poll
import com.keylesspalace.tusky.network.FilterModel
import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.usecase.TimelineCases
import com.keylesspalace.tusky.util.isHttpNotFound
import com.keylesspalace.tusky.viewdata.StatusViewData
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
@ -73,7 +68,6 @@ abstract class TimelineViewModel(
this . kind = kind
this . id = id
this . tags = tags
filterModel . kind = kind . toFilterKind ( )
if ( kind == Kind . HOME ) {
// Note the variable is "true if filter" but the underlying preference/settings text is "true if show"
@ -91,10 +85,27 @@ abstract class TimelineViewModel(
viewModelScope . launch {
eventHub . events
. collect { event -> handleEvent ( event ) }
. collect { event ->
when ( event ) {
is PreferenceChangedEvent -> {
onPreferenceChanged ( event . preferenceKey )
}
is FilterUpdatedEvent -> {
if ( filterContextMatchesKind ( this @TimelineViewModel . kind , event . filterContext ) ) {
filterModel . init ( kind . toFilterKind ( ) )
fullReload ( )
}
}
}
}
}
reloadFilters ( )
viewModelScope . launch {
val needsRefresh = filterModel . init ( kind . toFilterKind ( ) )
if ( needsRefresh ) {
fullReload ( )
}
}
}
fun reblog ( reblog : Boolean , status : StatusViewData . Concrete ) : Job = viewModelScope . launch {
@ -208,11 +219,6 @@ abstract class TimelineViewModel(
fullReload ( )
}
}
FilterV1 . HOME , FilterV1 . NOTIFICATIONS , FilterV1 . THREAD , FilterV1 . PUBLIC , FilterV1 . ACCOUNT -> {
if ( filterContextMatchesKind ( kind , listOf ( key ) ) ) {
reloadFilters ( )
}
}
PrefKeys . ALWAYS _SHOW _SENSITIVE _MEDIA -> {
// it is ok if only newly loaded statuses are affected, no need to fully refresh
alwaysShowSensitiveMedia =
@ -224,50 +230,6 @@ abstract class TimelineViewModel(
}
}
private fun handleEvent ( event : Event ) {
when ( event ) {
is PreferenceChangedEvent -> {
onPreferenceChanged ( event . preferenceKey )
}
is FilterUpdatedEvent -> {
if ( filterContextMatchesKind ( kind , event . filterContext ) ) {
fullReload ( )
}
}
}
}
private fun reloadFilters ( ) {
viewModelScope . launch {
api . getFilters ( ) . fold (
{
// After the filters are loaded we need to reload displayed content to apply them.
// It can happen during the usage or at startup, when we get statuses before filters.
invalidate ( )
} ,
{ throwable ->
if ( throwable . isHttpNotFound ( ) ) {
// Fallback to client-side filter code
val filters = api . getFiltersV1 ( ) . getOrElse {
Log . e ( TAG , " Failed to fetch filters " , it )
return @launch
}
filterModel . initWithFilters (
filters . filter {
filterContextMatchesKind ( kind , it . context )
}
)
// After the filters are loaded we need to reload displayed content to apply them.
// It can happen during the usage or at startup, when we get statuses before filters.
invalidate ( )
} else {
Log . e ( TAG , " Error getting filters " , throwable )
}
}
)
}
}
abstract suspend fun translate ( status : StatusViewData . Concrete ) : NetworkResult < Unit >
abstract fun untranslate ( status : StatusViewData . Concrete )