forked from dsutanto/bChot-android
First Commit
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id("io.element.android-library")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.libraries.recentemojis.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.libraries.architecture)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
|
||||
implementation(libs.kotlinx.collections.immutable)
|
||||
implementation(libs.matrix.emojibase.bindings)
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.recentemojis.api
|
||||
|
||||
fun interface AddRecentEmoji {
|
||||
suspend operator fun invoke(emoji: String): Result<Unit>
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.recentemojis.api
|
||||
|
||||
import io.element.android.emojibasebindings.EmojibaseStore
|
||||
|
||||
interface EmojibaseProvider {
|
||||
val emojibaseStore: EmojibaseStore
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.recentemojis.api
|
||||
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
/**
|
||||
* Returns the list of recently used emojis for reactions.
|
||||
*/
|
||||
fun interface GetRecentEmojis {
|
||||
suspend operator fun invoke(): Result<ImmutableList<String>>
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import extension.setupDependencyInjection
|
||||
|
||||
plugins {
|
||||
id("io.element.android-compose-library")
|
||||
id("kotlin-parcelize")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.libraries.recentemojis.impl"
|
||||
}
|
||||
|
||||
setupDependencyInjection()
|
||||
|
||||
dependencies {
|
||||
api(projects.libraries.recentemojis.api)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
implementation(libs.kotlinx.collections.immutable)
|
||||
implementation(libs.matrix.emojibase.bindings)
|
||||
|
||||
testImplementation(projects.libraries.recentemojis.test)
|
||||
testImplementation(libs.test.junit)
|
||||
testImplementation(libs.coroutines.test)
|
||||
testImplementation(libs.molecule.runtime)
|
||||
testImplementation(libs.test.truth)
|
||||
testImplementation(libs.test.turbine)
|
||||
testImplementation(projects.libraries.matrix.test)
|
||||
testImplementation(projects.tests.testutils)
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.recentemojis.impl
|
||||
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.recentemojis.api.AddRecentEmoji
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@ContributesBinding(SessionScope::class)
|
||||
class DefaultAddRecentEmoji(
|
||||
private val client: MatrixClient,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
) : AddRecentEmoji {
|
||||
override suspend operator fun invoke(emoji: String): Result<Unit> = withContext(dispatchers.io) {
|
||||
client.addRecentEmoji(emoji)
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.recentemojis.impl
|
||||
|
||||
import android.content.Context
|
||||
import io.element.android.emojibasebindings.EmojibaseDatasource
|
||||
import io.element.android.emojibasebindings.EmojibaseStore
|
||||
import io.element.android.libraries.recentemojis.api.EmojibaseProvider
|
||||
|
||||
class DefaultEmojibaseProvider(val context: Context) : EmojibaseProvider {
|
||||
override val emojibaseStore: EmojibaseStore by lazy {
|
||||
EmojibaseDatasource().load(context)
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.recentemojis.impl
|
||||
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.recentemojis.api.EmojibaseProvider
|
||||
import io.element.android.libraries.recentemojis.api.GetRecentEmojis
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@ContributesBinding(SessionScope::class)
|
||||
class DefaultGetRecentEmojis(
|
||||
private val client: MatrixClient,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
private val emojibaseProvider: EmojibaseProvider,
|
||||
) : GetRecentEmojis {
|
||||
override suspend operator fun invoke(): Result<ImmutableList<String>> = withContext(dispatchers.io) {
|
||||
val allEmojis = emojibaseProvider.emojibaseStore.allEmojis
|
||||
client.getRecentEmojis()
|
||||
.map { emojis ->
|
||||
// Remove any possible duplicates
|
||||
emojis.distinct()
|
||||
// Return only those emojis that are valid
|
||||
.filter { recent -> allEmojis.any { recent == it.unicode } }
|
||||
.toImmutableList()
|
||||
}
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.recentemojis.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.emojibasebindings.Emoji
|
||||
import io.element.android.emojibasebindings.EmojibaseCategory
|
||||
import io.element.android.emojibasebindings.EmojibaseCategory.People
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.recentemojis.test.FakeEmojibaseProvider
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.ImmutableMap
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class DefaultGetRecentEmojisTest {
|
||||
@Test
|
||||
fun `invoke - deduplicates results`() = runTest {
|
||||
val recentEmojiResult = persistentListOf(":)", ":D", ":)")
|
||||
val getRecentEmojis = createDefaultGetRecentEmojis(
|
||||
recentEmojis = { Result.success(recentEmojiResult) },
|
||||
emojibaseContents = persistentMapOf(People to recentEmojiResult.map { emoji(it) }.toImmutableList())
|
||||
)
|
||||
|
||||
assertThat(getRecentEmojis()).isEqualTo(Result.success(persistentListOf(":)", ":D")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `invoke - removes non-standard emojis`() = runTest {
|
||||
val recentEmojiResult = persistentListOf(":)", ":D", "Custom reaction")
|
||||
val getRecentEmojis = createDefaultGetRecentEmojis(
|
||||
recentEmojis = { Result.success(recentEmojiResult) },
|
||||
emojibaseContents = persistentMapOf(
|
||||
People to persistentListOf(emoji(":)"), emoji(":D"))
|
||||
)
|
||||
)
|
||||
|
||||
assertThat(getRecentEmojis()).isEqualTo(Result.success(persistentListOf(":)", ":D")))
|
||||
}
|
||||
|
||||
private fun emoji(unicode: String) = Emoji(
|
||||
hexcode = "",
|
||||
label = "",
|
||||
tags = null,
|
||||
shortcodes = persistentListOf(),
|
||||
unicode = unicode,
|
||||
skins = null,
|
||||
)
|
||||
|
||||
private fun TestScope.createDefaultGetRecentEmojis(
|
||||
recentEmojis: () -> Result<List<String>> = { Result.success(emptyList()) },
|
||||
emojibaseContents: ImmutableMap<EmojibaseCategory, ImmutableList<Emoji>> = persistentMapOf(People to persistentListOf(emoji(":)"))),
|
||||
) = DefaultGetRecentEmojis(
|
||||
client = FakeMatrixClient(getRecentEmojisLambda = recentEmojis),
|
||||
dispatchers = testCoroutineDispatchers(),
|
||||
emojibaseProvider = FakeEmojibaseProvider(emojibaseContents),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id("io.element.android-library")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.libraries.recentemojis.test"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.libraries.matrix.api)
|
||||
api(libs.coroutines.core)
|
||||
|
||||
implementation(libs.kotlinx.collections.immutable)
|
||||
implementation(libs.coroutines.test)
|
||||
implementation(projects.tests.testutils)
|
||||
implementation(projects.libraries.recentemojis.api)
|
||||
implementation(libs.matrix.emojibase.bindings)
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.recentemojis.test
|
||||
|
||||
import io.element.android.emojibasebindings.Emoji
|
||||
import io.element.android.emojibasebindings.EmojibaseCategory
|
||||
import io.element.android.emojibasebindings.EmojibaseStore
|
||||
import io.element.android.libraries.recentemojis.api.EmojibaseProvider
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentMap
|
||||
|
||||
class FakeEmojibaseProvider(
|
||||
val emojis: Map<EmojibaseCategory, ImmutableList<Emoji>> = mapOf(),
|
||||
) : EmojibaseProvider {
|
||||
override val emojibaseStore: EmojibaseStore
|
||||
get() = EmojibaseStore(emojis.toPersistentMap())
|
||||
}
|
||||
Reference in New Issue
Block a user