Konsist: add test to ensure filename match top level Composable View, and fix existing issue
This commit is contained in:
parent
6e5caebc60
commit
8929a90970
103 changed files with 1137 additions and 760 deletions
|
|
@ -34,7 +34,7 @@ import com.bumble.appyx.core.integrationpoint.NodeComponentActivity
|
|||
import com.bumble.appyx.core.plugin.NodeReadyObserver
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.designsystem.utils.LocalSnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import io.element.android.x.di.AppBindings
|
||||
import io.element.android.x.intent.SafeUriHandler
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package io.element.android.x.di
|
|||
|
||||
import com.squareup.anvil.annotations.ContributesTo
|
||||
import io.element.android.features.rageshake.api.reporter.BugReporter
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.tracing.TracingService
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import io.element.android.features.messages.impl.timeline.components.customreact
|
|||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.DefaultPreferences
|
||||
|
|
|
|||
|
|
@ -16,9 +16,15 @@
|
|||
|
||||
package io.element.android.app
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.lemonappdev.konsist.api.KoModifier
|
||||
import com.lemonappdev.konsist.api.Konsist
|
||||
import com.lemonappdev.konsist.api.ext.list.modifierprovider.withoutModifier
|
||||
import com.lemonappdev.konsist.api.ext.list.withAllAnnotationsOf
|
||||
import com.lemonappdev.konsist.api.ext.list.withAllParentsOf
|
||||
import com.lemonappdev.konsist.api.ext.list.withTopLevel
|
||||
import com.lemonappdev.konsist.api.ext.list.withoutName
|
||||
import com.lemonappdev.konsist.api.ext.list.withoutNameEndingWith
|
||||
import com.lemonappdev.konsist.api.verify.assertTrue
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
|
|
@ -46,4 +52,36 @@ class KonsistTest {
|
|||
it.hasNameEndingWith("DarkPreview").not()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `top level function with '@Composable' annotation starting with a upper case should be placed in a file with the same name`() {
|
||||
Konsist
|
||||
.scopeFromProject()
|
||||
.functions()
|
||||
.withTopLevel()
|
||||
.withoutModifier(KoModifier.PRIVATE)
|
||||
.withoutNameEndingWith("Preview")
|
||||
.withAllAnnotationsOf(Composable::class)
|
||||
.withoutName(
|
||||
// Add some exceptions...
|
||||
"OutlinedButton",
|
||||
"TextButton",
|
||||
"SimpleAlertDialogContent",
|
||||
)
|
||||
.assertTrue(
|
||||
additionalMessage =
|
||||
"""
|
||||
Please check the filename. It should match the top level Composable function. If the filename is correct:
|
||||
- consider making the Composable private or moving it to its own file
|
||||
- at last resort, you can add an exception in the Konsist test
|
||||
""".trimIndent()
|
||||
) {
|
||||
if (it.name.first().isLowerCase()) {
|
||||
true
|
||||
} else {
|
||||
val fileName = it.containingFile.name.removeSuffix(".kt")
|
||||
fileName == it.name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
package io.element.android.appnav
|
||||
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ import io.element.android.libraries.architecture.animation.rememberDefaultTransi
|
|||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.architecture.waitForChildAttached
|
||||
import io.element.android.libraries.deeplink.DeeplinkData
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.MAIN_SPACE
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ fun AddPeopleView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AddPeopleViewTopBar(
|
||||
private fun AddPeopleViewTopBar(
|
||||
hasSelectedUsers: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ fun ConfigureRoomView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ConfigureRoomToolbar(
|
||||
private fun ConfigureRoomToolbar(
|
||||
isNextActionEnabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
|
|
@ -207,7 +207,7 @@ fun ConfigureRoomToolbar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RoomNameWithAvatar(
|
||||
private fun RoomNameWithAvatar(
|
||||
avatarUri: Uri?,
|
||||
roomName: String,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -235,7 +235,7 @@ fun RoomNameWithAvatar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RoomTopic(
|
||||
private fun RoomTopic(
|
||||
topic: String,
|
||||
modifier: Modifier = Modifier,
|
||||
onTopicChanged: (String) -> Unit = {},
|
||||
|
|
@ -254,7 +254,7 @@ fun RoomTopic(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RoomPrivacyOptions(
|
||||
private fun RoomPrivacyOptions(
|
||||
selected: RoomPrivacy?,
|
||||
modifier: Modifier = Modifier,
|
||||
onOptionSelected: (RoomPrivacyItem) -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ fun CreateRoomRootView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CreateRoomRootViewTopBar(
|
||||
private fun CreateRoomRootViewTopBar(
|
||||
modifier: Modifier = Modifier,
|
||||
onClosePressed: () -> Unit = {},
|
||||
) {
|
||||
|
|
@ -148,7 +148,7 @@ fun CreateRoomRootViewTopBar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun CreateRoomActionButtonsList(
|
||||
private fun CreateRoomActionButtonsList(
|
||||
state: CreateRoomRootState,
|
||||
modifier: Modifier = Modifier,
|
||||
onNewRoomClicked: () -> Unit = {},
|
||||
|
|
@ -169,7 +169,7 @@ fun CreateRoomActionButtonsList(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun CreateRoomActionButton(
|
||||
private fun CreateRoomActionButton(
|
||||
@DrawableRes iconRes: Int,
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ fun InviteListView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun InviteListContent(
|
||||
private fun InviteListContent(
|
||||
state: InviteListState,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackClicked: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ internal fun InviteSummaryRow(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun DefaultInviteSummaryRow(
|
||||
private fun DefaultInviteSummaryRow(
|
||||
invite: InviteListInviteSummary,
|
||||
onAcceptClicked: () -> Unit = {},
|
||||
onDeclineClicked: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ fun LoginPasswordView(
|
|||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
internal fun LoginForm(
|
||||
private fun LoginForm(
|
||||
state: LoginPasswordState,
|
||||
isLoading: Boolean,
|
||||
onSubmit: () -> Unit,
|
||||
|
|
@ -272,7 +272,7 @@ internal fun LoginForm(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) {
|
||||
private fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) {
|
||||
ErrorDialog(
|
||||
title = stringResource(id = CommonStrings.dialog_title_error),
|
||||
content = stringResource(loginError(error)),
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ fun LogoutPreferenceView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun LogoutPreferenceContent(
|
||||
private fun LogoutPreferenceContent(
|
||||
onClick: () -> Unit = {},
|
||||
) {
|
||||
PreferenceText(
|
||||
|
|
@ -64,9 +64,9 @@ import io.element.android.libraries.architecture.Presenter
|
|||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum
|
|||
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ 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.TopAppBar
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ private fun MessageSummary(event: TimelineItem.Event, modifier: Modifier = Modif
|
|||
private val emojiRippleRadius = 24.dp
|
||||
|
||||
@Composable
|
||||
internal fun EmojiReactionsRow(
|
||||
private fun EmojiReactionsRow(
|
||||
highlightedEmojis: ImmutableList<String>,
|
||||
onEmojiReactionClicked: (String) -> Unit,
|
||||
onCustomReactionClicked: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ fun ForwardMessagesView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun SelectedRooms(
|
||||
private fun SelectedRooms(
|
||||
selectedRooms: ImmutableList<RoomSummaryDetails>,
|
||||
onRoomRemoved: (RoomSummaryDetails) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -221,7 +221,7 @@ internal fun SelectedRooms(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun RoomSummaryView(
|
||||
private fun RoomSummaryView(
|
||||
summary: RoomSummaryDetails,
|
||||
isSelected: Boolean,
|
||||
onSelection: (RoomSummaryDetails) -> Unit,
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ private fun MediaImageView(
|
|||
|
||||
@UnstableApi
|
||||
@Composable
|
||||
fun MediaVideoView(
|
||||
private fun MediaVideoView(
|
||||
localMediaViewState: LocalMediaViewState,
|
||||
localMedia: LocalMedia?,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -196,7 +196,7 @@ fun MediaVideoView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun MediaPDFView(
|
||||
private fun MediaPDFView(
|
||||
localMediaViewState: LocalMediaViewState,
|
||||
localMedia: LocalMedia?,
|
||||
zoomableState: ZoomableState,
|
||||
|
|
@ -211,7 +211,7 @@ fun MediaPDFView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun MediaFileView(
|
||||
private fun MediaFileView(
|
||||
localMediaViewState: LocalMediaViewState,
|
||||
uri: Uri?,
|
||||
info: MediaInfo?,
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ import io.element.android.features.messages.impl.media.local.LocalMediaActions
|
|||
import io.element.android.features.messages.impl.media.local.LocalMediaFactory
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
|
||||
import io.element.android.libraries.matrix.api.media.MediaFile
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package io.element.android.features.messages.impl.media.viewer
|
|||
import io.element.android.features.messages.impl.media.local.LocalMedia
|
||||
import io.element.android.features.messages.impl.media.local.MediaInfo
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||
|
||||
data class MediaViewerState(
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ 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.TopAppBar
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
|
||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||
import io.element.android.libraries.matrix.ui.media.MediaRequestData
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ internal fun AttachmentsBottomSheet(
|
|||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
internal fun AttachmentSourcePickerMenu(
|
||||
private fun AttachmentSourcePickerMenu(
|
||||
state: MessageComposerState,
|
||||
onSendLocationClicked: () -> Unit,
|
||||
onCreatePollClicked: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ import io.element.android.features.messages.impl.attachments.Attachment
|
|||
import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError
|
||||
import io.element.android.features.messages.impl.media.local.LocalMediaFactory
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ import dagger.assisted.AssistedInject
|
|||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runUpdatingState
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
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.room.MatrixRoom
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ fun TimelineView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun TimelineItemRow(
|
||||
private fun TimelineItemRow(
|
||||
timelineItem: TimelineItem,
|
||||
highlightedItem: String?,
|
||||
userHasPermissionToSendMessage: Boolean,
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ fun TimelineItemEventRow(
|
|||
* @param content the content to display.
|
||||
*/
|
||||
@Composable
|
||||
fun SwipeSensitivity(
|
||||
private fun SwipeSensitivity(
|
||||
sensitivityFactor: Float,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
|
|
@ -306,7 +306,7 @@ private fun TimelineItemEventRowContent(
|
|||
|
||||
// Reactions
|
||||
if (event.reactionsState.reactions.isNotEmpty()) {
|
||||
TimelineItemReactions(
|
||||
TimelineItemReactionsView(
|
||||
reactionsState = event.reactionsState,
|
||||
isOutgoing = event.isMine,
|
||||
onReactionClicked = onReactionClicked,
|
||||
|
|
@ -315,7 +315,7 @@ private fun TimelineItemEventRowContent(
|
|||
modifier = Modifier
|
||||
.constrainAs(reactions) {
|
||||
top.linkTo(message.bottom, margin = (-4).dp)
|
||||
this.linkStartOrEnd(event)
|
||||
linkStartOrEnd(event)
|
||||
}
|
||||
.zIndex(1f)
|
||||
.padding(start = if (event.isMine) 16.dp else 36.dp, end = 16.dp)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import io.element.android.libraries.designsystem.utils.CommonDrawables
|
|||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
fun TimelineItemReactions(
|
||||
fun TimelineItemReactionsView(
|
||||
reactionsState: TimelineItemReactions,
|
||||
isOutgoing: Boolean,
|
||||
onReactionClicked: (emoji: String) -> Unit,
|
||||
|
|
@ -46,16 +46,16 @@ fun TimelineItemReactions(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var expanded: Boolean by rememberSaveable { mutableStateOf(false) }
|
||||
TimelineItemReactionsView(
|
||||
modifier = modifier,
|
||||
reactions = reactionsState.reactions,
|
||||
expanded = expanded,
|
||||
isOutgoing = isOutgoing,
|
||||
onReactionClick = onReactionClicked,
|
||||
onReactionLongClick = onReactionLongClicked,
|
||||
onMoreReactionsClick = onMoreReactionsClicked,
|
||||
onToggleExpandClick = { expanded = !expanded },
|
||||
)
|
||||
TimelineItemReactionsView(
|
||||
modifier = modifier,
|
||||
reactions = reactionsState.reactions,
|
||||
expanded = expanded,
|
||||
isOutgoing = isOutgoing,
|
||||
onReactionClick = onReactionClicked,
|
||||
onReactionLongClick = onReactionLongClicked,
|
||||
onMoreReactionsClick = onMoreReactionsClicked,
|
||||
onToggleExpandClick = { expanded = !expanded },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -153,7 +153,7 @@ private fun ContentToPreview(
|
|||
reactions: ImmutableList<AggregatedReaction>,
|
||||
isOutgoing: Boolean = false
|
||||
) {
|
||||
TimelineItemReactions(
|
||||
TimelineItemReactionsView(
|
||||
reactionsState = TimelineItemReactions(
|
||||
reactions
|
||||
),
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ private fun SheetContent(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun AggregatedReactionButton(
|
||||
private fun AggregatedReactionButton(
|
||||
reaction: AggregatedReaction,
|
||||
isHighlighted: Boolean,
|
||||
onClick: () -> Unit,
|
||||
|
|
@ -215,7 +215,7 @@ fun AggregatedReactionButton(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun SenderRow(
|
||||
private fun SenderRow(
|
||||
avatarData: AvatarData,
|
||||
name: String,
|
||||
userId: String,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ internal fun RetrySendMessageMenu(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
internal fun RetrySendMessageMenuBottomSheet(
|
||||
private fun RetrySendMessageMenuBottomSheet(
|
||||
isVisible: Boolean,
|
||||
onRetry: () -> Unit,
|
||||
onRemoveFailed: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
|||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.featureflag.test.InMemoryPreferencesStore
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import io.element.android.features.messages.impl.media.viewer.MediaViewerPresent
|
|||
import io.element.android.features.messages.media.FakeLocalMediaActions
|
||||
import io.element.android.features.messages.media.FakeLocalMediaFactory
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.matrix.test.media.FakeMediaLoader
|
||||
import io.element.android.libraries.matrix.test.media.aMediaSource
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import com.google.common.truth.Truth.assertThat
|
|||
import io.element.android.features.messages.impl.report.ReportMessageEvents
|
||||
import io.element.android.features.messages.impl.report.ReportMessagePresenter
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer
|
|||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
|
||||
import io.element.android.features.messages.media.FakeLocalMediaFactory
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.networkmonitor.api.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.MutableTransitionState
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* A view that displays a connectivity indicator when the device is offline, passing the padding
|
||||
* needed to make sure the status bar is not overlapped to its content views.
|
||||
*/
|
||||
@Composable
|
||||
fun ConnectivityIndicatorContainer(
|
||||
isOnline: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable (topPadding: Dp) -> Unit = {},
|
||||
) {
|
||||
val isIndicatorVisible = remember { MutableTransitionState(!isOnline) }.apply { targetState = !isOnline }
|
||||
|
||||
val statusBarTopPadding = if (LocalInspectionMode.current) {
|
||||
// Needed to get valid UI previews
|
||||
24.dp
|
||||
} else {
|
||||
WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 6.dp
|
||||
}
|
||||
val target = remember(isIndicatorVisible.targetState, statusBarTopPadding) {
|
||||
if (!isIndicatorVisible.targetState) 0.dp else statusBarTopPadding
|
||||
}
|
||||
val animationStateOffset by animateDpAsState(
|
||||
targetValue = target,
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessMediumLow,
|
||||
visibilityThreshold = 1.dp,
|
||||
),
|
||||
label = "insets-animation",
|
||||
)
|
||||
|
||||
content(animationStateOffset)
|
||||
|
||||
// Display the network indicator with an animation
|
||||
AnimatedVisibility(
|
||||
visibleState = isIndicatorVisible,
|
||||
enter = fadeIn() + expandVertically(),
|
||||
exit = fadeOut() + shrinkVertically(),
|
||||
) {
|
||||
Indicator(modifier)
|
||||
}
|
||||
}
|
||||
|
|
@ -18,44 +18,17 @@ package io.element.android.features.networkmonitor.api.ui
|
|||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.MutableTransitionState
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
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.utils.CommonDrawables
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
/**
|
||||
* A view that displays a connectivity indicator when the device is offline, adding a default
|
||||
|
|
@ -88,75 +61,6 @@ fun ConnectivityIndicatorView(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A view that displays a connectivity indicator when the device is offline, passing the padding
|
||||
* needed to make sure the status bar is not overlapped to its content views.
|
||||
*/
|
||||
@Composable
|
||||
fun ConnectivityIndicatorContainer(
|
||||
isOnline: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable (topPadding: Dp) -> Unit,
|
||||
) {
|
||||
val isIndicatorVisible = remember { MutableTransitionState(!isOnline) }.apply { targetState = !isOnline }
|
||||
|
||||
val statusBarTopPadding = if (LocalInspectionMode.current) {
|
||||
// Needed to get valid UI previews
|
||||
24.dp
|
||||
} else {
|
||||
WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 6.dp
|
||||
}
|
||||
val target = remember(isIndicatorVisible.targetState, statusBarTopPadding) {
|
||||
if (!isIndicatorVisible.targetState) 0.dp else statusBarTopPadding
|
||||
}
|
||||
val animationStateOffset by animateDpAsState(
|
||||
targetValue = target,
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessMediumLow,
|
||||
visibilityThreshold = 1.dp,
|
||||
),
|
||||
label = "insets-animation",
|
||||
)
|
||||
|
||||
content(animationStateOffset)
|
||||
|
||||
// Display the network indicator with an animation
|
||||
AnimatedVisibility(
|
||||
visibleState = isIndicatorVisible,
|
||||
enter = fadeIn() + expandVertically(),
|
||||
exit = fadeOut() + shrinkVertically(),
|
||||
) {
|
||||
Indicator(modifier)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Indicator(modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.background(MaterialTheme.colorScheme.secondaryContainer)
|
||||
.statusBarsPadding()
|
||||
.padding(vertical = 6.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
val tint = MaterialTheme.colorScheme.primary
|
||||
Icon(
|
||||
resourceId = CommonDrawables.ic_compound_offline,
|
||||
contentDescription = null,
|
||||
tint = tint,
|
||||
modifier = Modifier.size(16.sp.toDp()),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = stringResource(CommonStrings.common_offline),
|
||||
style = ElementTheme.typography.fontBodyMdMedium,
|
||||
color = tint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun StatusBarPaddingSpacer(modifier: Modifier = Modifier) {
|
||||
Spacer(modifier = modifier.statusBarsPadding())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.networkmonitor.api.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
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.utils.CommonDrawables
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
internal fun Indicator(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.background(MaterialTheme.colorScheme.secondaryContainer)
|
||||
.statusBarsPadding()
|
||||
.padding(vertical = 6.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
val tint = MaterialTheme.colorScheme.primary
|
||||
Icon(
|
||||
resourceId = CommonDrawables.ic_compound_offline,
|
||||
contentDescription = null,
|
||||
tint = tint,
|
||||
modifier = Modifier.size(16.sp.toDp()),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = stringResource(CommonStrings.common_offline),
|
||||
style = ElementTheme.typography.fontBodyMdMedium,
|
||||
color = tint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -33,7 +33,7 @@ fun AboutView(
|
|||
onBackPressed: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_about)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.features.preferences.impl.R
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -33,7 +33,7 @@ fun AdvancedSettingsView(
|
|||
onBackPressed: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_advanced_settings)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -32,7 +32,7 @@ fun AnalyticsSettingsView(
|
|||
onBackPressed: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_analytics)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.featureflag.ui.FeatureListView
|
||||
|
|
@ -38,7 +38,7 @@ fun DeveloperSettingsView(
|
|||
onBackPressed: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_developer_options)
|
||||
|
|
@ -85,7 +85,7 @@ fun DeveloperSettingsView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun FeatureListContent(
|
||||
private fun FeatureListContent(
|
||||
state: DeveloperSettingsState,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ fun ConfigureTracingView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun CrateListContent(
|
||||
private fun CrateListContent(
|
||||
state: ConfigureTracingState,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
|
|
@ -178,7 +178,7 @@ private fun TargetAndLogLevelListView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun TargetAndLogLevelView(
|
||||
private fun TargetAndLogLevelView(
|
||||
target: Target,
|
||||
logLevel: LogLevel,
|
||||
onLogLevelChange: (LogLevel) -> Unit,
|
||||
|
|
@ -197,7 +197,7 @@ fun TargetAndLogLevelView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun LogLevelDropdownMenu(
|
||||
private fun LogLevelDropdownMenu(
|
||||
logLevel: LogLevel,
|
||||
onLogLevelChange: (LogLevel) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
|||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
|
|
@ -67,7 +67,7 @@ fun NotificationSettingsView(
|
|||
else -> Unit
|
||||
}
|
||||
}
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.screen_notification_settings_title)
|
||||
|
|
@ -79,7 +79,7 @@ fun NotificationSettingsView(
|
|||
onContinueClicked = { state.eventSink(NotificationSettingsEvents.FixConfigurationMismatch) },
|
||||
onDismissError = { state.eventSink(NotificationSettingsEvents.ClearConfigurationMismatchError) },
|
||||
)
|
||||
NotificationSettingsState.MatrixSettings.Uninitialized -> return@PreferenceView
|
||||
NotificationSettingsState.MatrixSettings.Uninitialized -> return@PreferencePage
|
||||
is NotificationSettingsState.MatrixSettings.Valid -> NotificationSettingsContentView(
|
||||
matrixSettings = state.matrixSettings,
|
||||
systemSettings = state.appSettings,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ fun EditDefaultNotificationSettingView(
|
|||
} else {
|
||||
CommonStrings.screen_notification_settings_group_chats
|
||||
}
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = title)
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||
import io.element.android.features.logout.api.LogoutPreferencePresenter
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package io.element.android.features.preferences.impl.root
|
||||
|
||||
import io.element.android.features.logout.api.LogoutPreferenceState
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
|
||||
data class PreferencesRootState(
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package io.element.android.features.preferences.impl.root
|
||||
|
||||
import io.element.android.features.logout.api.aLogoutPreferenceState
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
fun aPreferencesRootState() = PreferencesRootState(
|
||||
|
|
|
|||
|
|
@ -31,15 +31,15 @@ import androidx.compose.ui.unit.dp
|
|||
import io.element.android.features.logout.api.LogoutPreferenceView
|
||||
import io.element.android.features.preferences.impl.user.UserPreferences
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight
|
||||
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.components.MatrixUserProvider
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
|
@ -64,7 +64,7 @@ fun PreferencesRootView(
|
|||
val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage)
|
||||
|
||||
// Include pref from other modules
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
modifier = modifier,
|
||||
onBackPressed = onBackPressed,
|
||||
title = stringResource(id = CommonStrings.common_settings),
|
||||
|
|
@ -151,7 +151,7 @@ fun PreferencesRootView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) {
|
||||
private fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) {
|
||||
PreferenceText(
|
||||
title = stringResource(id = CommonStrings.common_developer_options),
|
||||
iconResourceId = CommonDrawables.ic_developer_mode,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import com.google.common.truth.Truth.assertThat
|
|||
import io.element.android.features.logout.impl.DefaultLogoutPreferencePresenter
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ fun CrashDetectionView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun CrashDetectionContent(
|
||||
private fun CrashDetectionContent(
|
||||
onNoClicked: () -> Unit = { },
|
||||
onYesClicked: () -> Unit = { },
|
||||
onDismiss: () -> Unit = { },
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ private fun TakeScreenshot(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RageshakeDialogContent(
|
||||
private fun RageshakeDialogContent(
|
||||
onNoClicked: () -> Unit = { },
|
||||
onDisableClicked: () -> Unit = { },
|
||||
onYesClicked: () -> Unit = { },
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ 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.preferences.PreferenceRow
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground
|
||||
|
|
@ -72,7 +72,7 @@ fun BugReportView(
|
|||
}
|
||||
|
||||
Box(modifier = modifier) {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
title = stringResource(id = CommonStrings.common_report_a_bug),
|
||||
onBackPressed = onBackPressed
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ fun RoomDetailsView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
internal fun RoomDetailsTopBar(
|
||||
private fun RoomDetailsTopBar(
|
||||
goBack: () -> Unit,
|
||||
onActionClicked: (RoomDetailsAction) -> Unit,
|
||||
showEdit: Boolean,
|
||||
|
|
@ -220,7 +220,7 @@ internal fun RoomDetailsTopBar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit, modifier: Modifier = Modifier) {
|
||||
private fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
|
||||
val roomNotificationSettings = state.roomNotificationSettings
|
||||
if (state.canShowNotificationSettings && roomNotificationSettings != null) {
|
||||
|
|
@ -252,7 +252,7 @@ internal fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun RoomHeaderSection(
|
||||
private fun RoomHeaderSection(
|
||||
avatarUrl: String?,
|
||||
roomId: String,
|
||||
roomName: String,
|
||||
|
|
@ -289,7 +289,7 @@ internal fun RoomHeaderSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun TopicSection(
|
||||
private fun TopicSection(
|
||||
roomTopic: RoomTopicState,
|
||||
onActionClicked: (RoomDetailsAction) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
|
|
@ -315,7 +315,7 @@ internal fun TopicSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun NotificationSection(
|
||||
private fun NotificationSection(
|
||||
isDefaultMode: Boolean,
|
||||
openRoomNotificationSettings: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
|
|
@ -336,7 +336,7 @@ internal fun NotificationSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun MembersSection(
|
||||
private fun MembersSection(
|
||||
memberCount: Long,
|
||||
openRoomMemberList: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -352,7 +352,7 @@ internal fun MembersSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun InviteSection(
|
||||
private fun InviteSection(
|
||||
invitePeople: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -366,7 +366,7 @@ internal fun InviteSection(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun SecuritySection(modifier: Modifier = Modifier) {
|
||||
private fun SecuritySection(modifier: Modifier = Modifier) {
|
||||
PreferenceCategory(title = stringResource(R.string.screen_room_details_security_title), modifier = modifier) {
|
||||
PreferenceText(
|
||||
title = stringResource(R.string.screen_room_details_encryption_enabled_title),
|
||||
|
|
@ -377,7 +377,7 @@ internal fun SecuritySection(modifier: Modifier = Modifier) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun OtherActionsSection(onLeaveRoom: () -> Unit, modifier: Modifier = Modifier) {
|
||||
private fun OtherActionsSection(onLeaveRoom: () -> Unit, modifier: Modifier = Modifier) {
|
||||
PreferenceCategory(showDivider = false, modifier = modifier) {
|
||||
PreferenceText(
|
||||
title = stringResource(R.string.screen_room_details_leave_room_title),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.roomdetails.impl.blockuser
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.features.roomdetails.impl.R
|
||||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsEvents
|
||||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
|
||||
@Composable
|
||||
fun BlockUserDialogs(state: RoomMemberDetailsState) {
|
||||
when (state.displayConfirmationDialog) {
|
||||
null -> Unit
|
||||
RoomMemberDetailsState.ConfirmationDialog.Block -> {
|
||||
BlockConfirmationDialog(
|
||||
onBlockAction = {
|
||||
state.eventSink(
|
||||
RoomMemberDetailsEvents.BlockUser(
|
||||
needsConfirmation = false
|
||||
)
|
||||
)
|
||||
},
|
||||
onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) }
|
||||
)
|
||||
}
|
||||
RoomMemberDetailsState.ConfirmationDialog.Unblock -> {
|
||||
UnblockConfirmationDialog(
|
||||
onUnblockAction = {
|
||||
state.eventSink(
|
||||
RoomMemberDetailsEvents.UnblockUser(
|
||||
needsConfirmation = false
|
||||
)
|
||||
)
|
||||
},
|
||||
onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BlockConfirmationDialog(onBlockAction: () -> Unit, onDismiss: () -> Unit) {
|
||||
ConfirmationDialog(
|
||||
title = stringResource(R.string.screen_dm_details_block_user),
|
||||
content = stringResource(R.string.screen_dm_details_block_alert_description),
|
||||
submitText = stringResource(R.string.screen_dm_details_block_alert_action),
|
||||
onSubmitClicked = onBlockAction,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UnblockConfirmationDialog(onUnblockAction: () -> Unit, onDismiss: () -> Unit) {
|
||||
ConfirmationDialog(
|
||||
title = stringResource(R.string.screen_dm_details_unblock_user),
|
||||
content = stringResource(R.string.screen_dm_details_unblock_alert_description),
|
||||
submitText = stringResource(R.string.screen_dm_details_unblock_alert_action),
|
||||
onSubmitClicked = onUnblockAction,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
|
@ -27,7 +27,6 @@ import io.element.android.features.roomdetails.impl.members.details.RoomMemberDe
|
|||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
|
|
@ -85,44 +84,3 @@ private fun PreferenceBlockUser(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun BlockUserDialogs(state: RoomMemberDetailsState) {
|
||||
when (state.displayConfirmationDialog) {
|
||||
null -> Unit
|
||||
RoomMemberDetailsState.ConfirmationDialog.Block -> {
|
||||
BlockConfirmationDialog(
|
||||
onBlockAction = { state.eventSink(RoomMemberDetailsEvents.BlockUser(needsConfirmation = false)) },
|
||||
onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) }
|
||||
)
|
||||
}
|
||||
RoomMemberDetailsState.ConfirmationDialog.Unblock -> {
|
||||
UnblockConfirmationDialog(
|
||||
onUnblockAction = { state.eventSink(RoomMemberDetailsEvents.UnblockUser(needsConfirmation = false)) },
|
||||
onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun BlockConfirmationDialog(onBlockAction: () -> Unit, onDismiss: () -> Unit) {
|
||||
ConfirmationDialog(
|
||||
title = stringResource(R.string.screen_dm_details_block_user),
|
||||
content = stringResource(R.string.screen_dm_details_block_alert_description),
|
||||
submitText = stringResource(R.string.screen_dm_details_block_alert_action),
|
||||
onSubmitClicked = onBlockAction,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun UnblockConfirmationDialog(onUnblockAction: () -> Unit, onDismiss: () -> Unit) {
|
||||
ConfirmationDialog(
|
||||
title = stringResource(R.string.screen_dm_details_unblock_user),
|
||||
content = stringResource(R.string.screen_dm_details_unblock_alert_description),
|
||||
submitText = stringResource(R.string.screen_dm_details_unblock_alert_action),
|
||||
onSubmitClicked = onUnblockAction,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ fun RoomInviteMembersView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RoomInviteMembersTopBar(
|
||||
private fun RoomInviteMembersTopBar(
|
||||
canSend: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -16,49 +16,27 @@
|
|||
|
||||
package io.element.android.features.roomdetails.impl.members.details
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.ChatBubbleOutline
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.features.roomdetails.impl.blockuser.BlockUserDialogs
|
||||
import io.element.android.features.roomdetails.impl.blockuser.BlockUserSection
|
||||
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.AvatarSize
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.button.MainActionButton
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight
|
||||
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.TopAppBar
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
|
|
@ -103,51 +81,9 @@ fun RoomMemberDetailsView(
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@Composable
|
||||
internal fun RoomMemberHeaderSection(
|
||||
avatarUrl: String?,
|
||||
userId: String,
|
||||
userName: String?,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Column(modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Box(modifier = Modifier.size(70.dp)) {
|
||||
Avatar(
|
||||
avatarData = AvatarData(userId, userName, avatarUrl, AvatarSize.UserHeader),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
if (userName != null) {
|
||||
Text(text = userName, style = ElementTheme.typography.fontHeadingLgBold)
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
}
|
||||
Text(
|
||||
text = userId,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Spacer(Modifier.height(40.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun RoomMemberMainActionsSection(onShareUser: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
|
||||
MainActionButton(
|
||||
title = stringResource(CommonStrings.action_share),
|
||||
iconResourceId = CommonDrawables.ic_compound_share_android,
|
||||
onClick = onShareUser
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier = Modifier) {
|
||||
private fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier = Modifier) {
|
||||
PreferenceCategory(modifier = modifier) {
|
||||
PreferenceText(
|
||||
title = stringResource(CommonStrings.action_send_message),
|
||||
|
|
@ -156,6 +92,7 @@ internal fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier =
|
|||
)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@PreviewWithLargeHeight
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.roomdetails.impl.members.details
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.AvatarSize
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
||||
@Composable
|
||||
fun RoomMemberHeaderSection(
|
||||
avatarUrl: String?,
|
||||
userId: String,
|
||||
userName: String?,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Column(modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Box(modifier = Modifier.size(70.dp)) {
|
||||
Avatar(
|
||||
avatarData = AvatarData(userId, userName, avatarUrl, AvatarSize.UserHeader),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
if (userName != null) {
|
||||
Text(text = userName, style = ElementTheme.typography.fontHeadingLgBold)
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
}
|
||||
Text(
|
||||
text = userId,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Spacer(Modifier.height(40.dp))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.roomdetails.impl.members.details
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.libraries.designsystem.components.button.MainActionButton
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
fun RoomMemberMainActionsSection(onShareUser: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
|
||||
MainActionButton(
|
||||
title = stringResource(CommonStrings.action_share),
|
||||
iconResourceId = CommonDrawables.ic_compound_share_android,
|
||||
onClick = onShareUser
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ fun RoomNotificationSettingsView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RoomNotificationSettingsTopBar(
|
||||
private fun RoomNotificationSettingsTopBar(
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
) {
|
||||
|
|
@ -125,7 +125,7 @@ fun RoomNotificationSettingsTopBar(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun RoomNotificationSettingsOptions(
|
||||
private fun RoomNotificationSettingsOptions(
|
||||
selected: RoomNotificationMode?,
|
||||
enabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ import io.element.android.features.networkmonitor.api.NetworkStatus
|
|||
import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource
|
||||
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.api.user.getCurrentUser
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package io.element.android.features.roomlist.impl
|
|||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomState
|
||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
|||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryPlaceholders
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ import io.element.android.libraries.designsystem.theme.components.Icon
|
|||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
||||
@Composable
|
||||
|
|
@ -124,7 +124,7 @@ fun RoomListView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun RoomListContent(
|
||||
private fun RoomListContent(
|
||||
state: RoomListState,
|
||||
onVerifyClicked: () -> Unit,
|
||||
onRoomClicked: (RoomId) -> Unit,
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ internal fun RoomSummaryRow(
|
|||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
internal fun RoomSummaryRealRow(
|
||||
private fun RoomSummaryRealRow(
|
||||
room: RoomListRoomSummary,
|
||||
onClick: (RoomListRoomSummary) -> Unit,
|
||||
onLongClick: (RoomListRoomSummary) -> Unit,
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ internal fun RoomListSearchResultView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
internal fun RoomListSearchResultContent(
|
||||
private fun RoomListSearchResultContent(
|
||||
state: RoomListState,
|
||||
onRoomClicked: (RoomId) -> Unit,
|
||||
onRoomLongClicked: (RoomListRoomSummary) -> Unit,
|
||||
|
|
@ -34,7 +34,7 @@ import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormat
|
|||
import io.element.android.libraries.dateformatter.test.FakeLastMessageTimestampFormatter
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
|
||||
import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ fun VerifySelfSessionView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier = Modifier) {
|
||||
private fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier = Modifier) {
|
||||
val iconResourceId = when (verificationFlowStep) {
|
||||
FlowStep.Initial -> R.drawable.ic_verification_devices
|
||||
FlowStep.Canceled -> R.drawable.ic_verification_warning
|
||||
|
|
@ -118,7 +118,7 @@ internal fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier =
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun Content(flowState: FlowStep, modifier: Modifier = Modifier) {
|
||||
private fun Content(flowState: FlowStep, modifier: Modifier = Modifier) {
|
||||
Column(modifier.fillMaxHeight(), verticalArrangement = Arrangement.Center) {
|
||||
when (flowState) {
|
||||
FlowStep.Initial, FlowStep.Ready, FlowStep.Canceled, FlowStep.Completed -> Unit
|
||||
|
|
@ -129,14 +129,14 @@ internal fun Content(flowState: FlowStep, modifier: Modifier = Modifier) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun ContentWaiting(modifier: Modifier = Modifier) {
|
||||
private fun ContentWaiting(modifier: Modifier = Modifier) {
|
||||
Row(modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier: Modifier = Modifier) {
|
||||
private fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier: Modifier = Modifier) {
|
||||
// We want each row to have up to 4 emojis
|
||||
val rows = verificationFlowStep.emojiList.chunked(4)
|
||||
Column(modifier = modifier.fillMaxWidth()) {
|
||||
|
|
@ -155,7 +155,7 @@ internal fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifier) {
|
||||
private fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifier) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier) {
|
||||
Text(
|
||||
text = emoji.code,
|
||||
|
|
@ -173,7 +173,7 @@ internal fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifi
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit) {
|
||||
private fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit) {
|
||||
val verificationViewState = screenState.verificationFlowStep
|
||||
val eventSink = screenState.eventSink
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ fun BlurHashAsyncImage(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun BlurHashImage(
|
||||
private fun BlurHashImage(
|
||||
blurHash: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
contentDescription: String? = null,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ fun ListDialog(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun ListDialogContent(
|
||||
private fun ListDialogContent(
|
||||
listItems: LazyListScope.() -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
onSubmitClicked: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ fun MultipleSelectionDialog(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun MultipleSelectionDialogContent(
|
||||
private fun MultipleSelectionDialogContent(
|
||||
options: ImmutableList<ListOption>,
|
||||
confirmButtonTitle: String,
|
||||
onConfirmClicked: (List<Int>) -> Unit,
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ fun SingleSelectionDialog(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun SingleSelectionDialogContent(
|
||||
private fun SingleSelectionDialogContent(
|
||||
options: ImmutableList<ListOption>,
|
||||
onOptionSelected: (Int) -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ fun PreferenceCategory(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun PreferenceCategoryTitle(title: String, modifier: Modifier = Modifier) {
|
||||
private fun PreferenceCategoryTitle(title: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
modifier = modifier.padding(
|
||||
top = 20.dp,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ import io.element.android.libraries.theme.ElementTheme
|
|||
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun PreferenceView(
|
||||
fun PreferencePage(
|
||||
title: String,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
|
|
@ -79,7 +79,7 @@ fun PreferenceView(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun PreferenceTopAppBar(
|
||||
private fun PreferenceTopAppBar(
|
||||
title: String,
|
||||
modifier: Modifier = Modifier,
|
||||
onBackPressed: () -> Unit = {},
|
||||
|
|
@ -104,7 +104,7 @@ fun PreferenceTopAppBar(
|
|||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun PreferenceViewPreview() = ElementPreview {
|
||||
PreferenceView(
|
||||
PreferencePage(
|
||||
title = "Preference screen"
|
||||
) {
|
||||
PreferenceCategory(
|
||||
|
|
@ -16,90 +16,11 @@
|
|||
|
||||
package io.element.android.libraries.designsystem.preview
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
||||
@Composable
|
||||
fun ElementPreviewLight(
|
||||
showBackground: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ElementPreviewDark(
|
||||
showBackground: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Suppress("ModifierMissing")
|
||||
fun ElementThemedPreview(
|
||||
showBackground: Boolean = true,
|
||||
vertical: Boolean = true,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(Color.Gray)
|
||||
.padding(4.dp)
|
||||
) {
|
||||
if (vertical) {
|
||||
Column {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
showBackground = showBackground,
|
||||
content = content,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Row {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
showBackground = showBackground,
|
||||
content = content,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Suppress("ModifierMissing")
|
||||
fun ElementPreview(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.preview
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
fun ElementPreviewDark(
|
||||
showBackground: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.preview
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
fun ElementPreviewLight(
|
||||
showBackground: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.preview
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
@Suppress("ModifierMissing")
|
||||
fun ElementThemedPreview(
|
||||
showBackground: Boolean = true,
|
||||
vertical: Boolean = true,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(Color.Gray)
|
||||
.padding(4.dp)
|
||||
) {
|
||||
if (vertical) {
|
||||
Column {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
showBackground = showBackground,
|
||||
content = content,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Row {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
showBackground = showBackground,
|
||||
content = content,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ fun Dp.applyScaleUp(): Dp = with(LocalDensity.current) {
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun DpScalePreview_0_75f() = WithFontScale(0.75f) {
|
||||
internal fun DpScale_0_75f_Preview() = WithFontScale(0.75f) {
|
||||
ElementPreviewLight {
|
||||
val fontSizeInDp = 16.dp
|
||||
Column(
|
||||
|
|
@ -77,7 +77,7 @@ internal fun DpScalePreview_0_75f() = WithFontScale(0.75f) {
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun DpScalePreview_1_0f() = WithFontScale(1f) {
|
||||
internal fun DpScale_1_0f_Preview() = WithFontScale(1f) {
|
||||
ElementPreviewLight {
|
||||
val fontSizeInDp = 16.dp
|
||||
Column(
|
||||
|
|
@ -102,7 +102,7 @@ internal fun DpScalePreview_1_0f() = WithFontScale(1f) {
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun DpScalePreview_1_5f() = WithFontScale(1.5f) {
|
||||
internal fun DpScale_1_5f_Preview() = WithFontScale(1.5f) {
|
||||
ElementPreviewLight {
|
||||
val fontSizeInDp = 16.dp
|
||||
Column(
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ fun TextButton(
|
|||
)
|
||||
|
||||
@Composable
|
||||
internal fun ButtonInternal(
|
||||
private fun ButtonInternal(
|
||||
text: String,
|
||||
onClick: () -> Unit,
|
||||
style: ButtonStyle,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.theme.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
||||
// Designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=425%3A24208&mode=design&t=G5hCfkLB6GgXDuWe-1
|
||||
|
||||
/**
|
||||
* List section header.
|
||||
* @param title The title of the section.
|
||||
* @param modifier The modifier to be applied to the section.
|
||||
* @param hasDivider Whether to show a divider above the section or not. Default is `true`.
|
||||
* @param description A description for the section. It's empty by default.
|
||||
*/
|
||||
@Composable
|
||||
fun ListSectionHeader(
|
||||
title: String,
|
||||
modifier: Modifier = Modifier,
|
||||
hasDivider: Boolean = true,
|
||||
description: @Composable () -> Unit = {},
|
||||
) {
|
||||
Column(modifier.fillMaxWidth()) {
|
||||
if (hasDivider) {
|
||||
HorizontalDivider(modifier = Modifier.padding(top = 16.dp))
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = ElementTheme.typography.fontBodyLgMedium,
|
||||
color = ElementTheme.colors.textPrimary,
|
||||
)
|
||||
CompositionLocalProvider(
|
||||
LocalTextStyle provides ElementTheme.typography.fontBodySmRegular,
|
||||
LocalContentColor provides ElementTheme.colors.textSecondary,
|
||||
) {
|
||||
description()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.ListSections, name = "List section header")
|
||||
@Composable
|
||||
internal fun ListSectionHeaderPreview() {
|
||||
ElementThemedPreview {
|
||||
ListSectionHeader(
|
||||
title = "List section",
|
||||
hasDivider = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.ListSections, name = "List section header with divider")
|
||||
@Composable
|
||||
internal fun ListSectionHeaderWithDividerPreview() {
|
||||
ElementThemedPreview {
|
||||
ListSectionHeader(
|
||||
title = "List section",
|
||||
hasDivider = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.ListSections, name = "List section header with description")
|
||||
@Composable
|
||||
internal fun ListSectionHeaderWithDescriptionPreview() {
|
||||
ElementThemedPreview {
|
||||
ListSectionHeader(
|
||||
title = "List section",
|
||||
description = {
|
||||
ListSupportingText(
|
||||
text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more",
|
||||
contentPadding = ListSupportingTextDefaults.Padding.None,
|
||||
)
|
||||
},
|
||||
hasDivider = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.ListSections, name = "List section header with description and divider")
|
||||
@Composable
|
||||
internal fun ListSectionHeaderWithDescriptionAndDividerPreview() {
|
||||
ElementThemedPreview {
|
||||
ListSectionHeader(
|
||||
title = "List section",
|
||||
description = {
|
||||
ListSupportingText(
|
||||
text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more",
|
||||
contentPadding = ListSupportingTextDefaults.Padding.None,
|
||||
)
|
||||
},
|
||||
hasDivider = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,15 +16,10 @@
|
|||
|
||||
package io.element.android.libraries.designsystem.theme.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.ExperimentalTextApi
|
||||
|
|
@ -40,43 +35,6 @@ import io.element.android.libraries.theme.ElementTheme
|
|||
|
||||
// Designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=425%3A24208&mode=design&t=G5hCfkLB6GgXDuWe-1
|
||||
|
||||
/**
|
||||
* List section header.
|
||||
* @param title The title of the section.
|
||||
* @param modifier The modifier to be applied to the section.
|
||||
* @param hasDivider Whether to show a divider above the section or not. Default is `true`.
|
||||
* @param description A description for the section. It's empty by default.
|
||||
*/
|
||||
@Composable
|
||||
fun ListSectionHeader(
|
||||
title: String,
|
||||
modifier: Modifier = Modifier,
|
||||
hasDivider: Boolean = true,
|
||||
description: @Composable () -> Unit = {},
|
||||
) {
|
||||
Column(modifier.fillMaxWidth()) {
|
||||
if (hasDivider) {
|
||||
HorizontalDivider(modifier = Modifier.padding(top = 16.dp))
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = ElementTheme.typography.fontBodyLgMedium,
|
||||
color = ElementTheme.colors.textPrimary,
|
||||
)
|
||||
CompositionLocalProvider(
|
||||
LocalTextStyle provides ElementTheme.typography.fontBodySmRegular,
|
||||
LocalContentColor provides ElementTheme.colors.textSecondary,
|
||||
) {
|
||||
description()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List supporting text item. Used to display an explanation in the list with a pre-formatted style.
|
||||
* @param text The text to display.
|
||||
|
|
@ -167,68 +125,6 @@ object ListSupportingTextDefaults {
|
|||
}
|
||||
}
|
||||
|
||||
// region: List header previews
|
||||
|
||||
@Preview(group = PreviewGroup.ListSections, name = "List section header")
|
||||
@Composable
|
||||
internal fun ListSectionHeaderPreview() {
|
||||
ElementThemedPreview {
|
||||
ListSectionHeader(
|
||||
title = "List section",
|
||||
hasDivider = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.ListSections, name = "List section header with divider")
|
||||
@Composable
|
||||
internal fun ListSectionHeaderWithDividerPreview() {
|
||||
ElementThemedPreview {
|
||||
ListSectionHeader(
|
||||
title = "List section",
|
||||
hasDivider = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.ListSections, name = "List section header with description")
|
||||
@Composable
|
||||
internal fun ListSectionHeaderWithDescriptionPreview() {
|
||||
ElementThemedPreview {
|
||||
ListSectionHeader(
|
||||
title = "List section",
|
||||
description = {
|
||||
ListSupportingText(
|
||||
text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more",
|
||||
contentPadding = ListSupportingTextDefaults.Padding.None,
|
||||
)
|
||||
},
|
||||
hasDivider = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.ListSections, name = "List section header with description and divider")
|
||||
@Composable
|
||||
internal fun ListSectionHeaderWithDescriptionAndDividerPreview() {
|
||||
ElementThemedPreview {
|
||||
ListSectionHeader(
|
||||
title = "List section",
|
||||
description = {
|
||||
ListSupportingText(
|
||||
text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more",
|
||||
contentPadding = ListSupportingTextDefaults.Padding.None,
|
||||
)
|
||||
},
|
||||
hasDivider = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region: List supporting text previews
|
||||
|
||||
@Preview(group = PreviewGroup.ListSections, name = "List supporting text - no padding")
|
||||
@Composable
|
||||
internal fun ListSupportingTextNoPaddingPreview() {
|
||||
|
|
@ -298,5 +194,3 @@ internal fun ListSupportingTextCustomPaddingPreview() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
|
@ -193,11 +193,11 @@ sealed interface SearchBarResultState<in T> {
|
|||
|
||||
@Preview(group = PreviewGroup.Search)
|
||||
@Composable
|
||||
internal fun SearchBarPreviewInactive() = ElementThemedPreview { ContentToPreview() }
|
||||
internal fun SearchBarInactivePreview() = ElementThemedPreview { ContentToPreview() }
|
||||
|
||||
@Preview(group = PreviewGroup.Search)
|
||||
@Composable
|
||||
internal fun SearchBarPreviewActiveEmptyQuery() = ElementThemedPreview {
|
||||
internal fun SearchBarActiveEmptyQueryPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "",
|
||||
active = true,
|
||||
|
|
@ -206,7 +206,7 @@ internal fun SearchBarPreviewActiveEmptyQuery() = ElementThemedPreview {
|
|||
|
||||
@Preview(group = PreviewGroup.Search)
|
||||
@Composable
|
||||
internal fun SearchBarPreviewActiveWithQuery() = ElementThemedPreview {
|
||||
internal fun SearchBarActiveWithQueryPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "search term",
|
||||
active = true,
|
||||
|
|
@ -215,7 +215,7 @@ internal fun SearchBarPreviewActiveWithQuery() = ElementThemedPreview {
|
|||
|
||||
@Preview(group = PreviewGroup.Search)
|
||||
@Composable
|
||||
internal fun SearchBarPreviewActiveWithQueryNoBackButton() = ElementThemedPreview {
|
||||
internal fun SearchBarActiveWithQueryNoBackButtonPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "search term",
|
||||
active = true,
|
||||
|
|
@ -225,7 +225,7 @@ internal fun SearchBarPreviewActiveWithQueryNoBackButton() = ElementThemedPrevie
|
|||
|
||||
@Preview(group = PreviewGroup.Search)
|
||||
@Composable
|
||||
internal fun SearchBarPreviewActiveWithNoResults() = ElementThemedPreview {
|
||||
internal fun SearchBarActiveWithNoResultsPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "search term",
|
||||
active = true,
|
||||
|
|
@ -235,7 +235,7 @@ internal fun SearchBarPreviewActiveWithNoResults() = ElementThemedPreview {
|
|||
|
||||
@Preview(group = PreviewGroup.Search)
|
||||
@Composable
|
||||
internal fun SearchBarPreviewActiveWithContent() = ElementThemedPreview {
|
||||
internal fun SearchBarActiveWithContentPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
query = "search term",
|
||||
active = true,
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@ import io.element.android.libraries.designsystem.preview.PreviewGroup
|
|||
|
||||
@Preview(group = PreviewGroup.DateTimePickers)
|
||||
@Composable
|
||||
internal fun DatePickerPreviewLight() {
|
||||
internal fun DatePickerLightPreview() {
|
||||
ElementPreviewLight { ContentToPreview() }
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.DateTimePickers)
|
||||
@Composable
|
||||
internal fun DatePickerPreviewDark() {
|
||||
internal fun DatePickerDarkPreview() {
|
||||
ElementPreviewDark { ContentToPreview() }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ internal fun TimePickerHorizontalPreview() {
|
|||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Preview(group = PreviewGroup.DateTimePickers)
|
||||
@Composable
|
||||
internal fun TimePickerVerticalPreviewLight() {
|
||||
internal fun TimePickerVerticalLightPreview() {
|
||||
ElementPreviewLight {
|
||||
AlertDialogContent(
|
||||
buttons = { /*TODO*/ },
|
||||
|
|
@ -77,7 +77,7 @@ internal fun TimePickerVerticalPreviewLight() {
|
|||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Preview(group = PreviewGroup.DateTimePickers)
|
||||
@Composable
|
||||
internal fun TimePickerVerticalPreviewDark() {
|
||||
internal fun TimePickerVerticalDarkPreview() {
|
||||
val pickerState = rememberTimePickerState(
|
||||
initialHour = 12,
|
||||
initialMinute = 0,
|
||||
|
|
|
|||
|
|
@ -14,11 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.utils
|
||||
package io.element.android.libraries.designsystem.utils.snackbar
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.SnackbarDuration
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
|
|
@ -26,11 +23,7 @@ import androidx.compose.runtime.State
|
|||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.button.ButtonVisuals
|
||||
import io.element.android.libraries.designsystem.theme.components.IconSource
|
||||
import io.element.android.libraries.designsystem.theme.components.Snackbar
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
|
|
@ -38,7 +31,6 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* A global dispatcher of [SnackbarMessage] to be displayed in [Snackbar] via a [SnackbarHostState].
|
||||
|
|
@ -78,23 +70,6 @@ fun SnackbarDispatcher.collectSnackbarMessageAsState(): State<SnackbarMessage?>
|
|||
return snackbarMessage.collectAsState(initial = null)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SnackbarHost(hostState: SnackbarHostState, modifier: Modifier = Modifier) {
|
||||
androidx.compose.material3.SnackbarHost(hostState, modifier) { data ->
|
||||
Snackbar(
|
||||
modifier = Modifier.padding(12.dp), // Add default padding
|
||||
message = data.visuals.message,
|
||||
action = data.visuals.actionLabel?.let { ButtonVisuals.Text(it, data::performAction) },
|
||||
dismissAction = if (data.visuals.withDismissAction) {
|
||||
ButtonVisuals.Icon(
|
||||
IconSource.Resource(CommonDrawables.ic_compound_close),
|
||||
data::dismiss
|
||||
)
|
||||
} else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to display a [SnackbarMessage] in a [SnackbarHostState] handling cancellations.
|
||||
*/
|
||||
|
|
@ -127,19 +102,3 @@ fun rememberSnackbarHostState(snackbarMessage: SnackbarMessage?): SnackbarHostSt
|
|||
}
|
||||
return snackbarHostState
|
||||
}
|
||||
|
||||
/**
|
||||
* A message to be displayed in a [Snackbar].
|
||||
* @param messageResId The message to be displayed.
|
||||
* @param duration The duration of the message. The default value is [SnackbarDuration.Short].
|
||||
* @param actionResId The action text to be displayed. The default value is `null`.
|
||||
* @param isDisplayed Used to track if the current message is already displayed or not.
|
||||
* @param action The action to be performed when the action is clicked.
|
||||
*/
|
||||
data class SnackbarMessage(
|
||||
@StringRes val messageResId: Int,
|
||||
val duration: SnackbarDuration = SnackbarDuration.Short,
|
||||
@StringRes val actionResId: Int? = null,
|
||||
val isDisplayed: AtomicBoolean = AtomicBoolean(false),
|
||||
val action: () -> Unit = {},
|
||||
)
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.utils.snackbar
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.button.ButtonVisuals
|
||||
import io.element.android.libraries.designsystem.theme.components.IconSource
|
||||
import io.element.android.libraries.designsystem.theme.components.Snackbar
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
|
||||
@Composable
|
||||
fun SnackbarHost(hostState: SnackbarHostState, modifier: Modifier = Modifier) {
|
||||
androidx.compose.material3.SnackbarHost(hostState, modifier) { data ->
|
||||
Snackbar(
|
||||
modifier = Modifier.padding(12.dp), // Add default padding
|
||||
message = data.visuals.message,
|
||||
action = data.visuals.actionLabel?.let { ButtonVisuals.Text(it, data::performAction) },
|
||||
dismissAction = if (data.visuals.withDismissAction) {
|
||||
ButtonVisuals.Icon(
|
||||
IconSource.Resource(CommonDrawables.ic_compound_close),
|
||||
data::dismiss
|
||||
)
|
||||
} else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.utils.snackbar
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material3.SnackbarDuration
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* A message to be displayed in a [Snackbar].
|
||||
* @param messageResId The message to be displayed.
|
||||
* @param duration The duration of the message. The default value is [SnackbarDuration.Short].
|
||||
* @param actionResId The action text to be displayed. The default value is `null`.
|
||||
* @param isDisplayed Used to track if the current message is already displayed or not.
|
||||
* @param action The action to be performed when the action is clicked.
|
||||
*/
|
||||
data class SnackbarMessage(
|
||||
@StringRes val messageResId: Int,
|
||||
val duration: SnackbarDuration = SnackbarDuration.Short,
|
||||
@StringRes val actionResId: Int? = null,
|
||||
val isDisplayed: AtomicBoolean = AtomicBoolean(false),
|
||||
val action: () -> Unit = {},
|
||||
)
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.utils
|
||||
package io.element.android.libraries.designsystem.utils.snackbar
|
||||
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
|
|
@ -46,7 +46,7 @@ fun FeatureListView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun FeaturePreferenceView(
|
||||
private fun FeaturePreferenceView(
|
||||
feature: FeatureUiModel,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -16,22 +16,13 @@
|
|||
|
||||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
import io.element.android.libraries.matrix.ui.model.getBestName
|
||||
|
|
@ -54,41 +45,6 @@ fun CheckableMatrixUserRow(
|
|||
enabled = enabled,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun CheckableUserRow(
|
||||
checked: Boolean,
|
||||
avatarData: AvatarData,
|
||||
name: String,
|
||||
subtext: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
onCheckedChange: (Boolean) -> Unit = {},
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(role = Role.Checkbox, enabled = enabled) {
|
||||
onCheckedChange(!checked)
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
UserRow(
|
||||
modifier = Modifier.weight(1f),
|
||||
avatarData = avatarData,
|
||||
name = name,
|
||||
subtext = subtext,
|
||||
)
|
||||
|
||||
Checkbox(
|
||||
modifier = Modifier
|
||||
.padding(end = 16.dp),
|
||||
checked = checked,
|
||||
onCheckedChange = null,
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun CheckableMatrixUserRowPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = ElementPreview {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
|
||||
@Composable
|
||||
fun CheckableUnresolvedUserRow(
|
||||
checked: Boolean,
|
||||
avatarData: AvatarData,
|
||||
id: String,
|
||||
modifier: Modifier = Modifier,
|
||||
onCheckedChange: (Boolean) -> Unit = {},
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(role = Role.Checkbox, enabled = enabled) {
|
||||
onCheckedChange(!checked)
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
UnresolvedUserRow(
|
||||
modifier = Modifier.weight(1f),
|
||||
avatarData = avatarData,
|
||||
id = id,
|
||||
)
|
||||
|
||||
Checkbox(
|
||||
modifier = Modifier.padding(end = 16.dp),
|
||||
checked = checked,
|
||||
onCheckedChange = null,
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun CheckableUnresolvedUserRowPreview() = ElementThemedPreview {
|
||||
val matrixUser = aMatrixUser()
|
||||
Column {
|
||||
CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value)
|
||||
HorizontalDivider()
|
||||
CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value)
|
||||
HorizontalDivider()
|
||||
CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value, enabled = false)
|
||||
HorizontalDivider()
|
||||
CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value, enabled = false)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||
|
||||
@Composable
|
||||
fun CheckableUserRow(
|
||||
checked: Boolean,
|
||||
avatarData: AvatarData,
|
||||
name: String,
|
||||
subtext: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
onCheckedChange: (Boolean) -> Unit = {},
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(role = Role.Checkbox, enabled = enabled) {
|
||||
onCheckedChange(!checked)
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
UserRow(
|
||||
modifier = Modifier.weight(1f),
|
||||
avatarData = avatarData,
|
||||
name = name,
|
||||
subtext = subtext,
|
||||
)
|
||||
|
||||
Checkbox(
|
||||
modifier = Modifier
|
||||
.padding(end = 16.dp),
|
||||
checked = checked,
|
||||
onCheckedChange = null,
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,28 +16,15 @@
|
|||
|
||||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
import io.element.android.libraries.matrix.ui.model.getBestName
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
||||
@Composable
|
||||
fun MatrixUserRow(
|
||||
|
|
@ -51,47 +38,6 @@ fun MatrixUserRow(
|
|||
modifier = modifier,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun UserRow(
|
||||
avatarData: AvatarData,
|
||||
name: String,
|
||||
subtext: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 56.dp)
|
||||
.padding(start = 16.dp, top = 4.dp, end = 16.dp, bottom = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Avatar(avatarData)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp),
|
||||
) {
|
||||
// Name
|
||||
Text(
|
||||
text = name,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
)
|
||||
// Id
|
||||
subtext?.let {
|
||||
Text(
|
||||
text = subtext,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun MatrixUserRowPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = ElementPreview {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
|
@ -29,7 +28,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -38,8 +36,6 @@ 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.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||
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.Text
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
|
|
@ -101,58 +97,9 @@ fun UnresolvedUserRow(
|
|||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CheckableUnresolvedUserRow(
|
||||
checked: Boolean,
|
||||
avatarData: AvatarData,
|
||||
id: String,
|
||||
modifier: Modifier = Modifier,
|
||||
onCheckedChange: (Boolean) -> Unit = {},
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(role = Role.Checkbox, enabled = enabled) {
|
||||
onCheckedChange(!checked)
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
UnresolvedUserRow(
|
||||
modifier = Modifier.weight(1f),
|
||||
avatarData = avatarData,
|
||||
id = id,
|
||||
)
|
||||
|
||||
Checkbox(
|
||||
modifier = Modifier.padding(end = 16.dp),
|
||||
checked = checked,
|
||||
onCheckedChange = null,
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
internal fun UnresolvedUserRowPreview() = ElementThemedPreview {
|
||||
val matrixUser = aMatrixUser()
|
||||
UnresolvedUserRow(matrixUser.getAvatarData(size = AvatarSize.UserListItem), matrixUser.userId.value)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun UnresolvedUserRowPreview() =
|
||||
ElementThemedPreview {
|
||||
val matrixUser = aMatrixUser()
|
||||
UnresolvedUserRow(matrixUser.getAvatarData(size = AvatarSize.UserListItem), matrixUser.userId.value)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun CheckableUnresolvedUserRowPreview() =
|
||||
ElementThemedPreview {
|
||||
val matrixUser = aMatrixUser()
|
||||
Column {
|
||||
CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value)
|
||||
HorizontalDivider()
|
||||
CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value)
|
||||
HorizontalDivider()
|
||||
CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value, enabled = false)
|
||||
HorizontalDivider()
|
||||
CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value, enabled = false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.ui.components
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
||||
@Composable
|
||||
internal fun UserRow(
|
||||
avatarData: AvatarData,
|
||||
name: String,
|
||||
subtext: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 56.dp)
|
||||
.padding(start = 16.dp, top = 4.dp, end = 16.dp, bottom = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Avatar(avatarData)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp),
|
||||
) {
|
||||
// Name
|
||||
Text(
|
||||
text = name,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
)
|
||||
// Id
|
||||
subtext?.let {
|
||||
Text(
|
||||
text = subtext,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,6 @@ import androidx.compose.material3.dynamicDarkColorScheme
|
|||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -138,27 +137,7 @@ fun ElementTheme(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to force a composable in dark theme.
|
||||
* It will automatically change the system ui colors back to normal when leaving the composition.
|
||||
*/
|
||||
@Composable
|
||||
fun ForcedDarkElementTheme(
|
||||
lightStatusBar: Boolean = false,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val wasDarkTheme = !ElementTheme.colors.isLight
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
systemUiController.applyTheme(colorScheme, wasDarkTheme)
|
||||
}
|
||||
}
|
||||
ElementTheme(darkTheme = true, lightStatusBar = lightStatusBar, content = content)
|
||||
}
|
||||
|
||||
private fun SystemUiController.applyTheme(
|
||||
internal fun SystemUiController.applyTheme(
|
||||
colorScheme: ColorScheme,
|
||||
darkTheme: Boolean,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.theme
|
||||
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
|
||||
/**
|
||||
* Can be used to force a composable in dark theme.
|
||||
* It will automatically change the system ui colors back to normal when leaving the composition.
|
||||
*/
|
||||
@Composable
|
||||
fun ForcedDarkElementTheme(
|
||||
lightStatusBar: Boolean = false,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val wasDarkTheme = !ElementTheme.colors.isLight
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
systemUiController.applyTheme(colorScheme, wasDarkTheme)
|
||||
}
|
||||
}
|
||||
ElementTheme(darkTheme = true, lightStatusBar = lightStatusBar, content = content)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue