feat: list of hidden posts (#966)

This commit is contained in:
Diego Beraldin 2024-06-11 00:15:07 +02:00 committed by GitHub
parent 4c65208907
commit 33aacd686f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
58 changed files with 1174 additions and 748 deletions

View File

@ -51,6 +51,7 @@ interface PostService {
@Query("saved_only") savedOnly: Boolean? = null,
@Query("liked_only") likedOnly: Boolean? = null,
@Query("disliked_only") dislikedOnly: Boolean? = null,
@Query("show_hidden") showHidden: Boolean? = null,
): GetPostsResponse
@GET("post")

View File

@ -416,4 +416,5 @@ internal val ArStrings =
override val communityVisibilityPublic = "عام"
override val noticeCommunityLocalOnly = "هذا المجتمع مرئي فقط في المثيل الحالي"
override val noticeBannedUser = "تم حظر المستخدم الحالي من هذا المجتمع"
override val settingsHiddenPosts = "المشاركات المخفية"
}

View File

@ -424,4 +424,5 @@ internal val BgStrings =
override val noticeCommunityLocalOnly =
"Тази общност е видима само в рамките на текущия екземпляр"
override val noticeBannedUser = "Настоящият потребител е забранен от тази общност"
override val settingsHiddenPosts = "Скрити публикации"
}

View File

@ -420,4 +420,5 @@ internal val CsStrings =
override val noticeCommunityLocalOnly =
"Tato komunita je viditelná pouze v aktuální instanci"
override val noticeBannedUser = "Aktuálnímu uživateli byl zakázán přístup do této komunity"
override val settingsHiddenPosts = "Skryté příspěvky"
}

View File

@ -420,4 +420,5 @@ internal val DaStrings =
"Dette fællesskab er kun synligt i den aktuelle forekomst"
override val noticeBannedUser =
"Den nuværende bruger er blevet udelukket fra dette fællesskab"
override val settingsHiddenPosts = "Skjulte indlæg"
}

View File

@ -424,4 +424,5 @@ internal val DeStrings =
override val noticeCommunityLocalOnly =
"Diese Community ist nur innerhalb der aktuellen Instanz sichtbar"
override val noticeBannedUser = "Der aktuelle Benutzer wurde aus dieser Community gesperrt"
override val settingsHiddenPosts = "Versteckte Beiträge"
}

View File

@ -427,4 +427,5 @@ internal val ElStrings =
override val noticeCommunityLocalOnly =
"Αυτή η κοινότητα είναι ορατή μόνο στην τρέχουσα παρουσία"
override val noticeBannedUser = "Ο τρέχων χρήστης έχει αποκλειστεί από αυτήν την κοινότητα"
override val settingsHiddenPosts = "Κρυφές αναρτήσεις"
}

View File

@ -417,4 +417,5 @@ internal val EnStrings =
override val noticeCommunityLocalOnly =
"This community is only visible within the current instance"
override val noticeBannedUser = "The current user has been banned from this community"
override val settingsHiddenPosts = "Hidden posts"
}

View File

@ -416,4 +416,5 @@ internal val EoStrings =
override val noticeCommunityLocalOnly =
"Ĉi tiu komunumo estas videbla nur ene de la nuna nodo"
override val noticeBannedUser = "La nuna uzanto estas malpermesita de ĉi tiu komunumo"
override val settingsHiddenPosts = "Kaŝitaj afiŝoj"
}

View File

@ -421,4 +421,5 @@ internal val EsStrings =
override val noticeCommunityLocalOnly =
"Esta comunidad sólo es visible dentro de la instancia actual"
override val noticeBannedUser = "El usuario actual ha sido baneado de esta comunidad"
override val settingsHiddenPosts = "Publicaciones escondidas"
}

View File

@ -422,4 +422,5 @@ internal val EtStrings =
override val noticeCommunityLocalOnly =
"See kommuun on nähtav ainult praeguses eksemplaris"
override val noticeBannedUser = "Praegune kasutaja on sellest kogukonnast keelatud"
override val settingsHiddenPosts = "Peidetud postitused"
}

View File

@ -417,4 +417,5 @@ internal val FiStrings =
override val communityVisibilityPublic = "julkinen"
override val noticeCommunityLocalOnly = "Tämä yhteisö näkyy vain nykyisessä ilmentymässä"
override val noticeBannedUser = "Nykyinen käyttäjä on estetty tästä yhteisöstä"
override val settingsHiddenPosts = "Piilotetut viestit"
}

View File

@ -426,4 +426,5 @@ internal val FrStrings =
override val noticeCommunityLocalOnly =
"Cette communauté n\'est visible que dans l\'instance actuelle"
override val noticeBannedUser = "L\'utilisateur actuel a été banni de cette communauté"
override val settingsHiddenPosts = "Messages masqués"
}

View File

@ -421,4 +421,5 @@ internal val GaStrings =
override val communityVisibilityPublic = "poiblí"
override val noticeCommunityLocalOnly = "Níl an pobal seo le feiceáil ach sa chás reatha"
override val noticeBannedUser = "Tá cosc ar an úsáideoir reatha ón bpobal seo"
override val settingsHiddenPosts = "Poist i bhfolach"
}

View File

@ -421,4 +421,5 @@ internal val HrStrings =
override val noticeCommunityLocalOnly =
"Ova je zajednica vidljiva samo unutar trenutne instance"
override val noticeBannedUser = "Trenutačni korisnik je zabranjen iz ove zajednice"
override val settingsHiddenPosts = "Skriveni postovi"
}

View File

@ -425,4 +425,5 @@ internal val HuStrings =
override val noticeCommunityLocalOnly =
"Ez a közösség csak az aktuális példányon belül látható"
override val noticeBannedUser = "A jelenlegi felhasználót kitiltották a közösségből"
override val settingsHiddenPosts = "Rejtett bejegyzések"
}

View File

@ -422,4 +422,5 @@ internal val ItStrings =
override val noticeCommunityLocalOnly =
"Questa comunità è visibile esclusivamente all'interno dell'istanza corrente"
override val noticeBannedUser = "L\'utente corrente è stato bannato da questa comunità"
override val settingsHiddenPosts = "Post nascosti"
}

View File

@ -420,4 +420,5 @@ internal val LtStrings =
"Ši bendruomenė matoma tik dabartiniame egzemplioriuje"
override val noticeBannedUser =
"Dabartinis vartotojas buvo uždraustas dalyvauti šioje bendruomenėje"
override val settingsHiddenPosts = "Paslėpti įrašai"
}

View File

@ -419,4 +419,5 @@ internal val LvStrings =
override val communityVisibilityPublic = "publiski"
override val noticeCommunityLocalOnly = "Šī kopiena ir redzama tikai pašreizējā instancē"
override val noticeBannedUser = "Pašreizējais lietotājs ir bloķēts no šīs kopienas"
override val settingsHiddenPosts = "Slēptās ziņas"
}

View File

@ -421,4 +421,5 @@ internal val MtStrings =
override val noticeCommunityLocalOnly: String =
"Din il-komunità hija viżibbli biss fl-istanza attwali"
override val noticeBannedUser = "L-utent attwali ġie pprojbit minn din il-komunità"
override val settingsHiddenPosts = "Postijiet moħbija"
}

View File

@ -422,4 +422,5 @@ internal val NlStrings =
override val noticeCommunityLocalOnly: String =
"Deze community is alleen zichtbaar binnen het huidige exemplaar"
override val noticeBannedUser = "De huidige gebruiker is uitgesloten van deze community"
override val settingsHiddenPosts = "Verborgen berichten"
}

View File

@ -419,4 +419,5 @@ internal val NoStrings =
"Dette fellesskapet er bare synlig i gjeldende forekomst"
override val noticeBannedUser =
"Den nåværende brukeren har blitt utestengt fra dette fellesskapet"
override val settingsHiddenPosts = "Skjulte innlegg"
}

View File

@ -421,4 +421,5 @@ internal val PlStrings =
override val noticeCommunityLocalOnly =
"Ta społeczność jest widoczna tylko w bieżącej instancji"
override val noticeBannedUser = "Bieżący użytkownik został zablokowany w tej społeczności"
override val settingsHiddenPosts = "Ukryte posty"
}

View File

@ -419,4 +419,5 @@ internal val PtBrStrings =
override val communityVisibilityPublic = "pública"
override val noticeCommunityLocalOnly = "Esta comunidade só é visível na instância atual"
override val noticeBannedUser = "O usuário atual foi banido desta comunidade"
override val settingsHiddenPosts = "Posts escondidos"
}

View File

@ -420,4 +420,5 @@ internal val PtStrings =
override val communityVisibilityPublic = "pública"
override val noticeCommunityLocalOnly = "Esta comunidade só é visível na instância atual"
override val noticeBannedUser = "O usuário atual foi banido desta comunidade"
override val settingsHiddenPosts = "Postagens ocultadas"
}

View File

@ -420,4 +420,5 @@ internal val RoStrings =
override val noticeCommunityLocalOnly =
"Această comunitate este vizibilă numai în instanța curentă"
override val noticeBannedUser = "Utilizatorul actual a fost exclus din această comunitate"
override val settingsHiddenPosts = "Postări ascunse"
}

View File

@ -422,4 +422,5 @@ internal val RuStrings =
override val communityVisibilityPublic = "общественный"
override val noticeCommunityLocalOnly = "Это сообщество видно только в текущем экземпляре"
override val noticeBannedUser = "Текущий пользователь заблокирован в этом сообществе"
override val settingsHiddenPosts = "Скрытые сообщения"
}

View File

@ -420,4 +420,5 @@ internal val SeStrings =
override val noticeCommunityLocalOnly =
"Denna grupp är endast synlig inom den aktuella instansen"
override val noticeBannedUser = "Den nuvarande användaren har blockerats från denna grupp"
override val settingsHiddenPosts = "Dolda inlägg"
}

View File

@ -422,4 +422,5 @@ internal val SkStrings =
override val noticeCommunityLocalOnly =
"Táto komunita je viditeľná iba v rámci aktuálnej inštancie"
override val noticeBannedUser = "Aktuálny používateľ má zakázaný prístup do tejto komunity"
override val settingsHiddenPosts = "Skryté príspevky"
}

View File

@ -420,4 +420,5 @@ internal val SlStrings =
override val noticeCommunityLocalOnly =
"Ta skupnost je vidna samo znotraj trenutne instance"
override val noticeBannedUser = "Trenutni uporabnik je bil izključen iz te skupnosti"
override val settingsHiddenPosts = "Skrite objave"
}

View File

@ -422,4 +422,5 @@ internal val SqStrings =
override val noticeCommunityLocalOnly =
"Ky komunitet është i dukshëm vetëm brenda shembullit aktual"
override val noticeBannedUser = "Përdoruesi aktual është përjashtuar nga ky komunitet"
override val settingsHiddenPosts = "Postimet e fshehura"
}

View File

@ -422,4 +422,5 @@ internal val SrStrings =
override val noticeCommunityLocalOnly =
"Ова заједница је видљива само у оквиру тренутне инстанце"
override val noticeBannedUser = "Тренутном кориснику је забрањен приступ овој заједници"
override val settingsHiddenPosts = "Скривени постови"
}

View File

@ -415,6 +415,7 @@ interface Strings {
val communityVisibilityPublic: String
val noticeCommunityLocalOnly: String
val noticeBannedUser: String
val settingsHiddenPosts: String
}
object Locales {

View File

@ -416,4 +416,5 @@ internal val TokStrings =
override val communityVisibilityPublic = "tawa ale"
override val noticeCommunityLocalOnly = "kulupu ni li ken lukin lon ilo nanpa ni taso"
override val noticeBannedUser = "sina ken lukin ala e lipu mute pi kulupu ni"
override val settingsHiddenPosts = "lipu pi lukin ala"
}

View File

@ -421,4 +421,5 @@ internal val TrStrings =
override val noticeCommunityLocalOnly =
"Bu topluluk yalnızca mevcut örnekte görülebilir"
override val noticeBannedUser = "Mevcut kullanıcı bu topluluktan yasaklandı"
override val settingsHiddenPosts = "Gizli gönderiler"
}

View File

@ -422,4 +422,5 @@ internal val UkStrings =
override val noticeCommunityLocalOnly =
"Цю спільноту можна побачити лише в поточному екземплярі"
override val noticeBannedUser = "Поточний користувач був забанений у цій спільноті"
override val settingsHiddenPosts = "Приховані пости"
}

View File

@ -27,8 +27,7 @@ internal class DefaultPostPaginationManager(
private val multiCommunityPaginator: MultiCommunityPaginator,
dispatcher: CoroutineDispatcher = Dispatchers.IO,
notificationCenter: NotificationCenter,
) : PostPaginationManager {
) : PostPaginationManager {
override var canFetchMore: Boolean = true
private set
override val history: MutableList<PostModel> = mutableListOf()
@ -197,6 +196,27 @@ internal class DefaultPostPaginationManager(
.deduplicate()
.filterDeleted()
}
is PostPaginationSpecification.Hidden -> {
val (itemList, nextPage) =
userRepository.getHiddenPosts(
auth = auth,
page = currentPage,
pageCursor = pageCursor,
sort = SortType.New,
) ?: (null to null)
if (!itemList.isNullOrEmpty()) {
currentPage++
}
if (nextPage != null) {
pageCursor = nextPage
}
canFetchMore = itemList?.isEmpty() != true
itemList
.orEmpty()
.deduplicate()
.filterDeleted()
}
}
history.addAll(result)

View File

@ -41,4 +41,8 @@ sealed interface PostPaginationSpecification {
data class Saved(
val sortType: SortType = SortType.Active,
) : PostPaginationSpecification
data class Hidden(
val sortType: SortType = SortType.Active,
) : PostPaginationSpecification
}

View File

@ -0,0 +1,56 @@
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository
import com.github.diegoberaldin.raccoonforlemmy.core.testutils.DispatcherTestRule
import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class DefaultGetSiteSupportsHiddenPostsUseCaseTest {
@get:Rule
val dispatcherTestRule = DispatcherTestRule()
private val isSiteVersionAtLeastUseCase: IsSiteVersionAtLeastUseCase = mockk()
private val sut =
DefaultGetSiteSupportsHiddenPostsUseCase(
isSiteVersionAtLeastUseCase = isSiteVersionAtLeastUseCase,
)
@Test
fun givenVersionAboveThreshold_whenInvoke_thenResultsIsAsExpected() =
runTest {
coEvery {
isSiteVersionAtLeastUseCase.execute(
major = any(),
minor = any(),
patch = any(),
otherInstance = any(),
)
} returns true
val res = sut.invoke()
assertTrue(res)
}
@Test
fun givenVersionBelowThreshold_whenInvoke_thenResultsIsAsExpected() =
runTest {
coEvery {
isSiteVersionAtLeastUseCase.execute(
major = any(),
minor = any(),
patch = any(),
otherInstance = any(),
)
} returns false
val res = sut.invoke()
assertFalse(res)
}
}

View File

@ -14,20 +14,19 @@ class DefaultGetSortTypesUseCaseTest {
@get:Rule
val dispatcherTestRule = DispatcherTestRule()
private val siteRepository: SiteRepository = mockk(relaxUnitFun = true)
private val isSiteVersionAtLeastUseCase: IsSiteVersionAtLeastUseCase = mockk()
private val sut = DefaultGetSortTypesUseCase(
siteRepository = siteRepository,
private val sut =
DefaultGetSortTypesUseCase(
isSiteVersionAtLeastUseCase = isSiteVersionAtLeastUseCase,
)
@Test
fun givenVersionEqualTo019_whenGetTypesForPosts_thenResultsIsAsExpected() = runTest {
fun givenVersionEqualToThreshold_whenGetTypesForPosts_thenResultsIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion(
auth = any(),
otherInstance = any()
)
} returns "0.19"
isSiteVersionAtLeastUseCase.execute(any(), any(), any(), any())
} returns true
val res = sut.getTypesForPosts()
@ -43,13 +42,11 @@ class DefaultGetSortTypesUseCaseTest {
}
@Test
fun givenVersionGreaterThan019WithPatch_whenGetTypesForPosts_thenResultsIsAsExpected() = runTest {
fun givenVersionGreaterThanThreshold_whenGetTypesForPosts_thenResultsIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion(
auth = any(),
otherInstance = any()
)
} returns "0.19.2"
isSiteVersionAtLeastUseCase.execute(any(), any(), any(), any())
} returns true
val res = sut.getTypesForPosts()
@ -65,35 +62,11 @@ class DefaultGetSortTypesUseCaseTest {
}
@Test
fun givenVersionGreaterThan019WithMinor_whenGetTypesForPosts_thenResultsIsAsExpected() = runTest {
fun givenVersionLessThanThreshold_whenGetTypesForPosts_thenResultsIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion(
auth = any(),
otherInstance = any()
)
} returns "0.20"
val res = sut.getTypesForPosts()
assertTrue(res.contains(SortType.Controversial))
assertTrue(res.contains(SortType.Scaled))
assertTrue(res.contains(SortType.Active))
assertTrue(res.contains(SortType.Hot))
assertTrue(res.contains(SortType.New))
assertTrue(res.contains(SortType.Old))
assertTrue(res.contains(SortType.MostComments))
assertTrue(res.contains(SortType.NewComments))
assertTrue(res.contains(SortType.Top.Generic))
}
@Test
fun givenVersionLessThan019_whenGetTypesForPosts_thenResultsIsAsExpected() = runTest {
coEvery {
siteRepository.getSiteVersion(
auth = any(),
otherInstance = any()
)
} returns "0.18.5"
isSiteVersionAtLeastUseCase.execute(any(), any(), any(), any())
} returns false
val res = sut.getTypesForPosts()
@ -109,13 +82,11 @@ class DefaultGetSortTypesUseCaseTest {
}
@Test
fun givenVersionEqualTo019_whenGetTypesForComments_thenResultsIsAsExpected() = runTest {
fun givenVersionGreaterThanThreshold_whenGetTypesForComments_thenResultsIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion(
auth = any(),
otherInstance = any()
)
} returns "0.19"
isSiteVersionAtLeastUseCase.execute(any(), any(), any(), any())
} returns true
val res = sut.getTypesForComments()
@ -127,49 +98,11 @@ class DefaultGetSortTypesUseCaseTest {
}
@Test
fun givenVersionGreaterThan019WithPatch_whenGetTypesForComments_thenResultsIsAsExpected() = runTest {
fun givenVersionLessThanThreshold_whenGetTypesForComments_thenResultsIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion(
auth = any(),
otherInstance = any()
)
} returns "0.19.2"
val res = sut.getTypesForComments()
assertTrue(res.contains(SortType.Controversial))
assertTrue(res.contains(SortType.Hot))
assertTrue(res.contains(SortType.New))
assertTrue(res.contains(SortType.Old))
assertTrue(res.contains(SortType.Top.Generic))
}
@Test
fun givenVersionGreaterThan019WithMinor_whenGetTypesForComments_thenResultsIsAsExpected() = runTest {
coEvery {
siteRepository.getSiteVersion(
auth = any(),
otherInstance = any()
)
} returns "0.20"
val res = sut.getTypesForPosts()
assertTrue(res.contains(SortType.Controversial))
assertTrue(res.contains(SortType.Hot))
assertTrue(res.contains(SortType.New))
assertTrue(res.contains(SortType.Old))
assertTrue(res.contains(SortType.Top.Generic))
}
@Test
fun givenVersionLessThan019_whenGetTypesForComments_thenResultsIsAsExpected() = runTest {
coEvery {
siteRepository.getSiteVersion(
auth = any(),
otherInstance = any()
)
} returns "0.18.5"
isSiteVersionAtLeastUseCase.execute(any(), any(), any(), any())
} returns false
val res = sut.getTypesForComments()
@ -181,7 +114,8 @@ class DefaultGetSortTypesUseCaseTest {
}
@Test
fun whenGetTypesForCommunities_thenResultsIsAsExpected() = runTest {
fun whenGetTypesForCommunities_thenResultsIsAsExpected() =
runTest {
val res = sut.getTypesForCommunities()
assertTrue(res.contains(SortType.Active))
@ -190,7 +124,8 @@ class DefaultGetSortTypesUseCaseTest {
}
@Test
fun whenGetTypesForSavedItems_thenResultsIsAsExpected() = runTest {
fun whenGetTypesForSavedItems_thenResultsIsAsExpected() =
runTest {
val res = sut.getTypesForSavedItems()
assertTrue(res.contains(SortType.Hot))

View File

@ -0,0 +1,103 @@
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository
import com.github.diegoberaldin.raccoonforlemmy.core.testutils.DispatcherTestRule
import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class DefaultIsSiteVersionAtLeastUseCaseTest {
@get:Rule
val dispatcherTestRule = DispatcherTestRule()
private val siteRepository = mockk<SiteRepository>()
private val sut = DefaultIsSiteVersionAtLeastUseCase(siteRepository = siteRepository)
@Test
fun givenSameVersion_whenExecute_thenResultIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion()
} returns "0.19.2"
val res = sut.execute(0, 19, 2)
assertTrue(res)
}
@Test
fun givenPatchLessThanThreshold_whenExecute_thenResultIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion()
} returns "0.19.2"
val res = sut.execute(0, 19, 3)
assertFalse(res)
}
@Test
fun givenPatchGreaterThanThreshold_whenExecute_thenResultIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion()
} returns "0.19.2"
val res = sut.execute(0, 19, 1)
assertTrue(res)
}
@Test
fun givenMinorLessThanThreshold_whenExecute_thenResultIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion()
} returns "0.18.2"
val res = sut.execute(0, 19, 1)
assertFalse(res)
}
@Test
fun givenMinorGreaterThanThreshold_whenExecute_thenResultIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion()
} returns "0.20.2"
val res = sut.execute(0, 19, 1)
assertTrue(res)
}
@Test
fun givenMajorLessThanThreshold_whenExecute_thenResultIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion()
} returns "0.2.1"
val res = sut.execute(1, 1, 1)
assertFalse(res)
}
@Test
fun givenMajorGreaterThanThreshold_whenExecute_thenResultIsAsExpected() =
runTest {
coEvery {
siteRepository.getSiteVersion()
} returns "1.1.0"
val res = sut.execute(0, 19, 1)
assertTrue(res)
}
}

View File

@ -44,19 +44,24 @@ class DefaultUserRepositoryTest {
every { comment } returns commentService
}
private val sut = DefaultUserRepository(
private val sut =
DefaultUserRepository(
services = serviceProvider,
customServices = customServiceProvider,
)
@Test
fun whenGetResolved_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetResolved_thenResultAndInteractionsAreAsExpected() =
runTest {
val userId = 1L
coEvery {
searchService.resolveObject(any(), any())
} returns mockk {
every { user } returns mockk(relaxed = true) {
every { person } returns mockk(relaxed = true) {
} returns
mockk {
every { user } returns
mockk(relaxed = true) {
every { person } returns
mockk(relaxed = true) {
every { id } returns userId
}
}
@ -76,7 +81,8 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenGet_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGet_thenResultAndInteractionsAreAsExpected() =
runTest {
val userId = 1L
coEvery {
userService.getDetails(
@ -84,9 +90,12 @@ class DefaultUserRepositoryTest {
auth = any(),
personId = any(),
)
} returns mockk {
every { personView } returns mockk(relaxed = true) {
every { person } returns mockk(relaxed = true) {
} returns
mockk {
every { personView } returns
mockk(relaxed = true) {
every { person } returns
mockk(relaxed = true) {
every { id } returns userId
}
}
@ -106,7 +115,8 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenGetPosts_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetPosts_thenResultAndInteractionsAreAsExpected() =
runTest {
val postId = 1L
coEvery {
userService.getDetails(
@ -120,14 +130,18 @@ class DefaultUserRepositoryTest {
savedOnly = any(),
communityId = any(),
)
} returns mockk {
every { personView } returns mockk(relaxed = true) {
every { posts } returns listOf(
} returns
mockk {
every { personView } returns
mockk(relaxed = true) {
every { posts } returns
listOf(
mockk(relaxed = true) {
every { post } returns
mockk(relaxed = true) {
every { post } returns mockk(relaxed = true) {
every { id } returns postId
}
}
},
)
}
}
@ -150,7 +164,8 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenGetSavedPosts_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetSavedPosts_thenResultAndInteractionsAreAsExpected() =
runTest {
val postId = 1L
coEvery {
userService.getDetails(
@ -164,14 +179,18 @@ class DefaultUserRepositoryTest {
savedOnly = any(),
communityId = any(),
)
} returns mockk {
every { personView } returns mockk(relaxed = true) {
every { posts } returns listOf(
} returns
mockk {
every { personView } returns
mockk(relaxed = true) {
every { posts } returns
listOf(
mockk(relaxed = true) {
every { post } returns
mockk(relaxed = true) {
every { post } returns mockk(relaxed = true) {
every { id } returns postId
}
}
},
)
}
}
@ -195,7 +214,8 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenGetComments_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetComments_thenResultAndInteractionsAreAsExpected() =
runTest {
val commentId = 1L
coEvery {
userService.getDetails(
@ -209,14 +229,18 @@ class DefaultUserRepositoryTest {
savedOnly = any(),
communityId = any(),
)
} returns mockk {
every { personView } returns mockk(relaxed = true) {
every { comments } returns listOf(
} returns
mockk {
every { personView } returns
mockk(relaxed = true) {
every { comments } returns
listOf(
mockk(relaxed = true) {
every { comment } returns
mockk(relaxed = true) {
every { comment } returns mockk(relaxed = true) {
every { id } returns commentId
}
}
},
)
}
}
@ -239,7 +263,8 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenGetSavedComments_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetSavedComments_thenResultAndInteractionsAreAsExpected() =
runTest {
val commentId = 1L
coEvery {
userService.getDetails(
@ -253,14 +278,18 @@ class DefaultUserRepositoryTest {
savedOnly = any(),
communityId = any(),
)
} returns mockk {
every { personView } returns mockk(relaxed = true) {
every { comments } returns listOf(
} returns
mockk {
every { personView } returns
mockk(relaxed = true) {
every { comments } returns
listOf(
mockk(relaxed = true) {
every { comment } returns
mockk(relaxed = true) {
every { comment } returns mockk(relaxed = true) {
every { id } returns commentId
}
}
},
)
}
}
@ -284,7 +313,8 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenGetMentions_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetMentions_thenResultAndInteractionsAreAsExpected() =
runTest {
val mentionId = 1L
coEvery {
userService.getMentions(
@ -295,14 +325,16 @@ class DefaultUserRepositoryTest {
sort = any(),
unreadOnly = any(),
)
} returns mockk {
every { mentions } returns listOf(
} returns
mockk {
every { mentions } returns
listOf(
mockk(relaxed = true) {
every { personMention } returns
mockk(relaxed = true) {
every { personMention } returns mockk(relaxed = true) {
every { id } returns mentionId
}
}
},
)
}
@ -324,7 +356,8 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenGetReplies_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetReplies_thenResultAndInteractionsAreAsExpected() =
runTest {
val replyId = 1L
coEvery {
userService.getReplies(
@ -335,13 +368,16 @@ class DefaultUserRepositoryTest {
sort = any(),
unreadOnly = any(),
)
} returns mockk {
every { replies } returns listOf(
} returns
mockk {
every { replies } returns
listOf(
mockk(relaxed = true) {
every { commentReply } returns
mockk(relaxed = true) {
every { commentReply } returns mockk(relaxed = true) {
every { id } returns replyId
}
}
},
)
}
@ -363,7 +399,8 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenSetMentionRead_thenInteractionsAreAsExpected() = runTest {
fun whenSetMentionRead_thenInteractionsAreAsExpected() =
runTest {
coEvery {
userService.markPersonMentionAsRead(any(), any())
} returns mockk(relaxed = true)
@ -373,23 +410,24 @@ class DefaultUserRepositoryTest {
read = true,
mentionId = mentionId,
auth = AUTH_TOKEN,
)
coVerify {
userService.markPersonMentionAsRead(
authHeader = AUTH_TOKEN.toAuthHeader(),
form = withArg {
form =
withArg {
assertEquals(mentionId, it.mentionId)
assertEquals(true, it.read)
assertEquals(AUTH_TOKEN, it.auth)
}
},
)
}
}
@Test
fun whenSetReplyRead_thenInteractionsAreAsExpected() = runTest {
fun whenSetReplyRead_thenInteractionsAreAsExpected() =
runTest {
coEvery {
commentService.markAsRead(any(), any())
} returns mockk(relaxed = true)
@ -399,23 +437,24 @@ class DefaultUserRepositoryTest {
read = true,
replyId = mentionId,
auth = AUTH_TOKEN,
)
coVerify {
commentService.markAsRead(
authHeader = AUTH_TOKEN.toAuthHeader(),
form = withArg {
form =
withArg {
assertEquals(mentionId, it.replyId)
assertEquals(true, it.read)
assertEquals(AUTH_TOKEN, it.auth)
}
},
)
}
}
@Test
fun whenBlock_thenInteractionsAreAsExpected() = runTest {
fun whenBlock_thenInteractionsAreAsExpected() =
runTest {
coEvery {
userService.block(any(), any())
} returns mockk(relaxed = true)
@ -430,17 +469,19 @@ class DefaultUserRepositoryTest {
coVerify {
userService.block(
authHeader = AUTH_TOKEN.toAuthHeader(),
form = withArg {
form =
withArg {
assertEquals(userId, it.personId)
assertEquals(true, it.block)
assertEquals(AUTH_TOKEN, it.auth)
}
},
)
}
}
@Test
fun whenGetModeratedCommunities_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetModeratedCommunities_thenResultAndInteractionsAreAsExpected() =
runTest {
val userId = 1L
val communityId = 2L
coEvery {
@ -455,14 +496,18 @@ class DefaultUserRepositoryTest {
savedOnly = any(),
communityId = any(),
)
} returns mockk {
every { personView } returns mockk(relaxed = true) {
every { moderates } returns listOf(
} returns
mockk {
every { personView } returns
mockk(relaxed = true) {
every { moderates } returns
listOf(
mockk(relaxed = true) {
every { community } returns
mockk(relaxed = true) {
every { community } returns mockk(relaxed = true) {
every { id } returns communityId
}
}
},
)
}
}
@ -482,7 +527,8 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenGetLikedPosts_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetLikedPosts_thenResultAndInteractionsAreAsExpected() =
runTest {
val postId = 1L
coEvery {
postService.getAll(
@ -495,17 +541,21 @@ class DefaultUserRepositoryTest {
type = any(),
likedOnly = any(),
dislikedOnly = any(),
showHidden = any(),
)
} returns mockk {
every { posts } returns listOf(
} returns
mockk {
every { posts } returns
listOf(
mockk(relaxed = true) {
every { post } returns mockk(relaxed = true) { every { id } returns postId }
}
},
)
every { nextPage } returns PAGE_CURSOR
}
val res = sut.getLikedPosts(
val res =
sut.getLikedPosts(
auth = AUTH_TOKEN,
page = 1,
liked = true,
@ -527,12 +577,14 @@ class DefaultUserRepositoryTest {
sort = SortType.New,
likedOnly = true,
dislikedOnly = null,
showHidden = any(),
)
}
}
@Test
fun whenGetLikedComments_thenResultAndInteractionsAreAsExpected() = runTest {
fun whenGetLikedComments_thenResultAndInteractionsAreAsExpected() =
runTest {
val commentId = 1L
coEvery {
commentService.getAll(
@ -545,15 +597,18 @@ class DefaultUserRepositoryTest {
likedOnly = any(),
dislikedOnly = any(),
)
} returns mockk {
every { comments } returns listOf(
} returns
mockk {
every { comments } returns
listOf(
mockk(relaxed = true) {
every { comment } returns mockk(relaxed = true) { every { id } returns commentId }
}
},
)
}
val res = sut.getLikedComments(
val res =
sut.getLikedComments(
auth = AUTH_TOKEN,
page = 1,
liked = true,
@ -577,10 +632,12 @@ class DefaultUserRepositoryTest {
}
@Test
fun whenPurge_thenInteractionsAreAsExpected() = runTest {
fun whenPurge_thenInteractionsAreAsExpected() =
runTest {
coEvery {
userService.purge(any(), any())
} returns mockk {
} returns
mockk {
every { success } returns true
}
@ -595,10 +652,64 @@ class DefaultUserRepositoryTest {
coVerify {
userService.purge(
authHeader = AUTH_TOKEN.toAuthHeader(),
form = withArg {
form =
withArg {
assertEquals(userId, it.personId)
assertEquals(reason, it.reason)
},
)
}
}
@Test
fun whenGetHiddenPosts_thenResultAndInteractionsAreAsExpected() =
runTest {
val postId = 1L
coEvery {
postService.getAll(
authHeader = any(),
auth = any(),
page = any(),
limit = any(),
pageCursor = any(),
sort = any(),
type = any(),
likedOnly = any(),
dislikedOnly = any(),
showHidden = any(),
)
} returns
mockk {
every { posts } returns
listOf(
mockk(relaxed = true) {
every { post } returns mockk(relaxed = true) { every { id } returns postId }
},
)
every { nextPage } returns PAGE_CURSOR
}
val res =
sut.getHiddenPosts(
auth = AUTH_TOKEN,
page = 1,
)
assertNotNull(res)
val posts = res.first
assertTrue(posts.isNotEmpty())
assertEquals(postId, posts.first().id)
assertEquals(PAGE_CURSOR, res.second)
coVerify {
postService.getAll(
authHeader = AUTH_TOKEN.toAuthHeader(),
auth = AUTH_TOKEN,
page = 1,
limit = 20,
type = ListingType.All,
pageCursor = null,
sort = SortType.New,
showHidden = true,
)
}
}

View File

@ -0,0 +1,18 @@
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository
internal class DefaultGetSiteSupportsHiddenPostsUseCase(
private val isSiteVersionAtLeastUseCase: IsSiteVersionAtLeastUseCase,
) : GetSiteSupportsHiddenPostsUseCase {
companion object {
const val THRESHOLD_MAJOR = 0
const val THRESHOLD_MINOR = 19
const val THRESHOLD_PATCH = 4
}
override suspend fun invoke(): Boolean =
isSiteVersionAtLeastUseCase.execute(
major = THRESHOLD_MAJOR,
minor = THRESHOLD_MINOR,
patch = THRESHOLD_PATCH,
)
}

View File

@ -3,49 +3,50 @@ package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SortType
internal class DefaultGetSortTypesUseCase(
private val siteRepository: SiteRepository,
private val isSiteVersionAtLeastUseCase: IsSiteVersionAtLeastUseCase,
) : GetSortTypesUseCase {
companion object {
private const val THRESHOLD_MAJOR = 0
private const val THRESHOLD_MINOR = 19
private val LEMMY_VERSION_REGEX = Regex("(?<major>\\d+).(?<minor>\\d+)(.(?<patch>\\d+))?")
}
override suspend fun getTypesForPosts(otherInstance: String?): List<SortType> {
val version = siteRepository.getSiteVersion(otherInstance = otherInstance).orEmpty()
val matchResult = LEMMY_VERSION_REGEX.find(version)
val major = matchResult?.groups?.get("major")?.value?.toIntOrNull() ?: 0
val minor = matchResult?.groups?.get("minor")?.value?.toIntOrNull() ?: 0
return buildList {
override suspend fun getTypesForPosts(otherInstance: String?): List<SortType> =
buildList {
val isAtLeastThreshold =
isSiteVersionAtLeastUseCase.execute(
major = THRESHOLD_MAJOR,
minor = THRESHOLD_MINOR,
otherInstance = otherInstance,
)
this += SortType.Active
this += SortType.Hot
this += SortType.New
this += SortType.NewComments
this += SortType.MostComments
this += SortType.Old
if (major >= THRESHOLD_MAJOR && minor >= THRESHOLD_MINOR) {
if (isAtLeastThreshold) {
this += SortType.Controversial
this += SortType.Scaled
}
this += SortType.Top.Generic
}
}
override suspend fun getTypesForComments(otherInstance: String?): List<SortType> {
val version = siteRepository.getSiteVersion(otherInstance = otherInstance).orEmpty()
val matchResult = LEMMY_VERSION_REGEX.find(version)
val major = matchResult?.groups?.get("major")?.value?.toIntOrNull() ?: 0
val minor = matchResult?.groups?.get("minor")?.value?.toIntOrNull() ?: 0
return buildList {
override suspend fun getTypesForComments(otherInstance: String?): List<SortType> =
buildList {
val isAtLeastThreshold =
isSiteVersionAtLeastUseCase.execute(
major = THRESHOLD_MAJOR,
minor = THRESHOLD_MINOR,
otherInstance = otherInstance,
)
this += SortType.Hot
this += SortType.New
this += SortType.Old
if (major >= THRESHOLD_MAJOR && minor >= THRESHOLD_MINOR) {
if (isAtLeastThreshold) {
this += SortType.Controversial
}
this += SortType.Top.Generic
}
}
override suspend fun getTypesForCommunities(otherInstance: String?): List<SortType> =
buildList {

View File

@ -0,0 +1,30 @@
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository
internal class DefaultIsSiteVersionAtLeastUseCase(
private val siteRepository: SiteRepository,
) : IsSiteVersionAtLeastUseCase {
companion object {
private val LEMMY_VERSION_REGEX = Regex("(?<major>\\d+).(?<minor>\\d+)(.(?<patch>\\d+))?")
}
override suspend fun execute(
major: Int,
minor: Int,
patch: Int,
otherInstance: String?,
): Boolean {
val version = siteRepository.getSiteVersion(otherInstance = otherInstance).orEmpty()
val matchResult = LEMMY_VERSION_REGEX.find(version)
val actualMajor = matchResult?.groups?.get("major")?.value?.toIntOrNull() ?: 0
val actualMinor = matchResult?.groups?.get("minor")?.value?.toIntOrNull() ?: 0
val actualPatch = matchResult?.groups?.get("patch")?.value?.toIntOrNull() ?: 0
return when {
actualMajor < major -> false
actualMajor > major -> true
actualMinor < minor -> false
actualMinor > minor -> true
actualPatch < patch -> false
else -> true
}
}
}

View File

@ -379,4 +379,29 @@ internal class DefaultUserRepository(
)
require(response.success)
}
override suspend fun getHiddenPosts(
auth: String?,
page: Int,
pageCursor: String?,
limit: Int,
sort: SortType,
): Pair<List<PostModel>, String?>? =
withContext(Dispatchers.IO) {
runCatching {
val response =
services.post.getAll(
authHeader = auth.toAuthHeader(),
auth = auth,
page = page,
pageCursor = pageCursor,
limit = limit,
sort = sort.toDto(),
type = ListingType.All,
showHidden = true,
)
val posts = response.posts.map { it.toModel() }
posts to response.nextPage
}.getOrNull()
}
}

View File

@ -0,0 +1,5 @@
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository
interface GetSiteSupportsHiddenPostsUseCase {
suspend operator fun invoke(): Boolean
}

View File

@ -0,0 +1,10 @@
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository
interface IsSiteVersionAtLeastUseCase {
suspend fun execute(
major: Int,
minor: Int = 0,
patch: Int = 0,
otherInstance: String? = null,
): Boolean
}

View File

@ -119,4 +119,12 @@ interface UserRepository {
id: Long,
reason: String? = null,
)
suspend fun getHiddenPosts(
auth: String?,
page: Int,
pageCursor: String? = null,
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
sort: SortType = SortType.New,
): Pair<List<PostModel>, String?>?
}

View File

@ -5,14 +5,18 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentR
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultCommentRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultCommunityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultGetSiteSupportsHiddenPostsUseCase
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultGetSortTypesUseCase
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultIsSiteVersionAtLeastUseCase
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultLemmyItemCache
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultModlogRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultPostRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultPrivateMessageRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultSiteRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultUserRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSiteSupportsHiddenPostsUseCase
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.IsSiteVersionAtLeastUseCase
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyItemCache
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.ModlogRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
@ -26,9 +30,14 @@ private const val CACHE_SIZE = 5
val repositoryModule =
module {
single<IsSiteVersionAtLeastUseCase> {
DefaultIsSiteVersionAtLeastUseCase(
siteRepository = get(),
)
}
single<GetSortTypesUseCase> {
DefaultGetSortTypesUseCase(
siteRepository = get(),
isSiteVersionAtLeastUseCase = get(),
)
}
single<PostRepository> {
@ -79,4 +88,9 @@ val repositoryModule =
userCache = LruCache.factory(CACHE_SIZE),
)
}
single<GetSiteSupportsHiddenPostsUseCase> {
DefaultGetSiteSupportsHiddenPostsUseCase(
isSiteVersionAtLeastUseCase = get(),
)
}
}

View File

@ -68,6 +68,7 @@ kotlin {
implementation(projects.unit.choosefont)
implementation(projects.unit.configureswipeactions)
implementation(projects.unit.configurecontentview)
implementation(projects.unit.filteredcontents)
}
}
val commonTest by getting {

View File

@ -23,6 +23,7 @@ val settingsTabModule =
crashReportConfiguration = get(),
getSortTypesUseCase = get(),
customTabsHelper = get(),
siteSupportsHiddenPosts = get(),
)
}
factory<SettingsColorAndFontMviModel> {

View File

@ -39,6 +39,7 @@ interface SettingsMviModel :
val availableSortTypesForPosts: List<SortType> = emptyList(),
val availableSortTypesForComments: List<SortType> = emptyList(),
val customTabsEnabled: Boolean = true,
val supportsHiddenPosts: Boolean = false,
)
sealed interface Effect

View File

@ -72,6 +72,9 @@ import com.github.diegoberaldin.raccoonforlemmy.unit.about.AboutDialog
import com.github.diegoberaldin.raccoonforlemmy.unit.accountsettings.AccountSettingsScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.configurecontentview.ConfigureContentViewScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.configureswipeactions.ConfigureSwipeActionsScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.filteredcontents.FilteredContentsScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.filteredcontents.FilteredContentsType
import com.github.diegoberaldin.raccoonforlemmy.unit.filteredcontents.toInt
import com.github.diegoberaldin.raccoonforlemmy.unit.manageban.ManageBanScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
import kotlinx.coroutines.flow.launchIn
@ -342,6 +345,21 @@ class SettingsScreen : Screen {
navigationCoordinator.pushScreen(screen)
},
)
if (uiState.supportsHiddenPosts) {
SettingsRow(
title = LocalStrings.current.settingsHiddenPosts,
disclosureIndicator = true,
onTap =
rememberCallback {
val screen =
FilteredContentsScreen(
type = FilteredContentsType.Hidden.toInt(),
)
navigationCoordinator.pushScreen(screen)
},
)
}
}
SettingsHeader(

View File

@ -22,6 +22,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SortType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toListingType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSiteSupportsHiddenPostsUseCase
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@ -37,6 +38,7 @@ class SettingsViewModel(
private val l10nManager: L10nManager,
private val getSortTypesUseCase: GetSortTypesUseCase,
private val customTabsHelper: CustomTabsHelper,
private val siteSupportsHiddenPosts: GetSiteSupportsHiddenPostsUseCase,
) : SettingsMviModel,
DefaultMviModel<SettingsMviModel.Intent, SettingsMviModel.UiState, SettingsMviModel.Effect>(
initialState = SettingsMviModel.UiState(),
@ -90,10 +92,12 @@ class SettingsViewModel(
val availableSortTypesForPosts = getSortTypesUseCase.getTypesForPosts()
val availableSortTypesForComments = getSortTypesUseCase.getTypesForComments()
val supportsHiddenPosts = siteSupportsHiddenPosts()
updateState {
it.copy(
availableSortTypesForPosts = availableSortTypesForPosts,
availableSortTypesForComments = availableSortTypesForComments,
supportsHiddenPosts = supportsHiddenPosts,
)
}

View File

@ -14,6 +14,8 @@ sealed interface FilteredContentsType {
data object Moderated : FilteredContentsType
data object Bookmarks : FilteredContentsType
data object Hidden : FilteredContentsType
}
fun FilteredContentsType.toInt(): Int =
@ -21,10 +23,12 @@ fun FilteredContentsType.toInt(): Int =
FilteredContentsType.Moderated -> 0
FilteredContentsType.Votes -> 1
FilteredContentsType.Bookmarks -> 2
FilteredContentsType.Hidden -> 3
}
fun Int.toFilteredContentsType(): FilteredContentsType =
when (this) {
3 -> FilteredContentsType.Hidden
2 -> FilteredContentsType.Bookmarks
1 -> FilteredContentsType.Votes
else -> FilteredContentsType.Moderated
@ -92,6 +96,7 @@ interface FilteredContentsMviModel :
val fadeReadPosts: Boolean = false,
val showUnreadComments: Boolean = false,
val downVoteEnabled: Boolean = true,
val isPostOnly: Boolean = false,
val actionsOnSwipeToStartPosts: List<ActionOnSwipe> = emptyList(),
val actionsOnSwipeToEndPosts: List<ActionOnSwipe> = emptyList(),
val actionsOnSwipeToStartComments: List<ActionOnSwipe> = emptyList(),

View File

@ -183,6 +183,7 @@ class FilteredContentsScreen(
FilteredContentsType.Moderated -> LocalStrings.current.moderatorZoneActionContents
FilteredContentsType.Votes -> LocalStrings.current.profileUpvotesDownvotes
FilteredContentsType.Bookmarks -> LocalStrings.current.navigationDrawerTitleBookmarks
FilteredContentsType.Hidden -> LocalStrings.current.settingsHiddenPosts
},
style = MaterialTheme.typography.titleMedium,
)
@ -266,6 +267,7 @@ class FilteredContentsScreen(
),
verticalArrangement = Arrangement.spacedBy(Spacing.s),
) {
if (!uiState.isPostOnly) {
SectionSelector(
titles =
listOf(
@ -286,6 +288,7 @@ class FilteredContentsScreen(
model.reduce(FilteredContentsMviModel.Intent.ChangeSection(section))
},
)
}
Box(
modifier =

View File

@ -49,10 +49,12 @@ class FilteredContentsViewModel(
init {
screenModelScope.launch {
updateState {
it.copy(contentsType = contentsType.toFilteredContentsType())
}
updateState {
it.copy(isAdmin = identityRepository.cachedUser?.admin == true)
val type = contentsType.toFilteredContentsType()
it.copy(
contentsType = type,
isAdmin = identityRepository.cachedUser?.admin == true,
isPostOnly = type == FilteredContentsType.Hidden,
)
}
themeRepository.postLayout.onEach { layout ->
updateState { it.copy(postLayout = layout) }
@ -76,12 +78,14 @@ class FilteredContentsViewModel(
}
}.launchIn(this)
notificationCenter.subscribe(NotificationCenterEvent.ChangedLikedType::class).onEach { evt ->
notificationCenter.subscribe(NotificationCenterEvent.ChangedLikedType::class)
.onEach { evt ->
changeLiked(evt.value)
}.launchIn(this)
if (uiState.value.initial) {
val downVoteEnabled = siteRepository.isDownVoteEnabled(identityRepository.authToken.value)
val downVoteEnabled =
siteRepository.isDownVoteEnabled(identityRepository.authToken.value)
updateState { it.copy(downVoteEnabled = downVoteEnabled) }
refresh(initial = true)
}
@ -208,6 +212,11 @@ class FilteredContentsViewModel(
PostPaginationSpecification.Saved(
sortType = SortType.New,
)
FilteredContentsType.Hidden ->
PostPaginationSpecification.Hidden(
sortType = SortType.New,
)
}
postPaginationManager.reset(postSpecification)
val commentSpecification =
@ -228,8 +237,12 @@ class FilteredContentsViewModel(
CommentPaginationSpecification.Saved(
sortType = SortType.New,
)
FilteredContentsType.Hidden -> null
}
if (commentSpecification != null) {
commentPaginationManager.reset(commentSpecification)
}
updateState {
it.copy(
canFetchMore = true,
@ -267,6 +280,9 @@ class FilteredContentsViewModel(
postPaginationManager.loadNextPage()
}.await()
val comments =
if (currentState.isPostOnly) {
emptyList()
} else {
async {
if (currentState.comments.isEmpty() || refreshing) {
// this is needed because otherwise on first selector change
@ -276,6 +292,7 @@ class FilteredContentsViewModel(
currentState.comments
}
}.await()
}
if (uiState.value.autoLoadImages) {
posts.forEach { post ->
post.imageUrl.takeIf { i -> i.isNotEmpty() }?.also { url ->