Merge branch 'release/0.2.2' into main

This commit is contained in:
Benoit Marty 2023-09-21 23:10:52 +02:00
commit 6e6a4c2cd6
1437 changed files with 5432 additions and 2445 deletions

View file

@ -1,3 +1,12 @@
Changes in Element X v0.2.2 (2023-09-21)
========================================
Bugfixes 🐛
----------
- Add animation when rendering the timeline to avoid glitches. ([#1323](https://github.com/vector-im/element-x-android/issues/1323))
- Fix crash when trying to take a photo or record a video. ([#1395](https://github.com/vector-im/element-x-android/issues/1395))
Changes in Element X v0.2.1 (2023-09-20) Changes in Element X v0.2.1 (2023-09-20)
======================================== ========================================

View file

@ -171,11 +171,11 @@ For instance, when updating the image `src` of an ImageView, please also conside
### Jetpack Compose ### Jetpack Compose
When adding or editing `@Composable`, make sure that you create an internal function annotated with `@DayNightPreviews`, with a name suffixed by `Preview`, and having `ElementPreview` as the root composable. When adding or editing `@Composable`, make sure that you create an internal function annotated with `@PreviewsDayNight`, with a name suffixed by `Preview`, and having `ElementPreview` as the root composable.
Example: Example:
```kotlin ```kotlin
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PinIconPreview() = ElementPreview { internal fun PinIconPreview() = ElementPreview {
PinIcon() PinIcon()

View file

@ -25,7 +25,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
@Composable @Composable
@ -47,7 +47,7 @@ fun LoggedInView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun LoggedInViewPreview(@PreviewParameter(LoggedInStateProvider::class) state: LoggedInState) = ElementPreview { internal fun LoggedInViewPreview(@PreviewParameter(LoggedInStateProvider::class) state: LoggedInState) = ElementPreview {
LoggedInView( LoggedInView(

View file

@ -33,7 +33,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
@ -81,7 +81,7 @@ fun SyncStateView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun SyncStateViewPreview() = ElementPreview { internal fun SyncStateViewPreview() = ElementPreview {
// Add a box to see the shadow // Add a box to see the shadow

View file

@ -34,7 +34,7 @@ import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorVi
import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
@ -100,7 +100,7 @@ private fun LoadingRoomTopBar(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun LoadingRoomNodeViewPreview(@PreviewParameter(LoadingRoomStateProvider::class) state: LoadingRoomState) = ElementPreview { internal fun LoadingRoomNodeViewPreview(@PreviewParameter(LoadingRoomStateProvider::class) state: LoadingRoomState) = ElementPreview {
LoadingRoomNodeView( LoadingRoomNodeView(

View file

@ -27,7 +27,7 @@ import io.element.android.features.rageshake.api.crash.CrashDetectionEvents
import io.element.android.features.rageshake.api.crash.CrashDetectionView import io.element.android.features.rageshake.api.crash.CrashDetectionView
import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvents import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvents
import io.element.android.features.rageshake.api.detection.RageshakeDetectionView import io.element.android.features.rageshake.api.detection.RageshakeDetectionView
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.services.apperror.impl.AppErrorView import io.element.android.services.apperror.impl.AppErrorView
@ -66,7 +66,7 @@ fun RootView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun RootPreview(@PreviewParameter(RootStateProvider::class) rootState: RootState) = ElementPreview { internal fun RootPreview(@PreviewParameter(RootStateProvider::class) rootState: RootState) = ElementPreview {
RootView(rootState) { RootView(rootState) {

View file

@ -62,7 +62,7 @@ allprojects {
config.from(files("$rootDir/tools/detekt/detekt.yml")) config.from(files("$rootDir/tools/detekt/detekt.yml"))
} }
dependencies { dependencies {
detektPlugins("io.nlopez.compose.rules:detekt:0.2.3") detektPlugins("io.nlopez.compose.rules:detekt:0.3.0")
} }
// KtLint // KtLint

View file

@ -0,0 +1,2 @@
Main changes in this version: bugfixes
Full changelog: https://github.com/vector-im/element-x-android/releases

View file

@ -24,7 +24,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.analytics.api.AnalyticsOptInEvents import io.element.android.features.analytics.api.AnalyticsOptInEvents
import io.element.android.libraries.designsystem.components.LINK_TAG import io.element.android.libraries.designsystem.components.LINK_TAG
import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.list.ListItemContent
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart
import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListItem
@ -70,7 +70,7 @@ fun AnalyticsPreferencesView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun AnalyticsPreferencesViewPreview(@PreviewParameter(AnalyticsPreferencesStateProvider::class) state: AnalyticsPreferencesState) = internal fun AnalyticsPreferencesViewPreview(@PreviewParameter(AnalyticsPreferencesStateProvider::class) state: AnalyticsPreferencesState) =
ElementPreview { ElementPreview {

View file

@ -30,7 +30,6 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.text.ClickableText
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Poll import androidx.compose.material.icons.filled.Poll
import androidx.compose.material.icons.rounded.Check
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -48,7 +47,7 @@ import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubti
import io.element.android.libraries.designsystem.atomic.molecules.InfoListItem import io.element.android.libraries.designsystem.atomic.molecules.InfoListItem
import io.element.android.libraries.designsystem.atomic.molecules.InfoListOrganism import io.element.android.libraries.designsystem.atomic.molecules.InfoListOrganism
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
@ -56,6 +55,7 @@ import io.element.android.libraries.designsystem.theme.components.ButtonSize
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.temporaryColorBgSpecial import io.element.android.libraries.designsystem.theme.temporaryColorBgSpecial
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.designsystem.utils.LogCompositions import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -147,7 +147,7 @@ private fun CheckIcon(modifier: Modifier = Modifier) {
.size(20.dp) .size(20.dp)
.background(color = MaterialTheme.colorScheme.background, shape = CircleShape) .background(color = MaterialTheme.colorScheme.background, shape = CircleShape)
.padding(2.dp), .padding(2.dp),
imageVector = Icons.Rounded.Check, resourceId = CommonDrawables.ic_compound_check,
contentDescription = null, contentDescription = null,
tint = ElementTheme.colors.textActionAccent, tint = ElementTheme.colors.textActionAccent,
) )
@ -209,7 +209,7 @@ private fun AnalyticsOptInFooter(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun AnalyticsOptInViewPreview(@PreviewParameter(AnalyticsOptInStateProvider::class) state: AnalyticsOptInState) = ElementPreview { internal fun AnalyticsOptInViewPreview(@PreviewParameter(AnalyticsOptInStateProvider::class) state: AnalyticsOptInState) = ElementPreview {
AnalyticsOptInView( AnalyticsOptInView(

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_analytics_prompt_data_usage">"Wir zeichnen keine persönlichen Daten auf und erstellen keine Profile."</string> <string name="screen_analytics_prompt_data_usage">"Wir zeichnen keine persönlichen Daten auf und erstellen keine Profile."</string>
<string name="screen_analytics_prompt_help_us_improve">"Teilen Sie anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen."</string> <string name="screen_analytics_prompt_help_us_improve">"Teile anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen."</string>
<string name="screen_analytics_prompt_read_terms">"Sie können alle unsere Bedingungen lesen%1$s."</string> <string name="screen_analytics_prompt_read_terms">"Du kannst alle unsere Bedingungen lesen %1$s."</string>
<string name="screen_analytics_prompt_read_terms_content_link">"hier"</string> <string name="screen_analytics_prompt_read_terms_content_link">"hier"</string>
<string name="screen_analytics_prompt_settings">"Du kannst diese Funktion jederzeit deaktivieren"</string> <string name="screen_analytics_prompt_settings">"Du kannst diese Funktion jederzeit deaktivieren"</string>
<string name="screen_analytics_prompt_third_party_sharing">"Wir geben deine Daten nicht an Dritte weiter"</string> <string name="screen_analytics_prompt_third_party_sharing">"Wir geben deine Daten nicht an Dritte weiter"</string>

View file

@ -24,8 +24,6 @@ import android.webkit.WebView
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -33,10 +31,11 @@ import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
typealias RequestPermissionCallback = (Array<String>) -> Unit typealias RequestPermissionCallback = (Array<String>) -> Unit
@ -58,7 +57,7 @@ internal fun CallScreenView(
title = { Text(stringResource(R.string.element_call)) }, title = { Text(stringResource(R.string.element_call)) },
navigationIcon = { navigationIcon = {
BackButton( BackButton(
imageVector = Icons.Default.Close, resourceId = CommonDrawables.ic_compound_close,
onClick = onClose onClick = onClose
) )
} }
@ -138,7 +137,7 @@ private fun WebView.setup(userAgent: String, onPermissionsRequested: (Permission
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun CallScreenViewPreview() { internal fun CallScreenViewPreview() {
ElementTheme { ElementTheme {

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="call_foreground_service_channel_title_android">"Текущий вызов"</string>
<string name="call_foreground_service_message_android">"Коснитесь, чтобы вернуться к вызову"</string>
<string name="call_foreground_service_title_android">"Идёт вызов"</string>
</resources>

View file

@ -48,6 +48,7 @@ dependencies {
implementation(projects.libraries.deeplink) implementation(projects.libraries.deeplink)
implementation(projects.libraries.mediapickers.api) implementation(projects.libraries.mediapickers.api)
implementation(projects.libraries.mediaupload.api) implementation(projects.libraries.mediaupload.api)
implementation(projects.libraries.permissions.api)
implementation(projects.libraries.usersearch.impl) implementation(projects.libraries.usersearch.impl)
implementation(projects.services.analytics.api) implementation(projects.services.analytics.api)
implementation(libs.coil.compose) implementation(libs.coil.compose)
@ -64,6 +65,7 @@ dependencies {
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.mediapickers.test) testImplementation(projects.libraries.mediapickers.test)
testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.mediaupload.test)
testImplementation(projects.libraries.permissions.test)
testImplementation(projects.libraries.usersearch.test) testImplementation(projects.libraries.usersearch.test)
testImplementation(projects.tests.testutils) testImplementation(projects.tests.testutils)

View file

@ -32,7 +32,7 @@ import io.element.android.features.createroom.impl.components.UserListView
import io.element.android.features.createroom.impl.userlist.UserListEvents import io.element.android.features.createroom.impl.userlist.UserListEvents
import io.element.android.features.createroom.impl.userlist.UserListState import io.element.android.features.createroom.impl.userlist.UserListState
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
@ -109,7 +109,7 @@ fun AddPeopleViewTopBar(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun AddPeopleViewPreview(@PreviewParameter(AddPeopleUserListStateProvider::class) state: UserListState) = ElementPreview { internal fun AddPeopleViewPreview(@PreviewParameter(AddPeopleUserListStateProvider::class) state: UserListState) = ElementPreview {
AddPeopleView(state = state) AddPeopleView(state = state)

View file

@ -31,7 +31,7 @@ import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.createroom.impl.configureroom.RoomPrivacyItem import io.element.android.features.createroom.impl.configureroom.RoomPrivacyItem
import io.element.android.features.createroom.impl.configureroom.roomPrivacyItems import io.element.android.features.createroom.impl.configureroom.roomPrivacyItems
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.RadioButton import io.element.android.libraries.designsystem.theme.components.RadioButton
@ -57,7 +57,7 @@ fun RoomPrivacyOption(
) { ) {
Icon( Icon(
modifier = Modifier.padding(horizontal = 8.dp), modifier = Modifier.padding(horizontal = 8.dp),
imageVector = roomPrivacyItem.icon, resourceId = roomPrivacyItem.icon,
contentDescription = "", contentDescription = "",
tint = MaterialTheme.colorScheme.secondary, tint = MaterialTheme.colorScheme.secondary,
) )
@ -90,7 +90,7 @@ fun RoomPrivacyOption(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun RoomPrivacyOptionPreview() = ElementPreview { internal fun RoomPrivacyOptionPreview() = ElementPreview {
val aRoomPrivacyItem = roomPrivacyItems().first() val aRoomPrivacyItem = roomPrivacyItems().first()

View file

@ -26,7 +26,7 @@ import androidx.compose.ui.unit.dp
import io.element.android.features.createroom.impl.userlist.UserListEvents import io.element.android.features.createroom.impl.userlist.UserListEvents
import io.element.android.features.createroom.impl.userlist.UserListState import io.element.android.features.createroom.impl.userlist.UserListState
import io.element.android.features.createroom.impl.userlist.UserListStateProvider import io.element.android.features.createroom.impl.userlist.UserListStateProvider
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.components.SelectedUsersList import io.element.android.libraries.matrix.ui.components.SelectedUsersList
@ -76,7 +76,7 @@ fun UserListView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun UserListViewPreview(@PreviewParameter(UserListStateProvider::class) state: UserListState) = ElementPreview { internal fun UserListViewPreview(@PreviewParameter(UserListStateProvider::class) state: UserListState) = ElementPreview {
UserListView(state = state) UserListView(state = state)

View file

@ -18,6 +18,7 @@ package io.element.android.features.createroom.impl.configureroom
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
@ -40,6 +41,8 @@ import io.element.android.libraries.matrix.api.createroom.RoomVisibility
import io.element.android.libraries.matrix.ui.media.AvatarAction import io.element.android.libraries.matrix.ui.media.AvatarAction
import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediapickers.api.PickerProvider
import io.element.android.libraries.mediaupload.api.MediaPreProcessor import io.element.android.libraries.mediaupload.api.MediaPreProcessor
import io.element.android.libraries.permissions.api.PermissionsEvents
import io.element.android.libraries.permissions.api.PermissionsPresenter
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -52,10 +55,15 @@ class ConfigureRoomPresenter @Inject constructor(
private val mediaPickerProvider: PickerProvider, private val mediaPickerProvider: PickerProvider,
private val mediaPreProcessor: MediaPreProcessor, private val mediaPreProcessor: MediaPreProcessor,
private val analyticsService: AnalyticsService, private val analyticsService: AnalyticsService,
permissionsPresenterFactory: PermissionsPresenter.Factory,
) : Presenter<ConfigureRoomState> { ) : Presenter<ConfigureRoomState> {
private val cameraPermissionPresenter: PermissionsPresenter = permissionsPresenterFactory.create(android.Manifest.permission.CAMERA)
private var pendingPermissionRequest = false
@Composable @Composable
override fun present(): ConfigureRoomState { override fun present(): ConfigureRoomState {
val cameraPermissionState = cameraPermissionPresenter.present()
val createRoomConfig = dataStore.getCreateRoomConfig().collectAsState(CreateRoomConfig()) val createRoomConfig = dataStore.getCreateRoomConfig().collectAsState(CreateRoomConfig())
val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(
@ -75,6 +83,13 @@ class ConfigureRoomPresenter @Inject constructor(
} }
} }
LaunchedEffect(cameraPermissionState.permissionGranted) {
if (cameraPermissionState.permissionGranted && pendingPermissionRequest) {
pendingPermissionRequest = false
cameraPhotoPicker.launch()
}
}
val localCoroutineScope = rememberCoroutineScope() val localCoroutineScope = rememberCoroutineScope()
val createRoomAction: MutableState<Async<RoomId>> = remember { mutableStateOf(Async.Uninitialized) } val createRoomAction: MutableState<Async<RoomId>> = remember { mutableStateOf(Async.Uninitialized) }
@ -93,7 +108,12 @@ class ConfigureRoomPresenter @Inject constructor(
is ConfigureRoomEvents.HandleAvatarAction -> { is ConfigureRoomEvents.HandleAvatarAction -> {
when (event.action) { when (event.action) {
AvatarAction.ChoosePhoto -> galleryImagePicker.launch() AvatarAction.ChoosePhoto -> galleryImagePicker.launch()
AvatarAction.TakePhoto -> cameraPhotoPicker.launch() AvatarAction.TakePhoto -> if (cameraPermissionState.permissionGranted) {
cameraPhotoPicker.launch()
} else {
pendingPermissionRequest = true
cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions)
}
AvatarAction.Remove -> dataStore.setAvatarUri(uri = null) AvatarAction.Remove -> dataStore.setAvatarUri(uri = null)
} }
} }
@ -106,6 +126,7 @@ class ConfigureRoomPresenter @Inject constructor(
config = createRoomConfig.value, config = createRoomConfig.value,
avatarActions = avatarActions, avatarActions = avatarActions,
createRoomAction = createRoomAction.value, createRoomAction = createRoomAction.value,
cameraPermissionState = cameraPermissionState,
eventSink = ::handleEvents, eventSink = ::handleEvents,
) )
} }

View file

@ -20,12 +20,14 @@ import io.element.android.libraries.matrix.ui.media.AvatarAction
import io.element.android.features.createroom.impl.CreateRoomConfig import io.element.android.features.createroom.impl.CreateRoomConfig
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.permissions.api.PermissionsState
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
data class ConfigureRoomState( data class ConfigureRoomState(
val config: CreateRoomConfig, val config: CreateRoomConfig,
val avatarActions: ImmutableList<AvatarAction>, val avatarActions: ImmutableList<AvatarAction>,
val createRoomAction: Async<RoomId>, val createRoomAction: Async<RoomId>,
val cameraPermissionState: PermissionsState,
val eventSink: (ConfigureRoomEvents) -> Unit val eventSink: (ConfigureRoomEvents) -> Unit
) { ) {
val isCreateButtonEnabled: Boolean = config.roomName.isNullOrEmpty().not() val isCreateButtonEnabled: Boolean = config.roomName.isNullOrEmpty().not()

View file

@ -20,6 +20,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.createroom.impl.CreateRoomConfig import io.element.android.features.createroom.impl.CreateRoomConfig
import io.element.android.features.createroom.impl.userlist.aListOfSelectedUsers import io.element.android.features.createroom.impl.userlist.aListOfSelectedUsers
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.permissions.api.aPermissionsState
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
open class ConfigureRoomStateProvider : PreviewParameterProvider<ConfigureRoomState> { open class ConfigureRoomStateProvider : PreviewParameterProvider<ConfigureRoomState> {
@ -41,5 +42,6 @@ fun aConfigureRoomState() = ConfigureRoomState(
config = CreateRoomConfig(), config = CreateRoomConfig(),
avatarActions = persistentListOf(), avatarActions = persistentListOf(),
createRoomAction = Async.Uninitialized, createRoomAction = Async.Uninitialized,
cameraPermissionState = aPermissionsState(showDialog = false),
eventSink = { }, eventSink = { },
) )

View file

@ -54,7 +54,7 @@ import io.element.android.libraries.designsystem.components.LabelledTextField
import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
@ -65,6 +65,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet
import io.element.android.libraries.matrix.ui.components.SelectedUsersList import io.element.android.libraries.matrix.ui.components.SelectedUsersList
import io.element.android.libraries.matrix.ui.components.UnsavedAvatar import io.element.android.libraries.matrix.ui.components.UnsavedAvatar
import io.element.android.libraries.permissions.api.PermissionsView
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -73,9 +74,9 @@ import kotlinx.coroutines.launch
@Composable @Composable
fun ConfigureRoomView( fun ConfigureRoomView(
state: ConfigureRoomState, state: ConfigureRoomState,
onBackPressed: () -> Unit,
onRoomCreated: (RoomId) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onBackPressed: () -> Unit = {},
onRoomCreated: (RoomId) -> Unit = {},
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val focusManager = LocalFocusManager.current val focusManager = LocalFocusManager.current
@ -172,6 +173,10 @@ fun ConfigureRoomView(
else -> Unit else -> Unit
} }
PermissionsView(
state = state.cameraPermissionState,
)
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -273,10 +278,12 @@ private fun Modifier.clearFocusOnTap(focusManager: FocusManager): Modifier =
}) })
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun ConfigureRoomViewPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = ElementPreview { internal fun ConfigureRoomViewPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = ElementPreview {
ConfigureRoomView( ConfigureRoomView(
state = state, state = state,
onBackPressed = {},
onRoomCreated = {},
) )
} }

View file

@ -16,19 +16,17 @@
package io.element.android.features.createroom.impl.configureroom package io.element.android.features.createroom.impl.configureroom
import androidx.compose.material.icons.Icons import androidx.annotation.DrawableRes
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material.icons.outlined.Public
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import io.element.android.features.createroom.impl.R import io.element.android.features.createroom.impl.R
import io.element.android.libraries.designsystem.utils.CommonDrawables
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
data class RoomPrivacyItem( data class RoomPrivacyItem(
val privacy: RoomPrivacy, val privacy: RoomPrivacy,
val icon: ImageVector, @DrawableRes val icon: Int,
val title: String, val title: String,
val description: String, val description: String,
) )
@ -40,13 +38,13 @@ fun roomPrivacyItems(): ImmutableList<RoomPrivacyItem> {
when (it) { when (it) {
RoomPrivacy.Private -> RoomPrivacyItem( RoomPrivacy.Private -> RoomPrivacyItem(
privacy = it, privacy = it,
icon = Icons.Outlined.Lock, icon = CommonDrawables.ic_compound_lock,
title = stringResource(R.string.screen_create_room_private_option_title), title = stringResource(R.string.screen_create_room_private_option_title),
description = stringResource(R.string.screen_create_room_private_option_description), description = stringResource(R.string.screen_create_room_private_option_description),
) )
RoomPrivacy.Public -> RoomPrivacyItem( RoomPrivacy.Public -> RoomPrivacyItem(
privacy = it, privacy = it,
icon = Icons.Outlined.Public, icon = CommonDrawables.ic_compound_public,
title = stringResource(R.string.screen_create_room_public_option_title), title = stringResource(R.string.screen_create_room_public_option_title),
description = stringResource(R.string.screen_create_room_public_option_description), description = stringResource(R.string.screen_create_room_public_option_description),
) )

View file

@ -27,8 +27,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -41,17 +39,17 @@ import androidx.compose.ui.unit.dp
import io.element.android.features.createroom.impl.R import io.element.android.features.createroom.impl.R
import io.element.android.features.createroom.impl.components.UserListView import io.element.android.features.createroom.impl.components.UserListView
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.VectorIcons
import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -141,14 +139,11 @@ fun CreateRoomRootViewTopBar(
) )
}, },
navigationIcon = { navigationIcon = {
IconButton(onClick = onClosePressed) { BackButton(
Icon( resourceId = CommonDrawables.ic_compound_close,
imageVector = Icons.Default.Close, onClick = onClosePressed,
contentDescription = stringResource(id = CommonStrings.action_close),
tint = MaterialTheme.colorScheme.primary,
) )
} }
}
) )
} }
@ -161,12 +156,12 @@ fun CreateRoomActionButtonsList(
) { ) {
Column(modifier = modifier) { Column(modifier = modifier) {
CreateRoomActionButton( CreateRoomActionButton(
iconRes = VectorIcons.Groups, iconRes = CommonDrawables.ic_groups,
text = stringResource(id = R.string.screen_create_room_action_create_room), text = stringResource(id = R.string.screen_create_room_action_create_room),
onClick = onNewRoomClicked, onClick = onNewRoomClicked,
) )
CreateRoomActionButton( CreateRoomActionButton(
iconRes = VectorIcons.Share, iconRes = CommonDrawables.ic_compound_share_android,
text = stringResource(id = CommonStrings.action_invite_friends_to_app, state.applicationName), text = stringResource(id = CommonStrings.action_invite_friends_to_app, state.applicationName),
onClick = onInvitePeopleClicked, onClick = onInvitePeopleClicked,
) )
@ -202,7 +197,7 @@ fun CreateRoomActionButton(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun CreateRoomRootViewPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: CreateRoomRootState) = internal fun CreateRoomRootViewPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: CreateRoomRootState) =
ElementPreview { ElementPreview {

View file

@ -37,6 +37,8 @@ import io.element.android.libraries.matrix.ui.media.AvatarAction
import io.element.android.libraries.mediapickers.test.FakePickerProvider import io.element.android.libraries.mediapickers.test.FakePickerProvider
import io.element.android.libraries.mediaupload.api.MediaUploadInfo import io.element.android.libraries.mediaupload.api.MediaUploadInfo
import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
import io.element.android.libraries.permissions.test.FakePermissionsPresenter
import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory
import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import io.mockk.every import io.mockk.every
@ -55,6 +57,7 @@ import org.robolectric.RobolectricTestRunner
import java.io.File import java.io.File
private const val AN_URI_FROM_CAMERA = "content://uri_from_camera" private const val AN_URI_FROM_CAMERA = "content://uri_from_camera"
private const val AN_URI_FROM_CAMERA_2 = "content://uri_from_camera_2"
private const val AN_URI_FROM_GALLERY = "content://uri_from_gallery" private const val AN_URI_FROM_GALLERY = "content://uri_from_gallery"
@RunWith(RobolectricTestRunner::class) @RunWith(RobolectricTestRunner::class)
@ -70,6 +73,7 @@ class ConfigureRoomPresenterTests {
private lateinit var fakePickerProvider: FakePickerProvider private lateinit var fakePickerProvider: FakePickerProvider
private lateinit var fakeMediaPreProcessor: FakeMediaPreProcessor private lateinit var fakeMediaPreProcessor: FakeMediaPreProcessor
private lateinit var fakeAnalyticsService: FakeAnalyticsService private lateinit var fakeAnalyticsService: FakeAnalyticsService
private lateinit var fakePermissionsPresenter: FakePermissionsPresenter
@Before @Before
fun setup() { fun setup() {
@ -79,12 +83,14 @@ class ConfigureRoomPresenterTests {
fakePickerProvider = FakePickerProvider() fakePickerProvider = FakePickerProvider()
fakeMediaPreProcessor = FakeMediaPreProcessor() fakeMediaPreProcessor = FakeMediaPreProcessor()
fakeAnalyticsService = FakeAnalyticsService() fakeAnalyticsService = FakeAnalyticsService()
fakePermissionsPresenter = FakePermissionsPresenter()
presenter = ConfigureRoomPresenter( presenter = ConfigureRoomPresenter(
dataStore = createRoomDataStore, dataStore = createRoomDataStore,
matrixClient = fakeMatrixClient, matrixClient = fakeMatrixClient,
mediaPickerProvider = fakePickerProvider, mediaPickerProvider = fakePickerProvider,
mediaPreProcessor = fakeMediaPreProcessor, mediaPreProcessor = fakeMediaPreProcessor,
analyticsService = fakeAnalyticsService, analyticsService = fakeAnalyticsService,
permissionsPresenterFactory = FakePermissionsPresenterFactory(fakePermissionsPresenter),
) )
mockkStatic(File::readBytes) mockkStatic(File::readBytes)
@ -170,8 +176,6 @@ class ConfigureRoomPresenterTests {
// Room avatar // Room avatar
// Pick avatar // Pick avatar
fakePickerProvider.givenResult(null) fakePickerProvider.givenResult(null)
newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.TakePhoto))
// From gallery // From gallery
val uriFromGallery = Uri.parse(AN_URI_FROM_GALLERY) val uriFromGallery = Uri.parse(AN_URI_FROM_GALLERY)
fakePickerProvider.givenResult(uriFromGallery) fakePickerProvider.givenResult(uriFromGallery)
@ -182,10 +186,23 @@ class ConfigureRoomPresenterTests {
// From camera // From camera
val uriFromCamera = Uri.parse(AN_URI_FROM_CAMERA) val uriFromCamera = Uri.parse(AN_URI_FROM_CAMERA)
fakePickerProvider.givenResult(uriFromCamera) fakePickerProvider.givenResult(uriFromCamera)
assertThat(newState.cameraPermissionState.permissionGranted).isFalse()
newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.TakePhoto)) newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.TakePhoto))
newState = awaitItem() newState = awaitItem()
assertThat(newState.cameraPermissionState.showDialog).isTrue()
fakePermissionsPresenter.setPermissionGranted()
newState = awaitItem()
assertThat(newState.cameraPermissionState.permissionGranted).isTrue()
newState = awaitItem()
expectedConfig = expectedConfig.copy(avatarUri = uriFromCamera) expectedConfig = expectedConfig.copy(avatarUri = uriFromCamera)
assertThat(newState.config).isEqualTo(expectedConfig) assertThat(newState.config).isEqualTo(expectedConfig)
// Do it again, no permission is requested
val uriFromCamera2 = Uri.parse(AN_URI_FROM_CAMERA_2)
fakePickerProvider.givenResult(uriFromCamera2)
newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.TakePhoto))
newState = awaitItem()
expectedConfig = expectedConfig.copy(avatarUri = uriFromCamera2)
assertThat(newState.config).isEqualTo(expectedConfig)
// Remove // Remove
newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.Remove)) newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.Remove))
newState = awaitItem() newState = awaitItem()

View file

@ -22,7 +22,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import io.element.android.features.ftue.impl.R import io.element.android.features.ftue.impl.R
import io.element.android.libraries.designsystem.atomic.pages.SunsetPage import io.element.android.libraries.designsystem.atomic.pages.SunsetPage
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
@Composable @Composable
@ -45,7 +45,7 @@ fun MigrationScreenView(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun MigrationViewPreview() = ElementPreview { internal fun MigrationViewPreview() = ElementPreview {
MigrationScreenView( MigrationScreenView(

View file

@ -65,7 +65,7 @@ class NotificationsOptInPresenter @AssistedInject constructor(
if (notificationsPermissionsState.permissionGranted) { if (notificationsPermissionsState.permissionGranted) {
callback.onNotificationsOptInFinished() callback.onNotificationsOptInFinished()
} else { } else {
notificationsPermissionsState.eventSink(PermissionsEvents.OpenSystemDialog) notificationsPermissionsState.eventSink(PermissionsEvents.RequestPermissions)
} }
} }
NotificationsOptInEvents.NotNowClicked -> { NotificationsOptInEvents.NotNowClicked -> {

View file

@ -28,6 +28,6 @@ open class NotificationsOptInStateProvider : PreviewParameterProvider<Notificati
} }
fun aNotificationsOptInState() = NotificationsOptInState( fun aNotificationsOptInState() = NotificationsOptInState(
notificationsPermissionState = aPermissionsState(), notificationsPermissionState = aPermissionsState(showDialog = false),
eventSink = {} eventSink = {}
) )

View file

@ -29,8 +29,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Notifications
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -45,11 +43,12 @@ import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -80,7 +79,7 @@ private fun NotificationsOptInHeader(
modifier = modifier, modifier = modifier,
title = stringResource(R.string.screen_notification_optin_title), title = stringResource(R.string.screen_notification_optin_title),
subTitle = stringResource(R.string.screen_notification_optin_subtitle), subTitle = stringResource(R.string.screen_notification_optin_subtitle),
iconImageVector = Icons.Default.Notifications, iconResourceId = CommonDrawables.ic_compound_notifications_solid,
) )
} }
@ -183,7 +182,7 @@ private fun NotificationRow(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun NotificationsOptInViewPreview( internal fun NotificationsOptInViewPreview(
@PreviewParameter(NotificationsOptInStateProvider::class) state: NotificationsOptInState @PreviewParameter(NotificationsOptInStateProvider::class) state: NotificationsOptInState

View file

@ -41,7 +41,7 @@ import io.element.android.libraries.designsystem.atomic.atoms.ElementLogoAtomSiz
import io.element.android.libraries.designsystem.atomic.molecules.InfoListItem import io.element.android.libraries.designsystem.atomic.molecules.InfoListItem
import io.element.android.libraries.designsystem.atomic.molecules.InfoListOrganism import io.element.android.libraries.designsystem.atomic.molecules.InfoListOrganism
import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
@ -123,7 +123,7 @@ private fun listItems() = persistentListOf(
), ),
) )
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun WelcomeViewPreview() { internal fun WelcomeViewPreview() {
ElementPreview { ElementPreview {

View file

@ -2,6 +2,8 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_migration_message">"Это одноразовый процесс, спасибо, что подождали."</string> <string name="screen_migration_message">"Это одноразовый процесс, спасибо, что подождали."</string>
<string name="screen_migration_title">"Настройка учетной записи."</string> <string name="screen_migration_title">"Настройка учетной записи."</string>
<string name="screen_notification_optin_subtitle">"Вы можете изменить настройки позже."</string>
<string name="screen_notification_optin_title">"Разрешите уведомления и никогда не пропустите сообщение"</string>
<string name="screen_welcome_bullet_1">"Звонки, опросы, поиск и многое другое будут добавлены позже в этом году."</string> <string name="screen_welcome_bullet_1">"Звонки, опросы, поиск и многое другое будут добавлены позже в этом году."</string>
<string name="screen_welcome_bullet_2">"История сообщений для зашифрованных комнат в этом обновлении будет недоступна."</string> <string name="screen_welcome_bullet_2">"История сообщений для зашифрованных комнат в этом обновлении будет недоступна."</string>
<string name="screen_welcome_bullet_3">"Мы будем рады услышать ваше мнение, сообщите нам об этом через страницу настроек."</string> <string name="screen_welcome_bullet_3">"Мы будем рады услышать ваше мнение, сообщите нам об этом через страницу настроек."</string>

View file

@ -25,6 +25,7 @@ import io.element.android.libraries.permissions.api.PermissionStateProvider
import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.permissions.api.PermissionsPresenter
import io.element.android.libraries.permissions.impl.FakePermissionStateProvider import io.element.android.libraries.permissions.impl.FakePermissionStateProvider
import io.element.android.libraries.permissions.test.FakePermissionsPresenter import io.element.android.libraries.permissions.test.FakePermissionsPresenter
import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory
import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -130,11 +131,7 @@ class NotificationsOptInPresenterTests {
permissionStateProvider: PermissionStateProvider = FakePermissionStateProvider(), permissionStateProvider: PermissionStateProvider = FakePermissionStateProvider(),
sdkIntVersion: Int = Build.VERSION_CODES.TIRAMISU, sdkIntVersion: Int = Build.VERSION_CODES.TIRAMISU,
) = NotificationsOptInPresenter( ) = NotificationsOptInPresenter(
permissionsPresenterFactory = object : PermissionsPresenter.Factory { permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionsPresenter),
override fun create(permission: String): PermissionsPresenter {
return permissionsPresenter
}
},
callback = object : NotificationsOptInNode.Callback { callback = object : NotificationsOptInNode.Callback {
override fun onNotificationsOptInFinished() { override fun onNotificationsOptInFinished() {
isFinished = true isFinished = true

View file

@ -39,7 +39,7 @@ import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
@ -170,7 +170,7 @@ fun InviteListContent(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun InviteListViewPreview(@PreviewParameter(InviteListStateProvider::class) state: InviteListState) = ElementPreview { internal fun InviteListViewPreview(@PreviewParameter(InviteListStateProvider::class) state: InviteListState) = ElementPreview {
InviteListView(state) InviteListView(state)

View file

@ -45,7 +45,7 @@ import io.element.android.features.invitelist.impl.model.InviteListInviteSummary
import io.element.android.features.invitelist.impl.model.InviteSender import io.element.android.features.invitelist.impl.model.InviteSender
import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.ButtonSize import io.element.android.libraries.designsystem.theme.components.ButtonSize
@ -184,7 +184,7 @@ private fun SenderRow(sender: InviteSender) {
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun InviteSummaryRowPreview(@PreviewParameter(InviteListInviteSummaryProvider::class) data: InviteListInviteSummary) = ElementPreview { internal fun InviteSummaryRowPreview(@PreviewParameter(InviteListInviteSummaryProvider::class) data: InviteListInviteSummary) = ElementPreview {
InviteSummaryRow(data) InviteSummaryRow(data)

View file

@ -27,7 +27,7 @@ import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -107,7 +107,7 @@ private fun LeaveRoomErrorDialog(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun LeaveRoomViewPreview( internal fun LeaveRoomViewPreview(
@PreviewParameter(LeaveRoomStateProvider::class) state: LeaveRoomState @PreviewParameter(LeaveRoomStateProvider::class) state: LeaveRoomState

View file

@ -37,12 +37,12 @@ import coil.request.ImageRequest
import io.element.android.features.location.api.internal.StaticMapPlaceholder import io.element.android.features.location.api.internal.StaticMapPlaceholder
import io.element.android.features.location.api.internal.StaticMapUrlBuilder import io.element.android.features.location.api.internal.StaticMapUrlBuilder
import io.element.android.features.location.api.internal.centerBottomEdge import io.element.android.features.location.api.internal.centerBottomEdge
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import timber.log.Timber import timber.log.Timber
import io.element.android.libraries.designsystem.R as DesignSystemR
/** /**
* Shows a static map image downloaded via a third party service's static maps API. * Shows a static map image downloaded via a third party service's static maps API.
@ -102,7 +102,7 @@ fun StaticMapView(
contentScale = ContentScale.Fit, contentScale = ContentScale.Fit,
) )
Icon( Icon(
resourceId = DesignSystemR.drawable.pin, resourceId = CommonDrawables.pin,
contentDescription = null, contentDescription = null,
tint = Color.Unspecified, tint = Color.Unspecified,
modifier = Modifier.centerBottomEdge(this), modifier = Modifier.centerBottomEdge(this),
@ -119,7 +119,7 @@ fun StaticMapView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun StaticMapViewPreview() = ElementPreview { internal fun StaticMapViewPreview() = ElementPreview {
StaticMapView( StaticMapView(

View file

@ -34,7 +34,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.location.api.R import io.element.android.features.location.api.R
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator 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.Icon
@ -78,7 +78,7 @@ internal fun StaticMapPlaceholder(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun StaticMapPlaceholderPreview( internal fun StaticMapPlaceholderPreview(
@PreviewParameter(BooleanParameterProvider::class) values: Boolean @PreviewParameter(BooleanParameterProvider::class) values: Boolean

View file

@ -52,7 +52,7 @@ import io.element.android.features.location.impl.R
import io.element.android.features.location.impl.common.PermissionDeniedDialog import io.element.android.features.location.impl.common.PermissionDeniedDialog
import io.element.android.features.location.impl.common.PermissionRationaleDialog import io.element.android.features.location.impl.common.PermissionRationaleDialog
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.BottomSheetScaffold import io.element.android.libraries.designsystem.theme.components.BottomSheetScaffold
@ -60,13 +60,13 @@ import io.element.android.libraries.designsystem.theme.components.FloatingAction
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.maplibre.compose.CameraMode import io.element.android.libraries.maplibre.compose.CameraMode
import io.element.android.libraries.maplibre.compose.CameraMoveStartedReason import io.element.android.libraries.maplibre.compose.CameraMoveStartedReason
import io.element.android.libraries.maplibre.compose.MapboxMap import io.element.android.libraries.maplibre.compose.MapboxMap
import io.element.android.libraries.maplibre.compose.rememberCameraPositionState import io.element.android.libraries.maplibre.compose.rememberCameraPositionState
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.libraries.designsystem.R as DesignSystemR
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
@Composable @Composable
@ -203,7 +203,7 @@ fun SendLocationView(
), ),
) )
Icon( Icon(
resourceId = DesignSystemR.drawable.pin, resourceId = CommonDrawables.pin,
contentDescription = null, contentDescription = null,
tint = Color.Unspecified, tint = Color.Unspecified,
modifier = Modifier.centerBottomEdge(this), modifier = Modifier.centerBottomEdge(this),
@ -223,7 +223,7 @@ fun SendLocationView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun SendLocationViewPreview( internal fun SendLocationViewPreview(
@PreviewParameter(SendLocationStateProvider::class) state: SendLocationState @PreviewParameter(SendLocationStateProvider::class) state: SendLocationState

View file

@ -25,7 +25,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.LocationSearching import androidx.compose.material.icons.filled.LocationSearching
import androidx.compose.material.icons.filled.MyLocation import androidx.compose.material.icons.filled.MyLocation
import androidx.compose.material.icons.outlined.Share
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
@ -42,7 +41,7 @@ import io.element.android.features.location.impl.common.MapDefaults
import io.element.android.features.location.impl.common.PermissionDeniedDialog import io.element.android.features.location.impl.common.PermissionDeniedDialog
import io.element.android.features.location.impl.common.PermissionRationaleDialog import io.element.android.features.location.impl.common.PermissionRationaleDialog
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.FloatingActionButton import io.element.android.libraries.designsystem.theme.components.FloatingActionButton
@ -51,6 +50,7 @@ import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.maplibre.compose.CameraMode import io.element.android.libraries.maplibre.compose.CameraMode
import io.element.android.libraries.maplibre.compose.CameraMoveStartedReason import io.element.android.libraries.maplibre.compose.CameraMoveStartedReason
import io.element.android.libraries.maplibre.compose.IconAnchor import io.element.android.libraries.maplibre.compose.IconAnchor
@ -62,7 +62,6 @@ import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.theme.compound.generated.TypographyTokens import io.element.android.libraries.theme.compound.generated.TypographyTokens
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.toImmutableMap import kotlinx.collections.immutable.toImmutableMap
import io.element.android.libraries.designsystem.R as DesignSystemR
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class) @OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
@Composable @Composable
@ -125,7 +124,10 @@ fun ShowLocationView(
}, },
actions = { actions = {
IconButton(onClick = { state.eventSink(ShowLocationEvents.Share) }) { IconButton(onClick = { state.eventSink(ShowLocationEvents.Share) }) {
Icon(imageVector = Icons.Outlined.Share, contentDescription = stringResource(CommonStrings.action_share)) Icon(
resourceId = CommonDrawables.ic_compound_share_android,
contentDescription = stringResource(CommonStrings.action_share),
)
} }
} }
) )
@ -163,7 +165,7 @@ fun ShowLocationView(
MapboxMap( MapboxMap(
styleUri = rememberTileStyleUrl(), styleUri = rememberTileStyleUrl(),
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
images = mapOf(PIN_ID to DesignSystemR.drawable.pin).toImmutableMap(), images = mapOf(PIN_ID to CommonDrawables.pin).toImmutableMap(),
cameraPositionState = cameraPositionState, cameraPositionState = cameraPositionState,
uiSettings = MapDefaults.uiSettings, uiSettings = MapDefaults.uiSettings,
symbolManagerSettings = MapDefaults.symbolManagerSettings, symbolManagerSettings = MapDefaults.symbolManagerSettings,
@ -183,7 +185,7 @@ fun ShowLocationView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun ShowLocationViewPreview(@PreviewParameter(ShowLocationStateProvider::class) state: ShowLocationState) = ElementPreview { internal fun ShowLocationViewPreview(@PreviewParameter(ShowLocationStateProvider::class) state: ShowLocationState) = ElementPreview {
ShowLocationView( ShowLocationView(

View file

@ -23,8 +23,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -35,11 +33,12 @@ import androidx.compose.ui.unit.dp
import io.element.android.features.login.impl.R import io.element.android.features.login.impl.R
import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtom import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtom
import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtomSize import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtomSize
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
/** /**
@ -75,7 +74,7 @@ fun AccountProviderView(
} else { } else {
RoundedIconAtom( RoundedIconAtom(
size = RoundedIconAtomSize.Medium, size = RoundedIconAtomSize.Medium,
imageVector = Icons.Filled.Search, resourceId = CommonDrawables.ic_compound_search,
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
) )
} }
@ -111,7 +110,7 @@ fun AccountProviderView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun AccountProviderViewPreview(@PreviewParameter(AccountProviderProvider::class) item: AccountProvider) = ElementPreview { internal fun AccountProviderViewPreview(@PreviewParameter(AccountProviderProvider::class) item: AccountProvider) = ElementPreview {
AccountProviderView( AccountProviderView(

View file

@ -25,7 +25,7 @@ import io.element.android.features.login.impl.error.ChangeServerError
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
@Composable @Composable
@ -68,7 +68,7 @@ fun ChangeServerView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun ChangeServerViewPreview(@PreviewParameter(ChangeServerStateProvider::class) state: ChangeServerState) = ElementPreview { internal fun ChangeServerViewPreview(@PreviewParameter(ChangeServerStateProvider::class) state: ChangeServerState) = ElementPreview {
ChangeServerView( ChangeServerView(

View file

@ -33,7 +33,7 @@ import io.element.android.features.login.impl.oidc.OidcUrlParser
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
@ -97,7 +97,7 @@ fun OidcView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun OidcViewPreview(@PreviewParameter(OidcStateProvider::class) state: OidcState) = ElementPreview { internal fun OidcViewPreview(@PreviewParameter(OidcStateProvider::class) state: OidcState) = ElementPreview {
OidcView( OidcView(

View file

@ -45,7 +45,7 @@ import io.element.android.features.login.impl.changeserver.ChangeServerEvents
import io.element.android.features.login.impl.changeserver.ChangeServerView import io.element.android.features.login.impl.changeserver.ChangeServerView
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
@ -124,7 +124,7 @@ fun ChangeAccountProviderView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun ChangeAccountProviderViewPreview(@PreviewParameter(ChangeAccountProviderStateProvider::class) state: ChangeAccountProviderState) = ElementPreview { internal fun ChangeAccountProviderViewPreview(@PreviewParameter(ChangeAccountProviderStateProvider::class) state: ChangeAccountProviderState) = ElementPreview {
ChangeAccountProviderView( ChangeAccountProviderView(

View file

@ -36,7 +36,7 @@ import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMo
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
@ -138,7 +138,7 @@ fun ConfirmAccountProviderView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun ConfirmAccountProviderViewPreview( internal fun ConfirmAccountProviderViewPreview(
@PreviewParameter(ConfirmAccountProviderStateProvider::class) state: ConfirmAccountProviderState @PreviewParameter(ConfirmAccountProviderStateProvider::class) state: ConfirmAccountProviderState

View file

@ -31,9 +31,6 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
@ -61,7 +58,7 @@ import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubti
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.components.form.textFieldState import io.element.android.libraries.designsystem.components.form.textFieldState
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
@ -72,6 +69,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.theme.components.autofill import io.element.android.libraries.designsystem.theme.components.autofill
import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@ -220,7 +218,7 @@ internal fun LoginForm(
IconButton(onClick = { IconButton(onClick = {
loginFieldState = "" loginFieldState = ""
}) { }) {
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(CommonStrings.action_clear)) Icon(resourceId = CommonDrawables.ic_compound_close, contentDescription = stringResource(CommonStrings.action_clear))
} }
} }
} else null, } else null,
@ -253,12 +251,12 @@ internal fun LoginForm(
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = { trailingIcon = {
val image = val image =
if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff if (passwordVisible) CommonDrawables.ic_compound_visibility_on else CommonDrawables.ic_compound_visibility_off
val description = val description =
if (passwordVisible) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) if (passwordVisible) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password)
IconButton(onClick = { passwordVisible = !passwordVisible }) { IconButton(onClick = { passwordVisible = !passwordVisible }) {
Icon(imageVector = image, description) Icon(resourceId = image, description)
} }
}, },
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(
@ -282,7 +280,7 @@ internal fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun LoginPasswordViewPreview(@PreviewParameter(LoginPasswordStateProvider::class) state: LoginPasswordState) = ElementPreview { internal fun LoginPasswordViewPreview(@PreviewParameter(LoginPasswordStateProvider::class) state: LoginPasswordState) = ElementPreview {
LoginPasswordView( LoginPasswordView(

View file

@ -32,9 +32,6 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@ -61,7 +58,7 @@ import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.form.textFieldState import io.element.android.libraries.designsystem.components.form.textFieldState
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator 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.Icon
@ -69,6 +66,7 @@ import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -105,7 +103,7 @@ fun SearchAccountProviderView(
item { item {
IconTitleSubtitleMolecule( IconTitleSubtitleMolecule(
modifier = Modifier.padding(top = 16.dp, bottom = 40.dp, start = 16.dp, end = 16.dp), modifier = Modifier.padding(top = 16.dp, bottom = 40.dp, start = 16.dp, end = 16.dp),
iconImageVector = Icons.Filled.Search, iconResourceId = CommonDrawables.ic_compound_search,
title = stringResource(id = R.string.screen_account_provider_form_title), title = stringResource(id = R.string.screen_account_provider_form_title),
subTitle = stringResource(id = R.string.screen_account_provider_form_subtitle), subTitle = stringResource(id = R.string.screen_account_provider_form_subtitle),
) )
@ -141,7 +139,7 @@ fun SearchAccountProviderView(
eventSink(SearchAccountProviderEvents.UserInput("")) eventSink(SearchAccountProviderEvents.UserInput(""))
}) { }) {
Icon( Icon(
imageVector = Icons.Filled.Close, resourceId = CommonDrawables.ic_compound_close,
contentDescription = stringResource(CommonStrings.action_clear) contentDescription = stringResource(CommonStrings.action_clear)
) )
} }
@ -208,7 +206,7 @@ private fun HomeserverData.toAccountProvider(): AccountProvider {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun SearchAccountProviderViewPreview(@PreviewParameter(SearchAccountProviderStateProvider::class) state: SearchAccountProviderState) = ElementPreview { internal fun SearchAccountProviderViewPreview(@PreviewParameter(SearchAccountProviderStateProvider::class) state: SearchAccountProviderState) = ElementPreview {
SearchAccountProviderView( SearchAccountProviderView(

View file

@ -36,7 +36,7 @@ import io.element.android.features.login.impl.error.loginError
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.pages.SunsetPage import io.element.android.libraries.designsystem.atomic.pages.SunsetPage
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
@ -144,7 +144,7 @@ private fun OverallContent(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun WaitListViewPreview(@PreviewParameter(WaitListStateProvider::class) state: WaitListState) = ElementPreview { internal fun WaitListViewPreview(@PreviewParameter(WaitListStateProvider::class) state: WaitListState) = ElementPreview {
WaitListView( WaitListView(

View file

@ -16,8 +16,6 @@
package io.element.android.features.logout.api package io.element.android.features.logout.api
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Logout
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@ -27,8 +25,9 @@ import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.components.preferences.PreferenceText import io.element.android.libraries.designsystem.components.preferences.PreferenceText
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.utils.CommonDrawables
@Composable @Composable
fun LogoutPreferenceView( fun LogoutPreferenceView(
@ -80,12 +79,12 @@ fun LogoutPreferenceContent(
) { ) {
PreferenceText( PreferenceText(
title = stringResource(id = R.string.screen_signout_preference_item), title = stringResource(id = R.string.screen_signout_preference_item),
icon = Icons.Filled.Logout, iconResourceId = CommonDrawables.ic_compound_leave,
onClick = onClick onClick = onClick
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun LogoutPreferenceViewPreview() = ElementPreview { internal fun LogoutPreferenceViewPreview() = ElementPreview {
LogoutPreferenceView( LogoutPreferenceView(

View file

@ -48,6 +48,7 @@ dependencies {
implementation(projects.libraries.mediapickers.api) implementation(projects.libraries.mediapickers.api)
implementation(projects.libraries.featureflag.api) implementation(projects.libraries.featureflag.api)
implementation(projects.libraries.mediaupload.api) implementation(projects.libraries.mediaupload.api)
implementation(projects.libraries.permissions.api)
implementation(projects.libraries.preferences.api) implementation(projects.libraries.preferences.api)
implementation(projects.features.networkmonitor.api) implementation(projects.features.networkmonitor.api)
implementation(projects.services.analytics.api) implementation(projects.services.analytics.api)
@ -77,6 +78,7 @@ dependencies {
testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.featureflag.test)
testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.mediaupload.test)
testImplementation(projects.libraries.mediapickers.test) testImplementation(projects.libraries.mediapickers.test)
testImplementation(projects.libraries.permissions.test)
testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.preferences.test)
testImplementation(projects.libraries.textcomposer.test) testImplementation(projects.libraries.textcomposer.test)
testImplementation(libs.test.mockk) testImplementation(libs.test.mockk)

View file

@ -71,7 +71,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
@ -390,7 +390,7 @@ private fun CantSendMessageBanner(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) state: MessagesState) = ElementPreview { internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) state: MessagesState) = ElementPreview {
MessagesView( MessagesView(

View file

@ -36,8 +36,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ListItem import androidx.compose.material.ListItem
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AddReaction
import androidx.compose.material.ripple.rememberRipple import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -71,13 +69,14 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.utils.messagesummary.MessageSummaryFormatterImpl import io.element.android.features.messages.impl.utils.messagesummary.MessageSummaryFormatterImpl
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.text.toSp import io.element.android.libraries.designsystem.text.toSp
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import io.element.android.libraries.designsystem.theme.components.hide import io.element.android.libraries.designsystem.theme.components.hide
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
@ -361,7 +360,7 @@ internal fun EmojiReactionsRow(
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Icon( Icon(
imageVector = Icons.Outlined.AddReaction, resourceId = CommonDrawables.ic_september_add_reaction,
contentDescription = "Emojis", contentDescription = "Emojis",
tint = MaterialTheme.colorScheme.secondary, tint = MaterialTheme.colorScheme.secondary,
modifier = Modifier modifier = Modifier
@ -411,7 +410,7 @@ private fun EmojiButton(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun SheetContentPreview( internal fun SheetContentPreview(
@PreviewParameter(ActionListStateProvider::class) state: ActionListState @PreviewParameter(ActionListStateProvider::class) state: ActionListState

View file

@ -19,7 +19,7 @@ package io.element.android.features.messages.impl.actionlist.model
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import io.element.android.libraries.designsystem.VectorIcons import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Immutable @Immutable
@ -28,13 +28,13 @@ sealed class TimelineItemAction(
@DrawableRes val icon: Int, @DrawableRes val icon: Int,
val destructive: Boolean = false val destructive: Boolean = false
) { ) {
data object Forward : TimelineItemAction(CommonStrings.action_forward, VectorIcons.Forward) data object Forward : TimelineItemAction(CommonStrings.action_forward, CommonDrawables.ic_september_forward)
data object Copy : TimelineItemAction(CommonStrings.action_copy, VectorIcons.Copy) data object Copy : TimelineItemAction(CommonStrings.action_copy, CommonDrawables.ic_september_copy)
data object Redact : TimelineItemAction(CommonStrings.action_remove, VectorIcons.Delete, destructive = true) data object Redact : TimelineItemAction(CommonStrings.action_remove, CommonDrawables.ic_compound_delete, destructive = true)
data object Reply : TimelineItemAction(CommonStrings.action_reply, VectorIcons.Reply) data object Reply : TimelineItemAction(CommonStrings.action_reply, CommonDrawables.ic_september_reply)
data object ReplyInThread : TimelineItemAction(CommonStrings.action_reply_in_thread, VectorIcons.Reply) data object ReplyInThread : TimelineItemAction(CommonStrings.action_reply_in_thread, CommonDrawables.ic_september_reply)
data object Edit : TimelineItemAction(CommonStrings.action_edit, VectorIcons.Edit) data object Edit : TimelineItemAction(CommonStrings.action_edit, CommonDrawables.ic_september_edit_outline)
data object ViewSource : TimelineItemAction(CommonStrings.action_view_source, VectorIcons.DeveloperMode) data object ViewSource : TimelineItemAction(CommonStrings.action_view_source, CommonDrawables.ic_september_view_source)
data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, VectorIcons.ReportContent, destructive = true) data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, CommonDrawables.ic_compound_chat_problem, destructive = true)
data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, VectorIcons.PollEnd) data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, CommonDrawables.ic_poll_end)
} }

View file

@ -48,7 +48,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialogDefaults import io.element.android.libraries.designsystem.components.dialogs.ErrorDialogDefaults
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
@ -279,7 +279,7 @@ private fun ForwardingErrorDialog(onDismiss: () -> Unit, modifier: Modifier = Mo
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun ForwardMessagesViewPreview(@PreviewParameter(ForwardMessagesStateProvider::class) state: ForwardMessagesState) = ElementPreview { internal fun ForwardMessagesViewPreview(@PreviewParameter(ForwardMessagesStateProvider::class) state: ForwardMessagesState) = ElementPreview {
ForwardMessagesView( ForwardMessagesView(

View file

@ -31,7 +31,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Attachment
import androidx.compose.material.icons.outlined.GraphicEq import androidx.compose.material.icons.outlined.GraphicEq
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -64,9 +63,9 @@ import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeAudio import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeAudio
import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeImage import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeImage
import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo
import io.element.android.libraries.designsystem.R
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import me.saket.telephoto.zoomable.ZoomSpec import me.saket.telephoto.zoomable.ZoomSpec
@ -124,7 +123,7 @@ private fun MediaImageView(
) { ) {
if (LocalInspectionMode.current) { if (LocalInspectionMode.current) {
Image( Image(
painter = painterResource(id = R.drawable.sample_background), painter = painterResource(id = CommonDrawables.sample_background),
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
contentDescription = null, contentDescription = null,
) )
@ -230,7 +229,8 @@ fun MediaFileView(
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
Icon( Icon(
imageVector = if (isAudio) Icons.Outlined.GraphicEq else Icons.Outlined.Attachment, imageVector = if (isAudio) Icons.Outlined.GraphicEq else null,
resourceId = if (isAudio) null else CommonDrawables.ic_september_attachment,
contentDescription = null, contentDescription = null,
tint = MaterialTheme.colorScheme.background, tint = MaterialTheme.colorScheme.background,
modifier = Modifier modifier = Modifier

View file

@ -29,9 +29,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.OpenInNew import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -61,6 +59,7 @@ import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.designsystem.utils.SnackbarHost import io.element.android.libraries.designsystem.utils.SnackbarHost
import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
@ -176,7 +175,10 @@ private fun MediaViewerTopBar(
eventSink(MediaViewerEvents.OpenWith) eventSink(MediaViewerEvents.OpenWith)
}, },
) { ) {
Icon(imageVector = Icons.Default.OpenInNew, contentDescription = stringResource(id = CommonStrings.action_open_with)) Icon(
imageVector = Icons.Default.OpenInNew,
contentDescription = stringResource(id = CommonStrings.action_open_with)
)
} }
IconButton( IconButton(
enabled = actionsEnabled, enabled = actionsEnabled,
@ -184,7 +186,10 @@ private fun MediaViewerTopBar(
eventSink(MediaViewerEvents.SaveOnDisk) eventSink(MediaViewerEvents.SaveOnDisk)
}, },
) { ) {
Icon(imageVector = Icons.Default.Download, contentDescription = stringResource(id = CommonStrings.action_save)) Icon(
resourceId = CommonDrawables.ic_compound_download,
contentDescription = stringResource(id = CommonStrings.action_save),
)
} }
IconButton( IconButton(
enabled = actionsEnabled, enabled = actionsEnabled,
@ -192,7 +197,10 @@ private fun MediaViewerTopBar(
eventSink(MediaViewerEvents.Share) eventSink(MediaViewerEvents.Share)
}, },
) { ) {
Icon(imageVector = Icons.Default.Share, contentDescription = stringResource(id = CommonStrings.action_share)) Icon(
resourceId = CommonDrawables.ic_compound_share_android,
contentDescription = stringResource(id = CommonStrings.action_share)
)
} }
} }
) )

View file

@ -22,14 +22,6 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ListItem import androidx.compose.material.ListItem
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AttachFile
import androidx.compose.material.icons.filled.BarChart
import androidx.compose.material.icons.filled.Collections
import androidx.compose.material.icons.filled.FormatColorText
import androidx.compose.material.icons.filled.LocationOn
import androidx.compose.material.icons.filled.PhotoCamera
import androidx.compose.material.icons.filled.Videocam
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -44,11 +36,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.messages.impl.R import io.element.android.features.messages.impl.R
import io.element.android.libraries.androidutils.ui.hideKeyboard import io.element.android.libraries.androidutils.ui.hideKeyboard
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@ -115,22 +108,22 @@ internal fun AttachmentSourcePickerMenu(
) { ) {
ListItem( ListItem(
modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.FromGallery) }, modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.FromGallery) },
icon = { Icon(Icons.Default.Collections, null) }, icon = { Icon(CommonDrawables.ic_september_photo_video_library, null) },
text = { Text(stringResource(R.string.screen_room_attachment_source_gallery)) }, text = { Text(stringResource(R.string.screen_room_attachment_source_gallery)) },
) )
ListItem( ListItem(
modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.FromFiles) }, modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.FromFiles) },
icon = { Icon(Icons.Default.AttachFile, null) }, icon = { Icon(CommonDrawables.ic_september_attachment, null) },
text = { Text(stringResource(R.string.screen_room_attachment_source_files)) }, text = { Text(stringResource(R.string.screen_room_attachment_source_files)) },
) )
ListItem( ListItem(
modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera) }, modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera) },
icon = { Icon(Icons.Default.PhotoCamera, null) }, icon = { Icon(CommonDrawables.ic_september_take_photo_camera, null) },
text = { Text(stringResource(R.string.screen_room_attachment_source_camera_photo)) }, text = { Text(stringResource(R.string.screen_room_attachment_source_camera_photo)) },
) )
ListItem( ListItem(
modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.VideoFromCamera) }, modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.VideoFromCamera) },
icon = { Icon(Icons.Default.Videocam, null) }, icon = { Icon(CommonDrawables.ic_september_video_call, null) },
text = { Text(stringResource(R.string.screen_room_attachment_source_camera_video)) }, text = { Text(stringResource(R.string.screen_room_attachment_source_camera_video)) },
) )
if (state.canShareLocation) { if (state.canShareLocation) {
@ -139,7 +132,7 @@ internal fun AttachmentSourcePickerMenu(
state.eventSink(MessageComposerEvents.PickAttachmentSource.Location) state.eventSink(MessageComposerEvents.PickAttachmentSource.Location)
onSendLocationClicked() onSendLocationClicked()
}, },
icon = { Icon(Icons.Default.LocationOn, null) }, icon = { Icon(CommonDrawables.ic_september_location, null) },
text = { Text(stringResource(R.string.screen_room_attachment_source_location)) }, text = { Text(stringResource(R.string.screen_room_attachment_source_location)) },
) )
} }
@ -149,21 +142,21 @@ internal fun AttachmentSourcePickerMenu(
state.eventSink(MessageComposerEvents.PickAttachmentSource.Poll) state.eventSink(MessageComposerEvents.PickAttachmentSource.Poll)
onCreatePollClicked() onCreatePollClicked()
}, },
icon = { Icon(Icons.Default.BarChart, null) }, icon = { Icon(CommonDrawables.ic_compound_polls, null) },
text = { Text(stringResource(R.string.screen_room_attachment_source_poll)) }, text = { Text(stringResource(R.string.screen_room_attachment_source_poll)) },
) )
} }
if (enableTextFormatting) { if (enableTextFormatting) {
ListItem( ListItem(
modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.ToggleTextFormatting(enabled = true)) }, modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.ToggleTextFormatting(enabled = true)) },
icon = { Icon(Icons.Default.FormatColorText, null) }, icon = { Icon(CommonDrawables.ic_september_text_formatting, null) },
text = { Text(stringResource(R.string.screen_room_attachment_text_formatting)) }, text = { Text(stringResource(R.string.screen_room_attachment_text_formatting)) },
) )
} }
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun AttachmentSourcePickerMenuPreview() = ElementPreview { internal fun AttachmentSourcePickerMenuPreview() = ElementPreview {
AttachmentSourcePickerMenu( AttachmentSourcePickerMenu(

View file

@ -16,6 +16,7 @@
package io.element.android.features.messages.impl.messagecomposer package io.element.android.features.messages.impl.messagecomposer
import android.Manifest
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -44,6 +45,8 @@ import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediapickers.api.PickerProvider
import io.element.android.libraries.mediaupload.api.MediaSender import io.element.android.libraries.mediaupload.api.MediaSender
import io.element.android.libraries.permissions.api.PermissionsEvents
import io.element.android.libraries.permissions.api.PermissionsPresenter
import io.element.android.libraries.textcomposer.Message import io.element.android.libraries.textcomposer.Message
import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.libraries.textcomposer.MessageComposerMode
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
@ -70,13 +73,18 @@ class MessageComposerPresenter @Inject constructor(
private val analyticsService: AnalyticsService, private val analyticsService: AnalyticsService,
private val messageComposerContext: MessageComposerContextImpl, private val messageComposerContext: MessageComposerContextImpl,
private val richTextEditorStateFactory: RichTextEditorStateFactory, private val richTextEditorStateFactory: RichTextEditorStateFactory,
permissionsPresenterFactory: PermissionsPresenter.Factory
) : Presenter<MessageComposerState> { ) : Presenter<MessageComposerState> {
private val cameraPermissionPresenter = permissionsPresenterFactory.create(Manifest.permission.CAMERA)
private var pendingEvent: MessageComposerEvents? = null
@SuppressLint("UnsafeOptInUsageError") @SuppressLint("UnsafeOptInUsageError")
@Composable @Composable
override fun present(): MessageComposerState { override fun present(): MessageComposerState {
val localCoroutineScope = rememberCoroutineScope() val localCoroutineScope = rememberCoroutineScope()
val cameraPermissionState = cameraPermissionPresenter.present()
val attachmentsState = remember { val attachmentsState = remember {
mutableStateOf<AttachmentsState>(AttachmentsState.None) mutableStateOf<AttachmentsState>(AttachmentsState.None)
} }
@ -132,6 +140,17 @@ class MessageComposerPresenter @Inject constructor(
} }
} }
LaunchedEffect(cameraPermissionState.permissionGranted) {
if (cameraPermissionState.permissionGranted) {
when (pendingEvent) {
is MessageComposerEvents.PickAttachmentSource.PhotoFromCamera -> cameraPhotoPicker.launch()
is MessageComposerEvents.PickAttachmentSource.VideoFromCamera -> cameraVideoPicker.launch()
else -> Unit
}
pendingEvent = null
}
}
fun handleEvents(event: MessageComposerEvents) { fun handleEvents(event: MessageComposerEvents) {
when (event) { when (event) {
MessageComposerEvents.ToggleFullScreenState -> isFullScreen.value = !isFullScreen.value MessageComposerEvents.ToggleFullScreenState -> isFullScreen.value = !isFullScreen.value
@ -163,11 +182,21 @@ class MessageComposerPresenter @Inject constructor(
} }
MessageComposerEvents.PickAttachmentSource.PhotoFromCamera -> localCoroutineScope.launch { MessageComposerEvents.PickAttachmentSource.PhotoFromCamera -> localCoroutineScope.launch {
showAttachmentSourcePicker = false showAttachmentSourcePicker = false
if (cameraPermissionState.permissionGranted) {
cameraPhotoPicker.launch() cameraPhotoPicker.launch()
} else {
pendingEvent = event
cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions)
}
} }
MessageComposerEvents.PickAttachmentSource.VideoFromCamera -> localCoroutineScope.launch { MessageComposerEvents.PickAttachmentSource.VideoFromCamera -> localCoroutineScope.launch {
showAttachmentSourcePicker = false showAttachmentSourcePicker = false
if (cameraPermissionState.permissionGranted) {
cameraVideoPicker.launch() cameraVideoPicker.launch()
} else {
pendingEvent = event
cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions)
}
} }
MessageComposerEvents.PickAttachmentSource.Location -> { MessageComposerEvents.PickAttachmentSource.Location -> {
showAttachmentSourcePicker = false showAttachmentSourcePicker = false

View file

@ -20,7 +20,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.textcomposer.Message import io.element.android.libraries.textcomposer.Message
import io.element.android.libraries.textcomposer.TextComposer import io.element.android.libraries.textcomposer.TextComposer
@ -81,7 +81,7 @@ fun MessageComposerView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun MessageComposerViewPreview(@PreviewParameter(MessageComposerStateProvider::class) state: MessageComposerState) = ElementPreview { internal fun MessageComposerViewPreview(@PreviewParameter(MessageComposerStateProvider::class) state: MessageComposerState) = ElementPreview {
MessageComposerView( MessageComposerView(

View file

@ -44,7 +44,7 @@ import androidx.compose.ui.unit.dp
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
@ -165,7 +165,7 @@ fun ReportMessageView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun ReportMessageViewPreview(@PreviewParameter(ReportMessageStateProvider::class) state: ReportMessageState) = ElementPreview { internal fun ReportMessageViewPreview(@PreviewParameter(ReportMessageStateProvider::class) state: ReportMessageState) = ElementPreview {
ReportMessageView( ReportMessageView(

View file

@ -36,8 +36,6 @@ import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDownward
import androidx.compose.material3.FloatingActionButtonDefaults import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
@ -49,6 +47,8 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
@ -64,10 +64,12 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContentProvider
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
import io.element.android.features.messages.impl.timeline.model.event.canBeRepliedTo import io.element.android.features.messages.impl.timeline.model.event.canBeRepliedTo
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.animation.alphaAnimation
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.FloatingActionButton import io.element.android.libraries.designsystem.theme.components.FloatingActionButton
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@ -105,7 +107,10 @@ fun TimelineView(
state.eventSink(TimelineEvents.PollAnswerSelected(pollStartId, answerId)) state.eventSink(TimelineEvents.PollAnswerSelected(pollStartId, answerId))
} }
Box(modifier = modifier) { // Animate alpha when timeline is first displayed, to avoid flashes or glitching when viewing rooms
val alpha by alphaAnimation(label = "alpha for timeline")
Box(modifier = modifier.alpha(alpha)) {
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
state = lazyListState, state = lazyListState,
@ -315,15 +320,17 @@ private fun JumpToBottomButton(
contentColor = ElementTheme.colors.iconSecondary contentColor = ElementTheme.colors.iconSecondary
) { ) {
Icon( Icon(
modifier = Modifier.size(24.dp), modifier = Modifier
imageVector = Icons.Filled.ArrowDownward, .size(24.dp)
.rotate(90f),
resourceId = CommonDrawables.ic_compound_arrow_right,
contentDescription = "", contentDescription = "",
) )
} }
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineViewPreview( internal fun TimelineViewPreview(
@PreviewParameter(TimelineItemEventContentProvider::class) content: TimelineItemEventContent @PreviewParameter(TimelineItemEventContentProvider::class) content: TimelineItemEventContent

View file

@ -39,7 +39,7 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItemGrou
import io.element.android.features.messages.impl.timeline.model.bubble.BubbleState import io.element.android.features.messages.impl.timeline.model.bubble.BubbleState
import io.element.android.features.messages.impl.timeline.model.bubble.BubbleStateProvider import io.element.android.features.messages.impl.timeline.model.bubble.BubbleStateProvider
import io.element.android.libraries.core.extensions.to01 import io.element.android.libraries.core.extensions.to01
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
@ -131,7 +131,7 @@ fun MessageEventBubble(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun MessageEventBubblePreview(@PreviewParameter(BubbleStateProvider::class) state: BubbleState) = ElementPreview { internal fun MessageEventBubblePreview(@PreviewParameter(BubbleStateProvider::class) state: BubbleState) = ElementPreview {
// Due to position offset, surround with a Box // Due to position offset, surround with a Box

View file

@ -31,7 +31,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
@ -66,7 +66,7 @@ fun MessageStateEventContainer(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun MessageStateEventContainerPreview() = ElementPreview { internal fun MessageStateEventContainerPreview() = ElementPreview {
Column { Column {

View file

@ -16,6 +16,7 @@
package io.element.android.features.messages.impl.timeline.components package io.element.android.features.messages.impl.timeline.components
import androidx.annotation.DrawableRes
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
@ -29,15 +30,12 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AddReaction
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -46,12 +44,13 @@ import io.element.android.features.messages.impl.R
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
import io.element.android.features.messages.impl.timeline.model.AggregatedReactionProvider import io.element.android.features.messages.impl.timeline.model.AggregatedReactionProvider
import io.element.android.features.messages.impl.timeline.model.aTimelineItemReactions import io.element.android.features.messages.impl.timeline.model.aTimelineItemReactions
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.text.toDp
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@Composable @Composable
@ -96,7 +95,7 @@ fun MessagesReactionButton(
color = buttonColor color = buttonColor
) { ) {
when (content) { when (content) {
is MessagesReactionsButtonContent.Icon -> IconContent(imageVector = content.imageVector) is MessagesReactionsButtonContent.Icon -> IconContent(resourceId = content.resourceId)
is MessagesReactionsButtonContent.Text -> TextContent(text = content.text) is MessagesReactionsButtonContent.Text -> TextContent(text = content.text)
is MessagesReactionsButtonContent.Reaction -> ReactionContent(reaction = content.reaction) is MessagesReactionsButtonContent.Reaction -> ReactionContent(reaction = content.reaction)
} }
@ -105,7 +104,7 @@ fun MessagesReactionButton(
sealed class MessagesReactionsButtonContent { sealed class MessagesReactionsButtonContent {
data class Text(val text: String) : MessagesReactionsButtonContent() data class Text(val text: String) : MessagesReactionsButtonContent()
data class Icon(val imageVector: ImageVector) : MessagesReactionsButtonContent() data class Icon(@DrawableRes val resourceId: Int) : MessagesReactionsButtonContent()
data class Reaction(val reaction: AggregatedReaction) : MessagesReactionsButtonContent() data class Reaction(val reaction: AggregatedReaction) : MessagesReactionsButtonContent()
@ -129,10 +128,10 @@ private fun TextContent(
@Composable @Composable
private fun IconContent( private fun IconContent(
imageVector: ImageVector, @DrawableRes resourceId: Int,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) = Icon( ) = Icon(
imageVector = imageVector, resourceId = resourceId,
contentDescription = stringResource(id = R.string.screen_room_timeline_add_reaction), contentDescription = stringResource(id = R.string.screen_room_timeline_add_reaction),
tint = ElementTheme.materialColors.secondary, tint = ElementTheme.materialColors.secondary,
modifier = modifier modifier = modifier
@ -165,7 +164,7 @@ private fun ReactionContent(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun MessagesReactionButtonPreview(@PreviewParameter(AggregatedReactionProvider::class) reaction: AggregatedReaction) = ElementPreview { internal fun MessagesReactionButtonPreview(@PreviewParameter(AggregatedReactionProvider::class) reaction: AggregatedReaction) = ElementPreview {
MessagesReactionButton( MessagesReactionButton(
@ -175,17 +174,17 @@ internal fun MessagesReactionButtonPreview(@PreviewParameter(AggregatedReactionP
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun MessagesAddReactionButtonPreview() = ElementPreview { internal fun MessagesAddReactionButtonPreview() = ElementPreview {
MessagesReactionButton( MessagesReactionButton(
content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction), content = MessagesReactionsButtonContent.Icon(CommonDrawables.ic_september_add_reaction),
onClick = {}, onClick = {},
onLongClick = {} onLongClick = {}
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun MessagesReactionExtraButtonsPreview() = ElementPreview { internal fun MessagesReactionExtraButtonsPreview() = ElementPreview {
Row { Row {

View file

@ -25,10 +25,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.VectorIcons import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.DayNightPreviews
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.utils.CommonDrawables
/** /**
* A swipe indicator that appears when swiping to reply to a message. * A swipe indicator that appears when swiping to reply to a message.
@ -49,11 +49,11 @@ fun RowScope.ReplySwipeIndicator(
alpha = swipeProgress() alpha = swipeProgress()
}, },
contentDescription = null, contentDescription = null,
resourceId = VectorIcons.Reply, resourceId = CommonDrawables.ic_september_reply,
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun ReplySwipeIndicatorPreview() = ElementPreview { internal fun ReplySwipeIndicatorPreview() = ElementPreview {
Column(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier.fillMaxWidth()) {

View file

@ -24,8 +24,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Error
import androidx.compose.material.ripple.rememberRipple import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -38,10 +36,11 @@ import androidx.compose.ui.unit.dp
import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -90,12 +89,17 @@ fun TimelineEventTimestampView(
) )
if (hasMessageSendingFailed && tint != null) { if (hasMessageSendingFailed && tint != null) {
Spacer(modifier = Modifier.width(2.dp)) Spacer(modifier = Modifier.width(2.dp))
Icon(imageVector = Icons.Default.Error, contentDescription = "Error sending message", tint = tint, modifier = Modifier.size(15.dp, 18.dp)) Icon(
resourceId = CommonDrawables.ic_compound_error,
contentDescription = "Error sending message",
tint = tint,
modifier = Modifier.size(15.dp, 18.dp),
)
} }
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineEventTimestampViewPreview(@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event) = ElementPreview { internal fun TimelineEventTimestampViewPreview(@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event) = ElementPreview {
TimelineEventTimestampView( TimelineEventTimestampView(

View file

@ -76,12 +76,11 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
import io.element.android.libraries.designsystem.VectorIcons
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.EqualWidthColumn
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.swipe.SwipeableActionsState import io.element.android.libraries.designsystem.swipe.SwipeableActionsState
@ -89,6 +88,7 @@ import io.element.android.libraries.designsystem.swipe.rememberSwipeableActionsS
import io.element.android.libraries.designsystem.text.toPx import io.element.android.libraries.designsystem.text.toPx
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
@ -403,7 +403,11 @@ private fun MessageEventBubbleContent(
horizontalArrangement = spacedBy(4.dp, Alignment.Start), horizontalArrangement = spacedBy(4.dp, Alignment.Start),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Icon(resourceId = VectorIcons.ThreadDecoration, contentDescription = null, tint = ElementTheme.colors.iconSecondary) Icon(
resourceId = CommonDrawables.ic_thread_decoration,
contentDescription = null,
tint = ElementTheme.colors.iconSecondary,
)
Text( Text(
text = stringResource(CommonStrings.common_thread), text = stringResource(CommonStrings.common_thread),
style = ElementTheme.typography.fontBodyXsRegular, style = ElementTheme.typography.fontBodyXsRegular,
@ -623,7 +627,7 @@ private fun textForInReplyTo(inReplyTo: InReplyTo.Ready): String {
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemEventRowPreview() = ElementPreview { internal fun TimelineItemEventRowPreview() = ElementPreview {
Column { Column {
@ -675,7 +679,7 @@ internal fun TimelineItemEventRowPreview() = ElementPreview {
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemEventRowWithReplyPreview() = ElementPreview { internal fun TimelineItemEventRowWithReplyPreview() = ElementPreview {
Column { Column {
@ -749,7 +753,7 @@ private fun aInReplyToReady(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemEventRowTimestampPreview( internal fun TimelineItemEventRowTimestampPreview(
@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event @PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event
@ -789,7 +793,7 @@ internal fun TimelineItemEventRowTimestampPreview(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemEventRowWithManyReactionsPreview() = ElementPreview { internal fun TimelineItemEventRowWithManyReactionsPreview() = ElementPreview {
Column { Column {

View file

@ -16,8 +16,6 @@
package io.element.android.features.messages.impl.timeline.components package io.element.android.features.messages.impl.timeline.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AddReaction
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.MeasureResult import androidx.compose.ui.layout.MeasureResult
@ -28,8 +26,9 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.messages.impl.R import io.element.android.features.messages.impl.R
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.utils.CommonDrawables
/** /**
* A flow layout for reactions that will show a collapse/expand button when the layout wraps over a defined number of rows. * A flow layout for reactions that will show a collapse/expand button when the layout wraps over a defined number of rows.
@ -181,7 +180,7 @@ fun TimelineItemReactionsLayout(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemReactionsLayoutPreview() = ElementPreview { internal fun TimelineItemReactionsLayoutPreview() = ElementPreview {
TimelineItemReactionsLayout( TimelineItemReactionsLayout(
@ -197,7 +196,7 @@ internal fun TimelineItemReactionsLayoutPreview() = ElementPreview {
}, },
addMoreButton = { addMoreButton = {
MessagesReactionButton( MessagesReactionButton(
content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction), content = MessagesReactionsButtonContent.Icon(CommonDrawables.ic_september_add_reaction),
onClick = {}, onClick = {},
onLongClick = {} onLongClick = {}
) )

View file

@ -16,8 +16,6 @@
package io.element.android.features.messages.impl.timeline.components package io.element.android.features.messages.impl.timeline.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AddReaction
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -33,8 +31,9 @@ import io.element.android.features.messages.impl.R
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.utils.CommonDrawables
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@Composable @Composable
@ -96,7 +95,7 @@ private fun TimelineItemReactionsView(
}, },
addMoreButton = { addMoreButton = {
MessagesReactionButton( MessagesReactionButton(
content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction), content = MessagesReactionsButtonContent.Icon(CommonDrawables.ic_september_add_reaction),
onClick = onMoreReactionsClick, onClick = onMoreReactionsClick,
onLongClick = {} onLongClick = {}
) )
@ -116,7 +115,7 @@ private fun TimelineItemReactionsView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemReactionsViewPreview() = ElementPreview { internal fun TimelineItemReactionsViewPreview() = ElementPreview {
ContentToPreview( ContentToPreview(
@ -124,7 +123,7 @@ internal fun TimelineItemReactionsViewPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemReactionsViewFewPreview() = ElementPreview { internal fun TimelineItemReactionsViewFewPreview() = ElementPreview {
ContentToPreview( ContentToPreview(
@ -132,7 +131,7 @@ internal fun TimelineItemReactionsViewFewPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemReactionsViewIncomingPreview() = ElementPreview { internal fun TimelineItemReactionsViewIncomingPreview() = ElementPreview {
ContentToPreview( ContentToPreview(
@ -140,7 +139,7 @@ internal fun TimelineItemReactionsViewIncomingPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemReactionsViewOutgoingPreview() = ElementPreview { internal fun TimelineItemReactionsViewOutgoingPreview() = ElementPreview {
ContentToPreview( ContentToPreview(

View file

@ -35,7 +35,7 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent
import io.element.android.features.messages.impl.timeline.util.defaultTimelineContentPadding import io.element.android.features.messages.impl.timeline.util.defaultTimelineContentPadding
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
@Composable @Composable
@ -76,7 +76,7 @@ fun TimelineItemStateEventRow(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemStateEventRowPreview() = ElementPreview { internal fun TimelineItemStateEventRowPreview() = ElementPreview {
TimelineItemStateEventRow( TimelineItemStateEventRow(

View file

@ -49,7 +49,7 @@ import io.element.android.emojibasebindings.Emoji
import io.element.android.emojibasebindings.EmojibaseCategory import io.element.android.emojibasebindings.EmojibaseCategory
import io.element.android.emojibasebindings.EmojibaseDatasource import io.element.android.emojibasebindings.EmojibaseDatasource
import io.element.android.emojibasebindings.EmojibaseStore import io.element.android.emojibasebindings.EmojibaseStore
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
@ -132,7 +132,7 @@ fun EmojiPicker(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun EmojiPickerPreview() = ElementPreview { internal fun EmojiPickerPreview() = ElementPreview {
EmojiPicker( EmojiPicker(

View file

@ -36,7 +36,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContentProvider
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
@ -86,7 +86,7 @@ fun TimelineItemAudioView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemAudioViewPreview(@PreviewParameter(TimelineItemAudioContentProvider::class) content: TimelineItemAudioContent) = internal fun TimelineItemAudioViewPreview(@PreviewParameter(TimelineItemAudioContentProvider::class) content: TimelineItemAudioContent) =
ElementPreview { ElementPreview {

View file

@ -16,14 +16,13 @@
package io.element.android.features.messages.impl.timeline.components.event package io.element.android.features.messages.impl.timeline.components.event
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Warning
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -36,13 +35,13 @@ fun TimelineItemEncryptedView(
TimelineItemInformativeView( TimelineItemInformativeView(
text = stringResource(id = CommonStrings.common_decryption_error), text = stringResource(id = CommonStrings.common_decryption_error),
iconDescription = stringResource(id = CommonStrings.dialog_title_warning), iconDescription = stringResource(id = CommonStrings.dialog_title_warning),
icon = Icons.Default.Warning, iconResourceId = CommonDrawables.ic_september_decryption_error,
extraPadding = extraPadding, extraPadding = extraPadding,
modifier = modifier modifier = modifier
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemEncryptedViewPreview() = ElementPreview { internal fun TimelineItemEncryptedViewPreview() = ElementPreview {
TimelineItemEncryptedView( TimelineItemEncryptedView(

View file

@ -24,8 +24,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Attachment
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -37,10 +35,11 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContentProvider
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@Composable @Composable
@ -60,7 +59,7 @@ fun TimelineItemFileView(
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
Icon( Icon(
imageVector = Icons.Outlined.Attachment, resourceId = CommonDrawables.ic_september_attachment,
contentDescription = "OpenFile", contentDescription = "OpenFile",
tint = ElementTheme.materialColors.primary, tint = ElementTheme.materialColors.primary,
modifier = Modifier modifier = Modifier
@ -88,7 +87,7 @@ fun TimelineItemFileView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemFileViewPreview(@PreviewParameter(TimelineItemFileContentProvider::class) content: TimelineItemFileContent) = ElementPreview { internal fun TimelineItemFileViewPreview(@PreviewParameter(TimelineItemFileContentProvider::class) content: TimelineItemFileContent) = ElementPreview {
TimelineItemFileView( TimelineItemFileView(

View file

@ -23,7 +23,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContentProvider
import io.element.android.libraries.designsystem.components.BlurHashAsyncImage import io.element.android.libraries.designsystem.components.BlurHashAsyncImage
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.matrix.ui.media.MediaRequestData import io.element.android.libraries.matrix.ui.media.MediaRequestData
@ -44,7 +44,7 @@ fun TimelineItemImageView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemImageViewPreview(@PreviewParameter(TimelineItemImageContentProvider::class) content: TimelineItemImageContent) = ElementPreview { internal fun TimelineItemImageViewPreview(@PreviewParameter(TimelineItemImageContentProvider::class) content: TimelineItemImageContent) = ElementPreview {
TimelineItemImageView(content) TimelineItemImageView(content)

View file

@ -16,31 +16,30 @@
package io.element.android.features.messages.impl.timeline.components.event package io.element.android.features.messages.impl.timeline.components.event
import androidx.annotation.DrawableRes
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@Composable @Composable
fun TimelineItemInformativeView( fun TimelineItemInformativeView(
text: String, text: String,
iconDescription: String, iconDescription: String,
icon: ImageVector, @DrawableRes iconResourceId: Int,
extraPadding: ExtraPadding, extraPadding: ExtraPadding,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
@ -49,7 +48,7 @@ fun TimelineItemInformativeView(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Icon( Icon(
imageVector = icon, resourceId = iconResourceId,
tint = MaterialTheme.colorScheme.secondary, tint = MaterialTheme.colorScheme.secondary,
contentDescription = iconDescription, contentDescription = iconDescription,
modifier = Modifier.size(16.dp) modifier = Modifier.size(16.dp)
@ -64,13 +63,13 @@ fun TimelineItemInformativeView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemInformativeViewPreview() = ElementPreview { internal fun TimelineItemInformativeViewPreview() = ElementPreview {
TimelineItemInformativeView( TimelineItemInformativeView(
text = "Info", text = "Info",
iconDescription = "", iconDescription = "",
icon = Icons.Default.Delete, iconResourceId = CommonDrawables.ic_compound_delete,
extraPadding = noExtraPadding, extraPadding = noExtraPadding,
) )
} }

View file

@ -27,7 +27,7 @@ import androidx.compose.ui.unit.dp
import io.element.android.features.location.api.StaticMapView import io.element.android.features.location.api.StaticMapView
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContentProvider
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
@ -56,7 +56,7 @@ fun TimelineItemLocationView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemLocationViewPreview(@PreviewParameter(TimelineItemLocationContentProvider::class) content: TimelineItemLocationContent) = internal fun TimelineItemLocationViewPreview(@PreviewParameter(TimelineItemLocationContentProvider::class) content: TimelineItemLocationContent) =
ElementPreview { ElementPreview {

View file

@ -22,7 +22,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContentProvider
import io.element.android.features.poll.api.PollContentView import io.element.android.features.poll.api.PollContentView
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
@ -44,7 +44,7 @@ fun TimelineItemPollView(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemPollViewPreview(@PreviewParameter(TimelineItemPollContentProvider::class) content: TimelineItemPollContent) = internal fun TimelineItemPollViewPreview(@PreviewParameter(TimelineItemPollContentProvider::class) content: TimelineItemPollContent) =
ElementPreview { ElementPreview {

View file

@ -16,14 +16,13 @@
package io.element.android.features.messages.impl.timeline.components.event package io.element.android.features.messages.impl.timeline.components.event
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
@ -35,13 +34,13 @@ fun TimelineItemRedactedView(
TimelineItemInformativeView( TimelineItemInformativeView(
text = stringResource(id = CommonStrings.common_message_removed), text = stringResource(id = CommonStrings.common_message_removed),
iconDescription = stringResource(id = CommonStrings.common_message_removed), iconDescription = stringResource(id = CommonStrings.common_message_removed),
icon = Icons.Default.Delete, iconResourceId = CommonDrawables.ic_compound_delete,
extraPadding = extraPadding, extraPadding = extraPadding,
modifier = modifier modifier = modifier
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemRedactedViewPreview() = ElementPreview { internal fun TimelineItemRedactedViewPreview() = ElementPreview {
TimelineItemRedactedView( TimelineItemRedactedView(

View file

@ -22,7 +22,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@ -41,7 +41,7 @@ fun TimelineItemStateView(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemStateViewPreview() = ElementPreview { internal fun TimelineItemStateViewPreview() = ElementPreview {
TimelineItemStateView( TimelineItemStateView(

View file

@ -29,7 +29,7 @@ import io.element.android.features.messages.impl.timeline.components.html.HtmlDo
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContentProvider
import io.element.android.libraries.designsystem.components.ClickableLinkText import io.element.android.libraries.designsystem.components.ClickableLinkText
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.text.toAnnotatedString import io.element.android.libraries.designsystem.text.toAnnotatedString
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@ -70,7 +70,7 @@ fun TimelineItemTextView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemTextViewPreview( internal fun TimelineItemTextViewPreview(
@PreviewParameter(TimelineItemTextBasedContentProvider::class) content: TimelineItemTextBasedContent @PreviewParameter(TimelineItemTextBasedContentProvider::class) content: TimelineItemTextBasedContent

View file

@ -16,14 +16,13 @@
package io.element.android.features.messages.impl.timeline.components.event package io.element.android.features.messages.impl.timeline.components.event
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
@ -35,13 +34,13 @@ fun TimelineItemUnknownView(
TimelineItemInformativeView( TimelineItemInformativeView(
text = stringResource(id = CommonStrings.common_unsupported_event), text = stringResource(id = CommonStrings.common_unsupported_event),
iconDescription = stringResource(id = CommonStrings.dialog_title_warning), iconDescription = stringResource(id = CommonStrings.dialog_title_warning),
icon = Icons.Default.Info, iconResourceId = CommonDrawables.ic_compound_info,
extraPadding = extraPadding, extraPadding = extraPadding,
modifier = modifier modifier = modifier
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemUnknownViewPreview() = ElementPreview { internal fun TimelineItemUnknownViewPreview() = ElementPreview {
TimelineItemUnknownView( TimelineItemUnknownView(

View file

@ -31,7 +31,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContentProvider
import io.element.android.libraries.designsystem.components.BlurHashAsyncImage import io.element.android.libraries.designsystem.components.BlurHashAsyncImage
import io.element.android.libraries.designsystem.modifiers.roundedBackground import io.element.android.libraries.designsystem.modifiers.roundedBackground
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.matrix.ui.media.MediaRequestData import io.element.android.libraries.matrix.ui.media.MediaRequestData
@ -63,7 +63,7 @@ fun TimelineItemVideoView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemVideoViewPreview(@PreviewParameter(TimelineItemVideoContentProvider::class) content: TimelineItemVideoContent) = ElementPreview { internal fun TimelineItemVideoViewPreview(@PreviewParameter(TimelineItemVideoContentProvider::class) content: TimelineItemVideoContent) = ElementPreview {
TimelineItemVideoView(content) TimelineItemVideoView(content)

View file

@ -24,21 +24,20 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExpandLess
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
private val CORNER_RADIUS = 8.dp private val CORNER_RADIUS = 8.dp
@ -77,18 +76,18 @@ fun GroupHeaderView(
color = MaterialTheme.colorScheme.secondary, color = MaterialTheme.colorScheme.secondary,
style = ElementTheme.typography.fontBodyMdRegular, style = ElementTheme.typography.fontBodyMdRegular,
) )
val icon = if (isExpanded) { Icon(
Icons.Default.ExpandLess modifier = Modifier.rotate(if (isExpanded) 180f else 0f),
} else { resourceId = CommonDrawables.ic_compound_chevron_down,
Icons.Default.ExpandMore contentDescription = null,
} tint = MaterialTheme.colorScheme.secondary
Icon(icon, "", tint = MaterialTheme.colorScheme.secondary) )
} }
} }
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun GroupHeaderViewPreview() = ElementPreview { internal fun GroupHeaderViewPreview() = ElementPreview {
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {

View file

@ -58,7 +58,7 @@ import io.element.android.features.messages.impl.timeline.components.event.Extra
import io.element.android.features.messages.impl.timeline.components.event.getDpSize import io.element.android.features.messages.impl.timeline.components.event.getDpSize
import io.element.android.features.messages.impl.timeline.components.event.noExtraPadding import io.element.android.features.messages.impl.timeline.components.event.noExtraPadding
import io.element.android.libraries.designsystem.components.ClickableLinkText import io.element.android.libraries.designsystem.components.ClickableLinkText
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.text.toDp
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
@ -612,7 +612,7 @@ private fun HtmlText(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun HtmlDocumentPreview(@PreviewParameter(DocumentProvider::class) document: Document) = ElementPreview { internal fun HtmlDocumentPreview(@PreviewParameter(DocumentProvider::class) document: Document) = ElementPreview {
HtmlDocument( HtmlDocument(

View file

@ -61,7 +61,7 @@ import io.element.android.features.messages.impl.timeline.model.AggregatedReacti
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
@ -266,7 +266,7 @@ fun SenderRow(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun SheetContentPreview( internal fun SheetContentPreview(
@PreviewParameter(ReactionSummaryStateProvider::class) state: ReactionSummaryState @PreviewParameter(ReactionSummaryStateProvider::class) state: ReactionSummaryState

View file

@ -34,7 +34,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.messages.impl.R import io.element.android.features.messages.impl.R
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
@ -149,7 +149,7 @@ private fun ColumnScope.RetrySendMenuContents(
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun RetrySendMessageMenuPreview(@PreviewParameter(RetrySendMenuStateProvider::class) state: RetrySendMenuState) = ElementPreview { internal fun RetrySendMessageMenuPreview(@PreviewParameter(RetrySendMenuStateProvider::class) state: RetrySendMenuState) = ElementPreview {
// TODO restore RetrySendMessageMenuBottomSheet once the issue with bottom sheet not being previewable is fixed // TODO restore RetrySendMessageMenuBottomSheet once the issue with bottom sheet not being previewable is fixed

View file

@ -21,9 +21,6 @@ import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -32,7 +29,9 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.messages.impl.R import io.element.android.features.messages.impl.R
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@Composable @Composable
@ -47,7 +46,7 @@ fun TimelineEncryptedHistoryBannerView(modifier: Modifier = Modifier) {
horizontalArrangement = Arrangement.spacedBy(16.dp) horizontalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
Icon( Icon(
imageVector = Icons.Default.Info, resourceId = CommonDrawables.ic_compound_info,
contentDescription = "Info", contentDescription = "Info",
tint = ElementTheme.colors.iconInfoPrimary tint = ElementTheme.colors.iconInfoPrimary
) )
@ -59,7 +58,7 @@ fun TimelineEncryptedHistoryBannerView(modifier: Modifier = Modifier) {
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineEncryptedHistoryBannerViewPreview() { internal fun TimelineEncryptedHistoryBannerViewPreview() {
ElementTheme { ElementTheme {

View file

@ -28,7 +28,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModel import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModel
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModelProvider import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModelProvider
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@ -53,7 +53,7 @@ internal fun TimelineItemDaySeparatorView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemDaySeparatorViewPreview( internal fun TimelineItemDaySeparatorViewPreview(
@PreviewParameter(TimelineItemDaySeparatorModelProvider::class) model: TimelineItemDaySeparatorModel @PreviewParameter(TimelineItemDaySeparatorModelProvider::class) model: TimelineItemDaySeparatorModel

View file

@ -24,7 +24,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
@ -43,7 +43,7 @@ internal fun TimelineLoadingMoreIndicator(modifier: Modifier = Modifier) {
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun TimelineLoadingMoreIndicatorPreview() = ElementPreview { internal fun TimelineLoadingMoreIndicatorPreview() = ElementPreview {
TimelineLoadingMoreIndicator() TimelineLoadingMoreIndicator()

View file

@ -33,9 +33,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.ArrowDropUp
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -46,19 +43,21 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@ -140,7 +139,8 @@ private fun CollapsibleSection(
) { ) {
Text(title, modifier = Modifier.weight(1f)) Text(title, modifier = Modifier.weight(1f))
Icon( Icon(
imageVector = if (isExpanded) Icons.Filled.ArrowDropUp else Icons.Filled.ArrowDropDown, modifier = Modifier.rotate(if (isExpanded) 180f else 0f),
resourceId = CommonDrawables.ic_compound_chevron_down,
contentDescription = null contentDescription = null
) )
} }
@ -172,7 +172,7 @@ private fun CopyableText(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun EventDebugInfoViewPreview() = ElementPreview { internal fun EventDebugInfoViewPreview() = ElementPreview {
EventDebugInfoView( EventDebugInfoView(

View file

@ -12,6 +12,7 @@
<string name="screen_room_attachment_source_gallery">"Фото и видео"</string> <string name="screen_room_attachment_source_gallery">"Фото и видео"</string>
<string name="screen_room_attachment_source_location">"Местоположение"</string> <string name="screen_room_attachment_source_location">"Местоположение"</string>
<string name="screen_room_attachment_source_poll">"Опрос"</string> <string name="screen_room_attachment_source_poll">"Опрос"</string>
<string name="screen_room_attachment_text_formatting">"Форматирование текста"</string>
<string name="screen_room_encrypted_history_banner">"В настоящее время история сообщений недоступна в этой комнате"</string> <string name="screen_room_encrypted_history_banner">"В настоящее время история сообщений недоступна в этой комнате"</string>
<string name="screen_room_error_failed_retrieving_user_details">"Не удалось получить данные о пользователе"</string> <string name="screen_room_error_failed_retrieving_user_details">"Не удалось получить данные о пользователе"</string>
<string name="screen_room_invite_again_alert_message">"Хотите пригласить их снова?"</string> <string name="screen_room_invite_again_alert_message">"Хотите пригласить их снова?"</string>

View file

@ -6,7 +6,7 @@
</plurals> </plurals>
<string name="screen_room_attachment_source_camera">"Camera"</string> <string name="screen_room_attachment_source_camera">"Camera"</string>
<string name="screen_room_attachment_source_camera_photo">"Take photo"</string> <string name="screen_room_attachment_source_camera_photo">"Take photo"</string>
<string name="screen_room_attachment_source_camera_video">"Record a video"</string> <string name="screen_room_attachment_source_camera_video">"Record video"</string>
<string name="screen_room_attachment_source_files">"Attachment"</string> <string name="screen_room_attachment_source_files">"Attachment"</string>
<string name="screen_room_attachment_source_gallery">"Photo &amp; Video Library"</string> <string name="screen_room_attachment_source_gallery">"Photo &amp; Video Library"</string>
<string name="screen_room_attachment_source_location">"Location"</string> <string name="screen_room_attachment_source_location">"Location"</string>

View file

@ -70,6 +70,9 @@ import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.mediapickers.test.FakePickerProvider import io.element.android.libraries.mediapickers.test.FakePickerProvider
import io.element.android.libraries.mediaupload.api.MediaSender import io.element.android.libraries.mediaupload.api.MediaSender
import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
import io.element.android.libraries.permissions.api.PermissionsPresenter
import io.element.android.libraries.permissions.test.FakePermissionsPresenter
import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory
import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.libraries.textcomposer.MessageComposerMode
import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
@ -601,6 +604,7 @@ class MessagesPresenterTest {
navigator: FakeMessagesNavigator = FakeMessagesNavigator(), navigator: FakeMessagesNavigator = FakeMessagesNavigator(),
clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(), clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(),
analyticsService: FakeAnalyticsService = FakeAnalyticsService(), analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(),
): MessagesPresenter { ): MessagesPresenter {
val messageComposerPresenter = MessageComposerPresenter( val messageComposerPresenter = MessageComposerPresenter(
appCoroutineScope = this, appCoroutineScope = this,
@ -613,7 +617,7 @@ class MessagesPresenterTest {
analyticsService = analyticsService, analyticsService = analyticsService,
messageComposerContext = MessageComposerContextImpl(), messageComposerContext = MessageComposerContextImpl(),
richTextEditorStateFactory = TestRichTextEditorStateFactory(), richTextEditorStateFactory = TestRichTextEditorStateFactory(),
permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionsPresenter),
) )
val timelinePresenter = TimelinePresenter( val timelinePresenter = TimelinePresenter(
timelineItemsFactory = aTimelineItemsFactory(), timelineItemsFactory = aTimelineItemsFactory(),

View file

@ -54,6 +54,9 @@ import io.element.android.libraries.mediaupload.api.MediaPreProcessor
import io.element.android.libraries.mediaupload.api.MediaSender import io.element.android.libraries.mediaupload.api.MediaSender
import io.element.android.libraries.mediaupload.api.MediaUploadInfo import io.element.android.libraries.mediaupload.api.MediaUploadInfo
import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
import io.element.android.libraries.permissions.api.PermissionsPresenter
import io.element.android.libraries.permissions.test.FakePermissionsPresenter
import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory
import io.element.android.libraries.textcomposer.Message import io.element.android.libraries.textcomposer.Message
import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.libraries.textcomposer.MessageComposerMode
import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService
@ -67,6 +70,7 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import java.io.File import java.io.File
@Suppress("LargeClass")
class MessageComposerPresenterTest { class MessageComposerPresenterTest {
@get:Rule @get:Rule
@ -487,18 +491,84 @@ class MessageComposerPresenterTest {
} }
@Test @Test
fun `present - Take photo`() = runTest { fun `present - create poll`() = runTest {
val room = FakeMatrixRoom() val room = FakeMatrixRoom()
val presenter = createPresenter(this, room = room) val presenter = createPresenter(this, room = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
skipItems(1)
val initialState = awaitItem()
initialState.eventSink(MessageComposerEvents.AddAttachment)
val attachmentOpenState = awaitItem()
assertThat(attachmentOpenState.showAttachmentSourcePicker).isTrue()
initialState.eventSink(MessageComposerEvents.PickAttachmentSource.Poll)
val finalState = awaitItem()
assertThat(finalState.showAttachmentSourcePicker).isFalse()
}
}
@Test
fun `present - share location`() = runTest {
val room = FakeMatrixRoom()
val presenter = createPresenter(this, room = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
skipItems(1)
val initialState = awaitItem()
initialState.eventSink(MessageComposerEvents.AddAttachment)
val attachmentOpenState = awaitItem()
assertThat(attachmentOpenState.showAttachmentSourcePicker).isTrue()
initialState.eventSink(MessageComposerEvents.PickAttachmentSource.Location)
val finalState = awaitItem()
assertThat(finalState.showAttachmentSourcePicker).isFalse()
}
}
@Test
fun `present - Take photo`() = runTest {
val room = FakeMatrixRoom()
val permissionPresenter = FakePermissionsPresenter().apply { setPermissionGranted() }
val presenter = createPresenter(
this,
room = room,
permissionPresenter = permissionPresenter,
)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
}.test { }.test {
skipItems(1) skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera) initialState.eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera)
val previewingState = awaitItem() val finalState = awaitItem()
assertThat(previewingState.showAttachmentSourcePicker).isFalse() assertThat(finalState.attachmentsState).isInstanceOf(AttachmentsState.Previewing::class.java)
assertThat(previewingState.attachmentsState).isInstanceOf(AttachmentsState.Previewing::class.java) cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - Take photo with permission request`() = runTest {
val room = FakeMatrixRoom()
val permissionPresenter = FakePermissionsPresenter()
val presenter = createPresenter(
this,
room = room,
permissionPresenter = permissionPresenter,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
skipItems(1)
val initialState = awaitItem()
initialState.eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera)
val permissionState = awaitItem()
assertThat(permissionState.showAttachmentSourcePicker).isFalse()
assertThat(permissionState.attachmentsState).isInstanceOf(AttachmentsState.None::class.java)
permissionPresenter.setPermissionGranted()
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.attachmentsState).isInstanceOf(AttachmentsState.Previewing::class.java)
cancelAndIgnoreRemainingEvents() cancelAndIgnoreRemainingEvents()
} }
} }
@ -506,16 +576,47 @@ class MessageComposerPresenterTest {
@Test @Test
fun `present - Record video`() = runTest { fun `present - Record video`() = runTest {
val room = FakeMatrixRoom() val room = FakeMatrixRoom()
val presenter = createPresenter(this, room = room) val permissionPresenter = FakePermissionsPresenter().apply { setPermissionGranted() }
val presenter = createPresenter(
this,
room = room,
permissionPresenter = permissionPresenter,
)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
}.test { }.test {
skipItems(1) skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(MessageComposerEvents.PickAttachmentSource.VideoFromCamera) initialState.eventSink(MessageComposerEvents.PickAttachmentSource.VideoFromCamera)
val previewingState = awaitItem() val finalState = awaitItem()
assertThat(previewingState.showAttachmentSourcePicker).isFalse() assertThat(finalState.attachmentsState).isInstanceOf(AttachmentsState.Previewing::class.java)
assertThat(previewingState.attachmentsState).isInstanceOf(AttachmentsState.Previewing::class.java) cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - Record video with permission request`() = runTest {
val room = FakeMatrixRoom()
val permissionPresenter = FakePermissionsPresenter()
val presenter = createPresenter(
this,
room = room,
permissionPresenter = permissionPresenter,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
skipItems(1)
val initialState = awaitItem()
initialState.eventSink(MessageComposerEvents.PickAttachmentSource.VideoFromCamera)
val permissionState = awaitItem()
assertThat(permissionState.showAttachmentSourcePicker).isFalse()
assertThat(permissionState.attachmentsState).isInstanceOf(AttachmentsState.None::class.java)
permissionPresenter.setPermissionGranted()
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.attachmentsState).isInstanceOf(AttachmentsState.Previewing::class.java)
cancelAndIgnoreRemainingEvents()
} }
} }
@ -612,6 +713,7 @@ class MessageComposerPresenterTest {
featureFlagService: FeatureFlagService = this.featureFlagService, featureFlagService: FeatureFlagService = this.featureFlagService,
mediaPreProcessor: MediaPreProcessor = this.mediaPreProcessor, mediaPreProcessor: MediaPreProcessor = this.mediaPreProcessor,
snackbarDispatcher: SnackbarDispatcher = this.snackbarDispatcher, snackbarDispatcher: SnackbarDispatcher = this.snackbarDispatcher,
permissionPresenter: PermissionsPresenter = FakePermissionsPresenter(),
) = MessageComposerPresenter( ) = MessageComposerPresenter(
coroutineScope, coroutineScope,
room, room,
@ -623,6 +725,7 @@ class MessageComposerPresenterTest {
analyticsService, analyticsService,
MessageComposerContextImpl(), MessageComposerContextImpl(),
TestRichTextEditorStateFactory(), TestRichTextEditorStateFactory(),
permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionPresenter),
) )
} }

View file

@ -25,7 +25,6 @@ import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -38,24 +37,23 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.WifiOff
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.text.toDp
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -144,10 +142,10 @@ private fun Indicator(modifier: Modifier = Modifier) {
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
val tint = MaterialTheme.colorScheme.primary val tint = MaterialTheme.colorScheme.primary
Image( Icon(
imageVector = Icons.Outlined.WifiOff, resourceId = CommonDrawables.ic_compound_offline,
contentDescription = null, contentDescription = null,
colorFilter = ColorFilter.tint(tint), tint = tint,
modifier = Modifier.size(16.sp.toDp()), modifier = Modifier.size(16.sp.toDp()),
) )
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
@ -164,7 +162,7 @@ private fun StatusBarPaddingSpacer(modifier: Modifier = Modifier) {
Spacer(modifier = modifier.statusBarsPadding()) Spacer(modifier = modifier.statusBarsPadding())
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun ConnectivityIndicatorViewPreview() { internal fun ConnectivityIndicatorViewPreview() {
ElementPreview { ElementPreview {

View file

@ -25,7 +25,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.QrCode import androidx.compose.material.icons.filled.QrCode
import androidx.compose.material.icons.filled.Settings
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Alignment.Companion.CenterHorizontally
@ -40,7 +39,7 @@ import io.element.android.libraries.designsystem.atomic.atoms.ElementLogoAtom
import io.element.android.libraries.designsystem.atomic.atoms.ElementLogoAtomSize import io.element.android.libraries.designsystem.atomic.atoms.ElementLogoAtomSize
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
@ -48,6 +47,7 @@ import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.IconSource
import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.OutlinedButton
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@ -140,7 +140,7 @@ private fun OnBoardingContent(
onClick = onOpenDeveloperSettings, onClick = onOpenDeveloperSettings,
) { ) {
Icon( Icon(
imageVector = Icons.Filled.Settings, resourceId = CommonDrawables.ic_compound_settings_solid,
contentDescription = stringResource(CommonStrings.common_settings) contentDescription = stringResource(CommonStrings.common_settings)
) )
} }
@ -190,7 +190,7 @@ private fun OnBoardingButtons(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun OnBoardingScreenPreview( internal fun OnBoardingScreenPreview(
@PreviewParameter(OnBoardingStateProvider::class) state: OnBoardingState @PreviewParameter(OnBoardingStateProvider::class) state: OnBoardingState

View file

@ -33,7 +33,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator
@ -108,7 +108,7 @@ internal fun PollAnswerView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollAnswerDisclosedNotSelectedPreview() = ElementPreview { internal fun PollAnswerDisclosedNotSelectedPreview() = ElementPreview {
PollAnswerView( PollAnswerView(
@ -116,7 +116,7 @@ internal fun PollAnswerDisclosedNotSelectedPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollAnswerDisclosedSelectedPreview() = ElementPreview { internal fun PollAnswerDisclosedSelectedPreview() = ElementPreview {
PollAnswerView( PollAnswerView(
@ -124,7 +124,7 @@ internal fun PollAnswerDisclosedSelectedPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollAnswerUndisclosedNotSelectedPreview() = ElementPreview { internal fun PollAnswerUndisclosedNotSelectedPreview() = ElementPreview {
PollAnswerView( PollAnswerView(
@ -132,7 +132,7 @@ internal fun PollAnswerUndisclosedNotSelectedPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollAnswerUndisclosedSelectedPreview() = ElementPreview { internal fun PollAnswerUndisclosedSelectedPreview() = ElementPreview {
PollAnswerView( PollAnswerView(
@ -140,7 +140,7 @@ internal fun PollAnswerUndisclosedSelectedPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollAnswerEndedWinnerNotSelectedPreview() = ElementPreview { internal fun PollAnswerEndedWinnerNotSelectedPreview() = ElementPreview {
PollAnswerView( PollAnswerView(
@ -148,7 +148,7 @@ internal fun PollAnswerEndedWinnerNotSelectedPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollAnswerEndedWinnerSelectedPreview() = ElementPreview { internal fun PollAnswerEndedWinnerSelectedPreview() = ElementPreview {
PollAnswerView( PollAnswerView(
@ -156,7 +156,7 @@ internal fun PollAnswerEndedWinnerSelectedPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollAnswerEndedSelectedPreview() = ElementPreview { internal fun PollAnswerEndedSelectedPreview() = ElementPreview {
PollAnswerView( PollAnswerView(

View file

@ -32,11 +32,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.VectorIcons import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.DayNightPreviews
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.poll.PollAnswer import io.element.android.libraries.matrix.api.poll.PollAnswer
import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.poll.PollKind
@ -87,13 +87,13 @@ private fun PollTitle(
) { ) {
if (isPollEnded) { if (isPollEnded) {
Icon( Icon(
resourceId = VectorIcons.PollEnd, resourceId = CommonDrawables.ic_poll_end,
contentDescription = stringResource(id = CommonStrings.a11y_poll_end), contentDescription = stringResource(id = CommonStrings.a11y_poll_end),
modifier = Modifier.size(22.dp) modifier = Modifier.size(22.dp)
) )
} else { } else {
Icon( Icon(
resourceId = VectorIcons.Poll, resourceId = CommonDrawables.ic_compound_polls,
contentDescription = stringResource(id = CommonStrings.a11y_poll), contentDescription = stringResource(id = CommonStrings.a11y_poll),
modifier = Modifier.size(22.dp) modifier = Modifier.size(22.dp)
) )
@ -157,7 +157,7 @@ private fun ColumnScope.UndisclosedPollBottomNotice(
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollContentUndisclosedPreview() = ElementPreview { internal fun PollContentUndisclosedPreview() = ElementPreview {
PollContentView( PollContentView(
@ -170,7 +170,7 @@ internal fun PollContentUndisclosedPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollContentDisclosedPreview() = ElementPreview { internal fun PollContentDisclosedPreview() = ElementPreview {
PollContentView( PollContentView(
@ -183,7 +183,7 @@ internal fun PollContentDisclosedPreview() = ElementPreview {
) )
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun PollContentEndedPreview() = ElementPreview { internal fun PollContentEndedPreview() = ElementPreview {
PollContentView( PollContentView(

View file

@ -44,11 +44,10 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.poll.impl.R import io.element.android.features.poll.impl.R
import io.element.android.libraries.designsystem.VectorIcons
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.list.ListItemContent
import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
@ -61,6 +60,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -165,7 +165,7 @@ fun CreatePollView(
}, },
trailingContent = ListItemContent.Custom { trailingContent = ListItemContent.Custom {
Icon( Icon(
resourceId = VectorIcons.Delete, resourceId = CommonDrawables.ic_compound_delete,
contentDescription = null, contentDescription = null,
modifier = Modifier.clickable(answer.canDelete) { modifier = Modifier.clickable(answer.canDelete) {
state.eventSink(CreatePollEvents.RemoveAnswer(index)) state.eventSink(CreatePollEvents.RemoveAnswer(index))
@ -210,7 +210,7 @@ fun CreatePollView(
} }
} }
@DayNightPreviews @PreviewsDayNight
@Composable @Composable
internal fun CreatePollViewPreview( internal fun CreatePollViewPreview(
@PreviewParameter(CreatePollStateProvider::class) state: CreatePollState @PreviewParameter(CreatePollStateProvider::class) state: CreatePollState

View file

@ -4,6 +4,8 @@
<string name="screen_create_poll_anonymous_desc">"Показывать результаты только после окончания опроса"</string> <string name="screen_create_poll_anonymous_desc">"Показывать результаты только после окончания опроса"</string>
<string name="screen_create_poll_anonymous_headline">"Анонимный опрос"</string> <string name="screen_create_poll_anonymous_headline">"Анонимный опрос"</string>
<string name="screen_create_poll_answer_hint">"Настройка %1$d"</string> <string name="screen_create_poll_answer_hint">"Настройка %1$d"</string>
<string name="screen_create_poll_discard_confirmation">"Вы действительно хотите отменить этот опрос?"</string>
<string name="screen_create_poll_discard_confirmation_title">"Отменить опрос"</string>
<string name="screen_create_poll_question_desc">"Вопрос или тема"</string> <string name="screen_create_poll_question_desc">"Вопрос или тема"</string>
<string name="screen_create_poll_question_hint">"Тема опроса?"</string> <string name="screen_create_poll_question_hint">"Тема опроса?"</string>
<string name="screen_create_poll_title">"Создать опрос"</string> <string name="screen_create_poll_title">"Создать опрос"</string>

View file

@ -47,6 +47,7 @@ dependencies {
implementation(projects.libraries.matrixui) implementation(projects.libraries.matrixui)
implementation(projects.libraries.mediapickers.api) implementation(projects.libraries.mediapickers.api)
implementation(projects.libraries.mediaupload.api) implementation(projects.libraries.mediaupload.api)
implementation(projects.libraries.permissions.api)
implementation(projects.features.rageshake.api) implementation(projects.features.rageshake.api)
implementation(projects.features.analytics.api) implementation(projects.features.analytics.api)
implementation(projects.features.ftue.api) implementation(projects.features.ftue.api)
@ -71,6 +72,7 @@ dependencies {
testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.featureflag.test)
testImplementation(projects.libraries.mediapickers.test) testImplementation(projects.libraries.mediapickers.test)
testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.mediaupload.test)
testImplementation(projects.libraries.permissions.test)
testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.preferences.test)
testImplementation(projects.libraries.pushstore.test) testImplementation(projects.libraries.pushstore.test)
testImplementation(projects.features.rageshake.test) testImplementation(projects.features.rageshake.test)

Some files were not shown because too many files have changed in this diff Show more