Add some Preview

This commit is contained in:
Benoit Marty 2023-02-10 16:05:11 +01:00 committed by Benoit Marty
parent 0f0c001c3c
commit fe44c8906d
19 changed files with 248 additions and 29 deletions

View file

@ -18,7 +18,9 @@ package io.element.android.x.root
import androidx.compose.runtime.Stable
import io.element.android.features.rageshake.crash.ui.CrashDetectionState
import io.element.android.features.rageshake.crash.ui.aCrashDetectionState
import io.element.android.features.rageshake.detection.RageshakeDetectionState
import io.element.android.features.rageshake.detection.aRageshakeDetectionState
@Stable
data class RootState(
@ -27,3 +29,10 @@ data class RootState(
val crashDetectionState: CrashDetectionState,
val eventSink: (RootEvents) -> Unit
)
fun aRootState() = RootState(
isShowkaseButtonVisible = false,
rageshakeDetectionState = aRageshakeDetectionState(),
crashDetectionState = aCrashDetectionState(),
eventSink = {}
)

View file

@ -24,10 +24,18 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.rageshake.crash.ui.CrashDetectionEvents
import io.element.android.features.rageshake.crash.ui.CrashDetectionView
import io.element.android.features.rageshake.crash.ui.aCrashDetectionState
import io.element.android.features.rageshake.detection.RageshakeDetectionEvents
import io.element.android.features.rageshake.detection.RageshakeDetectionView
import io.element.android.features.rageshake.detection.aRageshakeDetectionState
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.BooleanPreviewParameter
import io.element.android.tests.uitests.openShowkase
import io.element.android.x.component.ShowkaseButton
@ -68,3 +76,24 @@ fun RootView(
)
}
}
@Preview
@Composable
fun RootLightPreview(@PreviewParameter(BooleanPreviewParameter::class) dialogType: Boolean) = ElementPreviewLight { ContentToPreview(dialogType) }
@Preview
@Composable
fun RootDarkPreview(@PreviewParameter(BooleanPreviewParameter::class) dialogType: Boolean) = ElementPreviewDark { ContentToPreview(dialogType) }
@Composable
private fun ContentToPreview(dialogType: Boolean) {
RootView(
aRootState().copy(
isShowkaseButtonVisible = true,
rageshakeDetectionState = aRageshakeDetectionState().copy(showDialog = dialogType),
crashDetectionState = aCrashDetectionState().copy(crashDetected = !dialogType),
)
) {
Text("Children")
}
}

View file

@ -49,22 +49,33 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import io.element.android.features.messages.actionlist.ActionListEvents
import io.element.android.features.messages.actionlist.ActionListView
import io.element.android.features.messages.actionlist.anActionListState
import io.element.android.features.messages.actionlist.model.TimelineItemAction
import io.element.android.features.messages.textcomposer.MessageComposerView
import io.element.android.features.messages.textcomposer.aMessageComposerState
import io.element.android.features.messages.timeline.TimelineView
import io.element.android.features.messages.timeline.aTimelineState
import io.element.android.features.messages.timeline.createTimelineItemContent
import io.element.android.features.messages.timeline.createTimelineItems
import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.libraries.core.data.StableCharSequence
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.matrix.core.RoomId
import io.element.android.libraries.textcomposer.MessageComposerMode
import kotlinx.coroutines.launch
import timber.log.Timber
@ -72,7 +83,7 @@ import timber.log.Timber
fun MessagesView(
state: MessagesState,
modifier: Modifier = Modifier,
onBackPressed: () -> Unit,
onBackPressed: () -> Unit = {},
) {
LogCompositions(tag = "MessagesScreen", msg = "Root")
val itemActionsBottomSheetState = rememberModalBottomSheetState(
@ -197,6 +208,35 @@ fun MessagesViewTopBar(
)
}
}
)
}
@Preview
@Composable
fun MessagesViewLightPreview() = ElementPreviewLight { ContentToPreview() }
@Preview
@Composable
fun MessagesViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
MessagesView(
MessagesState(
roomId = RoomId(""),
roomName = "Room name",
roomAvatar = AvatarData("Room name"),
composerState = aMessageComposerState().copy(
text = StableCharSequence("Hello"),
isFullScreen = false,
mode = MessageComposerMode.Normal("Hello"),
),
timelineState = aTimelineState().copy(
timelineItems = createTimelineItems(createTimelineItemContent()),
hasMoreToLoad = false,
),
actionListState = anActionListState(),
eventSink = {}
)
)
}

View file

@ -36,3 +36,8 @@ data class ActionListState(
) : Target
}
}
fun anActionListState() = ActionListState(
target = ActionListState.Target.None,
eventSink = {}
)

View file

@ -28,7 +28,6 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ListItem
import androidx.compose.material.LocalContentColor
import androidx.compose.material.ModalBottomSheetState
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.Text
@ -38,12 +37,16 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import io.element.android.features.messages.actionlist.model.TimelineItemAction
import io.element.android.features.messages.timeline.createMessageEvent
import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.libraries.designsystem.components.VectorIcon
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheetLayout
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@ -115,13 +118,13 @@ private fun SheetContent(
text = {
Text(
text = action.title,
color = if (action.destructive) MaterialTheme.colorScheme.error else Color.Unspecified,
color = if (action.destructive) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary,
)
},
icon = {
VectorIcon(
resourceId = action.icon,
tint = if (action.destructive) MaterialTheme.colorScheme.error else LocalContentColor.current,
tint = if (action.destructive) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary,
)
}
)
@ -130,3 +133,57 @@ private fun SheetContent(
}
}
}
@Preview
@Composable
fun SheetContentNoneLightPreview() = ElementPreviewLight { ContentNoneToPreview() }
@Preview
@Composable
fun SheetContentNoneDarkPreview() = ElementPreviewDark { ContentNoneToPreview() }
@Composable
private fun ContentNoneToPreview() {
SheetContent(anActionListState())
}
@Preview
@Composable
fun SheetContentLoadingLightPreview() = ElementPreviewLight { ContentLoadingToPreview() }
@Preview
@Composable
fun SheetContentLoadingDarkPreview() = ElementPreviewDark { ContentLoadingToPreview() }
@Composable
private fun ContentLoadingToPreview() {
SheetContent(
anActionListState().copy(target = ActionListState.Target.Loading(createMessageEvent()))
)
}
@Preview
@Composable
fun SheetContentSuccessLightPreview() = ElementPreviewLight { ContentSuccessToPreview() }
@Preview
@Composable
fun SheetContentSuccessDarkPreview() = ElementPreviewDark { ContentSuccessToPreview() }
@Composable
private fun ContentSuccessToPreview() {
SheetContent(
anActionListState().copy(
target = ActionListState.Target.Success(
messageEvent = createMessageEvent(),
actions = persistentListOf(
TimelineItemAction.Reply,
TimelineItemAction.Forward,
TimelineItemAction.Copy,
TimelineItemAction.Edit,
TimelineItemAction.Redact,
)
)
)
)
}

View file

@ -29,3 +29,10 @@ data class MessageComposerState(
) {
val isSendButtonVisible: Boolean = text?.charSequence.isNullOrEmpty().not()
}
fun aMessageComposerState() = MessageComposerState(
text = StableCharSequence(""),
isFullScreen = false,
mode = MessageComposerMode.Normal(content = ""),
eventSink = {}
)

View file

@ -20,6 +20,7 @@ import androidx.compose.runtime.Immutable
import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.libraries.matrix.core.EventId
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@Immutable
data class TimelineState(
@ -28,3 +29,10 @@ data class TimelineState(
val highlightedEventId: EventId?,
val eventSink: (TimelineEvents) -> Unit
)
fun aTimelineState() = TimelineState(
timelineItems = persistentListOf(),
hasMoreToLoad = false,
highlightedEventId = null,
eventSink = {}
)

View file

@ -64,7 +64,6 @@ import io.element.android.features.messages.timeline.components.TimelineItemUnkn
import io.element.android.features.messages.timeline.model.AggregatedReaction
import io.element.android.features.messages.timeline.model.MessagesItemGroupPosition
import io.element.android.features.messages.timeline.model.TimelineItem
import io.element.android.features.messages.timeline.model.TimelineItemGroupPositionProvider
import io.element.android.features.messages.timeline.model.TimelineItemReactions
import io.element.android.features.messages.timeline.model.content.MessagesTimelineItemContentProvider
import io.element.android.features.messages.timeline.model.content.TimelineItemContent
@ -72,6 +71,7 @@ import io.element.android.features.messages.timeline.model.content.TimelineItemE
import io.element.android.features.messages.timeline.model.content.TimelineItemImageContent
import io.element.android.features.messages.timeline.model.content.TimelineItemRedactedContent
import io.element.android.features.messages.timeline.model.content.TimelineItemTextBasedContent
import io.element.android.features.messages.timeline.model.content.TimelineItemTextContent
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
@ -81,7 +81,6 @@ import io.element.android.libraries.designsystem.theme.components.CircularProgre
import io.element.android.libraries.designsystem.theme.components.FloatingActionButton
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.PairCombinedPreviewParameter
import io.element.android.libraries.matrix.core.EventId
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@ -366,7 +365,17 @@ fun LoginRootScreenDarkPreview(
@Composable
private fun ContentToPreview(content: TimelineItemContent) {
val timelineItems = persistentListOf(
val timelineItems = createTimelineItems(content)
TimelineView(
state = aTimelineState().copy(
timelineItems = timelineItems,
hasMoreToLoad = true,
)
)
}
internal fun createTimelineItems(content: TimelineItemContent): ImmutableList<TimelineItem> {
return persistentListOf(
// 3 items (First Middle Last) with isMine = false
createMessageEvent(
isMine = false,
@ -400,21 +409,13 @@ private fun ContentToPreview(content: TimelineItemContent) {
groupPosition = MessagesItemGroupPosition.First
),
)
TimelineView(
state = TimelineState(
timelineItems = timelineItems,
hasMoreToLoad = true,
highlightedEventId = null,
eventSink = {}
)
)
}
private fun createMessageEvent(
isMine: Boolean,
content: TimelineItemContent,
groupPosition: MessagesItemGroupPosition
): TimelineItem {
internal fun createMessageEvent(
isMine: Boolean = false,
content: TimelineItemContent = createTimelineItemContent(),
groupPosition: MessagesItemGroupPosition = MessagesItemGroupPosition.First
): TimelineItem.MessageEvent {
return TimelineItem.MessageEvent(
id = EventId(Math.random().toString()),
senderId = "senderId",
@ -430,3 +431,10 @@ private fun createMessageEvent(
groupPosition = groupPosition,
)
}
internal fun createTimelineItemContent(): TimelineItemContent {
return TimelineItemTextContent(
body = "Text",
htmlDocument = null
)
}

View file

@ -38,6 +38,7 @@ import io.element.android.features.roomlist.components.RoomSummaryRow
import io.element.android.features.roomlist.model.RoomListEvents
import io.element.android.features.roomlist.model.RoomListRoomSummary
import io.element.android.features.roomlist.model.RoomListState
import io.element.android.features.roomlist.model.aRoomListState
import io.element.android.features.roomlist.model.stubbedRoomSummaries
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
@ -165,12 +166,11 @@ fun RoomListViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
RoomListContent(
roomSummaries = stubbedRoomSummaries(),
matrixUser = MatrixUser(id = UserId("@id"), username = "User#1", avatarData = AvatarData("U")),
onRoomClicked = {},
filter = "filter",
onFilterChanged = {},
onScrollOver = {}
RoomListView(
aRoomListState().copy(
matrixUser = MatrixUser(id = UserId("@id"), username = "User#1", avatarData = AvatarData("U")),
roomList = stubbedRoomSummaries(),
filter = "filter",
)
)
}

View file

@ -19,6 +19,7 @@ package io.element.android.features.roomlist.model
import androidx.compose.runtime.Immutable
import io.element.android.libraries.matrix.ui.model.MatrixUser
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@Immutable
data class RoomListState(
@ -27,3 +28,10 @@ data class RoomListState(
val filter: String,
val eventSink: (RoomListEvents) -> Unit
)
fun aRoomListState() = RoomListState(
matrixUser = null,
roomList = persistentListOf(),
filter = "",
eventSink = {}
)

View file

@ -0,0 +1,24 @@
/*
* 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
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
open class BooleanPreviewParameter : PreviewParameterProvider<Boolean> {
override val values: Sequence<Boolean>
get() = sequenceOf(false, true)
}

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4a904cb92b66b66730f5ac1a81b46710668d440e702f5b51320ecf5a29823e47
size 4471

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bb0d3bfcfd75cbd75fd9270ff1dc27090e5dbac79ca8db8a46d91a4c12bc966b
size 4457

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4a904cb92b66b66730f5ac1a81b46710668d440e702f5b51320ecf5a29823e47
size 4471

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bb0d3bfcfd75cbd75fd9270ff1dc27090e5dbac79ca8db8a46d91a4c12bc966b
size 4457

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ce15df8f50bf352fa93f5682a23b255ba143c0665d29bc8b7d7ecd0f588011c9
size 14736

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:37edc587d96587aab57013d09def27c807d247d78fa90a69cdcb8d7d9a0344ec
size 13676

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:852dff8969883ccea1811254ea4d68c3f2c30a593ec8411d005b995bcb3ba816
size 41570

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:81dc3835d7e7d836f7de9b8f509896ec09f2670a0816fbda3be41e82244efc62
size 39078