feat: Add mute node functionality (#4181)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-01-10 15:35:01 -06:00 committed by GitHub
parent 42fe7e9b2e
commit a67b519abd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 2174 additions and 458 deletions

View file

@ -75,6 +75,7 @@ constructor(
when (action) {
is ServiceAction.Favorite -> handleFavorite(action, myNodeNum)
is ServiceAction.Ignore -> handleIgnore(action, myNodeNum)
is ServiceAction.Mute -> handleMute(action, myNodeNum)
is ServiceAction.Reaction -> handleReaction(action, myNodeNum)
is ServiceAction.ImportContact -> handleImportContact(action, myNodeNum)
is ServiceAction.SendContact -> {
@ -103,6 +104,12 @@ constructor(
nodeManager.updateNodeInfo(node.num) { it.isIgnored = !node.isIgnored }
}
private fun handleMute(action: ServiceAction.Mute, myNodeNum: Int) {
val node = action.node
commandSender.sendAdmin(myNodeNum) { toggleMutedNode = node.num }
nodeManager.updateNodeInfo(node.num) { it.isMuted = !node.isMuted }
}
private fun handleReaction(action: ServiceAction.Reaction, myNodeNum: Int) {
val channel = action.contactKey[0].digitToInt()
val destId = action.contactKey.substring(1)

View file

@ -614,17 +614,17 @@ constructor(
}
insert(packetToSave)
val isMuted = getContactSettings(contactKey).isMuted
if (!isMuted) {
if (packetToSave.port_num == Portnums.PortNum.ALERT_APP_VALUE) {
serviceNotifications.showAlertNotification(
contactKey,
getSenderName(dataPacket),
dataPacket.alert ?: getString(Res.string.critical_alert),
)
} else if (updateNotification) {
scope.handledLaunch { updateNotification(contactKey, dataPacket) }
}
val conversationMuted = getContactSettings(contactKey).isMuted
val nodeMuted = nodeManager.nodeDBbyID[dataPacket.from]?.isMuted == true
val isSilent = conversationMuted || nodeMuted
if (packetToSave.port_num == Portnums.PortNum.ALERT_APP_VALUE && !isSilent) {
serviceNotifications.showAlertNotification(
contactKey,
getSenderName(dataPacket),
dataPacket.alert ?: getString(Res.string.critical_alert),
)
} else if (updateNotification) {
scope.handledLaunch { updateNotification(contactKey, dataPacket, isSilent) }
}
}
}
@ -638,7 +638,7 @@ constructor(
return nodeManager.nodeDBbyID[packet.from]?.user?.longName ?: getString(Res.string.unknown_username)
}
private suspend fun updateNotification(contactKey: String, dataPacket: DataPacket) {
private suspend fun updateNotification(contactKey: String, dataPacket: DataPacket, isSilent: Boolean) {
when (dataPacket.dataType) {
Portnums.PortNum.TEXT_MESSAGE_APP_VALUE -> {
val message = dataPacket.text!!
@ -654,6 +654,7 @@ constructor(
message,
dataPacket.to == DataPacket.ID_BROADCAST,
channelName,
isSilent,
)
}
@ -664,6 +665,7 @@ constructor(
getSenderName(dataPacket),
message,
dataPacket.waypoint!!.id,
isSilent,
)
}
@ -712,26 +714,27 @@ constructor(
// Find the original packet to get the contactKey
packetRepository.get().getPacketByPacketId(packet.decoded.replyId)?.let { original ->
val contactKey = original.packet.contact_key
val isMuted = packetRepository.get().getContactSettings(contactKey).isMuted
if (!isMuted) {
val channelName =
if (original.packet.data.to == DataPacket.ID_BROADCAST) {
radioConfigRepository.channelSetFlow
.first()
.settingsList
.getOrNull(original.packet.data.channel)
?.name
} else {
null
}
serviceNotifications.updateReactionNotification(
contactKey,
getSenderName(dataMapper.toDataPacket(packet)!!),
emoji,
original.packet.data.to == DataPacket.ID_BROADCAST,
channelName,
)
}
val conversationMuted = packetRepository.get().getContactSettings(contactKey).isMuted
val nodeMuted = nodeManager.nodeDBbyID[fromId]?.isMuted == true
val isSilent = conversationMuted || nodeMuted
val channelName =
if (original.packet.data.to == DataPacket.ID_BROADCAST) {
radioConfigRepository.channelSetFlow
.first()
.settingsList
.getOrNull(original.packet.data.channel)
?.name
} else {
null
}
serviceNotifications.updateReactionNotification(
contactKey,
getSenderName(dataMapper.toDataPacket(packet)!!),
emoji,
original.packet.data.to == DataPacket.ID_BROADCAST,
channelName,
isSilent,
)
}
}

View file

@ -239,6 +239,7 @@ constructor(
entity.hopsAway = if (info.hasHopsAway()) info.hopsAway else -1
entity.isFavorite = info.isFavorite
entity.isIgnored = info.isIgnored
entity.isMuted = info.isMuted
}
}

View file

@ -313,8 +313,9 @@ constructor(
message: String,
isBroadcast: Boolean,
channelName: String?,
isSilent: Boolean,
) {
showConversationNotification(contactKey, isBroadcast, channelName)
showConversationNotification(contactKey, isBroadcast, channelName, isSilent = isSilent)
}
override suspend fun updateReactionNotification(
@ -323,8 +324,9 @@ constructor(
emoji: String,
isBroadcast: Boolean,
channelName: String?,
isSilent: Boolean,
) {
showConversationNotification(contactKey, isBroadcast, channelName, isSilent = isBroadcast)
showConversationNotification(contactKey, isBroadcast, channelName, isSilent = isSilent)
}
override suspend fun updateWaypointNotification(
@ -332,8 +334,9 @@ constructor(
name: String,
message: String,
waypointId: Int,
isSilent: Boolean,
) {
val notification = createWaypointNotification(name, message, waypointId)
val notification = createWaypointNotification(name, message, waypointId, isSilent)
notificationManager.notify(contactKey.hashCode(), notification)
}
@ -571,19 +574,30 @@ constructor(
return builder.build()
}
private fun createWaypointNotification(name: String, message: String, waypointId: Int): Notification {
private fun createWaypointNotification(
name: String,
message: String,
waypointId: Int,
isSilent: Boolean,
): Notification {
val person = Person.Builder().setName(name).build()
val style = NotificationCompat.MessagingStyle(person).addMessage(message, System.currentTimeMillis(), person)
return commonBuilder(NotificationType.Waypoint, createOpenWaypointIntent(waypointId))
.setCategory(Notification.CATEGORY_MESSAGE)
.setAutoCancel(true)
.setStyle(style)
.setGroup(GROUP_KEY_MESSAGES)
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.build()
val builder =
commonBuilder(NotificationType.Waypoint, createOpenWaypointIntent(waypointId))
.setCategory(Notification.CATEGORY_MESSAGE)
.setAutoCancel(true)
.setStyle(style)
.setGroup(GROUP_KEY_MESSAGES)
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
if (isSilent) {
builder.setSilent(true)
}
return builder.build()
}
private fun createAlertNotification(contactKey: String, name: String, alert: String): Notification {