Fix missing icon on shortcut entries

- adds locus id and context to the messages screen
- only shows shorcuts for the most recent rooms with activity (eventually this might want to be customised
This commit is contained in:
Adam Brown 2023-01-14 11:47:31 +00:00
parent 2e12e5e089
commit 9cd9520e52
10 changed files with 43 additions and 17 deletions

View File

@ -165,6 +165,7 @@ internal class FeatureModules internal constructor(
DirectoryModule(
context = context,
chatEngine = chatEngineModule.engine,
iconLoader = imageLoaderModule.iconLoader(),
)
}
val loginModule by unsafeLazy {

View File

@ -4,5 +4,6 @@ plugins {
dependencies {
compileOnly project(":domains:android:stub")
compileOnly libs.androidx.annotation
implementation project(":core")
}

View File

@ -1,20 +1,30 @@
package app.dapk.st.core
import android.os.Build
import androidx.annotation.ChecksSdkIntAtLeast
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O, lambda = 0)
fun <T> DeviceMeta.isAtLeastO(block: () -> T, fallback: () -> T = { throw IllegalStateException("not handled") }): T {
return if (this.apiVersion >= Build.VERSION_CODES.O) block() else fallback()
}
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.S)
fun DeviceMeta.isAtLeastS() = this.apiVersion >= Build.VERSION_CODES.S
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O, lambda = 0)
fun DeviceMeta.onAtLeastO(block: () -> Unit) {
if (this.apiVersion >= Build.VERSION_CODES.O) block()
whenXOrHigher(Build.VERSION_CODES.O, block, fallback = {})
}
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.R, lambda = 0)
fun DeviceMeta.onAtLeastR(block: () -> Unit) {
whenXOrHigher(Build.VERSION_CODES.R, block, fallback = {})
}
inline fun <T> DeviceMeta.whenPOrHigher(block: () -> T, fallback: () -> T) = whenXOrHigher(Build.VERSION_CODES.P, block, fallback)
inline fun <T> DeviceMeta.whenOOrHigher(block: () -> T, fallback: () -> T) = whenXOrHigher(Build.VERSION_CODES.O, block, fallback)
@ChecksSdkIntAtLeast(parameter = 0, lambda = 1)
inline fun <T> DeviceMeta.whenXOrHigher(version: Int, block: () -> T, fallback: () -> T): T {
return if (this.apiVersion >= version) block() else fallback()
}

View File

@ -8,6 +8,7 @@ android {
dependencies {
implementation project(":domains:android:compose-core")
implementation project(":domains:android:imageloader")
implementation "chat-engine:chat-engine"
implementation 'screen-state:screen-android'
implementation project(":features:messenger")

View File

@ -4,19 +4,17 @@ import android.content.Context
import app.dapk.st.core.JobBag
import app.dapk.st.core.ProvidableModule
import app.dapk.st.directory.state.DirectoryEvent
import app.dapk.st.directory.state.DirectoryState
import app.dapk.st.directory.state.directoryReducer
import app.dapk.st.engine.ChatEngine
import app.dapk.st.state.createStateViewModel
import app.dapk.st.imageloader.IconLoader
class DirectoryModule(
private val context: Context,
private val chatEngine: ChatEngine,
private val iconLoader: IconLoader,
) : ProvidableModule {
fun directoryState(): DirectoryState {
return createStateViewModel { directoryReducer(it) }
}
fun directoryReducer(eventEmitter: suspend (DirectoryEvent) -> Unit) = directoryReducer(chatEngine, shortcutHandler(), JobBag(), eventEmitter)
fun directoryReducer(eventEmitter: suspend (DirectoryEvent) -> Unit) = directoryReducer(chatEngine, ShortcutHandler(context), JobBag(), eventEmitter)
private fun shortcutHandler() = ShortcutHandler(context, iconLoader)
}

View File

@ -1,19 +1,24 @@
package app.dapk.st.directory
import android.content.Context
import android.content.pm.ShortcutInfo
import androidx.core.app.Person
import androidx.core.content.LocusIdCompat
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import app.dapk.st.engine.RoomOverview
import app.dapk.st.imageloader.IconLoader
import app.dapk.st.matrix.common.RoomId
import app.dapk.st.messenger.MessengerActivity
internal class ShortcutHandler(private val context: Context) {
internal class ShortcutHandler(
private val context: Context,
private val iconLoader: IconLoader,
) {
private val cachedRoomIds = mutableListOf<RoomId>()
fun onDirectoryUpdate(overviews: List<RoomOverview>) {
suspend fun onDirectoryUpdate(overviews: List<RoomOverview>) {
val update = overviews.map { it.roomId }
if (cachedRoomIds != update) {
cachedRoomIds.clear()
@ -21,12 +26,14 @@ internal class ShortcutHandler(private val context: Context) {
val maxShortcutCountPerActivity = ShortcutManagerCompat.getMaxShortcutCountPerActivity(context)
overviews
.sortedByDescending { it.lastMessage?.utcTimestamp }
.take(maxShortcutCountPerActivity)
.forEachIndexed { index, room ->
val build = ShortcutInfoCompat.Builder(context, room.roomId.value)
.setShortLabel(room.roomName ?: "N/A")
.setLongLabel(room.roomName ?: "N/A")
.setRank(index)
.setLocusId((LocusIdCompat(room.roomId.value)))
.run {
this.setPerson(
Person.Builder()
@ -35,9 +42,14 @@ internal class ShortcutHandler(private val context: Context) {
.build()
)
}
.run {
room.roomAvatarUrl?.let { iconLoader.load(it.value) }?.let {
this.setIcon(IconCompat.createFromIcon(context, it))
} ?: this
}
.setIntent(MessengerActivity.newShortcutInstance(context, room.roomId))
.setLongLived(true)
.setCategories(setOf(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION))
.setIsConversation()
.build()
ShortcutManagerCompat.pushDynamicShortcut(context, build)
}

View File

@ -3,6 +3,7 @@ package app.dapk.st.messenger
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.LocusId
import android.os.Bundle
import android.os.Parcelable
import androidx.compose.foundation.layout.fillMaxSize
@ -10,11 +11,8 @@ import androidx.compose.material3.Surface
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import app.dapk.st.core.AndroidUri
import app.dapk.st.core.DapkActivity
import app.dapk.st.core.MimeType
import app.dapk.st.core.*
import app.dapk.st.core.extensions.unsafeLazy
import app.dapk.st.core.module
import app.dapk.st.matrix.common.RoomId
import app.dapk.st.messenger.gallery.GetImageFromGallery
import app.dapk.st.messenger.state.ComposerStateChange
@ -58,6 +56,8 @@ class MessengerActivity : DapkActivity() {
val payload = readPayload<MessagerActivityPayload>()
val factory = ImageRequest.Builder(applicationContext).fetcherFactory(module.decryptingFetcherFactory(RoomId(payload.roomId)))
module.deviceMeta.onAtLeastR { setLocusContext(LocusId(payload.roomId), savedInstanceState) }
val galleryLauncher = registerForActivityResult(GetImageFromGallery()) {
it?.let { uri ->
state.dispatch(

View File

@ -16,7 +16,7 @@ class MessengerModule(
private val chatEngine: ChatEngine,
private val context: Context,
private val messageOptionsStore: MessageOptionsStore,
private val deviceMeta: DeviceMeta,
val deviceMeta: DeviceMeta,
) : ProvidableModule {
internal fun messengerState(launchPayload: MessagerActivityPayload): MessengerState {

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.app.Notification
import android.app.PendingIntent
import android.content.Context
import android.content.LocusId
import android.graphics.drawable.Icon
import app.dapk.st.core.DeviceMeta
import app.dapk.st.core.isAtLeastO
@ -41,7 +42,8 @@ class AndroidNotificationBuilder(
}
.ifNotNull(notification.category) { setCategory(it) }
.ifNotNull(notification.shortcutId) {
deviceMeta.onAtLeastO { setShortcutId(notification.shortcutId) }
setLocusId(LocusId(it))
deviceMeta.onAtLeastO { setShortcutId(it) }
}
.ifNotNull(notification.smallIcon) { setSmallIcon(it) }
.ifNotNull(notification.largeIcon) { setLargeIcon(it) }

View File

@ -13,6 +13,7 @@ sqldelight = { id = "com.squareup.sqldelight", version.ref = "sqldelight" }
[libraries]
android-desugar = { group = "com.android.tools", name = "desugar_jdk_libs", version = "1.1.5" }
androidx-annotation = { group = "androidx.annotation", name = "annotation", version = "1.5.0" }
compose-coil = { group = "io.coil-kt", name = "coil-compose", version = "2.2.2" }
accompanist-systemuicontroller = { group = "com.google.accompanist", name = "accompanist-systemuicontroller", version = "0.28.0" }