Loading data/src/main/java/com/moez/QKSMS/migration/QkRealmMigration.kt +7 −4 Original line number Diff line number Diff line Loading @@ -19,9 +19,9 @@ package com.moez.QKSMS.migration import android.annotation.SuppressLint import com.f2prateek.rx.preferences2.RxSharedPreferences import com.moez.QKSMS.extensions.map import com.moez.QKSMS.mapper.CursorToContactImpl import com.moez.QKSMS.util.Preferences import io.realm.DynamicRealm import io.realm.DynamicRealmObject import io.realm.FieldAttribute Loading @@ -32,7 +32,7 @@ import javax.inject.Inject class QkRealmMigration @Inject constructor( private val cursorToContact: CursorToContactImpl, private val prefs: RxSharedPreferences private val prefs: Preferences ) : RealmMigration { companion object { Loading Loading @@ -176,7 +176,7 @@ class QkRealmMigration @Inject constructor( // Migrate conversation themes val recipients = mutableMapOf<Long, Int>() // Map of recipientId:theme realm.where("Conversation").findAll().forEach { conversation -> val pref = prefs.getInteger("theme_${conversation.getLong("id")}") val pref = prefs.theme(conversation.getLong("id")) if (pref.isSet) { conversation.getList("Recipient").forEach { recipient -> recipients[recipient.getLong("id")] = pref.get() Loading @@ -187,9 +187,12 @@ class QkRealmMigration @Inject constructor( } recipients.forEach { (recipientId, theme) -> prefs.getInteger("theme_$recipientId").set(theme) prefs.theme(recipientId).set(theme) } // This is enabled for new users, but the behaviour shouldn't change automatically for old users prefs.autoColor.set(false) version++ } Loading domain/src/main/java/com/moez/QKSMS/util/Preferences.kt +7 −5 Original line number Diff line number Diff line Loading @@ -90,6 +90,7 @@ class Preferences @Inject constructor( val nightStart = rxPrefs.getString("nightStart", "18:00") val nightEnd = rxPrefs.getString("nightEnd", "6:00") val black = rxPrefs.getBoolean("black", false) val autoColor = rxPrefs.getBoolean("autoColor", true) val systemFont = rxPrefs.getBoolean("systemFont", false) val textSize = rxPrefs.getInteger("textSize", TEXT_SIZE_NORMAL) val blockingManager = rxPrefs.getInteger("blockingManager", BLOCKING_MANAGER_QKSMS) Loading Loading @@ -140,12 +141,13 @@ class Preferences @Inject constructor( sharedPrefs.registerOnSharedPreferenceChangeListener(listener) }.share() fun theme(recipientId: Long = 0): Preference<Int> { val default = rxPrefs.getInteger("theme", 0xFF0097A7.toInt()) fun theme( recipientId: Long = 0, default: Int = rxPrefs.getInteger("theme", 0xFF0097A7.toInt()).get() ): Preference<Int> { return when (recipientId) { 0L -> default else -> rxPrefs.getInteger("theme_$recipientId", default.get()) 0L -> rxPrefs.getInteger("theme", 0xFF0097A7.toInt()) else -> rxPrefs.getInteger("theme_$recipientId", default) } } Loading presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt +6 −13 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.moez.QKSMS.R import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.resolveThemeBoolean import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.extensions.Optional import com.moez.QKSMS.extensions.asObservable import com.moez.QKSMS.extensions.mapNotNull import com.moez.QKSMS.repository.ConversationRepository Loading Loading @@ -76,9 +77,9 @@ abstract class QkThemedActivity : QkActivity() { .switchMap { threadId -> val conversation = conversationRepo.getConversation(threadId) when { conversation == null -> Observable.just(0L) conversation == null -> Observable.just(Optional(null)) conversation.recipients.size == 1 -> Observable.just(conversation.recipients.first()?.id ?: 0L) conversation.recipients.size == 1 -> Observable.just(Optional(conversation.recipients.first())) else -> messageRepo.getLastIncomingMessage(conversation.id) .asObservable() Loading @@ -89,20 +90,12 @@ abstract class QkThemedActivity : QkActivity() { phoneNumberUtils.compare(recipient.address, message.address) } } .map { recipient -> recipient.id } .startWith(conversation.recipients.firstOrNull()?.id ?: 0) .map { recipient -> Optional(recipient) } .startWith(Optional(conversation.recipients.firstOrNull())) .distinctUntilChanged() } } .switchMap { colors.themeObservable(it) } /** * Emits an event whenever any theme changes, whether it be global or for some recipient. This is useful * for invalidating recyclerviews */ val allThemes by lazy { prefs.keyChanges.filter { key -> key.contains("theme") } } .switchMap { colors.themeObservable(it.value) } @SuppressLint("InlinedApi") override fun onCreate(savedInstanceState: Bundle?) { Loading presentation/src/main/java/com/moez/QKSMS/common/util/Colors.kt +57 −26 Original line number Diff line number Diff line Loading @@ -20,15 +20,23 @@ package com.moez.QKSMS.common.util import android.content.Context import android.graphics.Color import androidx.core.content.res.getColorOrThrow import com.moez.QKSMS.R import com.moez.QKSMS.common.util.extensions.getColorCompat import com.moez.QKSMS.model.Recipient import com.moez.QKSMS.util.PhoneNumberUtils import com.moez.QKSMS.util.Preferences import io.reactivex.Observable import javax.inject.Inject import javax.inject.Singleton import kotlin.math.absoluteValue @Singleton class Colors @Inject constructor(private val context: Context, private val prefs: Preferences) { class Colors @Inject constructor( private val context: Context, private val phoneNumberUtils: PhoneNumberUtils, private val prefs: Preferences ) { data class Theme(val theme: Int, private val colors: Colors) { val highlight by lazy { colors.highlightColorForTheme(theme) } Loading @@ -37,27 +45,31 @@ class Colors @Inject constructor(private val context: Context, private val prefs val textTertiary by lazy { colors.textTertiaryOnThemeForColor(theme) } } val materialColors = listOf( listOf(0xffffebee, 0xffffcdd2, 0xffef9a9a, 0xffe57373, 0xffef5350, 0xfff44336, 0xffe53935, 0xffd32f2f, 0xffc62828, 0xffb71c1c), listOf(0xffFCE4EC, 0xffF8BBD0, 0xffF48FB1, 0xffF06292, 0xffEC407A, 0xffE91E63, 0xffD81B60, 0xffC2185B, 0xffAD1457, 0xff880E4F), listOf(0xffF3E5F5, 0xffE1BEE7, 0xffCE93D8, 0xffBA68C8, 0xffAB47BC, 0xff9C27B0, 0xff8E24AA, 0xff7B1FA2, 0xff6A1B9A, 0xff4A148C), listOf(0xffEDE7F6, 0xffD1C4E9, 0xffB39DDB, 0xff9575CD, 0xff7E57C2, 0xff673AB7, 0xff5E35B1, 0xff512DA8, 0xff4527A0, 0xff311B92), listOf(0xffE8EAF6, 0xffC5CAE9, 0xff9FA8DA, 0xff7986CB, 0xff5C6BC0, 0xff3F51B5, 0xff3949AB, 0xff303F9F, 0xff283593, 0xff1A237E), listOf(0xffE3F2FD, 0xffBBDEFB, 0xff90CAF9, 0xff64B5F6, 0xff42A5F5, 0xff2196F3, 0xff1E88E5, 0xff1976D2, 0xff1565C0, 0xff0D47A1), listOf(0xffE1F5FE, 0xffB3E5FC, 0xff81D4FA, 0xff4FC3F7, 0xff29B6F6, 0xff03A9F4, 0xff039BE5, 0xff0288D1, 0xff0277BD, 0xff01579B), listOf(0xffE0F7FA, 0xffB2EBF2, 0xff80DEEA, 0xff4DD0E1, 0xff26C6DA, 0xff00BCD4, 0xff00ACC1, 0xff0097A7, 0xff00838F, 0xff006064), listOf(0xffE0F2F1, 0xffB2DFDB, 0xff80CBC4, 0xff4DB6AC, 0xff26A69A, 0xff009688, 0xff00897B, 0xff00796B, 0xff00695C, 0xff004D40), listOf(0xffE8F5E9, 0xffC8E6C9, 0xffA5D6A7, 0xff81C784, 0xff66BB6A, 0xff4CAF50, 0xff43A047, 0xff388E3C, 0xff2E7D32, 0xff1B5E20), listOf(0xffF1F8E9, 0xffDCEDC8, 0xffC5E1A5, 0xffAED581, 0xff9CCC65, 0xff8BC34A, 0xff7CB342, 0xff689F38, 0xff558B2F, 0xff33691E), listOf(0xffF9FBE7, 0xffF0F4C3, 0xffE6EE9C, 0xffDCE775, 0xffD4E157, 0xffCDDC39, 0xffC0CA33, 0xffAFB42B, 0xff9E9D24, 0xff827717), listOf(0xffFFFDE7, 0xffFFF9C4, 0xffFFF59D, 0xffFFF176, 0xffFFEE58, 0xffFFEB3B, 0xffFDD835, 0xffFBC02D, 0xffF9A825, 0xffF57F17), listOf(0xffFFF8E1, 0xffFFECB3, 0xffFFE082, 0xffFFD54F, 0xffFFCA28, 0xffFFC107, 0xffFFB300, 0xffFFA000, 0xffFF8F00, 0xffFF6F00), listOf(0xffFFF3E0, 0xffFFE0B2, 0xffFFCC80, 0xffFFB74D, 0xffFFA726, 0xffFF9800, 0xffFB8C00, 0xffF57C00, 0xffEF6C00, 0xffE65100), listOf(0xffFBE9E7, 0xffFFCCBC, 0xffFFAB91, 0xffFF8A65, 0xffFF7043, 0xffFF5722, 0xffF4511E, 0xffE64A19, 0xffD84315, 0xffBF360C), listOf(0xffEFEBE9, 0xffD7CCC8, 0xffBCAAA4, 0xffA1887F, 0xff8D6E63, 0xff795548, 0xff6D4C41, 0xff5D4037, 0xff4E342E, 0xff3E2723), listOf(0xffFAFAFA, 0xffF5F5F5, 0xffEEEEEE, 0xffE0E0E0, 0xffBDBDBD, 0xff9E9E9E, 0xff757575, 0xff616161, 0xff424242, 0xff212121), listOf(0xffECEFF1, 0xffCFD8DC, 0xffB0BEC5, 0xff90A4AE, 0xff78909C, 0xff607D8B, 0xff546E7A, 0xff455A64, 0xff37474F, 0xff263238)) .map { it.map { it.toInt() } } val materialColors: List<List<Int>> = listOf( R.array.material_red, R.array.material_pink, R.array.material_purple, R.array.material_deep_purple, R.array.material_indigo, R.array.material_blue, R.array.material_light_blue, R.array.material_cyan, R.array.material_teal, R.array.material_green, R.array.material_light_green, R.array.material_lime, R.array.material_yellow, R.array.material_amber, R.array.material_orange, R.array.material_deep_orange, R.array.material_brown, R.array.material_gray, R.array.material_blue_gray) .map { res -> context.resources.obtainTypedArray(res) } .map { typedArray -> (0 until typedArray.length()).map(typedArray::getColorOrThrow) } private val randomColors: List<Int> = context.resources.obtainTypedArray(R.array.random_colors) .let { typedArray -> (0 until typedArray.length()).map(typedArray::getColorOrThrow) } private val minimumContrastRatio = 2 Loading @@ -66,10 +78,21 @@ class Colors @Inject constructor(private val context: Context, private val prefs private val secondaryTextLuminance = measureLuminance(context.getColorCompat(R.color.textSecondaryDark)) private val tertiaryTextLuminance = measureLuminance(context.getColorCompat(R.color.textTertiaryDark)) fun theme(recipientId: Long = 0): Theme = Theme(prefs.theme(recipientId).get(), this) fun theme(recipient: Recipient? = null): Theme { val pref = prefs.theme(recipient?.id ?: 0) val color = when { recipient == null || !prefs.autoColor.get() || pref.isSet -> pref.get() else -> generateColor(recipient) } return Theme(color, this) } fun themeObservable(recipientId: Long = 0): Observable<Theme> { return prefs.theme(recipientId).asObservable() fun themeObservable(recipient: Recipient? = null): Observable<Theme> { val pref = when { recipient == null || !prefs.autoColor.get() -> prefs.theme() else -> prefs.theme(recipient.id, generateColor(recipient)) } return pref.asObservable() .map { color -> Theme(color, this) } } Loading Loading @@ -110,4 +133,12 @@ class Colors @Inject constructor(private val context: Context, private val prefs return 0.2126 * array[0] + 0.7152 * array[1] + 0.0722 * array[2] + 0.05 } private fun generateColor(recipient: Recipient): Int { val first = recipient.contact?.name?.firstOrNull() ?: phoneNumberUtils.normalizeNumber(recipient.address).firstOrNull() ?: '#' val index = first.hashCode().absoluteValue % randomColors.size return randomColors[index] } } presentation/src/main/java/com/moez/QKSMS/common/util/NotificationManagerImpl.kt +2 −2 Original line number Diff line number Diff line Loading @@ -139,7 +139,7 @@ class NotificationManagerImpl @Inject constructor( val notification = NotificationCompat.Builder(context, getChannelIdForNotification(threadId)) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setColor(colors.theme(lastRecipient?.id ?: 0).theme) .setColor(colors.theme(lastRecipient).theme) .setPriority(NotificationCompat.PRIORITY_MAX) .setSmallIcon(R.drawable.ic_notification) .setNumber(messages.size) Loading Loading @@ -325,7 +325,7 @@ class NotificationManagerImpl @Inject constructor( val notification = NotificationCompat.Builder(context, getChannelIdForNotification(threadId)) .setContentTitle(context.getString(R.string.notification_message_failed_title)) .setContentText(context.getString(R.string.notification_message_failed_text, conversation.getTitle())) .setColor(colors.theme(lastRecipient?.id ?: 0).theme) .setColor(colors.theme(lastRecipient).theme) .setPriority(NotificationManagerCompat.IMPORTANCE_MAX) .setSmallIcon(R.drawable.ic_notification_failed) .setAutoCancel(true) Loading Loading
data/src/main/java/com/moez/QKSMS/migration/QkRealmMigration.kt +7 −4 Original line number Diff line number Diff line Loading @@ -19,9 +19,9 @@ package com.moez.QKSMS.migration import android.annotation.SuppressLint import com.f2prateek.rx.preferences2.RxSharedPreferences import com.moez.QKSMS.extensions.map import com.moez.QKSMS.mapper.CursorToContactImpl import com.moez.QKSMS.util.Preferences import io.realm.DynamicRealm import io.realm.DynamicRealmObject import io.realm.FieldAttribute Loading @@ -32,7 +32,7 @@ import javax.inject.Inject class QkRealmMigration @Inject constructor( private val cursorToContact: CursorToContactImpl, private val prefs: RxSharedPreferences private val prefs: Preferences ) : RealmMigration { companion object { Loading Loading @@ -176,7 +176,7 @@ class QkRealmMigration @Inject constructor( // Migrate conversation themes val recipients = mutableMapOf<Long, Int>() // Map of recipientId:theme realm.where("Conversation").findAll().forEach { conversation -> val pref = prefs.getInteger("theme_${conversation.getLong("id")}") val pref = prefs.theme(conversation.getLong("id")) if (pref.isSet) { conversation.getList("Recipient").forEach { recipient -> recipients[recipient.getLong("id")] = pref.get() Loading @@ -187,9 +187,12 @@ class QkRealmMigration @Inject constructor( } recipients.forEach { (recipientId, theme) -> prefs.getInteger("theme_$recipientId").set(theme) prefs.theme(recipientId).set(theme) } // This is enabled for new users, but the behaviour shouldn't change automatically for old users prefs.autoColor.set(false) version++ } Loading
domain/src/main/java/com/moez/QKSMS/util/Preferences.kt +7 −5 Original line number Diff line number Diff line Loading @@ -90,6 +90,7 @@ class Preferences @Inject constructor( val nightStart = rxPrefs.getString("nightStart", "18:00") val nightEnd = rxPrefs.getString("nightEnd", "6:00") val black = rxPrefs.getBoolean("black", false) val autoColor = rxPrefs.getBoolean("autoColor", true) val systemFont = rxPrefs.getBoolean("systemFont", false) val textSize = rxPrefs.getInteger("textSize", TEXT_SIZE_NORMAL) val blockingManager = rxPrefs.getInteger("blockingManager", BLOCKING_MANAGER_QKSMS) Loading Loading @@ -140,12 +141,13 @@ class Preferences @Inject constructor( sharedPrefs.registerOnSharedPreferenceChangeListener(listener) }.share() fun theme(recipientId: Long = 0): Preference<Int> { val default = rxPrefs.getInteger("theme", 0xFF0097A7.toInt()) fun theme( recipientId: Long = 0, default: Int = rxPrefs.getInteger("theme", 0xFF0097A7.toInt()).get() ): Preference<Int> { return when (recipientId) { 0L -> default else -> rxPrefs.getInteger("theme_$recipientId", default.get()) 0L -> rxPrefs.getInteger("theme", 0xFF0097A7.toInt()) else -> rxPrefs.getInteger("theme_$recipientId", default) } } Loading
presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt +6 −13 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.moez.QKSMS.R import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.resolveThemeBoolean import com.moez.QKSMS.common.util.extensions.resolveThemeColor import com.moez.QKSMS.extensions.Optional import com.moez.QKSMS.extensions.asObservable import com.moez.QKSMS.extensions.mapNotNull import com.moez.QKSMS.repository.ConversationRepository Loading Loading @@ -76,9 +77,9 @@ abstract class QkThemedActivity : QkActivity() { .switchMap { threadId -> val conversation = conversationRepo.getConversation(threadId) when { conversation == null -> Observable.just(0L) conversation == null -> Observable.just(Optional(null)) conversation.recipients.size == 1 -> Observable.just(conversation.recipients.first()?.id ?: 0L) conversation.recipients.size == 1 -> Observable.just(Optional(conversation.recipients.first())) else -> messageRepo.getLastIncomingMessage(conversation.id) .asObservable() Loading @@ -89,20 +90,12 @@ abstract class QkThemedActivity : QkActivity() { phoneNumberUtils.compare(recipient.address, message.address) } } .map { recipient -> recipient.id } .startWith(conversation.recipients.firstOrNull()?.id ?: 0) .map { recipient -> Optional(recipient) } .startWith(Optional(conversation.recipients.firstOrNull())) .distinctUntilChanged() } } .switchMap { colors.themeObservable(it) } /** * Emits an event whenever any theme changes, whether it be global or for some recipient. This is useful * for invalidating recyclerviews */ val allThemes by lazy { prefs.keyChanges.filter { key -> key.contains("theme") } } .switchMap { colors.themeObservable(it.value) } @SuppressLint("InlinedApi") override fun onCreate(savedInstanceState: Bundle?) { Loading
presentation/src/main/java/com/moez/QKSMS/common/util/Colors.kt +57 −26 Original line number Diff line number Diff line Loading @@ -20,15 +20,23 @@ package com.moez.QKSMS.common.util import android.content.Context import android.graphics.Color import androidx.core.content.res.getColorOrThrow import com.moez.QKSMS.R import com.moez.QKSMS.common.util.extensions.getColorCompat import com.moez.QKSMS.model.Recipient import com.moez.QKSMS.util.PhoneNumberUtils import com.moez.QKSMS.util.Preferences import io.reactivex.Observable import javax.inject.Inject import javax.inject.Singleton import kotlin.math.absoluteValue @Singleton class Colors @Inject constructor(private val context: Context, private val prefs: Preferences) { class Colors @Inject constructor( private val context: Context, private val phoneNumberUtils: PhoneNumberUtils, private val prefs: Preferences ) { data class Theme(val theme: Int, private val colors: Colors) { val highlight by lazy { colors.highlightColorForTheme(theme) } Loading @@ -37,27 +45,31 @@ class Colors @Inject constructor(private val context: Context, private val prefs val textTertiary by lazy { colors.textTertiaryOnThemeForColor(theme) } } val materialColors = listOf( listOf(0xffffebee, 0xffffcdd2, 0xffef9a9a, 0xffe57373, 0xffef5350, 0xfff44336, 0xffe53935, 0xffd32f2f, 0xffc62828, 0xffb71c1c), listOf(0xffFCE4EC, 0xffF8BBD0, 0xffF48FB1, 0xffF06292, 0xffEC407A, 0xffE91E63, 0xffD81B60, 0xffC2185B, 0xffAD1457, 0xff880E4F), listOf(0xffF3E5F5, 0xffE1BEE7, 0xffCE93D8, 0xffBA68C8, 0xffAB47BC, 0xff9C27B0, 0xff8E24AA, 0xff7B1FA2, 0xff6A1B9A, 0xff4A148C), listOf(0xffEDE7F6, 0xffD1C4E9, 0xffB39DDB, 0xff9575CD, 0xff7E57C2, 0xff673AB7, 0xff5E35B1, 0xff512DA8, 0xff4527A0, 0xff311B92), listOf(0xffE8EAF6, 0xffC5CAE9, 0xff9FA8DA, 0xff7986CB, 0xff5C6BC0, 0xff3F51B5, 0xff3949AB, 0xff303F9F, 0xff283593, 0xff1A237E), listOf(0xffE3F2FD, 0xffBBDEFB, 0xff90CAF9, 0xff64B5F6, 0xff42A5F5, 0xff2196F3, 0xff1E88E5, 0xff1976D2, 0xff1565C0, 0xff0D47A1), listOf(0xffE1F5FE, 0xffB3E5FC, 0xff81D4FA, 0xff4FC3F7, 0xff29B6F6, 0xff03A9F4, 0xff039BE5, 0xff0288D1, 0xff0277BD, 0xff01579B), listOf(0xffE0F7FA, 0xffB2EBF2, 0xff80DEEA, 0xff4DD0E1, 0xff26C6DA, 0xff00BCD4, 0xff00ACC1, 0xff0097A7, 0xff00838F, 0xff006064), listOf(0xffE0F2F1, 0xffB2DFDB, 0xff80CBC4, 0xff4DB6AC, 0xff26A69A, 0xff009688, 0xff00897B, 0xff00796B, 0xff00695C, 0xff004D40), listOf(0xffE8F5E9, 0xffC8E6C9, 0xffA5D6A7, 0xff81C784, 0xff66BB6A, 0xff4CAF50, 0xff43A047, 0xff388E3C, 0xff2E7D32, 0xff1B5E20), listOf(0xffF1F8E9, 0xffDCEDC8, 0xffC5E1A5, 0xffAED581, 0xff9CCC65, 0xff8BC34A, 0xff7CB342, 0xff689F38, 0xff558B2F, 0xff33691E), listOf(0xffF9FBE7, 0xffF0F4C3, 0xffE6EE9C, 0xffDCE775, 0xffD4E157, 0xffCDDC39, 0xffC0CA33, 0xffAFB42B, 0xff9E9D24, 0xff827717), listOf(0xffFFFDE7, 0xffFFF9C4, 0xffFFF59D, 0xffFFF176, 0xffFFEE58, 0xffFFEB3B, 0xffFDD835, 0xffFBC02D, 0xffF9A825, 0xffF57F17), listOf(0xffFFF8E1, 0xffFFECB3, 0xffFFE082, 0xffFFD54F, 0xffFFCA28, 0xffFFC107, 0xffFFB300, 0xffFFA000, 0xffFF8F00, 0xffFF6F00), listOf(0xffFFF3E0, 0xffFFE0B2, 0xffFFCC80, 0xffFFB74D, 0xffFFA726, 0xffFF9800, 0xffFB8C00, 0xffF57C00, 0xffEF6C00, 0xffE65100), listOf(0xffFBE9E7, 0xffFFCCBC, 0xffFFAB91, 0xffFF8A65, 0xffFF7043, 0xffFF5722, 0xffF4511E, 0xffE64A19, 0xffD84315, 0xffBF360C), listOf(0xffEFEBE9, 0xffD7CCC8, 0xffBCAAA4, 0xffA1887F, 0xff8D6E63, 0xff795548, 0xff6D4C41, 0xff5D4037, 0xff4E342E, 0xff3E2723), listOf(0xffFAFAFA, 0xffF5F5F5, 0xffEEEEEE, 0xffE0E0E0, 0xffBDBDBD, 0xff9E9E9E, 0xff757575, 0xff616161, 0xff424242, 0xff212121), listOf(0xffECEFF1, 0xffCFD8DC, 0xffB0BEC5, 0xff90A4AE, 0xff78909C, 0xff607D8B, 0xff546E7A, 0xff455A64, 0xff37474F, 0xff263238)) .map { it.map { it.toInt() } } val materialColors: List<List<Int>> = listOf( R.array.material_red, R.array.material_pink, R.array.material_purple, R.array.material_deep_purple, R.array.material_indigo, R.array.material_blue, R.array.material_light_blue, R.array.material_cyan, R.array.material_teal, R.array.material_green, R.array.material_light_green, R.array.material_lime, R.array.material_yellow, R.array.material_amber, R.array.material_orange, R.array.material_deep_orange, R.array.material_brown, R.array.material_gray, R.array.material_blue_gray) .map { res -> context.resources.obtainTypedArray(res) } .map { typedArray -> (0 until typedArray.length()).map(typedArray::getColorOrThrow) } private val randomColors: List<Int> = context.resources.obtainTypedArray(R.array.random_colors) .let { typedArray -> (0 until typedArray.length()).map(typedArray::getColorOrThrow) } private val minimumContrastRatio = 2 Loading @@ -66,10 +78,21 @@ class Colors @Inject constructor(private val context: Context, private val prefs private val secondaryTextLuminance = measureLuminance(context.getColorCompat(R.color.textSecondaryDark)) private val tertiaryTextLuminance = measureLuminance(context.getColorCompat(R.color.textTertiaryDark)) fun theme(recipientId: Long = 0): Theme = Theme(prefs.theme(recipientId).get(), this) fun theme(recipient: Recipient? = null): Theme { val pref = prefs.theme(recipient?.id ?: 0) val color = when { recipient == null || !prefs.autoColor.get() || pref.isSet -> pref.get() else -> generateColor(recipient) } return Theme(color, this) } fun themeObservable(recipientId: Long = 0): Observable<Theme> { return prefs.theme(recipientId).asObservable() fun themeObservable(recipient: Recipient? = null): Observable<Theme> { val pref = when { recipient == null || !prefs.autoColor.get() -> prefs.theme() else -> prefs.theme(recipient.id, generateColor(recipient)) } return pref.asObservable() .map { color -> Theme(color, this) } } Loading Loading @@ -110,4 +133,12 @@ class Colors @Inject constructor(private val context: Context, private val prefs return 0.2126 * array[0] + 0.7152 * array[1] + 0.0722 * array[2] + 0.05 } private fun generateColor(recipient: Recipient): Int { val first = recipient.contact?.name?.firstOrNull() ?: phoneNumberUtils.normalizeNumber(recipient.address).firstOrNull() ?: '#' val index = first.hashCode().absoluteValue % randomColors.size return randomColors[index] } }
presentation/src/main/java/com/moez/QKSMS/common/util/NotificationManagerImpl.kt +2 −2 Original line number Diff line number Diff line Loading @@ -139,7 +139,7 @@ class NotificationManagerImpl @Inject constructor( val notification = NotificationCompat.Builder(context, getChannelIdForNotification(threadId)) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setColor(colors.theme(lastRecipient?.id ?: 0).theme) .setColor(colors.theme(lastRecipient).theme) .setPriority(NotificationCompat.PRIORITY_MAX) .setSmallIcon(R.drawable.ic_notification) .setNumber(messages.size) Loading Loading @@ -325,7 +325,7 @@ class NotificationManagerImpl @Inject constructor( val notification = NotificationCompat.Builder(context, getChannelIdForNotification(threadId)) .setContentTitle(context.getString(R.string.notification_message_failed_title)) .setContentText(context.getString(R.string.notification_message_failed_text, conversation.getTitle())) .setColor(colors.theme(lastRecipient?.id ?: 0).theme) .setColor(colors.theme(lastRecipient).theme) .setPriority(NotificationManagerCompat.IMPORTANCE_MAX) .setSmallIcon(R.drawable.ic_notification_failed) .setAutoCancel(true) Loading