-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: typing indicator in conversation view (WPB-4706) #2292
Merged
Merged
Changes from 48 commits
Commits
Show all changes
50 commits
Select commit
Hold shift + click to select a range
e914e25
feat: base wip for typing indicator
yamilmedina aa316e6
feat: adjustment for typing indicator
yamilmedina c77abb7
Merge branch 'develop' into feat/typing-indicator-receiver
yamilmedina 125fbd7
feat: kalium ref
yamilmedina f331564
feat: wip typing indicator
yamilmedina 74fb69e
feat: typing indicator user mapping
yamilmedina f712e4c
Merge branch 'develop' into feat/typing-indicator-receiver
yamilmedina d86e088
Merge branch 'develop' into feat/typing-indicator-receiver
yamilmedina fc5d91c
feat: mapping users summary
yamilmedina c13ffd2
Merge branch 'develop' into feat/typing-indicator-receiver
yamilmedina f493f8b
feat: kalium fec
yamilmedina d617f94
feat: use usecase to observer users and map to ui element
yamilmedina b544794
feat: wip
yamilmedina 914e42e
Merge branch 'develop' into feat/typing-indicator-receiver
yamilmedina c9ff7cb
feat: add typing indicator component v1
yamilmedina 58f8e5f
feat: add typing indicator component animation
yamilmedina c831abc
feat: add typing indicator component animation
yamilmedina f05ef0e
feat: add typing indicator component animation wip
yamilmedina 57dc860
feat: add typing indicator component animation and extract to file
yamilmedina 3e0f79c
feat: add typing indicator component animation and extract strings
yamilmedina 4756ce0
feat: add typing indicator component animation and extract strings
yamilmedina 22f974f
feat: add typing indicator component animation and extract strings
yamilmedina 1949554
feat: add typing indicator component animation and extract strings
yamilmedina 3fb4b53
feat: add typing indicator component animation and extract avatar pre…
yamilmedina a737bda
feat: add typing indicator component animation and extract avatar pre…
yamilmedina 7938ea4
feat: adjustment to text
yamilmedina bd80a66
Merge branch 'develop' into feat/typing-indicator-receiver
yamilmedina 378805b
feat: kalium ref
yamilmedina a9e6b9c
feat: kalium ref
yamilmedina 003ded3
feat: detekt
yamilmedina 8cf4d4e
feat: detekt
yamilmedina ed599d7
fix: broken testst
yamilmedina 6c0f026
fix: re-enable disabled test reset session
yamilmedina 456a9ce
fix: test coverage
yamilmedina bacd414
fix: test coverage
yamilmedina ed6d386
fix: test coverage
yamilmedina 5fdbe1b
fix: test coverage
yamilmedina 1a2ff0e
fix: detekt
yamilmedina eaa11a0
chore: kalium ref
yamilmedina f854bf7
Merge branch 'develop' into feat/typing-indicator-receiver
yamilmedina 77e1839
chore: address pr comments
yamilmedina 3fbe18d
chore: detekt
yamilmedina f28b2e9
chore: address pr comments
yamilmedina 51c78df
chore: kalium ref
yamilmedina 3297013
chore: test cov for new viewmodel
yamilmedina a04f6a0
chore: test cov for new viewmodel
yamilmedina 0b84210
chore: test cov for new viewmodel
yamilmedina 49338ed
Merge branch 'develop' into feat/typing-indicator-receiver
yamilmedina 48eba61
feat: not show status indicator in small preview
yamilmedina db395c0
feat: not show status indicator in small preview
yamilmedina File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
243 changes: 243 additions & 0 deletions
243
app/src/main/kotlin/com/wire/android/ui/home/conversations/UsersTypingIndicator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
/* | ||
* Wire | ||
* Copyright (C) 2023 Wire Swiss GmbH | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see http://www.gnu.org/licenses/. | ||
*/ | ||
package com.wire.android.ui.home.conversations | ||
|
||
import androidx.compose.animation.core.FastOutSlowInEasing | ||
import androidx.compose.animation.core.InfiniteTransition | ||
import androidx.compose.animation.core.RepeatMode | ||
import androidx.compose.animation.core.animateFloat | ||
import androidx.compose.animation.core.infiniteRepeatable | ||
import androidx.compose.animation.core.rememberInfiniteTransition | ||
import androidx.compose.animation.core.tween | ||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Row | ||
import androidx.compose.foundation.layout.fillMaxHeight | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.height | ||
import androidx.compose.foundation.layout.offset | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.layout.size | ||
import androidx.compose.foundation.shape.RoundedCornerShape | ||
import androidx.compose.material.icons.Icons | ||
import androidx.compose.material.icons.filled.Edit | ||
import androidx.compose.material.icons.filled.MoreHoriz | ||
import androidx.compose.material3.Icon | ||
import androidx.compose.material3.MaterialTheme | ||
import androidx.compose.material3.Text | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.res.pluralStringResource | ||
import androidx.compose.ui.res.stringResource | ||
import androidx.compose.ui.text.style.TextOverflow | ||
import androidx.compose.ui.unit.dp | ||
import com.sebaslogen.resaca.hilt.hiltViewModelScoped | ||
import com.wire.android.R | ||
import com.wire.android.model.UserAvatarData | ||
import com.wire.android.ui.common.UserProfileAvatar | ||
import com.wire.android.ui.common.colorsScheme | ||
import com.wire.android.ui.common.dimensions | ||
import com.wire.android.ui.home.conversations.details.participants.model.UIParticipant | ||
import com.wire.android.ui.home.conversations.typing.TypingIndicatorViewModel | ||
import com.wire.android.ui.home.conversationslist.model.Membership | ||
import com.wire.android.ui.theme.wireTypography | ||
import com.wire.android.util.ui.PreviewMultipleThemes | ||
import com.wire.kalium.logic.data.id.ConversationId | ||
import com.wire.kalium.logic.data.id.QualifiedID | ||
|
||
const val MAX_PREVIEWS_DISPLAY = 3 | ||
|
||
@Composable | ||
fun UsersTypingIndicatorForConversation( | ||
conversationId: ConversationId, | ||
viewModel: TypingIndicatorViewModel = hiltViewModelScoped(conversationId), | ||
) { | ||
UsersTypingIndicator(usersTyping = viewModel.usersTypingViewState.usersTyping) | ||
} | ||
|
||
@Composable | ||
fun UsersTypingIndicator(usersTyping: List<UIParticipant>) { | ||
if (usersTyping.isNotEmpty()) { | ||
val rememberTransition = | ||
rememberInfiniteTransition(label = stringResource(R.string.animation_label_typing_indicator_horizontal_transition)) | ||
Row( | ||
verticalAlignment = Alignment.CenterVertically, | ||
modifier = Modifier | ||
.height(dimensions().spacing24x) | ||
.background( | ||
color = colorsScheme().surface, | ||
shape = RoundedCornerShape(dimensions().corner14x), | ||
) | ||
) { | ||
UsersTypingAvatarPreviews(usersTyping) | ||
Text( | ||
text = pluralStringResource( | ||
R.plurals.typing_indicator_event_message, | ||
usersTyping.size, | ||
usersTyping.first().name, | ||
usersTyping.size - 1 | ||
), | ||
style = MaterialTheme.wireTypography.label01.copy(color = colorsScheme().secondaryText), | ||
maxLines = 1, | ||
overflow = TextOverflow.Ellipsis, | ||
modifier = Modifier | ||
.weight(weight = 1f, fill = false) | ||
.padding( | ||
top = dimensions().spacing4x, | ||
bottom = dimensions().spacing4x, | ||
end = dimensions().spacing8x, | ||
) | ||
) | ||
HorizontalBouncingWritingPen(infiniteTransition = rememberTransition) | ||
} | ||
} | ||
} | ||
|
||
@Suppress("MagicNumber") | ||
@Composable | ||
private fun UsersTypingAvatarPreviews(usersTyping: List<UIParticipant>, maxPreviewsDisplay: Int = MAX_PREVIEWS_DISPLAY) { | ||
usersTyping.take(maxPreviewsDisplay).forEachIndexed { index, user -> | ||
val isSingleUser = usersTyping.size == 1 || maxPreviewsDisplay == 1 | ||
UserProfileAvatar( | ||
avatarData = user.avatarData, | ||
size = dimensions().spacing16x, | ||
padding = dimensions().spacing2x, | ||
modifier = if (isSingleUser) Modifier | ||
else { | ||
Modifier.offset( | ||
x = if (index == 0) dimensions().spacing8x else -(dimensions().spacing6x) | ||
) | ||
} | ||
) | ||
} | ||
} | ||
|
||
@Suppress("MagicNumber") | ||
@Composable | ||
private fun HorizontalBouncingWritingPen( | ||
infiniteTransition: InfiniteTransition, | ||
) { | ||
Row(modifier = Modifier.fillMaxHeight()) { | ||
val position by infiniteTransition.animateFloat( | ||
initialValue = -5f, targetValue = -1f, | ||
animationSpec = infiniteRepeatable( | ||
animation = tween(1_000, easing = FastOutSlowInEasing), | ||
repeatMode = RepeatMode.Reverse | ||
), | ||
label = infiniteTransition.label | ||
) | ||
|
||
Icon( | ||
imageVector = Icons.Default.MoreHoriz, | ||
contentDescription = null, | ||
tint = colorsScheme().secondaryText, | ||
modifier = Modifier | ||
.size(dimensions().spacing12x) | ||
.offset(y = -dimensions().spacing2x) | ||
.align(Alignment.Bottom) | ||
) | ||
Icon( | ||
imageVector = Icons.Default.Edit, | ||
contentDescription = null, | ||
tint = colorsScheme().secondaryText, | ||
modifier = Modifier | ||
.size(dimensions().spacing12x) | ||
.offset(x = position.dp) | ||
.align(Alignment.CenterVertically), | ||
) | ||
} | ||
} | ||
|
||
@PreviewMultipleThemes | ||
@Composable | ||
fun PreviewUsersTypingOne() { | ||
Column( | ||
modifier = Modifier | ||
.background(color = colorsScheme().background) | ||
.fillMaxWidth(), | ||
horizontalAlignment = Alignment.CenterHorizontally | ||
) { | ||
UsersTypingIndicator( | ||
listOf( | ||
UIParticipant( | ||
id = QualifiedID("Alice", "wire.com"), | ||
name = "Alice", | ||
handle = "alice", | ||
isSelf = false, | ||
isService = false, | ||
avatarData = UserAvatarData(), | ||
membership = Membership.None, | ||
connectionState = null, | ||
unavailable = false, | ||
isDeleted = false, | ||
readReceiptDate = null, | ||
botService = null, | ||
isDefederated = false | ||
) | ||
) | ||
) | ||
} | ||
} | ||
|
||
@PreviewMultipleThemes | ||
@Composable | ||
fun PreviewUsersTypingMoreThanOne() { | ||
Column( | ||
modifier = Modifier | ||
.background(color = colorsScheme().background) | ||
.fillMaxWidth(), | ||
horizontalAlignment = Alignment.CenterHorizontally | ||
) { | ||
UsersTypingIndicator( | ||
listOf( | ||
UIParticipant( | ||
id = QualifiedID("Bob", "wire.com"), | ||
name = "Bob", | ||
handle = "bob", | ||
isSelf = false, | ||
isService = false, | ||
avatarData = UserAvatarData(), | ||
membership = Membership.None, | ||
connectionState = null, | ||
unavailable = false, | ||
isDeleted = false, | ||
readReceiptDate = null, | ||
botService = null, | ||
isDefederated = false | ||
), | ||
UIParticipant( | ||
id = QualifiedID("alice", "wire.com"), | ||
name = "Alice Smith", | ||
handle = "alice", | ||
isSelf = false, | ||
isService = false, | ||
avatarData = UserAvatarData(), | ||
membership = Membership.None, | ||
connectionState = null, | ||
unavailable = false, | ||
isDeleted = false, | ||
readReceiptDate = null, | ||
botService = null, | ||
isDefederated = false | ||
) | ||
) | ||
) | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexandreferris here I refactored to reuse this mapper since we had this
UserSummary
from several points :D