commit
3b428de991
108 changed files with 867 additions and 125 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
**/snapshots/**/*.png filter=lfs diff=lfs merge=lfs -text
|
||||||
9
.github/workflows/tests.yml
vendored
9
.github/workflows/tests.yml
vendored
|
|
@ -23,3 +23,12 @@ jobs:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: ./gradlew test $CI_GRADLE_ARG_PROPERTIES
|
run: ./gradlew test $CI_GRADLE_ARG_PROPERTIES
|
||||||
|
|
||||||
|
- name: Archive test results on error
|
||||||
|
if: failure()
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: screenshot-results
|
||||||
|
path: |
|
||||||
|
**/out/failures/
|
||||||
|
**/build/reports/tests/*UnitTest/
|
||||||
|
|
|
||||||
15
.github/workflows/validate-lfs.yml
vendored
Normal file
15
.github/workflows/validate-lfs.yml
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
name: Validate Git LFS
|
||||||
|
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Validate
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
lfs: 'true'
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
./tools/git/validate_lfs.sh
|
||||||
|
|
@ -16,6 +16,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import extension.allFeatures
|
||||||
|
import extension.allLibraries
|
||||||
|
|
||||||
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
|
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
|
||||||
@Suppress("DSL_SCOPE_VIOLATION")
|
@Suppress("DSL_SCOPE_VIOLATION")
|
||||||
plugins {
|
plugins {
|
||||||
|
|
@ -125,6 +128,7 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Waiting for https://github.com/google/ksp/issues/37
|
||||||
applicationVariants.all {
|
applicationVariants.all {
|
||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
getByName(name) {
|
getByName(name) {
|
||||||
|
|
@ -156,19 +160,9 @@ knit {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":libraries:designsystem"))
|
allLibraries()
|
||||||
implementation(project(":libraries:matrix"))
|
allFeatures()
|
||||||
implementation(project(":libraries:matrixui"))
|
implementation(project(":tests:uitests"))
|
||||||
implementation(project(":libraries:core"))
|
|
||||||
implementation(project(":libraries:architecture"))
|
|
||||||
implementation(project(":features:onboarding"))
|
|
||||||
implementation(project(":features:login"))
|
|
||||||
implementation(project(":features:logout"))
|
|
||||||
implementation(project(":features:roomlist"))
|
|
||||||
implementation(project(":features:messages"))
|
|
||||||
implementation(project(":features:rageshake"))
|
|
||||||
implementation(project(":features:preferences"))
|
|
||||||
implementation(project(":libraries:di"))
|
|
||||||
implementation(project(":anvilannotations"))
|
implementation(project(":anvilannotations"))
|
||||||
anvil(project(":anvilcodegen"))
|
anvil(project(":anvilcodegen"))
|
||||||
|
|
||||||
|
|
@ -184,7 +178,4 @@ dependencies {
|
||||||
|
|
||||||
implementation(libs.dagger)
|
implementation(libs.dagger)
|
||||||
kapt(libs.dagger.compiler)
|
kapt(libs.dagger.compiler)
|
||||||
|
|
||||||
implementation(libs.showkase)
|
|
||||||
ksp(libs.showkase.processor)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package io.element.android.x.root
|
package io.element.android.x.root
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
import androidx.compose.foundation.layout.BoxScope
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
|
@ -23,14 +24,12 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import com.airbnb.android.showkase.models.Showkase
|
|
||||||
import io.element.android.x.component.ShowkaseButton
|
import io.element.android.x.component.ShowkaseButton
|
||||||
import io.element.android.x.features.rageshake.crash.ui.CrashDetectionEvents
|
import io.element.android.x.features.rageshake.crash.ui.CrashDetectionEvents
|
||||||
import io.element.android.x.features.rageshake.crash.ui.CrashDetectionView
|
import io.element.android.x.features.rageshake.crash.ui.CrashDetectionView
|
||||||
import io.element.android.x.features.rageshake.detection.RageshakeDetectionEvents
|
import io.element.android.x.features.rageshake.detection.RageshakeDetectionEvents
|
||||||
import io.element.android.x.features.rageshake.detection.RageshakeDetectionView
|
import io.element.android.x.features.rageshake.detection.RageshakeDetectionView
|
||||||
import io.element.android.x.getBrowserIntent
|
import io.element.android.x.tests.uitests.openShowkase
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RootView(
|
fun RootView(
|
||||||
|
|
@ -57,7 +56,7 @@ fun RootView(
|
||||||
ShowkaseButton(
|
ShowkaseButton(
|
||||||
isVisible = state.isShowkaseButtonVisible,
|
isVisible = state.isShowkaseButtonVisible,
|
||||||
onCloseClicked = { eventSink(RootEvents.HideShowkaseButton) },
|
onCloseClicked = { eventSink(RootEvents.HideShowkaseButton) },
|
||||||
onClick = { ContextCompat.startActivity(context, Showkase.getBrowserIntent(context), null) }
|
onClick = { openShowkase(context as Activity) }
|
||||||
)
|
)
|
||||||
RageshakeDetectionView(
|
RageshakeDetectionView(
|
||||||
state = state.rageshakeDetectionState,
|
state = state.rageshakeDetectionState,
|
||||||
|
|
|
||||||
45
docs/screenshot_testing.md
Normal file
45
docs/screenshot_testing.md
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Screenshot testing
|
||||||
|
|
||||||
|
<!--- TOC -->
|
||||||
|
|
||||||
|
* [Overview](#overview)
|
||||||
|
* [Setup](#setup)
|
||||||
|
* [Recording](#recording)
|
||||||
|
* [Verifying](#verifying)
|
||||||
|
* [Contributing](#contributing)
|
||||||
|
|
||||||
|
<!--- END -->
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
- Screenshot tests are tests which record the content of a rendered screen and verify subsequent runs to check if the screen renders differently.
|
||||||
|
- ElementX uses [Paparazzi](https://github.com/cashapp/paparazzi) to render, record and verify Composable. All Composable Preview will be use to make screenshot test, thanks to the usage of [Showkase](https://github.com/airbnb/Showkase).
|
||||||
|
- The screenshot verification occurs on every pull request as part of the `tests.yml` workflow.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
- Install Git LFS through your package manager of choice (`brew install git-lfs` | `yay -S git-lfs`).
|
||||||
|
- Install the Git LFS hooks into the project.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# with element-android as the current working directory
|
||||||
|
git lfs install --local
|
||||||
|
```
|
||||||
|
|
||||||
|
- If installed correctly, `git push` and `git pull` will now include LFS content.
|
||||||
|
|
||||||
|
## Recording
|
||||||
|
|
||||||
|
- `./gradlew recordPaparazziDebug`
|
||||||
|
- Paparazzi will generate images in `:tests:uitests/src/test/snapshots`, which will need to be committed to the repository using Git LFS.
|
||||||
|
|
||||||
|
## Verifying
|
||||||
|
|
||||||
|
- `./gradlew verifyPaparazziDebug`
|
||||||
|
- In the case of failure, Paparazzi will generate images in `:tests:uitests/out/failure`. The images will show the expected and actual screenshots along with a delta of the two images.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
- Creating Previewable Composable will automatically creates new screenshot tests.
|
||||||
|
- After creating the new test, record and commit the newly rendered screens.
|
||||||
|
- `./tools/git/validate_lfs.sh` can be run to ensure everything is working correctly with Git LFS, the CI also runs this check.
|
||||||
|
|
@ -54,7 +54,6 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import io.element.android.x.architecture.Async
|
import io.element.android.x.architecture.Async
|
||||||
import io.element.android.x.core.compose.textFieldState
|
import io.element.android.x.core.compose.textFieldState
|
||||||
import io.element.android.x.designsystem.ElementXTheme
|
|
||||||
import io.element.android.x.designsystem.components.VectorIcon
|
import io.element.android.x.designsystem.components.VectorIcon
|
||||||
import io.element.android.x.features.login.R
|
import io.element.android.x.features.login.R
|
||||||
import io.element.android.x.features.login.error.changeServerError
|
import io.element.android.x.features.login.error.changeServerError
|
||||||
|
|
@ -183,9 +182,7 @@ fun ChangeServerView(
|
||||||
@Composable
|
@Composable
|
||||||
@Preview
|
@Preview
|
||||||
fun ChangeServerContentPreview() {
|
fun ChangeServerContentPreview() {
|
||||||
ElementXTheme {
|
ChangeServerView(
|
||||||
ChangeServerView(
|
state = ChangeServerState(homeserver = "matrix.org"),
|
||||||
state = ChangeServerState(homeserver = "matrix.org"),
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import io.element.android.x.core.compose.textFieldState
|
import io.element.android.x.core.compose.textFieldState
|
||||||
import io.element.android.x.designsystem.ElementXTheme
|
|
||||||
import io.element.android.x.features.login.error.loginError
|
import io.element.android.x.features.login.error.loginError
|
||||||
import io.element.android.x.matrix.core.SessionId
|
import io.element.android.x.matrix.core.SessionId
|
||||||
import io.element.android.x.ui.strings.R as StringR
|
import io.element.android.x.ui.strings.R as StringR
|
||||||
|
|
@ -224,11 +223,9 @@ fun LoginRootScreen(
|
||||||
@Composable
|
@Composable
|
||||||
@Preview
|
@Preview
|
||||||
fun LoginContentPreview() {
|
fun LoginContentPreview() {
|
||||||
ElementXTheme(darkTheme = false) {
|
LoginRootScreen(
|
||||||
LoginRootScreen(
|
state = LoginRootState(
|
||||||
state = LoginRootState(
|
homeserver = "matrix.org",
|
||||||
homeserver = "matrix.org",
|
),
|
||||||
),
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import io.element.android.x.architecture.Async
|
import io.element.android.x.architecture.Async
|
||||||
import io.element.android.x.designsystem.ElementXTheme
|
|
||||||
import io.element.android.x.designsystem.components.ProgressDialog
|
import io.element.android.x.designsystem.components.ProgressDialog
|
||||||
import io.element.android.x.designsystem.components.dialogs.ConfirmationDialog
|
import io.element.android.x.designsystem.components.dialogs.ConfirmationDialog
|
||||||
import io.element.android.x.designsystem.components.preferences.PreferenceCategory
|
import io.element.android.x.designsystem.components.preferences.PreferenceCategory
|
||||||
|
|
@ -92,7 +91,5 @@ fun LogoutPreferenceContent(
|
||||||
@Composable
|
@Composable
|
||||||
@Preview
|
@Preview
|
||||||
fun LogoutContentPreview() {
|
fun LogoutContentPreview() {
|
||||||
ElementXTheme(darkTheme = false) {
|
LogoutPreferenceView(LogoutPreferenceState())
|
||||||
LogoutPreferenceView(LogoutPreferenceState())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package io.element.android.x.features.messages.textcomposer
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import io.element.android.x.designsystem.LocalIsDarkTheme
|
||||||
import io.element.android.x.textcomposer.TextComposer
|
import io.element.android.x.textcomposer.TextComposer
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -50,6 +51,7 @@ fun MessageComposerView(
|
||||||
onComposerTextChange = ::onComposerTextChange,
|
onComposerTextChange = ::onComposerTextChange,
|
||||||
composerCanSendMessage = state.isSendButtonVisible,
|
composerCanSendMessage = state.isSendButtonVisible,
|
||||||
composerText = state.text?.charSequence?.toString(),
|
composerText = state.text?.charSequence?.toString(),
|
||||||
|
isInDarkMode = LocalIsDarkTheme.current,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ class MessagesItemGroupPositionToMessagesTimelineItemContentProvider :
|
||||||
)
|
)
|
||||||
|
|
||||||
@Suppress("PreviewPublic")
|
@Suppress("PreviewPublic")
|
||||||
@Preview(showBackground = true)
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineItemsPreview(
|
fun TimelineItemsPreview(
|
||||||
@PreviewParameter(MessagesTimelineItemContentProvider::class)
|
@PreviewParameter(MessagesTimelineItemContentProvider::class)
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ import coil.request.ImageRequest
|
||||||
import io.element.android.x.architecture.Async
|
import io.element.android.x.architecture.Async
|
||||||
import io.element.android.x.core.compose.LogCompositions
|
import io.element.android.x.core.compose.LogCompositions
|
||||||
import io.element.android.x.core.compose.textFieldState
|
import io.element.android.x.core.compose.textFieldState
|
||||||
import io.element.android.x.designsystem.ElementXTheme
|
|
||||||
import io.element.android.x.designsystem.components.LabelledCheckbox
|
import io.element.android.x.designsystem.components.LabelledCheckbox
|
||||||
import io.element.android.x.designsystem.components.dialogs.ErrorDialog
|
import io.element.android.x.designsystem.components.dialogs.ErrorDialog
|
||||||
import io.element.android.x.ui.strings.R as StringR
|
import io.element.android.x.ui.strings.R as StringR
|
||||||
|
|
@ -213,9 +212,7 @@ fun BugReportView(
|
||||||
@Composable
|
@Composable
|
||||||
@Preview
|
@Preview
|
||||||
fun BugReportContentPreview() {
|
fun BugReportContentPreview() {
|
||||||
ElementXTheme(darkTheme = false) {
|
BugReportView(
|
||||||
BugReportView(
|
state = BugReportState(),
|
||||||
state = BugReportState(),
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import io.element.android.x.core.compose.LogCompositions
|
import io.element.android.x.core.compose.LogCompositions
|
||||||
import io.element.android.x.designsystem.ElementXTheme
|
|
||||||
import io.element.android.x.designsystem.components.dialogs.ConfirmationDialog
|
import io.element.android.x.designsystem.components.dialogs.ConfirmationDialog
|
||||||
import io.element.android.x.ui.strings.R as StringR
|
import io.element.android.x.ui.strings.R as StringR
|
||||||
|
|
||||||
|
|
@ -66,9 +65,7 @@ fun CrashDetectionContent(
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun CrashDetectionContentPreview() {
|
fun CrashDetectionContentPreview() {
|
||||||
ElementXTheme {
|
CrashDetectionContent(
|
||||||
CrashDetectionContent(
|
state = CrashDetectionState()
|
||||||
state = CrashDetectionState()
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import io.element.android.x.core.compose.OnLifecycleEvent
|
||||||
import io.element.android.x.core.hardware.vibrate
|
import io.element.android.x.core.hardware.vibrate
|
||||||
import io.element.android.x.core.screenshot.ImageResult
|
import io.element.android.x.core.screenshot.ImageResult
|
||||||
import io.element.android.x.core.screenshot.screenshot
|
import io.element.android.x.core.screenshot.screenshot
|
||||||
import io.element.android.x.designsystem.ElementXTheme
|
|
||||||
import io.element.android.x.designsystem.components.dialogs.ConfirmationDialog
|
import io.element.android.x.designsystem.components.dialogs.ConfirmationDialog
|
||||||
import io.element.android.x.ui.strings.R as StringR
|
import io.element.android.x.ui.strings.R as StringR
|
||||||
|
|
||||||
|
|
@ -98,7 +97,5 @@ fun RageshakeDialogContent(
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun RageshakeDialogContentPreview() {
|
fun RageshakeDialogContentPreview() {
|
||||||
ElementXTheme {
|
RageshakeDialogContent()
|
||||||
RageshakeDialogContent()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,12 @@ fun RageshakePreferencesView(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview
|
@Preview
|
||||||
fun RageshakePreferencesPreview() {
|
fun RageshakePreferencesViewPreview() {
|
||||||
RageshakePreferencesView(RageshakePreferencesState(isEnabled = true, isSupported = true, sensitivity = 0.5f))
|
RageshakePreferencesView(RageshakePreferencesState(isEnabled = true, isSupported = true, sensitivity = 0.5f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview
|
||||||
|
fun RageshakePreferenceNotSupportedPreview() {
|
||||||
|
RageshakePreferencesView(RageshakePreferencesState(isEnabled = true, isSupported = false, sensitivity = 0.5f))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.Velocity
|
import androidx.compose.ui.unit.Velocity
|
||||||
import io.element.android.x.core.compose.LogCompositions
|
import io.element.android.x.core.compose.LogCompositions
|
||||||
import io.element.android.x.designsystem.ElementXTheme
|
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||||
import io.element.android.x.features.roomlist.components.RoomListTopBar
|
import io.element.android.x.features.roomlist.components.RoomListTopBar
|
||||||
import io.element.android.x.features.roomlist.components.RoomSummaryRow
|
import io.element.android.x.features.roomlist.components.RoomSummaryRow
|
||||||
|
|
@ -150,30 +149,13 @@ private fun RoomListRoomSummary.contentType() = isPlaceholder
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun PreviewableRoomListView() {
|
fun RoomListViewPreview() {
|
||||||
ElementXTheme(darkTheme = false) {
|
RoomListView(
|
||||||
RoomListView(
|
roomSummaries = stubbedRoomSummaries(),
|
||||||
roomSummaries = stubbedRoomSummaries(),
|
matrixUser = MatrixUser(id = UserId("@id"), username = "User#1", avatarData = AvatarData("U")),
|
||||||
matrixUser = MatrixUser(id = UserId("@id"), username = "User#1", avatarData = AvatarData("U")),
|
onRoomClicked = {},
|
||||||
onRoomClicked = {},
|
filter = "filter",
|
||||||
filter = "filter",
|
onFilterChanged = {},
|
||||||
onFilterChanged = {},
|
onScrollOver = {}
|
||||||
onScrollOver = {}
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview
|
|
||||||
@Composable
|
|
||||||
fun PreviewableDarkRoomListView() {
|
|
||||||
ElementXTheme(darkTheme = true) {
|
|
||||||
RoomListView(
|
|
||||||
roomSummaries = stubbedRoomSummaries(),
|
|
||||||
matrixUser = MatrixUser(id = UserId("@id"), username = "User#1", avatarData = AvatarData("U")),
|
|
||||||
onRoomClicked = {},
|
|
||||||
filter = "filter",
|
|
||||||
onFilterChanged = {},
|
|
||||||
onScrollOver = {}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ test_junitext = "1.1.3"
|
||||||
test_barista = "4.2.0"
|
test_barista = "4.2.0"
|
||||||
test_hamcrest = "2.2"
|
test_hamcrest = "2.2"
|
||||||
test_orchestrator = "1.4.1"
|
test_orchestrator = "1.4.1"
|
||||||
|
test_paparazzi = "1.2.0"
|
||||||
|
test_parameter_injector = "1.8"
|
||||||
|
|
||||||
#other
|
#other
|
||||||
coil = "2.2.2"
|
coil = "2.2.2"
|
||||||
|
|
@ -110,6 +112,7 @@ test_mockk = { module = "io.mockk:mockk", version.ref = "test_mockk" }
|
||||||
test_barista = { module = "com.adevinta.android:barista", version.ref = "test_barista" }
|
test_barista = { module = "com.adevinta.android:barista", version.ref = "test_barista" }
|
||||||
test_hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "test_hamcrest" }
|
test_hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "test_hamcrest" }
|
||||||
test_orchestrator = { module = "androidx.test:orchestrator", version.ref = "test_orchestrator" }
|
test_orchestrator = { module = "androidx.test:orchestrator", version.ref = "test_orchestrator" }
|
||||||
|
test_parameter_injector = { module = "com.google.testparameterinjector:test-parameter-injector", version.ref = "test_parameter_injector" }
|
||||||
|
|
||||||
# Others
|
# Others
|
||||||
coil = { module = "io.coil-kt:coil", version.ref = "coil" }
|
coil = { module = "io.coil-kt:coil", version.ref = "coil" }
|
||||||
|
|
@ -148,3 +151,4 @@ dependencygraph = { id = "com.savvasdalkitsis.module-dependency-graph", version.
|
||||||
dependencycheck = { id = "org.owasp.dependencycheck", version.ref = "dependencycheck" }
|
dependencycheck = { id = "org.owasp.dependencycheck", version.ref = "dependencycheck" }
|
||||||
stem = { id = "com.likethesalad.stem", version.ref = "stem" }
|
stem = { id = "com.likethesalad.stem", version.ref = "stem" }
|
||||||
stemlibrary = { id = "com.likethesalad.stem-library", version.ref = "stem" }
|
stemlibrary = { id = "com.likethesalad.stem-library", version.ref = "stem" }
|
||||||
|
paparazzi = { id = "app.cash.paparazzi", version.ref = "test_paparazzi" }
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,6 @@ private fun InitialsAvatar(
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun InitialsAvatar() {
|
fun InitialsAvatarPreview() {
|
||||||
InitialsAvatar(AvatarData("A"))
|
Avatar(AvatarData(name = "A"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ fun PreferenceCategory(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview(showBackground = false)
|
@Preview
|
||||||
fun PreferenceCategoryPreview() {
|
fun PreferenceCategoryPreview() {
|
||||||
PreferenceCategory(
|
PreferenceCategory(
|
||||||
title = "Category title",
|
title = "Category title",
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ fun PreferenceTopAppBar(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview(showBackground = false)
|
@Preview
|
||||||
fun PreferenceScreenPreview() {
|
fun PreferenceScreenPreview() {
|
||||||
PreferenceView(
|
PreferenceView(
|
||||||
title = "Preference screen"
|
title = "Preference screen"
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ fun PreferenceSlide(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview(showBackground = false)
|
@Preview
|
||||||
fun PreferenceSlidePreview() {
|
fun PreferenceSlidePreview() {
|
||||||
PreferenceSlide(
|
PreferenceSlide(
|
||||||
title = "Slide",
|
title = "Slide",
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ fun PreferenceSwitch(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview(showBackground = false)
|
@Preview
|
||||||
fun PreferenceSwitchPreview() {
|
fun PreferenceSwitchPreview() {
|
||||||
PreferenceSwitch(
|
PreferenceSwitch(
|
||||||
title = "Switch",
|
title = "Switch",
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ fun PreferenceText(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview(showBackground = false)
|
@Preview
|
||||||
fun PreferenceTextPreview() {
|
fun PreferenceTextPreview() {
|
||||||
PreferenceText(
|
PreferenceText(
|
||||||
title = "Title",
|
title = "Title",
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import io.element.android.x.designsystem.ElementXTheme
|
|
||||||
import io.element.android.x.designsystem.components.avatar.Avatar
|
import io.element.android.x.designsystem.components.avatar.Avatar
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
import io.element.android.x.designsystem.components.avatar.AvatarSize
|
||||||
|
|
@ -84,29 +83,25 @@ fun MatrixUserHeader(
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun MatrixUserHeaderPreview() {
|
fun MatrixUserHeaderPreview() {
|
||||||
ElementXTheme {
|
MatrixUserHeader(
|
||||||
MatrixUserHeader(
|
MatrixUser(
|
||||||
MatrixUser(
|
id = UserId("@alice:server.org"),
|
||||||
id = UserId("@alice:server.org"),
|
username = "Alice",
|
||||||
username = "Alice",
|
avatarUrl = null,
|
||||||
avatarUrl = null,
|
avatarData = AvatarData("Alice")
|
||||||
avatarData = AvatarData("Alice")
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun MatrixUserHeaderNoUsernamePreview() {
|
fun MatrixUserHeaderNoUsernamePreview() {
|
||||||
ElementXTheme {
|
MatrixUserHeader(
|
||||||
MatrixUserHeader(
|
MatrixUser(
|
||||||
MatrixUser(
|
id = UserId("@alice:server.org"),
|
||||||
id = UserId("@alice:server.org"),
|
username = null,
|
||||||
username = null,
|
avatarUrl = null,
|
||||||
avatarUrl = null,
|
avatarData = AvatarData("Alice")
|
||||||
avatarData = AvatarData("Alice")
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import io.element.android.x.designsystem.ElementXTheme
|
|
||||||
import io.element.android.x.designsystem.components.avatar.Avatar
|
import io.element.android.x.designsystem.components.avatar.Avatar
|
||||||
import io.element.android.x.designsystem.components.avatar.AvatarData
|
import io.element.android.x.designsystem.components.avatar.AvatarData
|
||||||
import io.element.android.x.matrix.core.UserId
|
import io.element.android.x.matrix.core.UserId
|
||||||
|
|
@ -88,14 +87,12 @@ fun MatrixUserRow(
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun MatrixUserRowPreview() {
|
fun MatrixUserRowPreview() {
|
||||||
ElementXTheme {
|
MatrixUserRow(
|
||||||
MatrixUserRow(
|
MatrixUser(
|
||||||
MatrixUser(
|
id = UserId("@alice:server.org"),
|
||||||
id = UserId("@alice:server.org"),
|
username = "Alice",
|
||||||
username = "Alice",
|
avatarUrl = null,
|
||||||
avatarUrl = null,
|
avatarData = AvatarData("Alice")
|
||||||
avatarData = AvatarData("Alice")
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package io.element.android.x.textcomposer
|
||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
|
@ -42,6 +41,7 @@ fun TextComposer(
|
||||||
composerText: String?,
|
composerText: String?,
|
||||||
composerMode: MessageComposerMode,
|
composerMode: MessageComposerMode,
|
||||||
composerCanSendMessage: Boolean,
|
composerCanSendMessage: Boolean,
|
||||||
|
isInDarkMode: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onSendMessage: (String) -> Unit = {},
|
onSendMessage: (String) -> Unit = {},
|
||||||
onFullscreenToggle: () -> Unit = {},
|
onFullscreenToggle: () -> Unit = {},
|
||||||
|
|
@ -51,7 +51,6 @@ fun TextComposer(
|
||||||
if (LocalInspectionMode.current) {
|
if (LocalInspectionMode.current) {
|
||||||
FakeComposer(modifier)
|
FakeComposer(modifier)
|
||||||
} else {
|
} else {
|
||||||
val isInDarkMode = isSystemInDarkTheme()
|
|
||||||
AndroidView(
|
AndroidView(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
factory = { context ->
|
factory = { context ->
|
||||||
|
|
@ -156,5 +155,6 @@ fun TextComposerPreview() {
|
||||||
onCloseSpecialMode = {},
|
onCloseSpecialMode = {},
|
||||||
composerCanSendMessage = true,
|
composerCanSendMessage = true,
|
||||||
composerText = "Message",
|
composerText = "Message",
|
||||||
|
isInDarkMode = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import gradle.kotlin.dsl.accessors._4b7ad2363fc1fce7c774e054dc9a9300.androidTest
|
||||||
import gradle.kotlin.dsl.accessors._4b7ad2363fc1fce7c774e054dc9a9300.debugImplementation
|
import gradle.kotlin.dsl.accessors._4b7ad2363fc1fce7c774e054dc9a9300.debugImplementation
|
||||||
import gradle.kotlin.dsl.accessors._4b7ad2363fc1fce7c774e054dc9a9300.implementation
|
import gradle.kotlin.dsl.accessors._4b7ad2363fc1fce7c774e054dc9a9300.implementation
|
||||||
import org.gradle.kotlin.dsl.DependencyHandlerScope
|
import org.gradle.kotlin.dsl.DependencyHandlerScope
|
||||||
|
import org.gradle.kotlin.dsl.project
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dependencies used by all the modules
|
* Dependencies used by all the modules
|
||||||
|
|
@ -48,3 +49,21 @@ fun DependencyHandlerScope.composeDependencies() {
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.5")
|
implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.5")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun DependencyHandlerScope.allLibraries() {
|
||||||
|
implementation(project(":libraries:designsystem"))
|
||||||
|
implementation(project(":libraries:matrix"))
|
||||||
|
implementation(project(":libraries:matrixui"))
|
||||||
|
implementation(project(":libraries:core"))
|
||||||
|
implementation(project(":libraries:architecture"))
|
||||||
|
implementation(project(":libraries:di"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DependencyHandlerScope.allFeatures() {
|
||||||
|
implementation(project(":features:onboarding"))
|
||||||
|
implementation(project(":features:login"))
|
||||||
|
implementation(project(":features:logout"))
|
||||||
|
implementation(project(":features:roomlist"))
|
||||||
|
implementation(project(":features:messages"))
|
||||||
|
implementation(project(":features:rageshake"))
|
||||||
|
implementation(project(":features:preferences"))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,14 @@ plugins {
|
||||||
android {
|
android {
|
||||||
androidConfig(project)
|
androidConfig(project)
|
||||||
composeConfig()
|
composeConfig()
|
||||||
|
// Waiting for https://github.com/google/ksp/issues/37
|
||||||
|
libraryVariants.all {
|
||||||
|
kotlin.sourceSets {
|
||||||
|
getByName(name) {
|
||||||
|
kotlin.srcDir("build/generated/ksp/$name/kotlin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,14 @@ plugins {
|
||||||
|
|
||||||
android {
|
android {
|
||||||
androidConfig(project)
|
androidConfig(project)
|
||||||
|
// Waiting for https://github.com/google/ksp/issues/37
|
||||||
|
libraryVariants.all {
|
||||||
|
kotlin.sourceSets {
|
||||||
|
getByName(name) {
|
||||||
|
kotlin.srcDir("build/generated/ksp/$name/kotlin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ include(":features:rageshake")
|
||||||
include(":features:preferences")
|
include(":features:preferences")
|
||||||
include(":libraries:designsystem")
|
include(":libraries:designsystem")
|
||||||
include(":libraries:di")
|
include(":libraries:di")
|
||||||
|
include(":tests:uitests")
|
||||||
include(":anvilannotations")
|
include(":anvilannotations")
|
||||||
include(":anvilcodegen")
|
include(":anvilcodegen")
|
||||||
include(":libraries:architecture")
|
include(":libraries:architecture")
|
||||||
|
|
|
||||||
1
tests/uitests/.gitignore
vendored
Normal file
1
tests/uitests/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
||||||
44
tests/uitests/build.gradle.kts
Normal file
44
tests/uitests/build.gradle.kts
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import extension.allFeatures
|
||||||
|
import extension.allLibraries
|
||||||
|
|
||||||
|
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
|
||||||
|
@Suppress("DSL_SCOPE_VIOLATION")
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-compose-library")
|
||||||
|
alias(libs.plugins.ksp)
|
||||||
|
alias(libs.plugins.paparazzi)
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.x.tests.uitests"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation(libs.test.junit)
|
||||||
|
testImplementation(libs.test.parameter.injector)
|
||||||
|
androidTestImplementation(libs.test.junitext)
|
||||||
|
ksp(libs.showkase.processor)
|
||||||
|
kspTest(libs.showkase.processor)
|
||||||
|
|
||||||
|
implementation(libs.showkase)
|
||||||
|
ksp(libs.showkase.processor)
|
||||||
|
|
||||||
|
allLibraries()
|
||||||
|
allFeatures()
|
||||||
|
}
|
||||||
0
tests/uitests/consumer-rules.pro
Normal file
0
tests/uitests/consumer-rules.pro
Normal file
21
tests/uitests/proguard-rules.pro
vendored
Normal file
21
tests/uitests/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.kts.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
18
tests/uitests/src/main/AndroidManifest.xml
Normal file
18
tests/uitests/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2022 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest/>
|
||||||
|
|
@ -14,10 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.x
|
package io.element.android.x.tests.uitests
|
||||||
|
|
||||||
import com.airbnb.android.showkase.annotation.ShowkaseRoot
|
import com.airbnb.android.showkase.annotation.ShowkaseRoot
|
||||||
import com.airbnb.android.showkase.annotation.ShowkaseRootModule
|
import com.airbnb.android.showkase.annotation.ShowkaseRootModule
|
||||||
|
|
||||||
@ShowkaseRoot
|
@ShowkaseRoot
|
||||||
class ElementRootModule : ShowkaseRootModule
|
class ElementXShowkaseRootModule : ShowkaseRootModule
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.x.tests.uitests
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Close
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ShowkaseButton(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onClick: () -> Unit = {},
|
||||||
|
) {
|
||||||
|
var isShowkaseButtonVisible by remember { mutableStateOf(BuildConfig.DEBUG) }
|
||||||
|
|
||||||
|
if (isShowkaseButtonVisible) {
|
||||||
|
Button(
|
||||||
|
modifier = modifier
|
||||||
|
.padding(top = 32.dp),
|
||||||
|
onClick = onClick
|
||||||
|
) {
|
||||||
|
Text(text = "Showkase Browser")
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 8.dp)
|
||||||
|
.size(16.dp),
|
||||||
|
onClick = { isShowkaseButtonVisible = false },
|
||||||
|
) {
|
||||||
|
Icon(imageVector = Icons.Filled.Close, contentDescription = "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(group = "Buttons", name = "Showkase button")
|
||||||
|
@Composable
|
||||||
|
fun ShowkaseButtonPreview() {
|
||||||
|
ShowkaseButton()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.x.tests.uitests
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import com.airbnb.android.showkase.models.Showkase
|
||||||
|
|
||||||
|
fun openShowkase(activity: Activity) {
|
||||||
|
activity.startActivity(Showkase.getBrowserIntent(activity))
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.x.tests.uitests
|
||||||
|
|
||||||
|
import app.cash.paparazzi.DeviceConfig
|
||||||
|
|
||||||
|
enum class BaseDeviceConfig(
|
||||||
|
val deviceConfig: DeviceConfig,
|
||||||
|
) {
|
||||||
|
NEXUS_5(DeviceConfig.NEXUS_5),
|
||||||
|
// PIXEL_C(DeviceConfig.PIXEL_C),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.x.tests.uitests
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.airbnb.android.showkase.models.ShowkaseBrowserColor
|
||||||
|
|
||||||
|
class ColorTestPreview(
|
||||||
|
private val showkaseBrowserColor: ShowkaseBrowserColor
|
||||||
|
) : TestPreview {
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(250.dp)
|
||||||
|
.background(showkaseBrowserColor.color)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "Color_${showkaseBrowserColor.colorGroup}_${showkaseBrowserColor.colorName}"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.x.tests.uitests
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import com.airbnb.android.showkase.models.ShowkaseBrowserComponent
|
||||||
|
|
||||||
|
class ComponentTestPreview(
|
||||||
|
private val showkaseBrowserComponent: ShowkaseBrowserComponent
|
||||||
|
) : TestPreview {
|
||||||
|
@Composable
|
||||||
|
override fun Content() = showkaseBrowserComponent.component()
|
||||||
|
override fun toString(): String = showkaseBrowserComponent.componentKey
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 The Android Open Source Project
|
||||||
|
* Copyright (c) 2022 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
|
||||||
|
*
|
||||||
|
* https://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.x.tests.uitests
|
||||||
|
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.os.LocaleList
|
||||||
|
import androidx.activity.OnBackPressedDispatcher
|
||||||
|
import androidx.activity.OnBackPressedDispatcherOwner
|
||||||
|
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.platform.LocalInspectionMode
|
||||||
|
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
|
import androidx.compose.ui.unit.Density
|
||||||
|
import app.cash.paparazzi.Paparazzi
|
||||||
|
import com.airbnb.android.showkase.models.Showkase
|
||||||
|
import com.google.testing.junit.testparameterinjector.TestParameter
|
||||||
|
import com.google.testing.junit.testparameterinjector.TestParameterInjector
|
||||||
|
import io.element.android.x.designsystem.ElementXTheme
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BMA: Inspired from https://github.com/airbnb/Showkase/blob/master/showkase-screenshot-testing-paparazzi-sample/src/test/java/com/airbnb/android/showkase/screenshot/testing/paparazzi/sample/PaparazziSampleScreenshotTest.kt
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Credit to Alex Vanyo for creating this sample in the Now In Android app by Google.
|
||||||
|
* PR here - https://github.com/android/nowinandroid/pull/101. Modified the test from that PR to
|
||||||
|
* my own needs for this sample.
|
||||||
|
*/
|
||||||
|
@RunWith(TestParameterInjector::class)
|
||||||
|
class ScreenshotTest {
|
||||||
|
|
||||||
|
object PreviewProvider : TestParameter.TestParameterValuesProvider {
|
||||||
|
override fun provideValues(): List<TestPreview> {
|
||||||
|
val metadata = Showkase.getMetadata()
|
||||||
|
val components = metadata.componentList.map(::ComponentTestPreview)
|
||||||
|
val colors = metadata.colorList.map(::ColorTestPreview)
|
||||||
|
val typography = metadata.typographyList.map(::TypographyTestPreview)
|
||||||
|
|
||||||
|
return components + colors + typography
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val paparazzi = Paparazzi(
|
||||||
|
maxPercentDifference = 0.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun preview_tests(
|
||||||
|
@TestParameter(valuesProvider = PreviewProvider::class) componentTestPreview: TestPreview,
|
||||||
|
@TestParameter baseDeviceConfig: BaseDeviceConfig,
|
||||||
|
@TestParameter(value = ["1.0"/*, "1.5"*/]) fontScale: Float,
|
||||||
|
@TestParameter(value = ["light", "dark"]) theme: String,
|
||||||
|
@TestParameter(value = ["en" /*"fr", "de", "ru"*/]) localeStr: String,
|
||||||
|
) {
|
||||||
|
paparazzi.unsafeUpdateConfig(
|
||||||
|
deviceConfig = baseDeviceConfig.deviceConfig.copy(
|
||||||
|
softButtons = false,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
paparazzi.snapshot {
|
||||||
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
|
CompositionLocalProvider(
|
||||||
|
LocalInspectionMode provides true,
|
||||||
|
LocalDensity provides Density(
|
||||||
|
density = LocalDensity.current.density,
|
||||||
|
fontScale = fontScale
|
||||||
|
),
|
||||||
|
LocalConfiguration provides Configuration().apply {
|
||||||
|
setLocales(LocaleList(localeStr.toLocale()))
|
||||||
|
},
|
||||||
|
// Needed so that UI that uses it don't crash during screenshot tests
|
||||||
|
LocalOnBackPressedDispatcherOwner provides object : OnBackPressedDispatcherOwner {
|
||||||
|
override fun getLifecycle() = lifecycleOwner.lifecycle
|
||||||
|
|
||||||
|
override fun getOnBackPressedDispatcher() = OnBackPressedDispatcher()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
ElementXTheme(darkTheme = (theme == "dark")) {
|
||||||
|
Box(modifier = Modifier.background(MaterialTheme.colorScheme.background)) {
|
||||||
|
componentTestPreview.Content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.toLocale(): Locale {
|
||||||
|
return when (this) {
|
||||||
|
"en" -> Locale.ENGLISH
|
||||||
|
"fr" -> Locale.FRANCE
|
||||||
|
"de" -> Locale.GERMAN
|
||||||
|
else -> Locale.Builder().setLanguage(this).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.x.tests.uitests
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
interface TestPreview {
|
||||||
|
@Composable
|
||||||
|
fun Content()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.x.tests.uitests
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.text.BasicText
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import com.airbnb.android.showkase.models.ShowkaseBrowserTypography
|
||||||
|
import com.airbnb.android.showkase.ui.padding4x
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
class TypographyTestPreview(
|
||||||
|
private val showkaseBrowserTypography: ShowkaseBrowserTypography
|
||||||
|
) : TestPreview {
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
BasicText(
|
||||||
|
text = showkaseBrowserTypography.typographyName.replaceFirstChar {
|
||||||
|
it.titlecase(Locale.getDefault())
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(padding4x),
|
||||||
|
style = showkaseBrowserTypography.textStyle.copy(
|
||||||
|
color = MaterialTheme.colorScheme.onBackground
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "Typo_${showkaseBrowserTypography.typographyGroup}_${showkaseBrowserTypography.typographyName}"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:457c973681addb003e8f84ce3706361cfe0bb88845799838971da910476a4ba8
|
||||||
|
size 4371
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:0c51ed0a004218e97af5f34e3011e0c4e4b50cccf0eff1417234186bdb786839
|
||||||
|
size 4983
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:f2c05b0f79fea3df1147a454202f1ca2973d48939e4fc296be171ad98f272333
|
||||||
|
size 4371
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1042b183b2703322af7a43d959992340b47618b27d706cfba8cf1556e70f793e
|
||||||
|
size 4984
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1d1b2622226f026d0231020c389b6e99a1c50cd0bc84d77df6060e390c8521fb
|
||||||
|
size 7056
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:77dcd8feab45cb713f3ee6cdc8ad86189e73176e0eff88494a2cb109431ddb33
|
||||||
|
size 7097
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:de0b7b271b6057db6ef81888356583bdc3432e4f26a52c58586f88043de20021
|
||||||
|
size 9476
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d02db7b3881676d8b194e6871e178af8af99e09bd5cc15b865a25bd405e3fc33
|
||||||
|
size 9445
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:9c0fb883d948d8177cd32eb81b24e7b104acd7b6b120b73d6693088f947701da
|
||||||
|
size 8295
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4a3e98c7f5dfc7bc02aa68d4c6da8ccd6b1e4a583f98900037417e69e5c184f4
|
||||||
|
size 8058
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:f6d88788a186b08d8e2834c39efb1c6476cf51aec70aa08dc806eb69e2d98d9a
|
||||||
|
size 20004
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:45860d45aefad7cfd7d7b9f92146799860a5ede7e815d5b28b606fc566b3838c
|
||||||
|
size 18344
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:39d924e3718d7f045c15888373a96ec85d4afd0ef405bf25edc453fddaacdc55
|
||||||
|
size 13082
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:5e5bf72f9d90cbe4b4136a4a2e30168895a3354c6f35ed1d4fc77bfe2987fdaf
|
||||||
|
size 12565
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4e23f8342179fc1a88c278f8e81ddb026034958a6b2fdbaae06ff26dc282d483
|
||||||
|
size 11654
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:64ed4f47adfb9f111552f44d7a1f3edf58ec1ab64527c2a5dd08b286b7437317
|
||||||
|
size 15076
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e258d66c313c6fd1e757978c408600328220aa4bcd374b19d202d2a45b1db3bb
|
||||||
|
size 18677
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:2e1f1e25446962151e621f230e4043ad3a649a7e71b65527fe73158478a4caaf
|
||||||
|
size 18709
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:eb61547b9e5b4666abd74145086ae2ee846dced3099f9b36dd2534047caf3266
|
||||||
|
size 8465
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e52fc3b6131d68424f77ecbf226ec80ad6d4e97a22fe8dbbf38cff301d918dc3
|
||||||
|
size 8619
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d5db2a9a3f2d9bec3d74b45892ee453c51afc3b3b41d6ec1624d72a8377176b4
|
||||||
|
size 7095
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:c01eabc9eb8d607d77070deb227365e8840e02b50b1adb0cb1f24f4d693a68be
|
||||||
|
size 7114
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:b9a36ce6978aa3182e519789a8ea7e1399ae63da630fa7f6727248ba8ba010f7
|
||||||
|
size 4837
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:421660fccaa66dc7190393ba57660a9bc4a439011bd2f7c1ade8b6a293c489bf
|
||||||
|
size 5843
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:f331a07e5b56c550023b9c4eff3afd71fece8dd4d649fd1e2aaa178c27557fda
|
||||||
|
size 5007
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:312b8aed8761fc31f445fee012a020e754c1ca60365f1651c2ffce8310f9ca3c
|
||||||
|
size 7401
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e302ba0695a7663e1abcb98d47cecf5b78968d76202841f9e251313d3dd8c579
|
||||||
|
size 10232
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:08918409e8daa9f2d3498fe9f463323e737e59ec8472a50b6bf5ec13a1abacfc
|
||||||
|
size 9576
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:0689e18b72a961ecbea6011c73568703ba255375fdb9bbe34b2e94f08c379cc7
|
||||||
|
size 27841
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:555b8b55dc2873ab2963ae65ac13e11913794d2e344ec01d53eebe48cbfbcb39
|
||||||
|
size 27048
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:bc2f6c7463b55716720344a2e873774ea09d98717add30b748a54f1e0374ec04
|
||||||
|
size 24751
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:40bbb72871c1eb6f1a9bae19ef5cd63d66eb7e2479eb72733bfa88f912e11957
|
||||||
|
size 24353
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:accc42a849df3c0d8a16de0e21842139558d8c68cdcf9efcccf6b58a7cb3b4b3
|
||||||
|
size 4742
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:48045852c9c677d54db29baa1484eb281aa9678518c4a47ae05e43b4604a77c5
|
||||||
|
size 8369
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:3d5fb95fb866a51e2dbc26239dc70e37a92bddc79d4edc027226948dfe323312
|
||||||
|
size 30189
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:5b7d3c2cf8d466f6e25404596079fb6254ad6e9fb3ba3f0f72ef1c0ba019dc60
|
||||||
|
size 31165
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1be16bc1a73ef5bb7af740b8720c508dbc202d4748d60fb2e10fabcfdeacc75c
|
||||||
|
size 43668
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:02c410850ed4b8658a21c4a60b62757baa9799d4c6dee4d53d2e6b2ca76f7b61
|
||||||
|
size 41942
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:19bcd322392a4d27742a25989810e38d4ac6a38edfb5a228bc13364ed36e7101
|
||||||
|
size 31691
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:0a0ea920c88ab127513918055621a75528de35d69296727a8be7368df4c848e9
|
||||||
|
size 33040
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:3ea0809dcddfc5df7aaba26f4ed74bebe404c86f5923c78541518fb7560e897e
|
||||||
|
size 55699
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:cc36b26cbaab9ee19c898a27bc5bc0a04c77e4004933c47fc69608df103e08d9
|
||||||
|
size 52964
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e50733c48b4cb37fc82c228a7013c7aa74e263b13014cb57c7bb1ca0c2ea91c6
|
||||||
|
size 28631
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:0500e499fb319057b0ca5feb9db9e429266a2832521b429d502d1f62804ee23f
|
||||||
|
size 29222
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:ab7cb0da1b64d2c6d87578debbc336feedbe203f6331726503a084101b9a10e6
|
||||||
|
size 51186
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:5535df19747bdec380b79eec8b9d8e2d7e6ed765fe0bb4e4c1c2ffeb4de46854
|
||||||
|
size 49115
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:a588e13eaa5fef1f93443445c15256037a70771260e24ca4ee6700e55519bf50
|
||||||
|
size 27107
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:58f4e6a4bed5bb2fe4cf2556ee04984dc3efb78ccc4bc501f98f733d1d849289
|
||||||
|
size 26636
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:9cf66a0074d1d7842ee176eb6a5e655fe9ed734a95078731cdacd4d7d8f2a80c
|
||||||
|
size 49391
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:8720a78b76ddac0f5194fd27a991f871cd49e5d51c999cf807493a790ad642c3
|
||||||
|
size 48739
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e04b3a5a4db346d18666fc4df81fdbb1fa84dc526020fdc257c33190e122c11f
|
||||||
|
size 29757
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:af0d4d6e3dcda60a7aa4aa20df2b012359c21d51bc9b94e4ed04b19b1d8f38e4
|
||||||
|
size 28409
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:a4c1e1b89f3692c1441ec502afe20c1b1d3746c996435ba7abfd624ee88995dc
|
||||||
|
size 34328
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:c74aecba85977483d6415f6cacc2a45199f763773fde1a590a96d43d83b2de0e
|
||||||
|
size 32407
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:0a0c3a23a06fa723cf6474fda8f8fb88f876b78d7293121ffb438eddacb834f8
|
||||||
|
size 4895
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:0b5eacc8332a8ec38df9a710d60b9ec87ecab771c764f0ae5f4e7e7dc6fa7cd7
|
||||||
|
size 19974
|
||||||
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