feat: Add a proper color parser

This commit is contained in:
Peter Vacho 2024-12-30 18:31:55 +01:00
parent 1cab0528ba
commit 58957c1792
Signed by: school
GPG key ID: 8CFC3837052871B4
3 changed files with 89 additions and 1 deletions

View file

@ -1,6 +1,7 @@
package com.p_vacho.neat_calendar.api
import android.content.Context
import android.graphics.Color
import android.util.Log
import com.google.gson.GsonBuilder
import com.p_vacho.neat_calendar.api.services.AuthService
@ -14,6 +15,7 @@ import retrofit2.HttpException
import java.io.IOException
import java.time.OffsetDateTime
import com.fatboyindustrial.gsonjavatime.OffsetDateTimeConverter
import com.p_vacho.neat_calendar.api.converters.ColorConverter
import com.p_vacho.neat_calendar.api.services.EventsService
object RetrofitClient {
@ -73,6 +75,7 @@ object RetrofitClient {
val gson = GsonBuilder()
.registerTypeAdapter(OffsetDateTime::class.java, OffsetDateTimeConverter())
.registerTypeAdapter(Color::class.java, ColorConverter())
.create()
return Retrofit.Builder()

View file

@ -0,0 +1,81 @@
package com.p_vacho.neat_calendar.api.converters
import android.graphics.Color
import android.util.Log
import com.google.gson.*
import java.lang.reflect.Type
import kotlinx.parcelize.Parceler
class ColorConverter : JsonDeserializer<Color>, JsonSerializer<Color> {
@Throws(JsonParseException::class)
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Color {
val colorString = json.asString
try {
validateColor(colorString) // Ensure the color is in a valid format
return parseColorToAndroidFormat(colorString) // Convert to a Color object
} catch (e: IllegalArgumentException) {
throw JsonParseException("Invalid color format: $colorString", e)
}
}
override fun serialize(src: Color, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
// Convert Color object back to #RRGGBB or #RRGGBBAA
return JsonPrimitive(colorToApiFormat(src))
}
/**
* Validates the color string to ensure it matches the #RRGGBB or #RRGGBBAA format.
*/
private fun validateColor(color: String) {
val regex = Regex("^#[A-Fa-f0-9]{6}([A-Fa-f0-9]{2})?$")
if (!regex.matches(color)) {
throw IllegalArgumentException("Invalid color string: $color. Must be in #RRGGBB or #RRGGBBAA format.")
}
}
/**
* Converts a #RRGGBBAA / #RRGGBB color string to a Color object.
*/
private fun parseColorToAndroidFormat(color: String): Color {
val colorInt = if (color.length == 9) {
// Convert #RRGGBBAA to #AARRGGBB
Color.parseColor("#${color.substring(7, 9)}${color.substring(1, 7)}")
} else {
// Already in #RRGGBB format
Color.parseColor(color)
}
return Color.valueOf(colorInt)
}
/**
* Converts a Color object to a #RRGGBB or #RRGGBBAA string for API use.
*/
private fun colorToApiFormat(color: Color): String {
val argb = color.toArgb() // Get ARGB as a single integer
val alpha = Color.alpha(argb)
val red = Color.red(argb)
val green = Color.green(argb)
val blue = Color.blue(argb)
return if (alpha < 255) {
// Include alpha if not fully opaque
String.format("#%02X%02X%02X%02X", red, green, blue, alpha)
} else {
// Exclude alpha if fully opaque
String.format("#%02X%02X%02X", red, green, blue)
}
}
}
object ColorParceler : Parceler<Color> {
override fun create(parcel: android.os.Parcel): Color {
val colorInt = parcel.readInt()
return Color.valueOf(colorInt)
}
override fun Color.write(parcel: android.os.Parcel, flags: Int) {
parcel.writeInt(this.toArgb())
}
}

View file

@ -1,10 +1,14 @@
package com.p_vacho.neat_calendar.api.models
import android.graphics.Color
import android.os.Parcelable
import com.p_vacho.neat_calendar.api.converters.ColorParceler
import kotlinx.parcelize.Parcelize
import kotlinx.parcelize.TypeParceler
import java.time.OffsetDateTime
@Parcelize
@TypeParceler<Color, ColorParceler>
data class EventResponse(
val id: String,
val title: String,
@ -12,7 +16,7 @@ data class EventResponse(
val category_ids: List<String>,
val start_time: OffsetDateTime,
val end_time: OffsetDateTime,
val color: String, // Hex color (e.g., #ff0000)
val color: Color,
val owner_user_id: String,
val attendee_ids: List<String>,
val created_at: OffsetDateTime