[dev QoL] Added AndroidStudio previews for [presentation.track] namespace (#10022)

* Created DummyTracker for use in tests and presentation previews

* Added previews for TrackerSearch

* Added previews for TrackLogoIcon

* Added preview for TrackInfoDialogSelector

* Added previews for TrackInfoDialogHome
This commit is contained in:
Caleb Morris 2023-10-22 06:30:34 -07:00 committed by GitHub
parent dcc3141080
commit 6d1e520c6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 367 additions and 0 deletions

View file

@ -44,14 +44,17 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.domain.track.model.toDbTrack import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.presentation.components.DropdownMenu import eu.kanade.presentation.components.DropdownMenu
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.presentation.track.components.TrackLogoIcon import eu.kanade.presentation.track.components.TrackLogoIcon
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.copyToClipboard
import tachiyomi.presentation.core.util.ThemePreviews
import java.text.DateFormat import java.text.DateFormat
private const val UnsetStatusTextAlpha = 0.5F private const val UnsetStatusTextAlpha = 0.5F
@ -168,6 +171,7 @@ private fun TrackInfoItem(
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface,
) )
} }
VerticalDivider() VerticalDivider()
@ -254,6 +258,7 @@ private fun TrackDetailsItem(
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
color = MaterialTheme.colorScheme.onSurface,
) )
} }
} }
@ -312,3 +317,12 @@ private fun TrackInfoItemMenu(
} }
} }
} }
@ThemePreviews
@Composable
private fun TrackInfoDialogHomePreviews(
@PreviewParameter(TrackInfoDialogHomePreviewProvider::class)
content: @Composable () -> Unit,
) {
TachiyomiTheme { content() }
}

View file

@ -0,0 +1,81 @@
package eu.kanade.presentation.track
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import eu.kanade.tachiyomi.dev.preview.DummyTracker
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import tachiyomi.domain.track.model.Track
import java.text.DateFormat
internal class TrackInfoDialogHomePreviewProvider :
PreviewParameterProvider<@Composable () -> Unit> {
private val aTrack = Track(
id = 1L,
mangaId = 2L,
syncId = 3L,
remoteId = 4L,
libraryId = null,
title = "Manage Name On Tracker Site",
lastChapterRead = 2.0,
totalChapters = 12L,
status = 1L,
score = 2.0,
remoteUrl = "https://example.com",
startDate = 0L,
finishDate = 0L,
)
private val trackItemWithoutTrack = TrackItem(
track = null,
tracker = DummyTracker(
id = 1L,
name = "Example Tracker",
),
)
private val trackItemWithTrack = TrackItem(
track = aTrack,
tracker = DummyTracker(
id = 2L,
name = "Example Tracker 2",
),
)
private val trackersWithAndWithoutTrack = @Composable {
TrackInfoDialogHome(
trackItems = listOf(
trackItemWithoutTrack,
trackItemWithTrack,
),
dateFormat = DateFormat.getDateInstance(),
onStatusClick = {},
onChapterClick = {},
onScoreClick = {},
onStartDateEdit = {},
onEndDateEdit = {},
onNewSearch = {},
onOpenInBrowser = {},
onRemoved = {},
)
}
private val noTrackers = @Composable {
TrackInfoDialogHome(
trackItems = listOf(),
dateFormat = DateFormat.getDateInstance(),
onStatusClick = {},
onChapterClick = {},
onScoreClick = {},
onStartDateEdit = {},
onEndDateEdit = {},
onNewSearch = {},
onOpenInBrowser = {},
onRemoved = {},
)
}
override val values: Sequence<@Composable () -> Unit>
get() = sequenceOf(
trackersWithAndWithoutTrack,
noTrackers,
)
}

View file

@ -30,12 +30,14 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.ScrollbarLazyColumn
import tachiyomi.presentation.core.components.WheelNumberPicker import tachiyomi.presentation.core.components.WheelNumberPicker
import tachiyomi.presentation.core.components.WheelTextPicker import tachiyomi.presentation.core.components.WheelTextPicker
import tachiyomi.presentation.core.components.material.AlertDialogContent import tachiyomi.presentation.core.components.material.AlertDialogContent
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.util.ThemePreviews
import tachiyomi.presentation.core.util.isScrolledToEnd import tachiyomi.presentation.core.util.isScrolledToEnd
import tachiyomi.presentation.core.util.isScrolledToStart import tachiyomi.presentation.core.util.isScrolledToStart
@ -218,3 +220,25 @@ private fun BaseSelector(
}, },
) )
} }
@ThemePreviews
@Composable
private fun TrackStatusSelectorPreviews() {
TachiyomiTheme {
TrackStatusSelector(
selection = 1,
onSelectionChange = {},
selections = mapOf(
// Anilist values
1 to R.string.reading,
2 to R.string.plan_to_read,
3 to R.string.completed,
4 to R.string.on_hold,
5 to R.string.dropped,
6 to R.string.repeating,
),
onConfirm = {},
onDismissRequest = {},
)
}
}

View file

@ -57,8 +57,10 @@ import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.toLowerCase import androidx.compose.ui.text.toLowerCase
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.manga.components.MangaCover import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.ScrollbarLazyColumn
@ -66,6 +68,7 @@ import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreen
import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.presentation.core.util.ThemePreviews
import tachiyomi.presentation.core.util.plus import tachiyomi.presentation.core.util.plus
import tachiyomi.presentation.core.util.runOnEnterKeyPressed import tachiyomi.presentation.core.util.runOnEnterKeyPressed
import tachiyomi.presentation.core.util.secondaryItemAlpha import tachiyomi.presentation.core.util.secondaryItemAlpha
@ -316,3 +319,12 @@ private fun SearchResultItemDetails(
) )
} }
} }
@ThemePreviews
@Composable
private fun TrackerSearchPreviews(
@PreviewParameter(TrackerSearchPreviewProvider::class)
content: @Composable () -> Unit,
) {
TachiyomiTheme { content() }
}

View file

@ -0,0 +1,84 @@
package eu.kanade.presentation.track
import androidx.compose.runtime.Composable
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import java.time.Instant
import java.time.temporal.ChronoUnit
import kotlin.random.Random
internal class TrackerSearchPreviewProvider : PreviewParameterProvider<@Composable () -> Unit> {
private val fullPageWithSecondSelected = @Composable {
val items = someTrackSearches().take(30).toList()
TrackerSearch(
query = TextFieldValue(text = "search text"),
onQueryChange = {},
onDispatchQuery = {},
queryResult = Result.success(items),
selected = items[1],
onSelectedChange = {},
onConfirmSelection = {},
onDismissRequest = {},
)
}
private val fullPageWithoutSelected = @Composable {
TrackerSearch(
query = TextFieldValue(text = ""),
onQueryChange = {},
onDispatchQuery = {},
queryResult = Result.success(someTrackSearches().take(30).toList()),
selected = null,
onSelectedChange = {},
onConfirmSelection = {},
onDismissRequest = {},
)
}
private val loading = @Composable {
TrackerSearch(
query = TextFieldValue(),
onQueryChange = {},
onDispatchQuery = {},
queryResult = null,
selected = null,
onSelectedChange = {},
onConfirmSelection = {},
onDismissRequest = {},
)
}
override val values: Sequence<@Composable () -> Unit> = sequenceOf(
fullPageWithSecondSelected,
fullPageWithoutSelected,
loading,
)
private fun someTrackSearches(): Sequence<TrackSearch> = sequence {
while (true) {
yield(randTrackSearch())
}
}
private fun randTrackSearch() = TrackSearch().let {
it.id = Random.nextLong()
it.manga_id = Random.nextLong()
it.sync_id = Random.nextInt()
it.media_id = Random.nextLong()
it.library_id = Random.nextLong()
it.title = lorem((1..10).random()).joinToString()
it.last_chapter_read = (0..100).random().toFloat()
it.total_chapters = (100..1000).random()
it.score = (0..10).random().toFloat()
it.status = Random.nextInt()
it.started_reading_date = 0L
it.finished_reading_date = 0L
it.tracking_url = "https://example.com/tracker-example"
it.cover_url = "https://example.com/cover.png"
it.start_date = Instant.now().minus((1L..365).random(), ChronoUnit.DAYS).toString()
it.summary = lorem((0..40).random()).joinToString()
it
}
private fun lorem(words: Int): Sequence<String> =
LoremIpsum(words).values
}

View file

@ -11,8 +11,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.Tracker
import tachiyomi.presentation.core.util.ThemePreviews
import tachiyomi.presentation.core.util.clickableNoIndication import tachiyomi.presentation.core.util.clickableNoIndication
@Composable @Composable
@ -39,3 +42,17 @@ fun TrackLogoIcon(
) )
} }
} }
@ThemePreviews
@Composable
private fun TrackLogoIconPreviews(
@PreviewParameter(TrackLogoIconPreviewProvider::class)
tracker: Tracker,
) {
TachiyomiTheme {
TrackLogoIcon(
tracker = tracker,
onClick = null,
)
}
}

View file

@ -0,0 +1,20 @@
package eu.kanade.presentation.track.components
import android.graphics.Color
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.dev.preview.DummyTracker
internal class TrackLogoIconPreviewProvider : PreviewParameterProvider<Tracker> {
override val values: Sequence<Tracker>
get() = sequenceOf(
DummyTracker(
id = 1L,
name = "Dummy Tracker",
valLogoColor = Color.rgb(18, 25, 35),
valLogo = R.drawable.ic_tracker_anilist,
),
)
}

View file

@ -0,0 +1,115 @@
package eu.kanade.tachiyomi.dev.preview
import android.graphics.Color
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import okhttp3.OkHttpClient
import tachiyomi.domain.track.model.Track
data class DummyTracker(
override val id: Long,
override val name: String,
override val supportsReadingDates: Boolean = false,
override val isLoggedIn: Boolean = false,
val valLogoColor: Int = Color.rgb(18, 25, 35),
val valLogo: Int = R.drawable.ic_tracker_anilist,
val valStatuses: List<Int> = (1..6).toList(),
val valReadingStatus: Int = 1,
val valRereadingStatus: Int = 1,
val valCompletionStatus: Int = 2,
val valScoreList: List<String> = (0..10).map(Int::toString),
val val10PointScore: Double = 5.4,
val valSearchResults: List<TrackSearch> = listOf(),
) : Tracker {
override val client: OkHttpClient
get() = TODO("Not yet implemented")
override fun getLogoColor(): Int = valLogoColor
override fun getLogo(): Int = valLogo
override fun getStatusList(): List<Int> = valStatuses
override fun getStatus(status: Int): Int? = when (status) {
1 -> R.string.reading
2 -> R.string.plan_to_read
3 -> R.string.completed
4 -> R.string.on_hold
5 -> R.string.dropped
6 -> R.string.repeating
else -> null
}
override fun getReadingStatus(): Int = valReadingStatus
override fun getRereadingStatus(): Int = valRereadingStatus
override fun getCompletionStatus(): Int = valCompletionStatus
override fun getScoreList(): List<String> = valScoreList
override fun get10PointScore(track: Track): Double = val10PointScore
override fun indexToScore(index: Int): Float = getScoreList()[index].toFloat()
override fun displayScore(track: eu.kanade.tachiyomi.data.database.models.Track): String =
track.score.toString()
override suspend fun update(
track: eu.kanade.tachiyomi.data.database.models.Track,
didReadChapter: Boolean,
): eu.kanade.tachiyomi.data.database.models.Track = track
override suspend fun bind(
track: eu.kanade.tachiyomi.data.database.models.Track,
hasReadChapters: Boolean,
): eu.kanade.tachiyomi.data.database.models.Track = track
override suspend fun search(query: String): List<TrackSearch> = valSearchResults
override suspend fun refresh(
track: eu.kanade.tachiyomi.data.database.models.Track,
): eu.kanade.tachiyomi.data.database.models.Track = track
override suspend fun login(username: String, password: String) = Unit
override fun logout() = Unit
override fun getUsername(): String = "username"
override fun getPassword(): String = "passw0rd"
override fun saveCredentials(username: String, password: String) = Unit
override suspend fun register(
item: eu.kanade.tachiyomi.data.database.models.Track,
mangaId: Long,
) = Unit
override suspend fun setRemoteStatus(
track: eu.kanade.tachiyomi.data.database.models.Track,
status: Int,
) = Unit
override suspend fun setRemoteLastChapterRead(
track: eu.kanade.tachiyomi.data.database.models.Track,
chapterNumber: Int,
) = Unit
override suspend fun setRemoteScore(
track: eu.kanade.tachiyomi.data.database.models.Track,
scoreString: String,
) = Unit
override suspend fun setRemoteStartDate(
track: eu.kanade.tachiyomi.data.database.models.Track,
epochMillis: Long,
) = Unit
override suspend fun setRemoteFinishDate(
track: eu.kanade.tachiyomi.data.database.models.Track,
epochMillis: Long,
) = Unit
}