diff --git a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactCard.kt b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactCard.kt index f380fea9d45859e40d2dd81c93e54759590e4aff..e89cedcc1e806170e2023924e3e093325b0d5bd2 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactCard.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactCard.kt @@ -19,19 +19,17 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.drawscope.withTransform import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import org.briarproject.bramble.api.contact.Contact import org.briarproject.briar.desktop.theme.outline import org.briarproject.briar.desktop.theme.selectedCard import org.briarproject.briar.desktop.theme.surfaceVariant -import org.briarproject.briar.desktop.ui.CVM import org.briarproject.briar.desktop.ui.Constants.HEADER_SIZE import org.briarproject.briar.desktop.ui.HorizontalDivider import org.briarproject.briar.desktop.utils.TimeUtils.getFormattedTimestamp @Composable fun ContactCard( - contact: Contact, - onSel: (Contact) -> Unit, + contactItem: ContactItem, + onSel: () -> Unit, selected: Boolean, drawNotifications: Boolean ) { @@ -42,7 +40,7 @@ fun ContactCard( val briarSurfaceVar = MaterialTheme.colors.surfaceVariant Card( - modifier = Modifier.fillMaxWidth().height(HEADER_SIZE).clickable(onClick = { onSel(contact) }), + modifier = Modifier.fillMaxWidth().height(HEADER_SIZE).clickable(onClick = onSel), shape = RoundedCornerShape(0.dp), backgroundColor = bgColor, contentColor = MaterialTheme.colors.onSurface @@ -50,7 +48,7 @@ fun ContactCard( Row(horizontalArrangement = Arrangement.SpaceBetween) { Row(modifier = Modifier.align(Alignment.CenterVertically).padding(horizontal = 16.dp)) { // TODO Pull profile pictures - ProfileCircle(36.dp, contact.author.id.bytes) + ProfileCircle(36.dp, contactItem.contact.author.id.bytes) // Draw notification badges if (drawNotifications) { Canvas( @@ -66,13 +64,12 @@ fun ContactCard( } Column(modifier = Modifier.align(Alignment.CenterVertically).padding(start = 12.dp)) { Text( - contact.author.name, + contactItem.contact.author.name, fontSize = 14.sp, modifier = Modifier.align(Alignment.Start).padding(bottom = 2.dp) ) - val latestMsgTime = CVM.current.getGroupCount(contact.id).latestMsgTime Text( - getFormattedTimestamp(latestMsgTime), + if (contactItem.isEmpty) "No messages." else getFormattedTimestamp(contactItem.timestamp), fontSize = 10.sp, modifier = Modifier.align(Alignment.Start) ) @@ -81,14 +78,12 @@ fun ContactCard( Canvas( modifier = Modifier.padding(start = 32.dp, end = 18.dp).size(22.dp).align(Alignment.CenterVertically), onDraw = { - val size = 16.dp.toPx() - drawCircle(color = outlineColor, radius = size / 2f) - // TODO check if contact online - if (true) { - drawCircle(color = briarSecondary, radius = 14.dp.toPx() / 2f) - } else { - drawCircle(color = briarSurfaceVar, radius = 14.dp.toPx() / 2f) - } + val size = 16.dp + drawCircle(color = outlineColor, radius = size.toPx() / 2f) + drawCircle( + color = if (contactItem.isConnected) briarSecondary else briarSurfaceVar, + radius = (size - 2.dp).toPx() / 2f + ) } ) } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactDrawerMakeIntro.kt b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactDrawerMakeIntro.kt index d0fc82fb2e26734d115c5ea87701893974ce0057..76e4c31547f7f835257621f1920b2ddd015d7a82 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactDrawerMakeIntro.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactDrawerMakeIntro.kt @@ -57,7 +57,8 @@ fun ContactDrawerMakeIntro(contact: Contact, contacts: List<Contact>, setInfoDra Column(Modifier.verticalScroll(rememberScrollState())) { for (c in contacts) { if (c.id != contact.id) { - ContactCard(c, { onCancelSel(c); introNextPg = true }, false, false) + // todo: refactor to use contactItem in IntroductionViewModel + //ContactCard(c, { onCancelSel(c); introNextPg = true }, false, false) } } } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactItem.kt b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactItem.kt new file mode 100644 index 0000000000000000000000000000000000000000..df2a19806f06e2b0ab2bff21385ecce9fac0da2b --- /dev/null +++ b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactItem.kt @@ -0,0 +1,16 @@ +package org.briarproject.briar.desktop.contact + +import org.briarproject.bramble.api.contact.Contact +import org.briarproject.briar.api.client.MessageTracker +import org.briarproject.briar.api.identity.AuthorInfo + +data class ContactItem( + val contact: Contact, + private val authorInfo: AuthorInfo, + val isConnected: Boolean, + private val groupCount: MessageTracker.GroupCount +) { + val isEmpty = groupCount.msgCount == 0 + val unread = groupCount.unreadCount + val timestamp = groupCount.latestMsgTime +} diff --git a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt index 528a52b6967bf73f272cf7b5396c6f35b6e54de9..345e3f80b4bb003099c0c49fc4aa20bc7e357d2e 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt @@ -37,8 +37,8 @@ fun ContactList( }, content = { LazyColumn { - itemsIndexed(viewModel.contactList) { index, contact -> - ContactCard(contact, { viewModel.selectContact(index) }, viewModel.isSelected(index), true) + itemsIndexed(viewModel.contactList) { index, contactItem -> + ContactCard(contactItem, { viewModel.selectContact(index) }, viewModel.isSelected(index), true) } } }, diff --git a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactsViewModel.kt b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactsViewModel.kt index b653272c29d7223b14fb0ab321b8fa22ed155797..01235ac0fd47bb96ee6bc4f516691565394786c7 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactsViewModel.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactsViewModel.kt @@ -4,12 +4,14 @@ import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import org.briarproject.bramble.api.FormatException -import org.briarproject.bramble.api.contact.Contact +import org.briarproject.bramble.api.connection.ConnectionRegistry import org.briarproject.bramble.api.contact.ContactManager import org.briarproject.bramble.api.db.ContactExistsException import org.briarproject.bramble.api.db.PendingContactExistsException import org.briarproject.bramble.api.identity.AuthorConstants import org.briarproject.bramble.util.StringUtils +import org.briarproject.briar.api.conversation.ConversationManager +import org.briarproject.briar.api.identity.AuthorManager import java.security.GeneralSecurityException import java.util.logging.Logger import javax.inject.Inject @@ -18,37 +20,48 @@ class ContactsViewModel @Inject constructor( private val contactManager: ContactManager, + private val authorManager: AuthorManager, + private val conversationManager: ConversationManager, + private val connectionRegistry: ConnectionRegistry, ) { companion object { private val LOG = Logger.getLogger(ContactsViewModel::class.java.name) } - private val _contactList = mutableListOf<Contact>() - private val _filteredContactList = mutableStateListOf<Contact>() + private val _contactList = mutableListOf<ContactItem>() + private val _filteredContactList = mutableStateListOf<ContactItem>() private val _filterBy = mutableStateOf("") private var _selectedContactIndex = -1; - private val _selectedContact = mutableStateOf<Contact?>(null) + private val _selectedContact = mutableStateOf<ContactItem?>(null) private val _addContactDialogVisible = mutableStateOf(false) private val _addContactAlias = mutableStateOf("") private val _addContactLink = mutableStateOf("") - val contactList: List<Contact> = _filteredContactList + val contactList: List<ContactItem> = _filteredContactList val filterBy: State<String> = _filterBy - val selectedContact: State<Contact?> = _selectedContact + val selectedContact: State<ContactItem?> = _selectedContact val addContactDialogVisible: State<Boolean> = _addContactDialogVisible val addContactAlias: State<String> = _addContactAlias val addContactLink: State<String> = _addContactLink - val addContactOwnLink = contactManager.handshakeLink + var addContactOwnLink = "" internal fun loadContacts() { _contactList.apply { clear() - addAll(contactManager.contacts) + addAll(contactManager.contacts.map { contact -> + ContactItem( + contact, + authorManager.getAuthorInfo(contact), + connectionRegistry.isConnected(contact.id), + conversationManager.getGroupCount(contact.id) + ) + }) } updateFilteredList() + addContactOwnLink = contactManager.handshakeLink } fun selectContact(index: Int) { @@ -63,7 +76,7 @@ constructor( clear() addAll(_contactList.filter { // todo: also filter on alias? - it.author.name.lowercase().contains(_filterBy.value) + it.contact.author.name.lowercase().contains(_filterBy.value) }) } } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/PrivateMessageView.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/PrivateMessageView.kt index d82bc21fcecb0154159fa866b545ab4fde131374..48370f4fbf2ac77904e0fc9d7c646dbc8fb94a55 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/conversation/PrivateMessageView.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/PrivateMessageView.kt @@ -27,8 +27,8 @@ fun PrivateMessageView( Column(modifier = Modifier.weight(1f).fillMaxHeight()) { contacts.selectedContact.value?.also { selectedContact -> Conversation( - selectedContact, - contacts.contactList, + selectedContact.contact, + contacts.contactList.map { c -> c.contact }, dropdownExpanded, setExpanded, infoDrawer,