Refactor Page into smaller component
This commit is contained in:
parent
0ee7de3cde
commit
de64718e10
18 changed files with 286 additions and 228 deletions
|
|
@ -8,8 +8,8 @@ import androidx.navigation.NavHostController
|
|||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.pixelized.biblib.ui.screen.home.BooksPage
|
||||
import com.pixelized.biblib.ui.screen.home.NewsPage
|
||||
import com.pixelized.biblib.ui.screen.home.page.books.BooksPage
|
||||
import com.pixelized.biblib.ui.screen.home.page.news.NewsPage
|
||||
|
||||
val LocalPageNavHostController = compositionLocalOf<NavHostController> {
|
||||
error("LocalHomePageNavHostController is not ready yet.")
|
||||
|
|
|
|||
|
|
@ -6,7 +6,18 @@ sealed class Screen(
|
|||
object Authentication : Screen(
|
||||
route = "authentication"
|
||||
)
|
||||
|
||||
object Home : Screen(
|
||||
route = "home"
|
||||
)
|
||||
|
||||
class BookDetail(id: Int) : Screen(
|
||||
route = "$ROOT/$id"
|
||||
) {
|
||||
companion object {
|
||||
const val ROOT = "detail"
|
||||
const val ARG_BOOK_ID = "id"
|
||||
const val route = "$ROOT/{$ARG_BOOK_ID}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import androidx.navigation.compose.NavHost
|
|||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.pixelized.biblib.ui.screen.authentication.AuthenticationScreen
|
||||
import com.pixelized.biblib.ui.screen.detail.DetailScreen
|
||||
import com.pixelized.biblib.ui.screen.home.HomeScreen
|
||||
|
||||
val LocalScreenNavHostController = compositionLocalOf<NavHostController> {
|
||||
|
|
@ -33,6 +34,9 @@ fun ScreenNavHost(
|
|||
composable(Screen.Home.route) {
|
||||
HomeScreen()
|
||||
}
|
||||
composable(Screen.BookDetail.route) {
|
||||
DetailScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.pixelized.biblib.ui.screen.detail
|
||||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.biblib.ui.old.viewmodel.book.BooksViewModel
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
|
||||
@Composable
|
||||
fun DetailScreen(
|
||||
booksViewModel: BooksViewModel = hiltViewModel()
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DetailScreenContent() {
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
|
||||
private fun DetailScreenContentPreview() {
|
||||
BibLibTheme {
|
||||
DetailScreenContent()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.biblib.ui.screen.home.item
|
||||
package com.pixelized.biblib.ui.screen.home.common.composable
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.*
|
||||
|
|
@ -16,8 +16,8 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.screen.home.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.uio.CoverUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.biblib.ui.screen.home.common
|
||||
package com.pixelized.biblib.ui.screen.home.common.composable
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
|
|
@ -19,9 +19,8 @@ import androidx.paging.compose.LazyPagingItems
|
|||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.items
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.screen.home.item.BookThumbnail
|
||||
import com.pixelized.biblib.ui.screen.home.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.uio.CoverUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.biblib.ui.screen.home.uio
|
||||
package com.pixelized.biblib.ui.screen.home.common.uio
|
||||
|
||||
import androidx.compose.runtime.State
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.biblib.ui.screen.home.uio
|
||||
package com.pixelized.biblib.ui.screen.home.common.uio
|
||||
|
||||
import com.pixelized.biblib.network.client.IBibLibClient.Companion.COVER_URL
|
||||
import java.net.URL
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.biblib.ui.screen.home.uio
|
||||
package com.pixelized.biblib.ui.screen.home.common.uio
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.Stable
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.pixelized.biblib.ui.screen.home.common.viewModel
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.utils.BitmapCache
|
||||
import com.pixelized.biblib.utils.extention.context
|
||||
import com.pixelized.biblib.utils.painterResource
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import java.net.URL
|
||||
|
||||
|
||||
abstract class ACoverViewModel(
|
||||
application: Application,
|
||||
private val cache: BitmapCache,
|
||||
) : AndroidViewModel(application) {
|
||||
|
||||
fun cover(
|
||||
cache: BitmapCache = this.cache,
|
||||
coroutineScope: CoroutineScope = viewModelScope,
|
||||
placeHolder: Painter = painterResource(context, R.drawable.ic_baseline_auto_stories_24),
|
||||
url: URL,
|
||||
) = cache.download(
|
||||
placeHolder = placeHolder,
|
||||
coroutineScope = coroutineScope,
|
||||
url = url,
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val PAGING_SIZE = 30
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.pixelized.biblib.ui.screen.home
|
||||
package com.pixelized.biblib.ui.screen.home.page.books
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.biblib.ui.screen.home.common.LazyBookThumbnailColumn
|
||||
import com.pixelized.biblib.ui.screen.home.viewModel.BooksViewModel
|
||||
import com.pixelized.biblib.ui.screen.home.page.news.NewsPage
|
||||
import com.pixelized.biblib.ui.screen.home.common.composable.LazyBookThumbnailColumn
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
|
||||
@Composable
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.pixelized.biblib.ui.screen.home.page.books
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.pixelized.biblib.model.book.Book
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.repository.book.IBookRepository
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.viewModel.ACoverViewModel
|
||||
import com.pixelized.biblib.utils.BitmapCache
|
||||
import com.pixelized.biblib.utils.extention.longDate
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import java.net.URL
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
@HiltViewModel
|
||||
class BooksViewModel @Inject constructor(
|
||||
application: Application,
|
||||
bookRepository: IBookRepository,
|
||||
cache: BitmapCache,
|
||||
) : ACoverViewModel(application, cache) {
|
||||
|
||||
private val booksSource = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
pagingSourceFactory = bookRepository.getBooksSource()
|
||||
.map { it.toThumbnail() }
|
||||
.asPagingSourceFactory(Dispatchers.IO)
|
||||
).flow
|
||||
|
||||
val books @Composable get() = booksSource.collectAsLazyPagingItems()
|
||||
|
||||
private fun Book.toThumbnail() = BookThumbnailUio(
|
||||
id = id,
|
||||
genre = genre?.joinToString { it.name } ?: "",
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
date = releaseDate.longDate(),
|
||||
isNew = isNew,
|
||||
cover = cover(url = URL("${IBibLibClient.THUMBNAIL_URL}/$id.jpg"))
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.pixelized.biblib.ui.screen.home.page.news
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.pixelized.biblib.model.book.Book
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.repository.book.IBookRepository
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.viewModel.ACoverViewModel
|
||||
import com.pixelized.biblib.utils.BitmapCache
|
||||
import com.pixelized.biblib.utils.extention.longDate
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.net.URL
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
@HiltViewModel
|
||||
class NewsBookViewModel @Inject constructor(
|
||||
application: Application,
|
||||
bookRepository: IBookRepository,
|
||||
cache: BitmapCache,
|
||||
) : ACoverViewModel(application, cache) {
|
||||
|
||||
private val newsSource: Flow<PagingData<BookThumbnailUio>> = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
pagingSourceFactory = bookRepository.getNewsSource()
|
||||
.map { it.toThumbnail() }
|
||||
.asPagingSourceFactory(Dispatchers.IO)
|
||||
).flow
|
||||
|
||||
val news @Composable get() = newsSource.collectAsLazyPagingItems()
|
||||
|
||||
private fun Book.toThumbnail() = BookThumbnailUio(
|
||||
id = id,
|
||||
genre = genre?.joinToString { it.name } ?: "",
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
date = releaseDate.longDate(),
|
||||
isNew = isNew,
|
||||
cover = cover(url = URL("${IBibLibClient.THUMBNAIL_URL}/$id.jpg"))
|
||||
)
|
||||
}
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
package com.pixelized.biblib.ui.screen.home
|
||||
package com.pixelized.biblib.ui.screen.home.page.news
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.biblib.ui.screen.home.common.LazyBookThumbnailColumn
|
||||
import com.pixelized.biblib.ui.screen.home.viewModel.BooksViewModel
|
||||
import com.pixelized.biblib.ui.screen.home.common.composable.LazyBookThumbnailColumn
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
|
||||
@Composable
|
||||
fun NewsPage(
|
||||
booksViewModel: BooksViewModel = hiltViewModel()
|
||||
booksViewModel: NewsBookViewModel = hiltViewModel()
|
||||
) {
|
||||
LazyBookThumbnailColumn(
|
||||
books = booksViewModel.news
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
package com.pixelized.biblib.ui.screen.home.viewModel
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.google.accompanist.drawablepainter.DrawablePainter
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.model.book.Book
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.network.factory.BookFactory
|
||||
import com.pixelized.biblib.repository.apiCache.IAPICacheRepository
|
||||
import com.pixelized.biblib.repository.book.IBookRepository
|
||||
import com.pixelized.biblib.ui.composable.StateUio
|
||||
import com.pixelized.biblib.ui.screen.home.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.uio.BookUio
|
||||
import com.pixelized.biblib.ui.screen.home.uio.CoverUio
|
||||
import com.pixelized.biblib.utils.BitmapCache
|
||||
import com.pixelized.biblib.utils.extention.capitalize
|
||||
import com.pixelized.biblib.utils.extention.context
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.net.URL
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
/**
|
||||
* TODO: there is some book related code that should be inside a Repository // DataSource.
|
||||
*/
|
||||
@HiltViewModel
|
||||
class BooksViewModel @Inject constructor(
|
||||
application: Application,
|
||||
private val bookRepository: IBookRepository,
|
||||
private val client: IBibLibClient,
|
||||
private val apiCache: IAPICacheRepository,
|
||||
private val cache: BitmapCache,
|
||||
) : AndroidViewModel(application) {
|
||||
private val formatterLong = SimpleDateFormat("MMMM yyyy", Locale.getDefault())
|
||||
private val formatterShort = SimpleDateFormat("MMM yyyy", Locale.getDefault())
|
||||
|
||||
private val _state = mutableStateOf<StateUio<Boolean>?>(null)
|
||||
val state: State<StateUio<Boolean>?> = _state
|
||||
|
||||
private val booksSource = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
pagingSourceFactory = bookRepository.getBooksSource()
|
||||
.map { it.toThumbnail() }
|
||||
.asPagingSourceFactory(Dispatchers.IO)
|
||||
).flow
|
||||
val books @Composable get() = booksSource.collectAsLazyPagingItems()
|
||||
|
||||
private val newsSource: Flow<PagingData<BookThumbnailUio>> = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
pagingSourceFactory = bookRepository.getNewsSource()
|
||||
.map { it.toThumbnail() }
|
||||
.asPagingSourceFactory(Dispatchers.IO)
|
||||
).flow
|
||||
val news @Composable get() = newsSource.collectAsLazyPagingItems()
|
||||
|
||||
fun updateBooks() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
_state.value = StateUio.Progress()
|
||||
try {
|
||||
val updated = loadNewBooks() && loadAllBooks()
|
||||
_state.value = StateUio.Success(updated)
|
||||
} catch (exception: Exception) {
|
||||
Log.e("BooksViewModel", exception.message, exception)
|
||||
_state.value = StateUio.Failure(exception = exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getBookDetail(id: Int): State<BookUio?> {
|
||||
val data = mutableStateOf<BookUio?>(null)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val factory = BookFactory()
|
||||
val response = client.service.detail(id)
|
||||
val book = factory.fromDetailResponseToBook(response)
|
||||
data.value = book.toUio()
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
fun send(id: Int, mail: String) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
client.service.send(bookId = id, mail = mail)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadNewBooks(): Boolean {
|
||||
val cached = apiCache.new
|
||||
val updated = client.service.new()
|
||||
return if (cached != updated) {
|
||||
apiCache.new = updated
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadAllBooks(): Boolean {
|
||||
client.service.list().let { response ->
|
||||
val newIds = apiCache.new?.data?.map { it.book_id } ?: listOf()
|
||||
val factory = BookFactory()
|
||||
val books = response.data?.map { dto ->
|
||||
val isNew = newIds.contains(dto.book_id)
|
||||
val index = newIds.indexOf(dto.book_id)
|
||||
factory.fromListResponseToBook(dto, isNew, index)
|
||||
}
|
||||
books?.let { data -> bookRepository.update(data) }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// region: UIO conversion
|
||||
|
||||
private fun Book.toThumbnail() = BookThumbnailUio(
|
||||
id = id,
|
||||
genre = genre?.joinToString { it.name } ?: "",
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
date = if (releaseDate.time < 0) {
|
||||
null
|
||||
} else {
|
||||
formatterLong.format(releaseDate).capitalize()
|
||||
},
|
||||
isNew = isNew,
|
||||
cover = cover(url = URL("${IBibLibClient.THUMBNAIL_URL}/$id.jpg"))
|
||||
)
|
||||
|
||||
private fun Book.toUio() = BookUio(
|
||||
id = id,
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
rating = rating?.toFloat() ?: 0.0f,
|
||||
language = language?.displayLanguage?.capitalize() ?: "",
|
||||
date = if (releaseDate.time < 0) {
|
||||
null
|
||||
} else {
|
||||
formatterShort.format(releaseDate).capitalize()
|
||||
},
|
||||
series = series?.name,
|
||||
description = synopsis ?: "",
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
private fun cover(
|
||||
cache: BitmapCache = this.cache,
|
||||
placeHolder: Painter = DrawablePainter(
|
||||
drawable = AppCompatResources.getDrawable(
|
||||
context,
|
||||
R.drawable.ic_baseline_auto_stories_24
|
||||
)!!
|
||||
),
|
||||
coroutineScope: CoroutineScope = viewModelScope,
|
||||
url: URL,
|
||||
): State<CoverUio> {
|
||||
if (cache.exist(url)) {
|
||||
val bitmap = cache.readFromDisk(url) ?: throw RuntimeException("")
|
||||
val resource = BitmapPainter(bitmap.asImageBitmap())
|
||||
return mutableStateOf(CoverUio(painter = resource))
|
||||
} else {
|
||||
val state = mutableStateOf(
|
||||
CoverUio(
|
||||
contentScale = ContentScale.None,
|
||||
painter = placeHolder
|
||||
)
|
||||
)
|
||||
coroutineScope.launch {
|
||||
val resource = cache.readFromDisk(url)?.let { BitmapPainter(it.asImageBitmap()) }
|
||||
if (resource != null) {
|
||||
state.value = CoverUio(painter = resource)
|
||||
} else {
|
||||
val downloaded = cache.download(url)
|
||||
if (downloaded != null) {
|
||||
cache.writeToDisk(url, downloaded)
|
||||
state.value = CoverUio(painter = BitmapPainter(downloaded.asImageBitmap()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PAGING_SIZE = 30
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,16 @@ import android.content.Context
|
|||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
|
@ -40,7 +49,7 @@ class BitmapCache @Inject constructor(context: Context) {
|
|||
}
|
||||
|
||||
suspend fun download(url: URL): Bitmap? {
|
||||
Log.v("BitmapCache","download: $url")
|
||||
Log.v("BitmapCache", "download: $url")
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
BitmapFactory.decodeStream(url.openStream())
|
||||
|
|
@ -51,5 +60,38 @@ class BitmapCache @Inject constructor(context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun download(
|
||||
coroutineScope: CoroutineScope,
|
||||
placeHolder: Painter,
|
||||
url: URL,
|
||||
): State<CoverUio> {
|
||||
if (exist(url)) {
|
||||
val bitmap = readFromDisk(url) ?: throw RuntimeException("")
|
||||
val resource = BitmapPainter(bitmap.asImageBitmap())
|
||||
return mutableStateOf(CoverUio(painter = resource))
|
||||
} else {
|
||||
val state = mutableStateOf(
|
||||
CoverUio(
|
||||
contentScale = ContentScale.None,
|
||||
painter = placeHolder
|
||||
)
|
||||
)
|
||||
coroutineScope.launch {
|
||||
val resource = readFromDisk(url)?.let { BitmapPainter(it.asImageBitmap()) }
|
||||
if (resource != null) {
|
||||
state.value = CoverUio(painter = resource)
|
||||
} else {
|
||||
val downloaded = download(url)
|
||||
if (downloaded != null) {
|
||||
writeToDisk(url, downloaded)
|
||||
state.value = CoverUio(painter = BitmapPainter(downloaded.asImageBitmap()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
private fun file(url: URL): File = File(cache?.absolutePath + url.file)
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.pixelized.biblib.utils.extention
|
||||
|
||||
import java.text.Format
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
fun Date.longDate(
|
||||
default: String? = null,
|
||||
formatter: Format = SimpleDateFormat("MMMM yyyy", Locale.getDefault()),
|
||||
): String? = format(
|
||||
default = default,
|
||||
formatter = formatter
|
||||
)
|
||||
|
||||
fun Date.shortDate(
|
||||
default: String? = null,
|
||||
formatter: Format = SimpleDateFormat("MMM yyyy", Locale.getDefault()),
|
||||
): String? = format(
|
||||
default = default,
|
||||
formatter = formatter
|
||||
)
|
||||
|
||||
private fun Date.format(
|
||||
default: String?,
|
||||
formatter: Format,
|
||||
): String? {
|
||||
return if (time < 0) {
|
||||
default
|
||||
} else {
|
||||
formatter.format(this).capitalize()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.pixelized.biblib.utils
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.google.accompanist.drawablepainter.DrawablePainter
|
||||
|
||||
@Composable
|
||||
fun painterResource(@DrawableRes res: Int): Painter {
|
||||
val context = LocalContext.current
|
||||
val drawable = AppCompatResources.getDrawable(context, res)
|
||||
return DrawablePainter(drawable = drawable ?: error(""))
|
||||
}
|
||||
|
||||
fun painterResource(context: Context, @DrawableRes res: Int): Painter {
|
||||
val drawable = AppCompatResources.getDrawable(context, res)
|
||||
return DrawablePainter(drawable = drawable ?: error(""))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue