mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	[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:
		@@ -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,
 | 
			
		||||
                        ),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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(),
 | 
			
		||||
                        ),
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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())))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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 {} },
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 = {},
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user