Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Option to create parser-specific Emoji object #190

Merged
merged 15 commits into from
Mar 17, 2024
Merged
58 changes: 16 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,14 @@ allprojects {
}
```

### Step 2. Add the dependency:
### Step 2. Add the dependencies:

You must use one of our artifact `serializer-kotlinx`, `serializer-gson` or `serializer-moshi`

```groovy
dependencies {
implementation 'com.github.anitrend:android-emojify:{latest_version}'
implementation 'com.github.anitrend:serializer-kotlinx:{latest_version}'
}
```

Expand All @@ -177,75 +180,46 @@ dependencies {
Don't know how to do that?? Take a look at
the [application class example](./app/src/main/java/io/wax911/emojifysample/App.kt)

**In order for EmojiInitilizer to work you need to add in your build.gradle `implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2"`

```kotlin
class App : Application() {

/**
* Application scope bound emojiManager, you could keep a reference to this object in a
* dependency injector framework like as a singleton in `Hilt`, `Dagger` or `Koin`
*/
/**
* Application scope bound emojiManager, you could keep a reference to this object in a
* dependency injector framework like as a singleton in `Hilt`, `Dagger` or `Koin`
*/
internal val emojiManager: EmojiManager by lazy {
// should already be initialized if we haven't disabled initialization in manifest
// see: https://developer.android.com/topic/libraries/app-startup#disable-individual
AppInitializer.getInstance(this)
.initializeComponent(EmojiInitializer::class.java)
EmojiManager.create(this, KotlinxDeserializer())
}
}
```

### Optional - Custom Serializer

`EmojiInitializer` is using kotlinx.serialization as default serializer. If you wish to use another serializer

#### Step 1. Create Custom EmojiInitializer and implement IEmojiDeserializer (moshi for this example)
### Step4. Optional - Init EmojiManager with androidx-startup
```kotlin
class CustomEmojiInitializer: AbstractEmojiInitializer() {
class MoshiDeserializer: IEmojiDeserializer {
private val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()

override fun decodeFromStream(inputStream: InputStream): List<Emoji> {
val myType = Types.newParameterizedType(List::class.java, Emoji::class.java)
return moshi.adapter<List<Emoji>>(myType).fromJson(inputStream.source().buffer()) ?: listOf()
}
}

override val serializer: IEmojiDeserializer = MoshiDeserializer()
class EmojiInitializer : AbstractEmojiInitializer() {
override val serializer: IEmojiDeserializer = KotlinxDeserializer()
}
```

#### Step 2. Modify your application class
```kotlin
class App : Application() {

/**
* Application scope bound emojiManager, you could keep a reference to this object in a
* dependency injector framework like as a singleton in `Hilt`, `Dagger` or `Koin`
*/
class App : Application() {
internal val emojiManager: EmojiManager by lazy {
// should already be initialized if we haven't disabled initialization in manifest
// see: https://developer.android.com/topic/libraries/app-startup#disable-individual
AppInitializer.getInstance(this)
.initializeComponent(CustomEmojiInitializer::class.java)
.initializeComponent(EmojiInitializer::class.java)
}
}
```

#### Step 3. Modify AndroidManifest.xml of your application
**AndroidManifest.xml**
```xml
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.package.CustomEmojiInitializer"
android:value="androidx.startup" />
<meta-data
android:name="io.wax911.emojify.initializer.EmojiInitializer"
android:value="androidx.startup"
tools:node="remove" />
android:value="androidx.startup" />
</provider>
```

Expand Down
6 changes: 2 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ plugins {

dependencies {
implementation(project(Libraries.AniTrend.Emojify.emojify))
implementation(project(Libraries.AniTrend.Emojify.contract))
implementation(project(Libraries.AniTrend.Emojify.serializerKotlinx))

implementation(libs.google.android.material)
implementation(libs.androidx.constraintlayout)

implementation(libs.moshi.kotlin)
implementation(libs.gson)
implementation(libs.jackson.databind)

implementation(libs.jetbrains.kotlinx.coroutines.android)
implementation(libs.jetbrains.kotlinx.coroutines.core)

Expand Down
22 changes: 9 additions & 13 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,15 @@
</intent-filter>
</activity>

<!-- <provider-->
<!-- android:name="androidx.startup.InitializationProvider"-->
<!-- android:authorities="${applicationId}.androidx-startup"-->
<!-- android:exported="false"-->
<!-- tools:node="merge">-->
<!-- <meta-data-->
<!-- android:name="io.wax911.emojifysample.CustomEmojiInitializer"-->
<!-- android:value="androidx.startup" />-->
<!-- <meta-data-->
<!-- android:name="io.wax911.emojify.initializer.EmojiInitializer"-->
<!-- android:value="androidx.startup"-->
<!-- tools:node="remove" />-->
<!-- </provider>-->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="io.wax911.emojify.initializer.EmojiInitializer"
android:value="androidx.startup" />
</provider>
</application>

</manifest>
11 changes: 9 additions & 2 deletions app/src/main/java/io/wax911/emojifysample/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,26 @@ package io.wax911.emojifysample
import android.app.Application
import androidx.startup.AppInitializer
import io.wax911.emojify.EmojiManager
import io.wax911.emojify.initializer.EmojiInitializer
import io.wax911.emojify.serializer.KotlinxDeserializer

/**
* Created by max on 2017/09/22.
*/

class App : Application() {

/**
* Application scope bound emojiManager, you could keep a reference to this object in a
* dependency injector framework like as a singleton in `Hilt`, `Dagger` or `Koin`
*/
internal val emojiManager: EmojiManager by lazy {
EmojiManager.create(this, KotlinxDeserializer())
}

/**
* Application scope bound emojiManager, you could keep a reference to this object in a
* dependency injector framework like as a singleton in `Hilt`, `Dagger` or `Koin`
*/
internal val startupEmojiManager: EmojiManager by lazy {
// should already be initialized if we haven't disabled initialization in manifest
// see: https://developer.android.com/topic/libraries/app-startup#disable-individual
AppInitializer.getInstance(this)
Expand Down

This file was deleted.

9 changes: 9 additions & 0 deletions app/src/main/java/io/wax911/emojifysample/EmojiInitializer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.wax911.emojifysample

import io.wax911.emojify.contract.serializer.IEmojiDeserializer
import io.wax911.emojify.initializer.AbstractEmojiInitializer
import io.wax911.emojify.serializer.KotlinxDeserializer

class EmojiInitializer : AbstractEmojiInitializer() {
override val serializer: IEmojiDeserializer = KotlinxDeserializer()
}
6 changes: 5 additions & 1 deletion buildSrc/src/main/java/io/wax911/emoji/buildSrc/Libraries.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ object Libraries {

object Emojify {
val emojify = Modules.Library.Emojify.path()
val contract = Modules.Library.Contract.path()
val serializerKotlinx = Modules.Library.SerializerKotlinx.path()
val serializerGson = Modules.Library.SerializerGson.path()
val serializerMoshi = Modules.Library.SerializerMoshi.path()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ internal object Modules {
}

enum class Library(override val id: String) : Module {
Emojify("emojify")
Emojify("emojify"),
Contract("contract"),
SerializerKotlinx("serializer:kotlinx"),
SerializerGson("serializer:gson"),
SerializerMoshi("serializer:moshi"),
}
}
}
1 change: 1 addition & 0 deletions contract/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
21 changes: 21 additions & 0 deletions contract/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
}

android {
namespace = "io.wax911.emojify.contract"
compileSdk = 34

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}

dependencies {
api(libs.androidx.startup.runtime)
}
2 changes: 2 additions & 0 deletions contract/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest />
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.wax911.emojify.contract.model

import java.nio.charset.Charset

/**
* Abstract class holding some logic.
* To implement for parser-specific data representation with their annotation
*/
abstract class AbstractEmoji: IEmoji {
override val unicode: String by lazy(LazyThreadSafetyMode.NONE) {
String(emoji.toByteArray(), Charset.forName("UTF-8"))
}

override val htmlDec by lazy(LazyThreadSafetyMode.NONE) {
html("&#%d;")
}

override val htmlHex by lazy(LazyThreadSafetyMode.NONE) {
html("&#x%x;")
}

private fun html(format: String): String {
val stringLength = unicode.length
val points = arrayOfNulls<String>(stringLength)
var count = 0
var offset = 0
while (offset < stringLength) {
val codePoint = unicode.codePointAt(offset)
points[count++] = String.format(format, codePoint)
offset += Character.charCount(codePoint)
}
return points.joinToString(limit = count, truncated = "", separator = "")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.wax911.emojify.contract.model

/**
* @property aliases a list of aliases for this emoji
* @property description the (optional) description of the emoji
* @property emoji unicode emoji
* @property emojiChar actual raw emoji
* @property supportsFitzpatrick true if the emoji supports the Fitzpatrick modifiers, else false
* @property supportsGender true if the emoji supports the gender modifiers, else false
* @property tags a list of tags for this emoji
*/
internal interface IEmoji {
val aliases: List<String>?
val description: String?
val emoji: String
val emojiChar: String
val supportsFitzpatrick: Boolean
val supportsGender: Boolean
val tags: List<String>?

val unicode: String
val htmlDec: String
val htmlHex: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.wax911.emojify.contract.serializer

import io.wax911.emojify.contract.model.AbstractEmoji
import java.io.InputStream

/**
* Interface to implement for custom deserializer.
*/
interface IEmojiDeserializer {
/**
* Decodes the given [InputStream] to an object of type List<[AbstractEmoji]>
*/
fun decodeFromStream(inputStream: InputStream): List<AbstractEmoji>
}
Loading
Loading