Ensure PinUnlockActivity and IncomingCallActivity use the internal theme set by the user.

This commit is contained in:
Benoit Marty 2024-07-08 18:17:44 +02:00
parent c0e1c33159
commit 7c37cdee5f
4 changed files with 113 additions and 82 deletions

View file

@ -20,8 +20,15 @@ import android.os.Bundle
import android.view.WindowManager import android.view.WindowManager
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.core.content.IntentCompat import androidx.core.content.IntentCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.theme.Theme
import io.element.android.compound.theme.isDark
import io.element.android.compound.theme.mapToTheme
import io.element.android.features.call.api.CallType import io.element.android.features.call.api.CallType
import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.features.call.api.ElementCallEntryPoint
import io.element.android.features.call.impl.di.CallBindings import io.element.android.features.call.impl.di.CallBindings
@ -29,6 +36,7 @@ import io.element.android.features.call.impl.notifications.CallNotificationData
import io.element.android.features.call.impl.utils.ActiveCallManager import io.element.android.features.call.impl.utils.ActiveCallManager
import io.element.android.features.call.impl.utils.CallState import io.element.android.features.call.impl.utils.CallState
import io.element.android.libraries.architecture.bindings import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -51,6 +59,9 @@ class IncomingCallActivity : AppCompatActivity() {
@Inject @Inject
lateinit var activeCallManager: ActiveCallManager lateinit var activeCallManager: ActiveCallManager
@Inject
lateinit var appPreferencesStore: AppPreferencesStore
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -68,11 +79,19 @@ class IncomingCallActivity : AppCompatActivity() {
val notificationData = intent?.let { IntentCompat.getParcelableExtra(it, EXTRA_NOTIFICATION_DATA, CallNotificationData::class.java) } val notificationData = intent?.let { IntentCompat.getParcelableExtra(it, EXTRA_NOTIFICATION_DATA, CallNotificationData::class.java) }
if (notificationData != null) { if (notificationData != null) {
setContent { setContent {
IncomingCallScreen( val theme by remember {
notificationData = notificationData, appPreferencesStore.getThemeFlow().mapToTheme()
onAnswer = ::onAnswer, }
onCancel = ::onCancel, .collectAsState(initial = Theme.System)
) ElementTheme(
darkTheme = theme.isDark()
) {
IncomingCallScreen(
notificationData = notificationData,
onAnswer = ::onAnswer,
onCancel = ::onCancel,
)
}
} }
} else { } else {
// No data, finish the activity // No data, finish the activity

View file

@ -64,67 +64,65 @@ internal fun IncomingCallScreen(
onAnswer: (CallNotificationData) -> Unit, onAnswer: (CallNotificationData) -> Unit,
onCancel: () -> Unit, onCancel: () -> Unit,
) { ) {
ElementTheme { OnboardingBackground()
OnboardingBackground() Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Bottom
) {
Column( Column(
modifier = Modifier.fillMaxSize(), modifier = Modifier
horizontalAlignment = Alignment.CenterHorizontally, .fillMaxWidth()
verticalArrangement = Arrangement.Bottom .padding(start = 20.dp, end = 20.dp, top = 124.dp)
.weight(1f),
horizontalAlignment = Alignment.CenterHorizontally
) { ) {
Column( Avatar(
modifier = Modifier avatarData = AvatarData(
.fillMaxWidth() id = notificationData.senderId.value,
.padding(start = 20.dp, end = 20.dp, top = 124.dp) name = notificationData.senderName,
.weight(1f), url = notificationData.avatarUrl,
horizontalAlignment = Alignment.CenterHorizontally size = AvatarSize.IncomingCall,
) {
Avatar(
avatarData = AvatarData(
id = notificationData.senderId.value,
name = notificationData.senderName,
url = notificationData.avatarUrl,
size = AvatarSize.IncomingCall,
)
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = notificationData.senderName ?: notificationData.senderId.value,
style = ElementTheme.typography.fontHeadingMdBold,
textAlign = TextAlign.Center,
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.screen_incoming_call_subtitle_android),
style = ElementTheme.typography.fontBodyLgRegular,
color = ElementTheme.colors.textSecondary,
textAlign = TextAlign.Center,
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(start = 24.dp, end = 24.dp, bottom = 64.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
ActionButton(
size = 64.dp,
onClick = { onAnswer(notificationData) },
icon = CompoundIcons.VoiceCall(),
title = stringResource(CommonStrings.action_accept),
backgroundColor = ElementTheme.colors.iconSuccessPrimary,
borderColor = ElementTheme.colors.borderSuccessSubtle
) )
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = notificationData.senderName ?: notificationData.senderId.value,
style = ElementTheme.typography.fontHeadingMdBold,
textAlign = TextAlign.Center,
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.screen_incoming_call_subtitle_android),
style = ElementTheme.typography.fontBodyLgRegular,
color = ElementTheme.colors.textSecondary,
textAlign = TextAlign.Center,
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(start = 24.dp, end = 24.dp, bottom = 64.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
ActionButton(
size = 64.dp,
onClick = { onAnswer(notificationData) },
icon = CompoundIcons.VoiceCall(),
title = stringResource(CommonStrings.action_accept),
backgroundColor = ElementTheme.colors.iconSuccessPrimary,
borderColor = ElementTheme.colors.borderSuccessSubtle
)
ActionButton( ActionButton(
size = 64.dp, size = 64.dp,
onClick = onCancel, onClick = onCancel,
icon = CompoundIcons.EndCall(), icon = CompoundIcons.EndCall(),
title = stringResource(CommonStrings.action_reject), title = stringResource(CommonStrings.action_reject),
backgroundColor = ElementTheme.colors.iconCriticalPrimary, backgroundColor = ElementTheme.colors.iconCriticalPrimary,
borderColor = ElementTheme.colors.borderCriticalSubtle borderColor = ElementTheme.colors.borderCriticalSubtle
) )
}
} }
} }
} }
@ -145,7 +143,8 @@ private fun ActionButton(
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
FilledIconButton( FilledIconButton(
modifier = Modifier.size(size + borderSize) modifier = Modifier
.size(size + borderSize)
.border(borderSize, borderColor, CircleShape), .border(borderSize, borderColor, CircleShape),
onClick = onClick, onClick = onClick,
colors = IconButtonDefaults.filledIconButtonColors( colors = IconButtonDefaults.filledIconButtonColors(
@ -171,22 +170,20 @@ private fun ActionButton(
@PreviewsDayNight @PreviewsDayNight
@Composable @Composable
internal fun IncomingCallScreenPreview() { internal fun IncomingCallScreenPreview() = ElementPreview {
ElementPreview { IncomingCallScreen(
IncomingCallScreen( notificationData = CallNotificationData(
notificationData = CallNotificationData( sessionId = SessionId("@alice:matrix.org"),
sessionId = SessionId("@alice:matrix.org"), roomId = RoomId("!1234:matrix.org"),
roomId = RoomId("!1234:matrix.org"), eventId = EventId("\$asdadadsad:matrix.org"),
eventId = EventId("\$asdadadsad:matrix.org"), senderId = UserId("@bob:matrix.org"),
senderId = UserId("@bob:matrix.org"), roomName = "A room",
roomName = "A room", senderName = "Bob",
senderName = "Bob", avatarUrl = null,
avatarUrl = null, notificationChannelId = "incoming_call",
notificationChannelId = "incoming_call", timestamp = 0L,
timestamp = 0L, ),
), onAnswer = {},
onAnswer = {}, onCancel = {},
onCancel = {}, )
)
}
} }

View file

@ -40,6 +40,7 @@ dependencies {
implementation(projects.libraries.designsystem) implementation(projects.libraries.designsystem)
implementation(projects.libraries.featureflag.api) implementation(projects.libraries.featureflag.api)
implementation(projects.libraries.cryptography.api) implementation(projects.libraries.cryptography.api)
implementation(projects.libraries.preferences.api)
implementation(projects.libraries.uiStrings) implementation(projects.libraries.uiStrings)
implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.sessionStorage.api)
implementation(projects.services.appnavstate.api) implementation(projects.services.appnavstate.api)

View file

@ -23,14 +23,21 @@ import androidx.activity.OnBackPressedCallback
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.theme.Theme
import io.element.android.compound.theme.isDark
import io.element.android.compound.theme.mapToTheme
import io.element.android.features.lockscreen.api.LockScreenLockState import io.element.android.features.lockscreen.api.LockScreenLockState
import io.element.android.features.lockscreen.api.LockScreenService import io.element.android.features.lockscreen.api.LockScreenService
import io.element.android.features.lockscreen.impl.unlock.PinUnlockPresenter import io.element.android.features.lockscreen.impl.unlock.PinUnlockPresenter
import io.element.android.features.lockscreen.impl.unlock.PinUnlockView import io.element.android.features.lockscreen.impl.unlock.PinUnlockView
import io.element.android.features.lockscreen.impl.unlock.di.PinUnlockBindings import io.element.android.features.lockscreen.impl.unlock.di.PinUnlockBindings
import io.element.android.libraries.architecture.bindings import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -43,13 +50,20 @@ class PinUnlockActivity : AppCompatActivity() {
@Inject lateinit var presenter: PinUnlockPresenter @Inject lateinit var presenter: PinUnlockPresenter
@Inject lateinit var lockScreenService: LockScreenService @Inject lateinit var lockScreenService: LockScreenService
@Inject lateinit var appPreferencesStore: AppPreferencesStore
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge() enableEdgeToEdge()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
bindings<PinUnlockBindings>().inject(this) bindings<PinUnlockBindings>().inject(this)
setContent { setContent {
ElementTheme { val theme by remember {
appPreferencesStore.getThemeFlow().mapToTheme()
}
.collectAsState(initial = Theme.System)
ElementTheme(
darkTheme = theme.isDark()
) {
val state = presenter.present() val state = presenter.present()
PinUnlockView(state = state, isInAppUnlock = false) PinUnlockView(state = state, isInAppUnlock = false)
} }