Initial commit.

This commit is contained in:
Thomas Andres Gomez 2021-05-06 18:03:34 +02:00
commit 1a225e3732
54 changed files with 2097 additions and 0 deletions

View file

@ -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"
)
}
}
}

View file

@ -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,
)
}
}
}

View file

@ -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)
)
}
}

View file

@ -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))
}
}
}
}

View file

@ -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
}
}

View file

@ -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"
)
}
}