Merge pull request #4375 from element-hq/feature/bma/moreWorkOnIcons

Migrate some icons to Compound icon
This commit is contained in:
Benoit Marty
2025-03-07 17:53:13 +01:00
committed by GitHub
81 changed files with 265 additions and 312 deletions

View File

@@ -110,7 +110,7 @@ class RingingCallNotificationCreator @Inject constructor(
)
return NotificationCompat.Builder(context, notificationChannelId)
.setSmallIcon(CommonDrawables.ic_notification_small)
.setSmallIcon(CommonDrawables.ic_notification)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setStyle(NotificationCompat.CallStyle.forIncomingCall(caller, declineIntent, answerIntent).setIsVideo(true))

View File

@@ -67,7 +67,7 @@ class CallForegroundService : Service() {
val callActivityIntent = Intent(this, ElementCallActivity::class.java)
val pendingIntent = PendingIntentCompat.getActivity(this, 0, callActivityIntent, 0, false)
val notification = NotificationCompat.Builder(this, foregroundServiceChannel.id)
.setSmallIcon(IconCompat.createWithResource(this, CommonDrawables.ic_notification_small))
.setSmallIcon(IconCompat.createWithResource(this, CommonDrawables.ic_notification))
.setContentTitle(getString(R.string.call_foreground_service_title_android))
.setContentText(getString(R.string.call_foreground_service_message_android))
.setContentIntent(pendingIntent)

View File

@@ -25,7 +25,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
@@ -33,31 +32,24 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.textcomposer.R
import io.element.android.libraries.designsystem.theme.components.IconColorButton
import io.element.android.libraries.designsystem.theme.components.IconColorButtonStyle
@Composable
internal fun DisabledComposerView(
modifier: Modifier = Modifier,
) {
Row(
modifier = modifier.padding(3.dp)
modifier = modifier
.padding(3.dp)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
IconButton(
modifier = Modifier
.size(48.dp),
enabled = false,
IconColorButton(
onClick = {},
) {
Icon(
modifier = Modifier.size(30.dp),
resourceId = CommonDrawables.ic_plus_composer,
contentDescription = stringResource(R.string.rich_text_editor_a11y_add_attachment),
tint = ElementTheme.colors.iconDisabled,
)
}
imageVector = CompoundIcons.Plus(),
iconColorButtonStyle = IconColorButtonStyle.Disabled,
)
val bgColor = ElementTheme.colors.bgCanvasDisabled
val borderColor = ElementTheme.colors.borderDisabled

View File

@@ -12,10 +12,7 @@ import io.element.android.libraries.designsystem.R
// This list and all the drawable it contains should be removed at some point.
// All the icons should be defined in Compound.
internal val iconsOther = listOf(
R.drawable.ic_cancel,
R.drawable.ic_encryption_enabled,
R.drawable.ic_notification_small,
R.drawable.ic_plus_composer,
R.drawable.ic_notification,
R.drawable.ic_stop,
R.drawable.pin,
)

View File

@@ -0,0 +1,111 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.designsystem.theme.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.ui.strings.CommonStrings
/**
* Button with colored background.
* Figma: https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=1956-37586
*/
@Composable
fun IconColorButton(
onClick: () -> Unit,
imageVector: ImageVector,
modifier: Modifier = Modifier,
buttonSize: ButtonSize = ButtonSize.Large,
iconColorButtonStyle: IconColorButtonStyle = IconColorButtonStyle.Primary,
) {
val bgColor = when (iconColorButtonStyle) {
IconColorButtonStyle.Primary -> ElementTheme.colors.iconPrimary
IconColorButtonStyle.Secondary -> ElementTheme.colors.iconSecondary
IconColorButtonStyle.Disabled -> ElementTheme.colors.iconDisabled
}
IconButton(
modifier = modifier.size(48.dp),
onClick = onClick,
) {
Icon(
modifier = Modifier
.clip(CircleShape)
.size(buttonSize.toContainerSize())
.background(bgColor)
.padding(buttonSize.toContainerPadding()),
imageVector = imageVector,
contentDescription = stringResource(CommonStrings.action_close),
tint = ElementTheme.colors.iconOnSolidPrimary
)
}
}
enum class IconColorButtonStyle {
Primary,
Secondary,
Disabled,
}
private fun ButtonSize.toContainerSize() = when (this) {
ButtonSize.Small -> 20.dp
ButtonSize.Medium -> 24.dp
ButtonSize.Large,
ButtonSize.MediumLowPadding,
ButtonSize.LargeLowPadding -> 30.dp
}
private fun ButtonSize.toContainerPadding() = when (this) {
ButtonSize.Small -> 2.dp
ButtonSize.Medium -> 2.dp
ButtonSize.Large,
ButtonSize.MediumLowPadding,
ButtonSize.LargeLowPadding -> 3.dp
}
@PreviewsDayNight
@Composable
internal fun IconColorButtonPreview() = ElementPreview {
Column {
listOf(
IconColorButtonStyle.Primary,
IconColorButtonStyle.Secondary,
IconColorButtonStyle.Disabled,
).forEach { style ->
Row(
modifier = Modifier.padding(4.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalAlignment = Alignment.CenterVertically
) {
listOf(ButtonSize.Large, ButtonSize.Medium, ButtonSize.Small).forEach { size ->
IconColorButton(
onClick = {},
imageVector = CompoundIcons.Close(),
buttonSize = size,
iconColorButtonStyle = style,
)
}
}
}
}
}

View File

@@ -1,16 +0,0 @@
<!--
~ Copyright 2023 New Vector Ltd.
~
~ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
~ Please see LICENSE files in the repository root for full details.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="30dp"
android:height="30dp"
android:viewportWidth="30"
android:viewportHeight="30">
<path
android:pathData="M4.393,4.393C-1.464,10.251 -1.464,19.749 4.393,25.607C10.251,31.465 19.749,31.465 25.607,25.607C31.465,19.749 31.465,10.251 25.607,4.393C19.749,-1.464 10.251,-1.464 4.393,4.393ZM11.465,19.95L15,16.414L18.535,19.95C18.736,20.15 18.972,20.25 19.243,20.25C19.514,20.25 19.749,20.15 19.95,19.95C20.15,19.749 20.25,19.514 20.25,19.243C20.25,18.972 20.15,18.736 19.95,18.535L16.414,15L19.95,11.465C20.15,11.264 20.25,11.028 20.25,10.757C20.25,10.486 20.15,10.251 19.95,10.05C19.749,9.85 19.514,9.75 19.243,9.75C18.972,9.75 18.736,9.85 18.535,10.05L15,13.586L11.465,10.05C11.264,9.85 11.028,9.75 10.757,9.75C10.486,9.75 10.251,9.85 10.05,10.05C9.85,10.251 9.75,10.486 9.75,10.757C9.75,11.028 9.85,11.264 10.05,11.465L13.586,15L10.05,18.535C9.85,18.736 9.75,18.972 9.75,19.243C9.75,19.514 9.85,19.749 10.05,19.95C10.251,20.15 10.486,20.25 10.757,20.25C11.028,20.25 11.264,20.15 11.465,19.95Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
</vector>

View File

@@ -1,15 +0,0 @@
<!--
~ Copyright 2023 New Vector Ltd.
~
~ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
~ Please see LICENSE files in the repository root for full details.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6,22C5.5,22 5,21.8 4.6,21.4C4.2,21 4,20.6 4,20V10C4,9.5 4.2,9 4.6,8.6C5,8.2 5.5,8 6,8H7V6C7,4.6 7.5,3.4 8.5,2.5C9.4,1.5 10.6,1 12,1C13.4,1 14.6,1.5 15.5,2.5C16.5,3.4 17,4.6 17,6V8H18C18.6,8 19,8.2 19.4,8.6C19.8,9 20,9.5 20,10V20C20,20.6 19.8,21 19.4,21.4C19,21.8 18.6,22 18,22H6ZM6,20H18V10H6V20ZM12,17C12.6,17 13,16.8 13.4,16.4C13.8,16 14,15.6 14,15C14,14.5 13.8,14 13.4,13.6C13,13.2 12.6,13 12,13C11.5,13 11,13.2 10.6,13.6C10.2,14 10,14.5 10,15C10,15.6 10.2,16 10.6,16.4C11,16.8 11.5,17 12,17ZM9,8H15V6C15,5.2 14.7,4.5 14.1,3.9C13.5,3.3 12.8,3 12,3C11.2,3 10.5,3.3 9.9,3.9C9.3,4.5 9,5.2 9,6V8Z"
android:fillColor="#000000"/>
</vector>

View File

@@ -1,19 +0,0 @@
<!--
~ Copyright 2023 New Vector Ltd.
~
~ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
~ Please see LICENSE files in the repository root for full details.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="30dp"
android:height="30dp"
android:viewportWidth="30"
android:viewportHeight="30">
<path
android:pathData="M0,15C0,23.284 6.716,30 15,30C23.284,30 30,23.284 30,15C30,6.716 23.284,0 15,0C6.716,0 0,6.716 0,15ZM16,21V16H21C21.283,16 21.521,15.904 21.712,15.712C21.904,15.521 22,15.283 22,15C22,14.717 21.904,14.479 21.712,14.288C21.521,14.096 21.283,14 21,14H16V9C16,8.717 15.904,8.479 15.712,8.288C15.521,8.096 15.283,8 15,8C14.717,8 14.479,8.096 14.288,8.288C14.096,8.479 14,8.717 14,9L14,14L9,14C8.717,14 8.479,14.096 8.288,14.288C8.096,14.479 8,14.717 8,15C8,15.283 8.096,15.521 8.288,15.712C8.479,15.904 8.717,16 9,16H14V21C14,21.283 14.096,21.521 14.288,21.712C14.479,21.904 14.717,22 15,22C15.283,22 15.521,21.904 15.712,21.712C15.904,21.521 16,21.283 16,21Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M14,16H9C8.717,16 8.479,15.904 8.288,15.712C8.096,15.521 8,15.283 8,15C8,14.717 8.096,14.479 8.288,14.288C8.479,14.096 8.717,14 9,14H14V9C14,8.717 14.096,8.479 14.288,8.288C14.479,8.096 14.717,8 15,8C15.283,8 15.521,8.096 15.712,8.288C15.904,8.479 16,8.717 16,9V14H21C21.283,14 21.521,14.096 21.712,14.288C21.904,14.479 22,14.717 22,15C22,15.283 21.904,15.521 21.712,15.712C21.521,15.904 21.283,16 21,16H16V21C16,21.283 15.904,21.521 15.712,21.712C15.521,21.904 15.283,22 15,22C14.717,22 14.479,21.904 14.288,21.712C14.096,21.521 14,21.283 14,21V16Z"
android:fillColor="#00000000"/>
</vector>

View File

@@ -119,7 +119,7 @@ class DefaultNotificationCreator @Inject constructor(
else -> pendingIntentFactory.createOpenRoomPendingIntent(roomInfo.sessionId, roomInfo.roomId)
}
val smallIcon = CommonDrawables.ic_notification_small
val smallIcon = CommonDrawables.ic_notification
val containsMissedCall = events.any { it.type == EventType.CALL_NOTIFY }
val channelId = if (containsMissedCall) {
@@ -219,7 +219,7 @@ class DefaultNotificationCreator @Inject constructor(
override fun createRoomInvitationNotification(
inviteNotifiableEvent: InviteNotifiableEvent
): Notification {
val smallIcon = CommonDrawables.ic_notification_small
val smallIcon = CommonDrawables.ic_notification
val channelId = notificationChannels.getChannelIdForMessage(inviteNotifiableEvent.noisy)
return NotificationCompat.Builder(context, channelId)
.setOnlyAlertOnce(true)
@@ -261,7 +261,7 @@ class DefaultNotificationCreator @Inject constructor(
override fun createSimpleEventNotification(
simpleNotifiableEvent: SimpleNotifiableEvent,
): Notification {
val smallIcon = CommonDrawables.ic_notification_small
val smallIcon = CommonDrawables.ic_notification
val channelId = notificationChannels.getChannelIdForMessage(simpleNotifiableEvent.noisy)
return NotificationCompat.Builder(context, channelId)
@@ -294,7 +294,7 @@ class DefaultNotificationCreator @Inject constructor(
override fun createFallbackNotification(
fallbackNotifiableEvent: FallbackNotifiableEvent,
): Notification {
val smallIcon = CommonDrawables.ic_notification_small
val smallIcon = CommonDrawables.ic_notification
val channelId = notificationChannels.getChannelIdForMessage(false)
return NotificationCompat.Builder(context, channelId)
@@ -330,7 +330,7 @@ class DefaultNotificationCreator @Inject constructor(
noisy: Boolean,
lastMessageTimestamp: Long
): Notification {
val smallIcon = CommonDrawables.ic_notification_small
val smallIcon = CommonDrawables.ic_notification
val channelId = notificationChannels.getChannelIdForMessage(noisy)
return NotificationCompat.Builder(context, channelId)
.setOnlyAlertOnce(true)
@@ -367,7 +367,7 @@ class DefaultNotificationCreator @Inject constructor(
return NotificationCompat.Builder(context, notificationChannels.getChannelIdForTest())
.setContentTitle(buildMeta.applicationName)
.setContentText(stringProvider.getString(R.string.notification_test_push_notification_content))
.setSmallIcon(CommonDrawables.ic_notification_small)
.setSmallIcon(CommonDrawables.ic_notification)
.setLargeIcon(getBitmap(R.drawable.element_logo_green))
.setColor(accentColor)
.setPriority(NotificationCompat.PRIORITY_MAX)

View File

@@ -46,6 +46,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconColorButton
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
@@ -54,8 +55,6 @@ import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails
import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetailsProvider
import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.textcomposer.components.ComposerOptionsButton
import io.element.android.libraries.textcomposer.components.DismissTextFormattingButton
import io.element.android.libraries.textcomposer.components.SendButton
import io.element.android.libraries.textcomposer.components.TextFormatting
import io.element.android.libraries.textcomposer.components.VoiceMessageDeleteButton
@@ -141,10 +140,9 @@ fun TextComposer(
Spacer(modifier = Modifier.width(16.dp))
}
else -> {
ComposerOptionsButton(
modifier = Modifier
.size(48.dp),
onClick = onAddAttachment
IconColorButton(
onClick = onAddAttachment,
imageVector = CompoundIcons.Plus(),
)
}
}
@@ -285,7 +283,10 @@ fun TextComposer(
modifier = layoutModifier,
textInput = textInput,
dismissTextFormattingButton = {
DismissTextFormattingButton(onClick = onDismissTextFormatting)
IconColorButton(
onClick = onDismissTextFormatting,
imageVector = CompoundIcons.Close(),
)
},
textFormatting = textFormattingOptions,
sendButton = sendButton,

View File

@@ -1,46 +0,0 @@
/*
* Copyright 2023, 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.textcomposer.components
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.textcomposer.R
@Composable
internal fun ComposerOptionsButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
IconButton(
modifier = modifier
.size(48.dp),
onClick = onClick
) {
Icon(
modifier = Modifier.size(30.dp),
resourceId = CommonDrawables.ic_plus_composer,
contentDescription = stringResource(R.string.rich_text_editor_a11y_add_attachment),
tint = ElementTheme.colors.iconPrimary,
)
}
}
@PreviewsDayNight
@Composable
internal fun ComposerOptionsButtonPreview() = ElementPreview {
ComposerOptionsButton(onClick = {})
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright 2023, 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.textcomposer.components
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
internal fun DismissTextFormattingButton(
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
IconButton(
modifier = modifier
.size(48.dp),
onClick = onClick
) {
Icon(
modifier = Modifier.size(30.dp),
resourceId = CommonDrawables.ic_cancel,
contentDescription = stringResource(CommonStrings.action_close),
tint = ElementTheme.colors.iconPrimary,
)
}
}
@PreviewsDayNight
@Composable
internal fun DismissTextFormattingButtonPreview() = ElementPreview {
DismissTextFormattingButton(onClick = {})
}