Initial commit.
This commit is contained in:
commit
1a225e3732
54 changed files with 2097 additions and 0 deletions
|
|
@ -0,0 +1,122 @@
|
|||
package com.pixelized.biblib.ui.composable.items
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.NavigateNext
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.data.ui.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.ui.theme.Teal200
|
||||
import com.pixelized.biblib.utils.extention.toImage
|
||||
import com.pixelized.biblib.utils.mock.BookThumbnailMock
|
||||
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun BookThumbnailComposablePreview() {
|
||||
val mock = BookThumbnailMock()
|
||||
BibLibTheme {
|
||||
BookThumbnailComposable(thumbnail = mock.bookThumbnail)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun BookThumbnailComposablePreviewDark() {
|
||||
val mock = BookThumbnailMock()
|
||||
BibLibTheme(darkTheme = true) {
|
||||
BookThumbnailComposable(thumbnail = mock.bookThumbnail)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BookThumbnailComposable(
|
||||
thumbnail: BookThumbnailUio,
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: ((BookThumbnailUio) -> Unit)? = null,
|
||||
) {
|
||||
val typography = MaterialTheme.typography
|
||||
Card(
|
||||
modifier = modifier.clickable {
|
||||
onClick?.invoke(thumbnail)
|
||||
},
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.width(60.dp)
|
||||
.height(96.dp),
|
||||
placeHolder = painterResource(id = R.drawable.ic_launcher_foreground),
|
||||
contentUrl = thumbnail.cover,
|
||||
colorFilter = if (MaterialTheme.colors.isLight) ColorFilter.tint(Teal200) else null,
|
||||
contentDescription = thumbnail.title
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(8.dp)
|
||||
) {
|
||||
Text(
|
||||
style = typography.h6,
|
||||
text = thumbnail.title,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
Text(
|
||||
style = typography.body1,
|
||||
text = thumbnail.author,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Row {
|
||||
Text(
|
||||
style = typography.caption,
|
||||
text = thumbnail.genre,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
style = typography.caption,
|
||||
text = thumbnail.series ?: "",
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.width(0.dp)
|
||||
.weight(1f)
|
||||
)
|
||||
Text(
|
||||
style = typography.caption,
|
||||
text = thumbnail.date,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
modifier = Modifier.align(Alignment.CenterVertically),
|
||||
imageVector = Icons.Default.NavigateNext, contentDescription = "navigate"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.pixelized.biblib.ui.composable.items
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.core.MutableTransitionState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.DefaultAlpha
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import com.pixelized.biblib.utils.extention.toImage
|
||||
import java.net.URL
|
||||
|
||||
@Composable
|
||||
fun Image(
|
||||
placeHolder: Painter,
|
||||
contentUrl: URL,
|
||||
contentDescription: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
alignment: Alignment = Alignment.Center,
|
||||
contentScale: ContentScale = ContentScale.Fit,
|
||||
alpha: Float = DefaultAlpha,
|
||||
colorFilter: ColorFilter? = null
|
||||
) {
|
||||
val cover by remember { contentUrl.toImage(placeHolder) }
|
||||
|
||||
Crossfade(targetState = cover) {
|
||||
if (it == placeHolder) {
|
||||
androidx.compose.foundation.Image(
|
||||
painter = placeHolder,
|
||||
contentDescription = contentDescription,
|
||||
modifier = modifier,
|
||||
alignment = alignment,
|
||||
contentScale = contentScale,
|
||||
alpha = alpha,
|
||||
colorFilter = colorFilter,
|
||||
)
|
||||
} else {
|
||||
androidx.compose.foundation.Image(
|
||||
painter = cover,
|
||||
contentDescription = contentDescription,
|
||||
modifier = modifier,
|
||||
alignment = alignment,
|
||||
contentScale = contentScale,
|
||||
alpha = alpha,
|
||||
colorFilter = colorFilter,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
package com.pixelized.biblib.ui.composable.pages
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.data.ui.BookUio
|
||||
import com.pixelized.biblib.ui.composable.items.Image
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.ui.theme.Teal200
|
||||
import com.pixelized.biblib.utils.mock.BookMock
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun DetailPageComposablePreview() {
|
||||
BibLibTheme {
|
||||
val mock = BookMock()
|
||||
DetailPageComposable(mock.book)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DetailPageComposable(book: BookUio) {
|
||||
val typography = MaterialTheme.typography
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(vertical = 16.dp),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
placeHolder = painterResource(id = R.drawable.ic_launcher_foreground),
|
||||
contentUrl = book.cover,
|
||||
colorFilter = if (MaterialTheme.colors.isLight) ColorFilter.tint(Teal200) else null,
|
||||
contentDescription = book.title
|
||||
)
|
||||
Row(modifier = Modifier.padding(bottom = 16.dp)) {
|
||||
Button(
|
||||
modifier = Modifier.weight(1f),
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
backgroundColor = Teal200,
|
||||
contentColor = Color.Black,
|
||||
),
|
||||
onClick = { }) {
|
||||
Text(text = "EPUB")
|
||||
}
|
||||
Button(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 8.dp),
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
backgroundColor = Teal200,
|
||||
contentColor = Color.Black,
|
||||
),
|
||||
onClick = { }) {
|
||||
Text(text = "MOBI")
|
||||
}
|
||||
Button(
|
||||
modifier = Modifier.weight(1f),
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
backgroundColor = Teal200,
|
||||
contentColor = Color.Black,
|
||||
),
|
||||
onClick = { }) {
|
||||
Text(text = "SEND")
|
||||
}
|
||||
}
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.CenterHorizontally)
|
||||
.padding(bottom = 4.dp),
|
||||
style = typography.h5,
|
||||
text = book.title,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.CenterHorizontally)
|
||||
.padding(bottom = 16.dp),
|
||||
style = typography.h6,
|
||||
text = book.author,
|
||||
)
|
||||
Row(modifier = Modifier.padding(bottom = 16.dp)) {
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
style = typography.body2,
|
||||
text = stringResource(id = R.string.detail_rating),
|
||||
)
|
||||
Text(
|
||||
style = typography.body1,
|
||||
text = book.rating.toString(),
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
style = typography.body2,
|
||||
text = stringResource(id = R.string.detail_language),
|
||||
)
|
||||
Text(
|
||||
style = typography.body1,
|
||||
text = book.language,
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
style = typography.body2,
|
||||
text = stringResource(id = R.string.detail_Release),
|
||||
)
|
||||
Text(
|
||||
style = typography.body1,
|
||||
text = book.date,
|
||||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
style = typography.body1,
|
||||
text = book.description,
|
||||
modifier = Modifier.padding(bottom = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.pixelized.biblib.ui.composable.pages
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.biblib.ui.composable.items.BookThumbnailComposable
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.ui.viewmodel.NavigationViewModel
|
||||
import com.pixelized.biblib.ui.viewmodel.NavigationViewModel.Page.Detail
|
||||
import com.pixelized.biblib.utils.mock.BookMock
|
||||
import com.pixelized.biblib.utils.mock.BookThumbnailMock
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun HomePageComposablePreview() {
|
||||
BibLibTheme {
|
||||
HomePageComposable(null)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HomePageComposable(navigationViewModel: NavigationViewModel?) {
|
||||
val mock = BookThumbnailMock()
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
items(mock.bookThumbnails) { thumbnail ->
|
||||
BookThumbnailComposable(
|
||||
thumbnail = thumbnail,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
) { item ->
|
||||
// TODO:
|
||||
val bookMock = BookMock().let { it.books[item.id] ?: it.book }
|
||||
navigationViewModel?.navigateTo(Detail(bookMock))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.pixelized.biblib.ui.composable.screen
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.sharp.ArrowBack
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.composable.pages.DetailPageComposable
|
||||
import com.pixelized.biblib.ui.composable.pages.HomePageComposable
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.ui.viewmodel.NavigationViewModel
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MainScreenComposablePreview() {
|
||||
val viewModel = NavigationViewModel()
|
||||
BibLibTheme {
|
||||
MainScreenComposable(navigationViewModel = viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MainScreenComposable(navigationViewModel: NavigationViewModel) {
|
||||
val page by navigationViewModel.page.observeAsState()
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text(stringResource(id = R.string.app_name)) },
|
||||
navigationIcon = navigationIcon(navigationViewModel)
|
||||
)
|
||||
},
|
||||
) {
|
||||
Crossfade(targetState = page, animationSpec = tween(1000)) {
|
||||
when (it) {
|
||||
is NavigationViewModel.Page.HomePage -> HomePageComposable(navigationViewModel)
|
||||
is NavigationViewModel.Page.Detail -> DetailPageComposable(it.book)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun navigationIcon(navigationViewModel: NavigationViewModel): (@Composable () -> Unit)? {
|
||||
val page by navigationViewModel.page.observeAsState()
|
||||
|
||||
return if (page !is NavigationViewModel.Page.HomePage) {
|
||||
{
|
||||
IconButton(onClick = {
|
||||
navigationViewModel.navigateBack()
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.Sharp.ArrowBack,
|
||||
contentDescription = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.pixelized.biblib.ui.composable.screen
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.ui.viewmodel.NavigationViewModel
|
||||
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SplashScreenComposablePreview() {
|
||||
val viewModel = NavigationViewModel()
|
||||
BibLibTheme {
|
||||
SplashScreenComposable(viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SplashScreenComposable(navigationViewModel: NavigationViewModel) {
|
||||
val typography = MaterialTheme.typography
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.fillMaxWidth(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
style = typography.h4,
|
||||
text = "Welcome to BibLib"
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue