diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0647d4d1..b2904249 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -70,6 +70,10 @@ android:name=".c2dm.ReplyReceiver" android:exported="false" /> + + { + val server = + dbChannel.server?.let { db.serverQueries.findById(it).executeAsOneOrNull() } + val iconUrl = server?.iconId?.let { "$STOAT_FILES/icons/$it" } + iconUrl?.let { runCatching { loadBitmap(it) }.getOrNull() } + ?: generateLetterBitmap(server?.name ?: channelName) + } + + "Group" -> { + val iconUrl = dbChannel.iconId?.let { "$STOAT_FILES/icons/$it" } + iconUrl?.let { runCatching { loadBitmap(it) }.getOrNull() } + ?: generateLetterBitmap(dbChannel.name ?: channelName) + } + + else -> authorBitmap + } + val author = Person.Builder() .setBot(false) .setKey(authorId) - .setIcon(IconCompat.createWithBitmap(bitmap)) + .setIcon(IconCompat.createWithBitmap(authorBitmap)) .setName(authorName) .build() @@ -137,7 +219,7 @@ class HandlerService : FirebaseMessagingService() { val shortcut = ShortcutInfoCompat.Builder(this, shortcutId) .setShortLabel(channelName) .setLongLabel(channelName) - .setIcon(IconCompat.createWithBitmap(bitmap)) + .setIcon(IconCompat.createWithBitmap(conversationBitmap)) .setIntent(conversationIntent) .setLongLived(true) .setPerson(author) @@ -154,7 +236,7 @@ class HandlerService : FirebaseMessagingService() { putExtra("channelId", channelId) } - val action: NotificationCompat.Action = + val replyAction: NotificationCompat.Action = NotificationCompat.Action.Builder( R.drawable.ic_reply_24dp, getString(R.string.message_context_sheet_actions_reply), @@ -168,6 +250,24 @@ class HandlerService : FirebaseMessagingService() { .addRemoteInput(remoteInput) .build() + val markAsReadIntent = Intent(this, MarkAsReadReceiver::class.java).apply { + putExtra("channelId", channelId) + putExtra("messageId", messageId) + } + + val markAsReadAction: NotificationCompat.Action = + NotificationCompat.Action.Builder( + R.drawable.ic_mark_chat_read_24dp, + getString(R.string.channel_context_sheet_actions_mark_read), + PendingIntent.getBroadcast( + this, + channelId.hashCode() xor 1, + markAsReadIntent, + PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT + ) + ) + .build() + val contentIntent = PendingIntent.getActivity( this, channelId.hashCode(), @@ -182,11 +282,13 @@ class HandlerService : FirebaseMessagingService() { .setContentIntent(contentIntent) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setStyle( - NotificationCompat.MessagingStyle(author) + NotificationCompat.MessagingStyle(self) + .setGroupConversation(dbChannel?.channelType != "DirectMessage") .setConversationTitle(channelName) .addMessage(body, messageTimestamp, author) ) - .addAction(action) + .addAction(replyAction) + .addAction(markAsReadAction) .setPriority(NotificationCompat.PRIORITY_HIGH) .setAutoCancel(true) @@ -204,7 +306,7 @@ class HandlerService : FirebaseMessagingService() { val bubbleMetadata = NotificationCompat.BubbleMetadata.Builder( bubbleIntent, - IconCompat.createWithBitmap(bitmap) + IconCompat.createWithBitmap(conversationBitmap) ) .setDesiredHeight(600) .setAutoExpandBubble(false) diff --git a/app/src/main/java/chat/stoat/c2dm/MarkAsReadReceiver.kt b/app/src/main/java/chat/stoat/c2dm/MarkAsReadReceiver.kt new file mode 100644 index 00000000..1f127445 --- /dev/null +++ b/app/src/main/java/chat/stoat/c2dm/MarkAsReadReceiver.kt @@ -0,0 +1,39 @@ +package chat.stoat.c2dm + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import androidx.core.app.NotificationManagerCompat +import chat.stoat.api.StoatAPI +import chat.stoat.api.routes.channel.ackChannel +import chat.stoat.persistence.KVStorage +import kotlinx.coroutines.runBlocking +import logcat.LogPriority +import logcat.asLog +import logcat.logcat + +class MarkAsReadReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val channelId = intent.getStringExtra("channelId") ?: run { + logcat(LogPriority.ERROR) { "No channel ID, aborting" } + return + } + + val messageId = intent.getStringExtra("messageId") ?: run { + logcat(LogPriority.ERROR) { "No message ID, aborting" } + return + } + + runBlocking { + val token = KVStorage(context).get("sessionToken") ?: run { + logcat(LogPriority.ERROR) { "No session token, aborting" } + return@runBlocking + } + StoatAPI.setSessionHeader(token) + runCatching { ackChannel(channelId, messageId) } + .onFailure { logcat(LogPriority.ERROR) { "Ack failed: ${it.asLog()}" } } + } + + NotificationManagerCompat.from(context).cancel(channelId, NotificationID.NEW_MESSAGE) + } +} diff --git a/app/src/main/java/chat/stoat/screens/chat/ChatRouterScreen.kt b/app/src/main/java/chat/stoat/screens/chat/ChatRouterScreen.kt index 25191aef..846e7a4f 100644 --- a/app/src/main/java/chat/stoat/screens/chat/ChatRouterScreen.kt +++ b/app/src/main/java/chat/stoat/screens/chat/ChatRouterScreen.kt @@ -73,6 +73,9 @@ import chat.stoat.api.realtime.DisconnectionState import chat.stoat.api.realtime.RealtimeSocket import chat.stoat.api.routes.microservices.gazette.getLatestChangelog import chat.stoat.api.routes.push.subscribePush +import chat.stoat.api.routes.user.fetchSelf +import chat.stoat.core.model.data.STOAT_FILES +import chat.stoat.core.model.schemas.User import chat.stoat.api.settings.SyncedSettings import chat.stoat.callbacks.Action import chat.stoat.callbacks.ActionChannel @@ -162,6 +165,12 @@ class ChatRouterViewModel( init { viewModelScope.launch { + runCatching { fetchSelf() }.getOrNull()?.let { user -> + kvStorage.set("selfId", user.id ?: "") + kvStorage.set("selfName", User.resolveDefaultName(user)) + kvStorage.set("selfAvatarUrl", user.avatar?.id?.let { "$STOAT_FILES/avatars/$it" } ?: "") + } + val pendingChannel = NotificationDeepLink.pendingChannelId.value if (pendingChannel != null) { NotificationDeepLink.pendingChannelId.value = null diff --git a/app/src/main/java/chat/stoat/screens/settings/SettingsScreen.kt b/app/src/main/java/chat/stoat/screens/settings/SettingsScreen.kt index 8eef0b4b..994c881c 100644 --- a/app/src/main/java/chat/stoat/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/chat/stoat/screens/settings/SettingsScreen.kt @@ -48,6 +48,9 @@ class SettingsScreenViewModel( fun logout() { runBlocking { kvStorage.remove("sessionToken") + kvStorage.remove("selfId") + kvStorage.remove("selfName") + kvStorage.remove("selfAvatarUrl") LoadedSettings.reset() StoatAPI.logout() }