@ -21,10 +21,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import androidx.paging.PagingData
import at.connyduck.calladapter.networkresult.NetworkResult
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 at.connyduck.calladapter.networkresult.getOrThrow
import com.keylesspalace.tusky.appstore.Event
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.FilterUpdatedEvent
import com.keylesspalace.tusky.appstore.FilterUpdatedEvent
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
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.components.timeline.util.ifExpected
import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.entity.FilterV1
import com.keylesspalace.tusky.entity.Poll
import com.keylesspalace.tusky.entity.Poll
import com.keylesspalace.tusky.network.FilterModel
import com.keylesspalace.tusky.network.FilterModel
import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.usecase.TimelineCases
import com.keylesspalace.tusky.usecase.TimelineCases
import com.keylesspalace.tusky.util.isHttpNotFound
import com.keylesspalace.tusky.viewdata.StatusViewData
import com.keylesspalace.tusky.viewdata.StatusViewData
import kotlinx.coroutines.Job
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
@ -73,7 +68,6 @@ abstract class TimelineViewModel(
this . kind = kind
this . kind = kind
this . id = id
this . id = id
this . tags = tags
this . tags = tags
filterModel . kind = kind . toFilterKind ( )
if ( kind == Kind . HOME ) {
if ( kind == Kind . HOME ) {
// Note the variable is "true if filter" but the underlying preference/settings text is "true if show"
// 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 {
viewModelScope . launch {
eventHub . events
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 {
fun reblog ( reblog : Boolean , status : StatusViewData . Concrete ) : Job = viewModelScope . launch {
@ -208,11 +219,6 @@ abstract class TimelineViewModel(
fullReload ( )
fullReload ( )
}
}
}
}
FilterV1 . HOME , FilterV1 . NOTIFICATIONS , FilterV1 . THREAD , FilterV1 . PUBLIC , FilterV1 . ACCOUNT -> {
if ( filterContextMatchesKind ( kind , listOf ( key ) ) ) {
reloadFilters ( )
}
}
PrefKeys . ALWAYS _SHOW _SENSITIVE _MEDIA -> {
PrefKeys . ALWAYS _SHOW _SENSITIVE _MEDIA -> {
// it is ok if only newly loaded statuses are affected, no need to fully refresh
// it is ok if only newly loaded statuses are affected, no need to fully refresh
alwaysShowSensitiveMedia =
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 suspend fun translate ( status : StatusViewData . Concrete ) : NetworkResult < Unit >
abstract fun untranslate ( status : StatusViewData . Concrete )
abstract fun untranslate ( status : StatusViewData . Concrete )