Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions atox/src/androidTest/kotlin/ui/AvatarFactoryTest.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022 Robin Lindén <[email protected]>
// SPDX-FileCopyrightText: 2022-2025 Robin Lindén <[email protected]>
//
// SPDX-License-Identifier: GPL-3.0-only

Expand All @@ -7,16 +7,19 @@ package ltd.evilcorp.atox.ui
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import kotlin.test.Test
import ltd.evilcorp.core.vo.PublicKey
import org.junit.runner.RunWith

private val pk = PublicKey("123")

@RunWith(AndroidJUnit4::class)
class AvatarFactoryTest {
@Test
fun emptyName() {
AvatarFactory.create(
InstrumentationRegistry.getInstrumentation().targetContext.resources,
name = "",
publicKey = "123",
pk = pk,
)
}

Expand All @@ -25,7 +28,7 @@ class AvatarFactoryTest {
AvatarFactory.create(
InstrumentationRegistry.getInstrumentation().targetContext.resources,
name = "a ",
publicKey = "123",
pk = pk,
)
}
}
10 changes: 5 additions & 5 deletions atox/src/main/kotlin/ActionReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,18 @@ class ActionReceiver : BroadcastReceiver() {
Log.e(TAG, "Got intent without required key $KEY_CONTACT_PK $intent")
return@launch
}
if (!contactRepository.exists(pk.string())) {
if (!contactRepository.exists(pk)) {
notificationHelper.dismissNotifications(pk)
notificationHelper.dismissCallNotification(pk)
return@launch
}

RemoteInput.getResultsFromIntent(intent)?.let { results ->
results.getCharSequence(KEY_TEXT_REPLY)?.toString()?.let { input ->
contactRepository.setHasUnreadMessages(pk.string(), false)
contactRepository.setHasUnreadMessages(pk, false)
chatManager.sendMessage(pk, input)
notificationHelper.showMessageNotification(
Contact(pk.string(), tox.getName()),
Contact(pk, tox.getName()),
input,
outgoing = true,
)
Expand All @@ -103,7 +103,7 @@ class ActionReceiver : BroadcastReceiver() {
}
Action.CallIgnore -> callManager.removePendingCall(pk)
Action.MarkAsRead -> {
contactRepository.setHasUnreadMessages(pk.string(), false)
contactRepository.setHasUnreadMessages(pk, false)
notificationHelper.dismissNotifications(pk)
}
null -> Log.e(TAG, "Missing action in intent $intent")
Expand All @@ -117,7 +117,7 @@ class ActionReceiver : BroadcastReceiver() {
it
} else {
Log.e(TAG, "Unable to get contact ${pk.fingerprint()} for call notification")
Contact(publicKey = pk.string(), name = pk.fingerprint())
Contact(publicKey = pk, name = pk.fingerprint())
}
}

Expand Down
2 changes: 1 addition & 1 deletion atox/src/main/kotlin/ToxService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class ToxService : LifecycleService() {
}

lifecycleScope.launch(Dispatchers.Default) {
userRepository.get(tox.publicKey.string())
userRepository.get(tox.publicKey)
.filterNotNull()
.filter { it.connectionStatus != connectionStatus }
.flowWithLifecycle(lifecycle)
Expand Down
21 changes: 9 additions & 12 deletions atox/src/main/kotlin/tox/EventListenerCallbacks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ private fun isImage(filename: String) = try {
false
}

private const val FINGERPRINT_LEN = 8
private fun String.fingerprint() = this.take(FINGERPRINT_LEN)

@Singleton
class EventListenerCallbacks @Inject constructor(
private val ctx: Context,
Expand All @@ -73,7 +70,7 @@ class EventListenerCallbacks @Inject constructor(
private var audioPlayer: AudioPlayer? = null
private val scope = CoroutineScope(Dispatchers.Default)

private suspend fun tryGetContact(pk: String, tag: String) = contactRepository.get(pk).firstOrNull().let {
private suspend fun tryGetContact(pk: PublicKey, tag: String) = contactRepository.get(pk).firstOrNull().let {
if (it == null) Log.e(TAG, "$tag -> unable to get contact for ${pk.fingerprint()}")
it
}
Expand Down Expand Up @@ -147,7 +144,7 @@ class EventListenerCallbacks @Inject constructor(
}

fileRecvHandler = { publicKey, fileNo, kind, fileSize, filename ->
val name = if (kind == FileKind.Avatar.ordinal) publicKey else filename
val name = if (kind == FileKind.Avatar.ordinal) publicKey.string() else filename

val id = fileTransferManager.add(FileTransfer(publicKey, fileNo, kind, fileSize, name, outgoing = false))

Expand All @@ -168,16 +165,16 @@ class EventListenerCallbacks @Inject constructor(
}
}

fileRecvControlHandler = { publicKey: String, fileNo: Int, control: ToxFileControl ->
fileTransferManager.setStatus(publicKey, fileNo, control)
fileRecvControlHandler = { pk: PublicKey, fileNo: Int, control: ToxFileControl ->
fileTransferManager.setStatus(pk, fileNo, control)
}

fileChunkRequestHandler = { publicKey: String, fileNo: Int, position: Long, length: Int ->
fileTransferManager.sendChunk(publicKey, fileNo, position, length)
fileChunkRequestHandler = { pk: PublicKey, fileNo: Int, position: Long, length: Int ->
fileTransferManager.sendChunk(pk, fileNo, position, length)
}

selfConnectionStatusHandler = { status ->
userRepository.updateConnection(tox.publicKey.string(), status)
userRepository.updateConnection(tox.publicKey, status)
}

friendTypingHandler = { publicKey, isTyping ->
Expand All @@ -201,8 +198,8 @@ class EventListenerCallbacks @Inject constructor(
audioPlayer?.stop()
audioPlayer?.release()
audioPlayer = null
notificationHelper.dismissCallNotification(PublicKey(pk))
callManager.endCall(PublicKey(pk))
notificationHelper.dismissCallNotification(pk)
callManager.endCall(pk)
}
}

Expand Down
8 changes: 5 additions & 3 deletions atox/src/main/kotlin/ui/AvatarFactory.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2019-2022 aTox contributors
// SPDX-FileCopyrightText: 2019-2025 Robin Lindén <[email protected]>
// SPDX-FileCopyrightText: 2021-2022 aTox contributors
//
// SPDX-License-Identifier: GPL-3.0-only

Expand All @@ -14,6 +15,7 @@ import android.graphics.RectF
import android.graphics.Typeface
import kotlin.math.abs
import ltd.evilcorp.atox.R
import ltd.evilcorp.core.vo.PublicKey

internal object AvatarFactory {

Expand All @@ -27,7 +29,7 @@ internal object AvatarFactory {
fun create(
resources: Resources,
name: String,
publicKey: String,
pk: PublicKey,
size: Px = Px(resources.getDimension(R.dimen.default_avatar_size).toInt()),
): Bitmap {
val defaultAvatarSize = resources.getDimension(R.dimen.default_avatar_size)
Expand All @@ -37,7 +39,7 @@ internal object AvatarFactory {
val canvas = Canvas(bitmap)
val rect = RectF(0f, 0f, bitmap.width.toFloat(), bitmap.height.toFloat())
val colors = resources.getIntArray(R.array.contactBackgrounds)
val backgroundPaint = Paint().apply { color = colors[abs(publicKey.hashCode()).rem(colors.size)] }
val backgroundPaint = Paint().apply { color = colors[abs(pk.hashCode()).rem(colors.size)] }

val textPaint = Paint().apply {
color = Color.WHITE
Expand Down
5 changes: 3 additions & 2 deletions atox/src/main/kotlin/ui/AvatarImageView.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: 2022 aTox contributors
// SPDX-FileCopyrightText: 2022-2024 Robin Lindén <[email protected]>
// SPDX-FileCopyrightText: 2022-2025 Robin Lindén <[email protected]>
//
// SPDX-License-Identifier: GPL-3.0-only

Expand All @@ -21,6 +21,7 @@ import kotlin.math.sqrt
import ltd.evilcorp.atox.R
import ltd.evilcorp.core.vo.ConnectionStatus
import ltd.evilcorp.core.vo.Contact
import ltd.evilcorp.core.vo.PublicKey
import ltd.evilcorp.core.vo.UserStatus

private const val STATUS_INDICATOR_SIZE_RATIO_WITH_AVATAR = 12f / 50
Expand Down Expand Up @@ -50,7 +51,7 @@ class AvatarImageView @JvmOverloads constructor(context: Context, attrs: Attribu
}

private var name = ""
private var publicKey = ""
private var publicKey = PublicKey("")
private var avatarUri = ""

fun setFrom(contact: Contact) {
Expand Down
35 changes: 20 additions & 15 deletions atox/src/main/kotlin/ui/NotificationHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {
.setSmallIcon(android.R.drawable.sym_action_chat)
.setContentTitle(contact.name.ifEmpty { context.getText(R.string.contact_default_name) })
.setContentText(message)
.setContentIntent(deepLinkToChat(PublicKey(contact.publicKey)))
.setContentIntent(deepLinkToChat(contact.publicKey))
.setAutoCancel(true)
.setSilent(silent)

Expand All @@ -143,13 +143,15 @@ class NotificationHelper @Inject constructor(private val context: Context) {

val chatPartner = Person.Builder()
.setName(contact.name.ifEmpty { context.getText(R.string.contact_default_name) })
.setKey(if (outgoing) "myself" else contact.publicKey)
.setKey(if (outgoing) "myself" else contact.publicKey.string())
.setIcon(icon)
.setImportant(true)
.build()

val style =
notifierOld.activeNotifications.find { it.notification.group == contact.publicKey }?.notification?.let {
notifierOld.activeNotifications.find {
it.notification.group == contact.publicKey.string()
}?.notification?.let {
NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification(it)
} ?: NotificationCompat.MessagingStyle(chatPartner)

Expand All @@ -159,7 +161,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {

notificationBuilder
.setStyle(style)
.setGroup(contact.publicKey)
.setGroup(contact.publicKey.string())
}

// I can't find it in the documentation for RemoteInput or anything, but per
Expand All @@ -174,7 +176,10 @@ class NotificationHelper @Inject constructor(private val context: Context) {
PendingIntentCompat.getBroadcast(
context,
contact.publicKey.hashCode(),
Intent(context, ActionReceiver::class.java).putExtra(KEY_CONTACT_PK, contact.publicKey),
Intent(context, ActionReceiver::class.java).putExtra(
KEY_CONTACT_PK,
contact.publicKey.string(),
),
PendingIntent.FLAG_UPDATE_CURRENT,
mutable = true,
),
Expand All @@ -194,7 +199,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {
.Builder(
IconCompat.createWithResource(context, R.drawable.ic_send),
context.getString(R.string.reply),
deepLinkToChat(PublicKey(contact.publicKey), focusMessageBox = true),
deepLinkToChat(contact.publicKey, focusMessageBox = true),
)
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY)
.build(),
Expand All @@ -209,7 +214,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {
context,
"${contact.publicKey}_mark_as_read".hashCode(),
Intent(context, ActionReceiver::class.java)
.putExtra(KEY_CONTACT_PK, contact.publicKey)
.putExtra(KEY_CONTACT_PK, contact.publicKey.string())
.putExtra(KEY_ACTION, Action.MarkAsRead),
PendingIntent.FLAG_UPDATE_CURRENT,
),
Expand Down Expand Up @@ -258,7 +263,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {
return
}

dismissCallNotification(PublicKey(contact.publicKey))
dismissCallNotification(contact.publicKey)
val notificationBuilder = NotificationCompat.Builder(context, CALL)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setSmallIcon(android.R.drawable.ic_menu_call)
Expand All @@ -274,8 +279,8 @@ class NotificationHelper @Inject constructor(private val context: Context) {
.setContentIntent(
NavDeepLinkBuilder(context)
.setGraph(R.navigation.nav_graph)
.addDestination(R.id.chatFragment, bundleOf(CONTACT_PUBLIC_KEY to contact.publicKey))
.addDestination(R.id.callFragment, bundleOf(CONTACT_PUBLIC_KEY to contact.publicKey))
.addDestination(R.id.chatFragment, bundleOf(CONTACT_PUBLIC_KEY to contact.publicKey.string()))
.addDestination(R.id.callFragment, bundleOf(CONTACT_PUBLIC_KEY to contact.publicKey.string()))
.createPendingIntent(),
)
.addAction(
Expand All @@ -287,7 +292,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {
context,
"${contact.publicKey}_end_call".hashCode(),
Intent(context, ActionReceiver::class.java)
.putExtra(KEY_CONTACT_PK, contact.publicKey)
.putExtra(KEY_CONTACT_PK, contact.publicKey.string())
.putExtra(KEY_ACTION, Action.CallEnd),
PendingIntent.FLAG_UPDATE_CURRENT,
),
Expand Down Expand Up @@ -315,7 +320,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {
.setSmallIcon(android.R.drawable.ic_menu_call)
.setContentTitle(context.getString(R.string.incoming_call))
.setContentText(context.getString(R.string.incoming_call_from, c.name))
.setContentIntent(deepLinkToChat(PublicKey(c.publicKey)))
.setContentIntent(deepLinkToChat(c.publicKey))
.addAction(
NotificationCompat.Action
.Builder(
Expand All @@ -325,7 +330,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {
context,
"${c.publicKey}_accept_call".hashCode(),
Intent(context, ActionReceiver::class.java)
.putExtra(KEY_CONTACT_PK, c.publicKey)
.putExtra(KEY_CONTACT_PK, c.publicKey.string())
.putExtra(KEY_ACTION, Action.CallAccept),
PendingIntent.FLAG_UPDATE_CURRENT,
),
Expand All @@ -342,7 +347,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {
context,
"${c.publicKey}_reject_call".hashCode(),
Intent(context, ActionReceiver::class.java)
.putExtra(KEY_CONTACT_PK, c.publicKey)
.putExtra(KEY_CONTACT_PK, c.publicKey.string())
.putExtra(KEY_ACTION, Action.CallReject),
PendingIntent.FLAG_UPDATE_CURRENT,
),
Expand All @@ -354,7 +359,7 @@ class NotificationHelper @Inject constructor(private val context: Context) {
context,
"${c.publicKey}_ignore_call".hashCode(),
Intent(context, ActionReceiver::class.java)
.putExtra(KEY_CONTACT_PK, c.publicKey)
.putExtra(KEY_CONTACT_PK, c.publicKey.string())
.putExtra(KEY_ACTION, Action.CallIgnore),
PendingIntent.FLAG_UPDATE_CURRENT,
),
Expand Down
4 changes: 2 additions & 2 deletions atox/src/main/kotlin/ui/addcontact/AddContactFragment.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2024 Robin Lindén <[email protected]>
// SPDX-FileCopyrightText: 2019-2025 Robin Lindén <[email protected]>
// SPDX-FileCopyrightText: 2020 aTox contributors
//
// SPDX-License-Identifier: GPL-3.0-only
Expand Down Expand Up @@ -87,7 +87,7 @@ class AddContactFragment : BaseFragment<FragmentAddContactBinding>(FragmentAddCo
}

if (toxId.error == null) {
if (contacts.find { it.publicKey == input.toPublicKey().string() } != null) {
if (contacts.find { it.publicKey == input.toPublicKey() } != null) {
toxId.error = getString(R.string.tox_id_error_already_exists)
}
}
Expand Down
8 changes: 5 additions & 3 deletions atox/src/main/kotlin/ui/addcontact/AddContactViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2019-2022 aTox contributors
// SPDX-FileCopyrightText: 2019-2025 Robin Lindén <[email protected]>
// SPDX-FileCopyrightText: 2022 aTox contributors
//
// SPDX-License-Identifier: GPL-3.0-only

Expand All @@ -16,6 +17,7 @@ import ltd.evilcorp.core.repository.MessageRepository
import ltd.evilcorp.core.vo.Contact
import ltd.evilcorp.core.vo.Message
import ltd.evilcorp.core.vo.MessageType
import ltd.evilcorp.core.vo.PublicKey
import ltd.evilcorp.core.vo.Sender
import ltd.evilcorp.domain.feature.ContactManager
import ltd.evilcorp.domain.tox.Tox
Expand All @@ -35,7 +37,7 @@ class AddContactViewModel @Inject constructor(
fun isToxRunning() = tox.started
fun tryLoadTox(): Boolean = toxStarter.tryLoadTox(null) == ToxSaveStatus.Ok

private fun addToChatLog(publicKey: String, message: String) = scope.launch {
private fun addToChatLog(publicKey: PublicKey, message: String) = scope.launch {
messageRepository.add(
Message(
publicKey,
Expand All @@ -50,6 +52,6 @@ class AddContactViewModel @Inject constructor(

fun addContact(toxId: ToxID, message: String) {
contactManager.add(toxId, message)
addToChatLog(toxId.toPublicKey().string(), message)
addToChatLog(toxId.toPublicKey(), message)
}
}
Loading
Loading