[dev QoL] Added AndroidStudio previews for [presentation.history] namespace (#10012)

* Added display preview for HistoryDialogs

* Added preview with provider for each branch for HistoryItem

* Added previews for HistoryScreen

Created in-memory preferences construct for when its needed at top-level injection

* Fixed ktlint violations
This commit is contained in:
Caleb Morris
2023-10-14 19:23:11 -07:00
committed by GitHub
parent 0be7ac5871
commit 447bcb28ef
7 changed files with 348 additions and 1 deletions

View File

@@ -11,6 +11,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions
@@ -18,13 +19,16 @@ import eu.kanade.presentation.components.AppBarTitle
import eu.kanade.presentation.components.RelativeDateHeader
import eu.kanade.presentation.components.SearchToolbar
import eu.kanade.presentation.history.components.HistoryItem
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.history.HistoryScreenModel
import tachiyomi.core.preference.InMemoryPreferenceStore
import tachiyomi.domain.history.model.HistoryWithRelations
import tachiyomi.presentation.core.components.FastScrollLazyColumn
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.screens.EmptyScreen
import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.presentation.core.util.ThemePreviews
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Date
@@ -37,6 +41,7 @@ fun HistoryScreen(
onClickCover: (mangaId: Long) -> Unit,
onClickResume: (mangaId: Long, chapterId: Long) -> Unit,
onDialogChange: (HistoryScreenModel.Dialog?) -> Unit,
preferences: UiPreferences = Injekt.get(),
) {
Scaffold(
topBar = { scrollBehavior ->
@@ -82,6 +87,7 @@ fun HistoryScreen(
onClickCover = { history -> onClickCover(history.mangaId) },
onClickResume = { history -> onClickResume(history.mangaId, history.chapterId) },
onClickDelete = { item -> onDialogChange(HistoryScreenModel.Dialog.Delete(item)) },
preferences = preferences,
)
}
}
@@ -95,7 +101,7 @@ private fun HistoryScreenContent(
onClickCover: (HistoryWithRelations) -> Unit,
onClickResume: (HistoryWithRelations) -> Unit,
onClickDelete: (HistoryWithRelations) -> Unit,
preferences: UiPreferences = Injekt.get(),
preferences: UiPreferences,
) {
val relativeTime = remember { preferences.relativeTime().get() }
val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat().get()) }
@@ -141,3 +147,32 @@ sealed interface HistoryUiModel {
data class Header(val date: Date) : HistoryUiModel
data class Item(val item: HistoryWithRelations) : HistoryUiModel
}
@ThemePreviews
@Composable
internal fun HistoryScreenPreviews(
@PreviewParameter(HistoryScreenModelStateProvider::class)
historyState: HistoryScreenModel.State,
) {
TachiyomiTheme {
HistoryScreen(
state = historyState,
snackbarHostState = SnackbarHostState(),
onSearchQueryChange = {},
onClickCover = {},
onClickResume = { _, _ -> run {} },
onDialogChange = {},
preferences = UiPreferences(
InMemoryPreferenceStore(
sequenceOf(
InMemoryPreferenceStore.InMemoryPreference(
key = "relative_time_v2",
data = false,
defaultValue = false,
),
),
),
),
)
}
}

View File

@@ -0,0 +1,109 @@
package eu.kanade.presentation.history
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import eu.kanade.tachiyomi.ui.history.HistoryScreenModel
import tachiyomi.domain.history.model.HistoryWithRelations
import tachiyomi.domain.manga.model.MangaCover
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.Date
import kotlin.random.Random
class HistoryScreenModelStateProvider : PreviewParameterProvider<HistoryScreenModel.State> {
private val multiPage = HistoryScreenModel.State(
searchQuery = null,
list =
listOf(HistoryUiModelExamples.headerToday)
.asSequence()
.plus(HistoryUiModelExamples.items().take(3))
.plus(HistoryUiModelExamples.header { it.minus(1, ChronoUnit.DAYS) })
.plus(HistoryUiModelExamples.items().take(1))
.plus(HistoryUiModelExamples.header { it.minus(2, ChronoUnit.DAYS) })
.plus(HistoryUiModelExamples.items().take(7))
.toList(),
dialog = null,
)
private val shortRecent = HistoryScreenModel.State(
searchQuery = null,
list = listOf(
HistoryUiModelExamples.headerToday,
HistoryUiModelExamples.items().first(),
),
dialog = null,
)
private val shortFuture = HistoryScreenModel.State(
searchQuery = null,
list = listOf(
HistoryUiModelExamples.headerTomorrow,
HistoryUiModelExamples.items().first(),
),
dialog = null,
)
private val empty = HistoryScreenModel.State(
searchQuery = null,
list = listOf(),
dialog = null,
)
private val loadingWithSearchQuery = HistoryScreenModel.State(
searchQuery = "Example Search Query",
)
private val loading = HistoryScreenModel.State(
searchQuery = null,
list = null,
dialog = null,
)
override val values: Sequence<HistoryScreenModel.State> = sequenceOf(
multiPage,
shortRecent,
shortFuture,
empty,
loadingWithSearchQuery,
loading,
)
private object HistoryUiModelExamples {
val headerToday = header()
val headerTomorrow =
HistoryUiModel.Header(Date.from(Instant.now().plus(1, ChronoUnit.DAYS)))
fun header(instantBuilder: (Instant) -> Instant = { it }) =
HistoryUiModel.Header(Date.from(instantBuilder(Instant.now())))
fun items() = sequence {
var count = 1
while (true) {
yield(randItem { it.copy(title = "Example Title $count") })
count += 1
}
}
fun randItem(historyBuilder: (HistoryWithRelations) -> HistoryWithRelations = { it }) =
HistoryUiModel.Item(
historyBuilder(
HistoryWithRelations(
id = Random.nextLong(),
chapterId = Random.nextLong(),
mangaId = Random.nextLong(),
title = "Test Title",
chapterNumber = Random.nextDouble(),
readAt = Date.from(Instant.now()),
readDuration = Random.nextLong(),
coverData = MangaCover(
mangaId = Random.nextLong(),
sourceId = Random.nextLong(),
isMangaFavorite = Random.nextBoolean(),
url = "https://example.com/cover.png",
lastModified = Random.nextLong(),
),
),
),
)
}
}

View File

@@ -0,0 +1,13 @@
package eu.kanade.presentation.history
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import java.time.Instant
import java.util.Date
object HistoryUiModelProviders {
class HeadNow : PreviewParameterProvider<HistoryUiModel> {
override val values: Sequence<HistoryUiModel> =
sequenceOf(HistoryUiModel.Header(Date.from(Instant.now())))
}
}

View File

@@ -18,7 +18,9 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.R
import tachiyomi.presentation.core.util.ThemePreviews
@Composable
fun HistoryDeleteDialog(
@@ -101,3 +103,14 @@ fun HistoryDeleteAllDialog(
},
)
}
@ThemePreviews
@Composable
internal fun HistoryDeleteDialogPreview() {
TachiyomiTheme {
HistoryDeleteDialog(
onDismissRequest = {},
onDelete = { _ -> run {} },
)
}
}

View File

@@ -19,13 +19,16 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.presentation.util.formatChapterNumber
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.lang.toTimestampString
import tachiyomi.domain.history.model.HistoryWithRelations
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.util.ThemePreviews
private val HISTORY_ITEM_HEIGHT = 96.dp
@@ -87,3 +90,19 @@ fun HistoryItem(
}
}
}
@ThemePreviews
@Composable
internal fun HistoryItemPreviews(
@PreviewParameter(HistoryWithRelationsProvider::class)
historyWithRelations: HistoryWithRelations,
) {
TachiyomiTheme {
HistoryItem(
history = historyWithRelations,
onClickCover = {},
onClickResume = {},
onClickDelete = {},
)
}
}

View File

@@ -0,0 +1,62 @@
package eu.kanade.presentation.history.components
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import tachiyomi.domain.history.model.HistoryWithRelations
import java.util.Date
internal class HistoryWithRelationsProvider : PreviewParameterProvider<HistoryWithRelations> {
private val simple = HistoryWithRelations(
id = 1L,
chapterId = 2L,
mangaId = 3L,
title = "Test Title",
chapterNumber = 10.2,
readAt = Date(1697247357L),
readDuration = 123L,
coverData = tachiyomi.domain.manga.model.MangaCover(
mangaId = 3L,
sourceId = 4L,
isMangaFavorite = false,
url = "https://example.com/cover.png",
lastModified = 5L,
),
)
private val historyWithoutReadAt = HistoryWithRelations(
id = 1L,
chapterId = 2L,
mangaId = 3L,
title = "Test Title",
chapterNumber = 10.2,
readAt = null,
readDuration = 123L,
coverData = tachiyomi.domain.manga.model.MangaCover(
mangaId = 3L,
sourceId = 4L,
isMangaFavorite = false,
url = "https://example.com/cover.png",
lastModified = 5L,
),
)
private val historyWithNegativeChapterNumber = HistoryWithRelations(
id = 1L,
chapterId = 2L,
mangaId = 3L,
title = "Test Title",
chapterNumber = -2.0,
readAt = Date(1697247357L),
readDuration = 123L,
coverData = tachiyomi.domain.manga.model.MangaCover(
mangaId = 3L,
sourceId = 4L,
isMangaFavorite = false,
url = "https://example.com/cover.png",
lastModified = 5L,
),
)
override val values: Sequence<HistoryWithRelations>
get() = sequenceOf(simple, historyWithoutReadAt, historyWithNegativeChapterNumber)
}