Replace TextDrawable with an implementation that supports tint

This commit is contained in:
MM20 2021-12-04 13:51:38 +01:00
parent 0e1ca1c1f9
commit fa22eb4d71
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
12 changed files with 217 additions and 161 deletions

View File

@ -107,7 +107,6 @@ dependencies {
implementation(libs.lottie.core) implementation(libs.lottie.core)
implementation(libs.textdrawable)
implementation(libs.bundles.materialdialogs) implementation(libs.bundles.materialdialogs)

View File

@ -0,0 +1,47 @@
package de.mm20.launcher2.graphics
import android.content.res.ColorStateList
import android.graphics.*
import android.graphics.drawable.Drawable
class TextDrawable(
val text: String,
val color: Int = Color.WHITE,
fontSize: Float = 13f,
typeface: Typeface = Typeface.DEFAULT
): Drawable() {
private val paint = Paint()
private val rect = Rect()
init {
paint.textAlign = Paint.Align.CENTER
paint.textSize = fontSize
paint.color = color
paint.isAntiAlias = true
paint.typeface = typeface
paint.style = Paint.Style.FILL
}
override fun draw(canvas: Canvas) {
val bounds = bounds
paint.getTextBounds(text, 0, text.length, rect)
canvas.drawText(text, bounds.exactCenterX(), bounds.exactCenterY() + rect.height() / 2f, paint)
}
override fun setAlpha(alpha: Int) {
paint.alpha = alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.colorFilter = colorFilter
}
override fun getOpacity(): Int {
return PixelFormat.TRANSLUCENT
}
override fun setTintList(tint: ColorStateList?) {
paint.color = tint?.defaultColor ?: color
}
}

View File

@ -77,14 +77,6 @@ val OpenSourceLicenses = arrayOf(
copyrightNote = "Copyright (c) 2009-2021 Jonathan Hedley <https://jsoup.org/>", copyrightNote = "Copyright (c) 2009-2021 Jonathan Hedley <https://jsoup.org/>",
url = "https://jsoup.org/" url = "https://jsoup.org/"
), ),
OpenSourceLibrary(
name = "TextDrawable",
description = "A light-weight library providing images with letter/text like the Gmail app",
licenseName = R.string.mit_license_name,
licenseText = R.raw.license_mit,
copyrightNote = "Copyright (c) 2014 Amulya Khare",
url = "https://github.com/amulyakhare/TextDrawable"
),
OpenSourceLibrary( OpenSourceLibrary(
name = "Glide", name = "Glide",
description = "A fast and efficient open source media management and image loading framework for Android", description = "A fast and efficient open source media management and image loading framework for Android",

View File

@ -40,7 +40,6 @@ dependencies {
implementation(libs.androidx.core) implementation(libs.androidx.core)
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
implementation(libs.textdrawable)
implementation(libs.koin.android) implementation(libs.koin.android)

View File

@ -4,7 +4,6 @@ import android.Manifest
import android.content.ContentUris import android.content.ContentUris
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color import android.graphics.Color
import android.graphics.Typeface import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
@ -16,29 +15,27 @@ import androidx.core.graphics.ColorUtils
import androidx.core.graphics.blue import androidx.core.graphics.blue
import androidx.core.graphics.green import androidx.core.graphics.green
import androidx.core.graphics.red import androidx.core.graphics.red
import com.amulyakhare.textdrawable.TextDrawable
import de.mm20.launcher2.calendar.R import de.mm20.launcher2.calendar.R
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.graphics.TextDrawable
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.checkPermission import de.mm20.launcher2.ktx.checkPermission
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import org.json.JSONObject
import java.lang.NullPointerException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
class CalendarEvent( class CalendarEvent(
override val label: String, override val label: String,
val id: Long, val id: Long,
val color: Int, val color: Int,
val startTime: Long, val startTime: Long,
val endTime: Long, val endTime: Long,
val allDay: Boolean, val allDay: Boolean,
val location: String, val location: String,
val attendees: List<String>, val attendees: List<String>,
val description: String, val description: String,
val calendar: Long val calendar: Long
) : Searchable() { ) : Searchable() {
override val key: String override val key: String
@ -51,31 +48,27 @@ class CalendarEvent(
df.applyPattern("MMM") df.applyPattern("MMM")
val month = df.format(startTime) val month = df.format(startTime)
val fgLayers = arrayOf( val fgLayers = arrayOf(
TextDrawable TextDrawable(
.builder() day,
.beginConfig() color = Color.WHITE,
.textColor(Color.WHITE) fontSize = 40 * context.dp,
.useFont(Typeface.DEFAULT_BOLD) typeface = Typeface.DEFAULT_BOLD
.fontSize((36 * context.dp).toInt()) ),
.endConfig() TextDrawable(
.buildRect(day, 0), month,
TextDrawable color = Color.WHITE,
.builder() fontSize = 26 * context.dp,
.beginConfig() typeface = Typeface.DEFAULT_BOLD
.textColor(Color.WHITE) )
.bold()
.fontSize((26 * context.dp).toInt())
.endConfig()
.buildRect(month, 0)
) )
val foreground = LayerDrawable(fgLayers) val foreground = LayerDrawable(fgLayers)
foreground.setLayerInset(0, 0, 0, 0, (26 * context.dp).toInt()) foreground.setLayerInset(0, 0, 0, 0, (26 * context.dp).toInt())
foreground.setLayerInset(1, 0, (36 * context.dp).toInt(), 0, 0) foreground.setLayerInset(1, 0, (40 * context.dp).toInt(), 0, 0)
val background = ColorDrawable(getDisplayColor(context, color)) val background = ColorDrawable(getDisplayColor(context, color))
return LauncherIcon( return LauncherIcon(
foreground = foreground, foreground = foreground,
background = background, background = background,
foregroundScale = 0.74f foregroundScale = 0.74f
) )
} }
@ -84,14 +77,15 @@ class CalendarEvent(
} }
companion object { companion object {
fun search(context: Context, fun search(
query: String, context: Context,
intervalStart: Long, query: String,
intervalEnd: Long, intervalStart: Long,
limit: Int = 10, intervalEnd: Long,
hideAllDayEvents: Boolean = false, limit: Int = 10,
unselectedCalendars: List<Long> = emptyList(), hideAllDayEvents: Boolean = false,
hiddenEvents: List<Long> = emptyList() unselectedCalendars: List<Long> = emptyList(),
hiddenEvents: List<Long> = emptyList()
): List<CalendarEvent> { ): List<CalendarEvent> {
val results = mutableListOf<CalendarEvent>() val results = mutableListOf<CalendarEvent>()
if (!query.isEmpty() && query.length < 3) return results if (!query.isEmpty() && query.length < 3) return results
@ -104,15 +98,15 @@ class CalendarEvent(
ContentUris.appendId(builder, intervalEnd) ContentUris.appendId(builder, intervalEnd)
val uri = builder.build() val uri = builder.build()
val projection = arrayOf( val projection = arrayOf(
CalendarContract.Instances.EVENT_ID, CalendarContract.Instances.EVENT_ID,
CalendarContract.Instances.TITLE, CalendarContract.Instances.TITLE,
CalendarContract.Instances.BEGIN, CalendarContract.Instances.BEGIN,
CalendarContract.Instances.END, CalendarContract.Instances.END,
CalendarContract.Instances.ALL_DAY, CalendarContract.Instances.ALL_DAY,
CalendarContract.Instances.DISPLAY_COLOR, CalendarContract.Instances.DISPLAY_COLOR,
CalendarContract.Instances.EVENT_LOCATION, CalendarContract.Instances.EVENT_LOCATION,
CalendarContract.Instances.CALENDAR_ID, CalendarContract.Instances.CALENDAR_ID,
CalendarContract.Instances.DESCRIPTION CalendarContract.Instances.DESCRIPTION
) )
val selection = mutableListOf<String>() val selection = mutableListOf<String>()
if (query.isNotEmpty()) selection.add("${CalendarContract.Instances.TITLE} LIKE ?") if (query.isNotEmpty()) selection.add("${CalendarContract.Instances.TITLE} LIKE ?")
@ -120,25 +114,32 @@ class CalendarEvent(
if (unselectedCalendars.isNotEmpty()) selection.add("${CalendarContract.Instances.CALENDAR_ID} NOT IN (${unselectedCalendars.joinToString()})") if (unselectedCalendars.isNotEmpty()) selection.add("${CalendarContract.Instances.CALENDAR_ID} NOT IN (${unselectedCalendars.joinToString()})")
if (hideAllDayEvents) selection.add("${CalendarContract.Instances.ALL_DAY} = 0") if (hideAllDayEvents) selection.add("${CalendarContract.Instances.ALL_DAY} = 0")
val selArgs = if (query.isBlank()) null else arrayOf("%$query%") val selArgs = if (query.isBlank()) null else arrayOf("%$query%")
val sort = "${CalendarContract.Instances.BEGIN} ASC" + if (limit > -1) " LIMIT $limit" else "" val sort =
val cursor = context.contentResolver.query(uri, projection, selection.joinToString(separator = " AND "), selArgs, sort) "${CalendarContract.Instances.BEGIN} ASC" + if (limit > -1) " LIMIT $limit" else ""
?: return mutableListOf() val cursor = context.contentResolver.query(
uri,
projection,
selection.joinToString(separator = " AND "),
selArgs,
sort
)
?: return mutableListOf()
val proj = arrayOf( val proj = arrayOf(
CalendarContract.Attendees.EVENT_ID, CalendarContract.Attendees.EVENT_ID,
CalendarContract.Attendees.ATTENDEE_NAME, CalendarContract.Attendees.ATTENDEE_NAME,
CalendarContract.Attendees.ATTENDEE_EMAIL CalendarContract.Attendees.ATTENDEE_EMAIL
) )
val s = "${CalendarContract.Attendees.ATTENDEE_NAME} COLLATE NOCASE ASC" val s = "${CalendarContract.Attendees.ATTENDEE_NAME} COLLATE NOCASE ASC"
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
val sel = "${CalendarContract.Attendees.EVENT_ID} = ${cursor.getLong(0)}" val sel = "${CalendarContract.Attendees.EVENT_ID} = ${cursor.getLong(0)}"
val cur = context.contentResolver.query( val cur = context.contentResolver.query(
CalendarContract.Attendees.CONTENT_URI, CalendarContract.Attendees.CONTENT_URI,
proj, sel, null, s proj, sel, null, s
) ?: return mutableListOf() ) ?: return mutableListOf()
val attendees = mutableListOf<String>() val attendees = mutableListOf<String>()
while (cur.moveToNext()) { while (cur.moveToNext()) {
attendees.add(cur.getString(1).takeUnless { it.isNullOrBlank() } attendees.add(cur.getString(1).takeUnless { it.isNullOrBlank() }
?: cur.getString(2)) ?: cur.getString(2))
} }
cur.close() cur.close()
val allday = cursor.getInt(4) > 0 val allday = cursor.getInt(4) > 0
@ -150,17 +151,17 @@ class CalendarEvent(
0 0
} }
val event = CalendarEvent( val event = CalendarEvent(
label = cursor.getString(1) ?: "", label = cursor.getString(1) ?: "",
id = cursor.getLong(0), id = cursor.getLong(0),
color = cursor.getInt(5), color = cursor.getInt(5),
startTime = begin - tzOffset, startTime = begin - tzOffset,
endTime = cursor.getLong(3) - tzOffset - if (allday) 1 else 0, endTime = cursor.getLong(3) - tzOffset - if (allday) 1 else 0,
allDay = allday, allDay = allday,
location = cursor.getString(6) ?: "", location = cursor.getString(6) ?: "",
attendees = attendees, attendees = attendees,
description = cursor.getStringOrNull(8) description = cursor.getStringOrNull(8)
?: "", ?: "",
calendar = cursor.getLong(7) calendar = cursor.getLong(7)
) )
results.add(event) results.add(event)
} }
@ -173,24 +174,26 @@ class CalendarEvent(
val calendars = mutableListOf<UserCalendar>() val calendars = mutableListOf<UserCalendar>()
val uri = CalendarContract.Calendars.CONTENT_URI val uri = CalendarContract.Calendars.CONTENT_URI
val proj = arrayOf( val proj = arrayOf(
CalendarContract.Calendars._ID, CalendarContract.Calendars._ID,
CalendarContract.Calendars.NAME, CalendarContract.Calendars.NAME,
CalendarContract.Calendars.ACCOUNT_NAME, CalendarContract.Calendars.ACCOUNT_NAME,
CalendarContract.Calendars.CALENDAR_COLOR, CalendarContract.Calendars.CALENDAR_COLOR,
CalendarContract.Calendars.VISIBLE, CalendarContract.Calendars.VISIBLE,
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,
) )
if (!context.checkPermission(Manifest.permission.READ_CALENDAR)) return calendars if (!context.checkPermission(Manifest.permission.READ_CALENDAR)) return calendars
val cursor = context.contentResolver.query(uri, proj, null, null, null) val cursor = context.contentResolver.query(uri, proj, null, null, null)
?: return emptyList() ?: return emptyList()
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
try { try {
calendars.add(UserCalendar( calendars.add(
UserCalendar(
id = cursor.getLong(0), id = cursor.getLong(0),
name = cursor.getString(5) ?: cursor.getString(1) ?: "", name = cursor.getString(5) ?: cursor.getString(1) ?: "",
owner = cursor.getString(2), owner = cursor.getString(2),
color = cursor.getInt(3) color = cursor.getInt(3)
)) )
)
} catch (e: NullPointerException) { } catch (e: NullPointerException) {
continue continue
} }
@ -206,7 +209,13 @@ class CalendarEvent(
it it
} }
return if (context.resources.getBoolean(R.bool.is_dark_theme)) { return if (context.resources.getBoolean(R.bool.is_dark_theme)) {
if (ColorUtils.calculateContrast(ContextCompat.getColor(context, R.color.calendar_foreground_color), color) < 2.5 || true) { if (ColorUtils.calculateContrast(
ContextCompat.getColor(
context,
R.color.calendar_foreground_color
), color
) < 2.5 || true
) {
if (color.red == color.green && color.red == color.blue) { if (color.red == color.green && color.red == color.blue) {
val level = 0xFF - ((0xFF - color.red) * 0.7f).toInt() val level = 0xFF - ((0xFF - color.red) * 0.7f).toInt()
Color.rgb(level, level, level) Color.rgb(level, level, level)
@ -217,7 +226,13 @@ class CalendarEvent(
} }
} else return color } else return color
} else { } else {
if (ColorUtils.calculateContrast(ContextCompat.getColor(context, R.color.calendar_foreground_color), color) < 1.8) { if (ColorUtils.calculateContrast(
ContextCompat.getColor(
context,
R.color.calendar_foreground_color
), color
) < 1.8
) {
if (color.red == color.green && color.red == color.blue) { if (color.red == color.green && color.red == color.blue) {
val level = (color.red * 0.7f).toInt() val level = (color.red * 0.7f).toInt()
Color.rgb(level, level, level) Color.rgb(level, level, level)
@ -235,8 +250,8 @@ class CalendarEvent(
} }
data class UserCalendar( data class UserCalendar(
val id: Long, val id: Long,
val name: String, val name: String,
val owner: String, val owner: String,
val color: Int val color: Int
) )

View File

@ -40,7 +40,6 @@ dependencies {
implementation(libs.androidx.core) implementation(libs.androidx.core)
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
implementation(libs.textdrawable)
implementation(libs.koin.android) implementation(libs.koin.android)

View File

@ -1,33 +1,33 @@
package de.mm20.launcher2.search.data package de.mm20.launcher2.search.data
import android.Manifest
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.provider.ContactsContract import android.provider.ContactsContract
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.database.getStringOrNull import androidx.core.database.getStringOrNull
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import com.amulyakhare.textdrawable.TextDrawable
import de.mm20.launcher2.contacts.R import de.mm20.launcher2.contacts.R
import de.mm20.launcher2.ktx.asBitmap import de.mm20.launcher2.graphics.TextDrawable
import de.mm20.launcher2.ktx.jsonObjectOf
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.asBitmap
import de.mm20.launcher2.ktx.sp
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import org.json.JSONObject
class Contact( class Contact(
val id: Long, val id: Long,
val firstName: String, val firstName: String,
val lastName: String, val lastName: String,
val displayName: String, val displayName: String,
val lookupKey: String, val lookupKey: String,
val phones: Set<String>, val phones: Set<String>,
val emails: Set<String>, val emails: Set<String>,
val telegram: Set<String>, val telegram: Set<String>,
val whatsapp: Set<String>, val whatsapp: Set<String>,
val postals: Set<String> val postals: Set<String>
) : Searchable() { ) : Searchable() {
override val key: String override val key: String
get() = "contact://$id" get() = "contact://$id"
@ -40,19 +40,22 @@ class Contact(
} }
override fun getPlaceholderIcon(context: Context): LauncherIcon { override fun getPlaceholderIcon(context: Context): LauncherIcon {
val iconText = if (firstName.isNotEmpty()) firstName[0].toString() else "" + if (lastName.isNotEmpty()) lastName[0].toString() else "" val iconText =
if (firstName.isNotEmpty()) firstName[0].toString() else "" + if (lastName.isNotEmpty()) lastName[0].toString() else ""
return LauncherIcon( return LauncherIcon(
foreground = TextDrawable.builder().buildRect(iconText, ContextCompat.getColor(context, R.color.blue)) foreground = TextDrawable(iconText, Color.WHITE, fontSize = 40 * context.sp, typeface = Typeface.DEFAULT_BOLD),
background = ColorDrawable(ContextCompat.getColor(context, R.color.blue))
) )
} }
override suspend fun loadIconAsync(context: Context, size: Int): LauncherIcon? { override suspend fun loadIconAsync(context: Context, size: Int): LauncherIcon? {
val contentResolver = context.contentResolver val contentResolver = context.contentResolver
val uri = ContactsContract.Contacts.getLookupUri(id, lookupKey) ?: return null val uri = ContactsContract.Contacts.getLookupUri(id, lookupKey) ?: return null
val bmp = ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, uri, false)?.asBitmap() val bmp = ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, uri, false)
?: return null ?.asBitmap()
?: return null
return LauncherIcon( return LauncherIcon(
foreground = bmp.toDrawable(context.resources) foreground = bmp.toDrawable(context.resources)
) )
} }
@ -70,13 +73,14 @@ class Contact(
return mutableListOf() return mutableListOf()
} }
val proj = arrayOf( val proj = arrayOf(
ContactsContract.RawContacts.CONTACT_ID, ContactsContract.RawContacts.CONTACT_ID,
ContactsContract.RawContacts._ID ContactsContract.RawContacts._ID
) )
val sel = "${ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY} LIKE ?" val sel = "${ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY} LIKE ?"
val selArgs = arrayOf("%$query%") val selArgs = arrayOf("%$query%")
val cursor = context.contentResolver.query( val cursor = context.contentResolver.query(
ContactsContract.RawContacts.CONTENT_URI, proj, sel, selArgs, null) ?: return mutableListOf() ContactsContract.RawContacts.CONTENT_URI, proj, sel, selArgs, null
) ?: return mutableListOf()
//Maps raw contact ids to contact ids //Maps raw contact ids to contact ids
val contactMap = mutableMapOf<Long, MutableSet<Long>>() val contactMap = mutableMapOf<Long, MutableSet<Long>>()
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
@ -92,7 +96,7 @@ class Contact(
internal fun contactById(context: Context, id: Long, rawIds: Set<Long>): Contact? { internal fun contactById(context: Context, id: Long, rawIds: Set<Long>): Contact? {
val s = "(" + rawIds.joinToString(separator = " OR ", val s = "(" + rawIds.joinToString(separator = " OR ",
transform = { "${ContactsContract.Data.RAW_CONTACT_ID} = $it" }) + ")" + transform = { "${ContactsContract.Data.RAW_CONTACT_ID} = $it" }) + ")" +
" AND (${ContactsContract.Data.MIMETYPE} = \"${ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE}\"" + " AND (${ContactsContract.Data.MIMETYPE} = \"${ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE}\"" +
" OR ${ContactsContract.Data.MIMETYPE} = \"${ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE}\"" + " OR ${ContactsContract.Data.MIMETYPE} = \"${ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE}\"" +
" OR ${ContactsContract.Data.MIMETYPE} = \"${ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}\"" + " OR ${ContactsContract.Data.MIMETYPE} = \"${ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}\"" +
@ -101,8 +105,8 @@ class Contact(
" OR ${ContactsContract.Data.MIMETYPE} = \"vnd.android.cursor.item/vnd.com.whatsapp.profile\"" + " OR ${ContactsContract.Data.MIMETYPE} = \"vnd.android.cursor.item/vnd.com.whatsapp.profile\"" +
")" ")"
val dataCursor = context.contentResolver.query( val dataCursor = context.contentResolver.query(
ContactsContract.Data.CONTENT_URI, ContactsContract.Data.CONTENT_URI,
null, s, null, null null, s, null, null
) ?: return null ) ?: return null
val phones = mutableSetOf<String>() val phones = mutableSetOf<String>()
val emails = mutableSetOf<String>() val emails = mutableSetOf<String>()
@ -113,12 +117,18 @@ class Contact(
var lastName = "" var lastName = ""
var displayName = "" var displayName = ""
val mimeTypeColumn = dataCursor.getColumnIndex(ContactsContract.Data.MIMETYPE) val mimeTypeColumn = dataCursor.getColumnIndex(ContactsContract.Data.MIMETYPE)
val emailAddressColumn = dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS) val emailAddressColumn =
val numberColumn = dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER) dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS)
val addressColumn = dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS) val numberColumn =
val displayNameColumn = dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME) dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
val givenNameColumn = dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME) val addressColumn =
val familyNameColumn = dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME) dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS)
val displayNameColumn =
dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME)
val givenNameColumn =
dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)
val familyNameColumn =
dataCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)
val data1Column = dataCursor.getColumnIndex(ContactsContract.Data.DATA1) val data1Column = dataCursor.getColumnIndex(ContactsContract.Data.DATA1)
val data3Column = dataCursor.getColumnIndex(ContactsContract.Data.DATA3) val data3Column = dataCursor.getColumnIndex(ContactsContract.Data.DATA3)
val idColumn = dataCursor.getColumnIndex(ContactsContract.Data._ID) val idColumn = dataCursor.getColumnIndex(ContactsContract.Data._ID)
@ -139,14 +149,14 @@ class Contact(
} }
"vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile" -> { "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile" -> {
val data1 = dataCursor.getStringOrNull(data1Column) val data1 = dataCursor.getStringOrNull(data1Column)
?: continue@loop ?: continue@loop
val data3 = dataCursor.getStringOrNull(data3Column) val data3 = dataCursor.getStringOrNull(data3Column)
?: continue@loop ?: continue@loop
telegram.add("$data1$$data3") telegram.add("$data1$$data3")
} }
"vnd.android.cursor.item/vnd.com.whatsapp.profile" -> { "vnd.android.cursor.item/vnd.com.whatsapp.profile" -> {
val data1 = dataCursor.getStringOrNull(data1Column) val data1 = dataCursor.getStringOrNull(data1Column)
?: continue@loop ?: continue@loop
val dataId = dataCursor.getLong(idColumn) val dataId = dataCursor.getLong(idColumn)
whatsapp.add("$dataId$+${data1.substringBefore('@')}") whatsapp.add("$dataId$+${data1.substringBefore('@')}")
} }
@ -155,11 +165,11 @@ class Contact(
dataCursor.close() dataCursor.close()
val lookupKeyCursor = context.contentResolver.query( val lookupKeyCursor = context.contentResolver.query(
ContactsContract.Contacts.CONTENT_URI, ContactsContract.Contacts.CONTENT_URI,
arrayOf(ContactsContract.Contacts.LOOKUP_KEY), arrayOf(ContactsContract.Contacts.LOOKUP_KEY),
"${ContactsContract.Contacts._ID} = ?", "${ContactsContract.Contacts._ID} = ?",
arrayOf(id.toString()), arrayOf(id.toString()),
null null
) ?: return null ) ?: return null
var lookUpKey = "" var lookUpKey = ""
if (lookupKeyCursor.moveToNext()) { if (lookupKeyCursor.moveToNext()) {
@ -168,16 +178,16 @@ class Contact(
lookupKeyCursor.close() lookupKeyCursor.close()
return Contact( return Contact(
id = id, id = id,
emails = emails, emails = emails,
phones = phones, phones = phones,
firstName = firstName, firstName = firstName,
lastName = lastName, lastName = lastName,
displayName = displayName, displayName = displayName,
postals = postals, postals = postals,
telegram = telegram, telegram = telegram,
whatsapp = whatsapp, whatsapp = whatsapp,
lookupKey = lookUpKey lookupKey = lookUpKey
) )
} }

View File

@ -291,10 +291,6 @@ dependencyResolutionManagement {
.to("org.jsoup", "jsoup") .to("org.jsoup", "jsoup")
.version("1.14.2") .version("1.14.2")
alias("textdrawable")
.to("com.amulyakhare", "com.amulyakhare.textdrawable")
.version("1.0.1")
alias("glide") alias("glide")
.to("com.github.bumptech.glide", "glide") .to("com.github.bumptech.glide", "glide")
.version("4.12.0") .version("4.12.0")

View File

@ -68,7 +68,6 @@ dependencies {
implementation(libs.androidx.transition) implementation(libs.androidx.transition)
implementation(libs.materialcomponents) implementation(libs.materialcomponents)
implementation(libs.viewpropertyobjectanimator) implementation(libs.viewpropertyobjectanimator)
implementation(libs.textdrawable)
implementation(libs.glide) implementation(libs.glide)
implementation(libs.draglinearlayout) implementation(libs.draglinearlayout)
implementation(libs.lottie.core) implementation(libs.lottie.core)

View File

@ -1,12 +1,12 @@
package de.mm20.launcher2.ui.legacy.data package de.mm20.launcher2.ui.legacy.data
import android.content.Context import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.amulyakhare.textdrawable.TextDrawable import de.mm20.launcher2.graphics.TextDrawable
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.sp
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
/** /**
@ -22,8 +22,7 @@ class InformationText(
override fun getPlaceholderIcon(context: Context): LauncherIcon { override fun getPlaceholderIcon(context: Context): LauncherIcon {
return LauncherIcon( return LauncherIcon(
foreground = TextDrawable.builder() foreground = TextDrawable("i", fontSize = 40 * context.sp),
.buildRect("i", Color.WHITE),
background = ColorDrawable(ContextCompat.getColor(context, R.color.grey)) background = ColorDrawable(ContextCompat.getColor(context, R.color.grey))
) )
} }

View File

@ -46,7 +46,6 @@ dependencies {
implementation(libs.okhttp) implementation(libs.okhttp)
implementation(libs.glide) implementation(libs.glide)
implementation(libs.textdrawable)
implementation(libs.jsoup) implementation(libs.jsoup)
implementation(libs.koin.android) implementation(libs.koin.android)

View File

@ -3,6 +3,7 @@ package de.mm20.launcher2.search.data
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.net.Uri import android.net.Uri
import android.util.Log import android.util.Log
@ -10,11 +11,12 @@ import android.webkit.URLUtil
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.graphics.toColorInt import androidx.core.graphics.toColorInt
import androidx.palette.graphics.Palette import androidx.palette.graphics.Palette
import com.amulyakhare.textdrawable.TextDrawable
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import de.mm20.launcher2.graphics.TextDrawable
import de.mm20.launcher2.helper.NetworkUtils import de.mm20.launcher2.helper.NetworkUtils
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.jsonObjectOf import de.mm20.launcher2.ktx.jsonObjectOf
import de.mm20.launcher2.ktx.sp
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.preferences.WebsiteProtocols import de.mm20.launcher2.preferences.WebsiteProtocols
import de.mm20.launcher2.websites.R import de.mm20.launcher2.websites.R
@ -67,7 +69,7 @@ class Website(
override fun getPlaceholderIcon(context: Context): LauncherIcon { override fun getPlaceholderIcon(context: Context): LauncherIcon {
val drawable = if (label.isNotEmpty()) { val drawable = if (label.isNotEmpty()) {
TextDrawable.builder().buildRect(label[0].toString(), 0) TextDrawable(label[0].toString(), typeface = Typeface.DEFAULT_BOLD, fontSize = 40 * context.sp)
} else context.getDrawable(R.drawable.ic_website)!! } else context.getDrawable(R.drawable.ic_website)!!
return LauncherIcon( return LauncherIcon(
foreground = drawable, foreground = drawable,