refactor: jetpack compose (4/n)
This commit is contained in:
+10
-10
@@ -60,15 +60,16 @@ dependencies {
|
||||
implementation("androidx.navigation:navigation-compose:2.7.7")
|
||||
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
|
||||
implementation 'androidx.preference:preference:1.2.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
|
||||
implementation 'androidx.activity:activity-compose:1.8.2'
|
||||
implementation platform('androidx.compose:compose-bom:2023.08.00')
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.2'
|
||||
implementation 'androidx.activity:activity-compose:1.9.0'
|
||||
implementation platform('androidx.compose:compose-bom:2024.06.00')
|
||||
implementation 'androidx.compose.ui:ui'
|
||||
implementation 'androidx.compose.ui:ui-graphics'
|
||||
implementation 'androidx.compose.ui:ui-tooling-preview'
|
||||
implementation 'androidx.compose.material3:material3'
|
||||
androidTestImplementation platform('androidx.compose:compose-bom:2023.08.00')
|
||||
implementation 'androidx.compose.material:material'
|
||||
androidTestImplementation platform('androidx.compose:compose-bom:2024.06.00')
|
||||
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
|
||||
debugImplementation 'androidx.compose.ui:ui-tooling'
|
||||
debugImplementation 'androidx.compose.ui:ui-test-manifest'
|
||||
@@ -91,14 +92,13 @@ dependencies {
|
||||
implementation ('com.squareup.retrofit2:retrofit:2.9.0')
|
||||
implementation ('com.squareup.retrofit2:converter-gson:2.9.0')
|
||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
||||
implementation 'androidx.preference:preference-ktx:1.2.0'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.5'
|
||||
implementation "androidx.navigation:navigation-ui-ktx:2.7.5"
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0"
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.22"
|
||||
implementation 'androidx.core:core-ktx:1.13.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.lsp.view.common
|
||||
|
||||
class Config(val safeMode:Boolean,val source:String) {
|
||||
companion object{
|
||||
fun setConfig(config: Config){
|
||||
PreUtils.putString(PreKV.SOURCE_NAME,config.source)
|
||||
PreUtils.putBool(PreKV.SAFE_MODE,config.safeMode)
|
||||
}
|
||||
|
||||
fun getConfig():Config{
|
||||
return Config(PreUtils.getBool(PreKV.SAFE_MODE,true),PreUtils.getString(PreKV.SOURCE_NAME,SOURCE.YANDE_RE.values.first()))
|
||||
}
|
||||
|
||||
fun setSafeMode(value:Boolean){
|
||||
PreUtils.putBool(PreKV.SAFE_MODE,value)
|
||||
}
|
||||
|
||||
fun getSafeMode():Boolean{
|
||||
return PreUtils.getBool(PreKV.SAFE_MODE,true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object SOURCE {
|
||||
val YANDE_RE = mapOf("yande.re" to "https://yande.re/")
|
||||
val KONACHAN = mapOf("konachan" to "https://konachan.com/")
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.lsp.view.common
|
||||
|
||||
object PreKV {
|
||||
const val SOURCE_NAME = "source_name"
|
||||
const val SAFE_MODE = "safe_mode"
|
||||
}
|
||||
|
||||
object Pre{
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.lsp.view.common
|
||||
|
||||
import android.content.Context
|
||||
import com.lsp.view.YandViewApplication
|
||||
|
||||
object PreUtils {
|
||||
private val PRE = YandViewApplication.context!!.getSharedPreferences(Pre.NAME,Context.MODE_PRIVATE)
|
||||
fun getString(key:String,default:String):String{
|
||||
return PRE.getString(key,default)!!
|
||||
}
|
||||
|
||||
fun putString(key: String,value:String){
|
||||
PRE.edit().putString(key,value).apply()
|
||||
}
|
||||
|
||||
fun getBool(key: String,default:Boolean):Boolean{
|
||||
return PRE.getBoolean(key,default)
|
||||
}
|
||||
|
||||
fun putBool(key: String,value: Boolean){
|
||||
PRE.edit().putBoolean(key, value).apply()
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.lsp.view.repository.exception.UnableConstructObjectException
|
||||
import com.lsp.view.repository.network.api.PostApi
|
||||
import com.lsp.view.repository.network.api.PostApiImpl
|
||||
import com.lsp.view.bean.YandPost
|
||||
import com.lsp.view.common.Config
|
||||
import com.lsp.view.common.Pre
|
||||
import com.lsp.view.common.PreKV
|
||||
|
||||
@@ -26,27 +27,13 @@ class PostDataSource {
|
||||
data class Load(
|
||||
val tags: String?,
|
||||
val page: Int,
|
||||
val safe:Boolean
|
||||
val safe:Boolean,
|
||||
val source:String
|
||||
){
|
||||
lateinit var source:String
|
||||
|
||||
companion object{
|
||||
fun Builder(tags: String?, page: Int, safe:Boolean): Load {
|
||||
val sourceNameArray = YandViewApplication.context!!.resources.getStringArray(R.array.pic_source)
|
||||
val sourceUrlArray = YandViewApplication.context!!.resources.getStringArray(R.array.url_source)
|
||||
val configSp = YandViewApplication.context?.getSharedPreferences(Pre.NAME, 0)
|
||||
val nowSourceName: String = configSp?.getString(PreKV.SOURCE_NAME,null) ?: PostDataSource.YANDE_RE
|
||||
val load = Load(tags,page,safe)
|
||||
|
||||
//初始化数据
|
||||
for ((index,sourceName) in sourceNameArray.withIndex()){
|
||||
if (sourceName == nowSourceName){
|
||||
load.source = sourceUrlArray[index]
|
||||
return load
|
||||
}
|
||||
}
|
||||
|
||||
throw UnableConstructObjectException("Unable construct load object.")
|
||||
fun builder(tags: String?, page: Int): Load {
|
||||
val config = Config.getConfig()
|
||||
return Load(tags,page,config.safeMode,config.source)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package com.lsp.view.repository.network
|
||||
|
||||
import com.lsp.view.bean.YandPost
|
||||
import com.lsp.view.common.Config
|
||||
|
||||
|
||||
class PostRepository {
|
||||
private val dataSource = PostDataSource()
|
||||
|
||||
//获取post
|
||||
suspend fun fetchPostData(searchTarget :String?,safe:Boolean,page:Int): ArrayList<YandPost> {
|
||||
suspend fun fetchPostData(searchTarget :String?,page:Int): ArrayList<YandPost> {
|
||||
var target = searchTarget
|
||||
var isNum = true
|
||||
|
||||
@@ -22,10 +23,10 @@ class PostRepository {
|
||||
target = "id:$searchTarget"
|
||||
}
|
||||
|
||||
val load = Load.Builder(target,page,safe)
|
||||
val load = Load.builder(target,page)
|
||||
val dataList = dataSource.fetchNewPost(load)
|
||||
|
||||
return if (safe){
|
||||
return if (Config.getSafeMode()){
|
||||
ArrayList(dataList.filter { it.rating == "s" })
|
||||
}else{
|
||||
dataList
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.lsp.view.service
|
||||
|
||||
import android.accounts.NetworkErrorException
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -14,14 +13,25 @@ import kotlinx.coroutines.async
|
||||
import okhttp3.Request
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.Serializable
|
||||
|
||||
class Result(val success:Boolean,val message: String,val exception: Exception?){
|
||||
companion object{
|
||||
fun success(message:String):Result{
|
||||
return Result(true,message,null)
|
||||
}
|
||||
|
||||
fun failure(message: String = "",exception: Exception? = null):Result{
|
||||
return Result(false,message,exception)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
class DownloadService : Service() {
|
||||
private val mBinder = DownloadBinder(this)
|
||||
|
||||
class DownloadBinder(val context: Context) : Binder() {
|
||||
|
||||
fun downloadImage(fileUrl: String): Deferred<Result<Serializable>> {
|
||||
fun downloadImage(fileUrl: String): Deferred<Result> {
|
||||
return CoroutineScope(Dispatchers.IO).async {
|
||||
val fileDir =
|
||||
File("${Environment.getExternalStorageDirectory()}/${Environment.DIRECTORY_PICTURES}/LspMake/")
|
||||
@@ -33,7 +43,7 @@ class DownloadService : Service() {
|
||||
val file =
|
||||
File("${Environment.getExternalStorageDirectory()}/${Environment.DIRECTORY_PICTURES}/LspMake/$fileName")
|
||||
if (file.exists()) {
|
||||
return@async Result.failure<Exception>(Exception("File exists"))
|
||||
return@async Result.failure("File exists")
|
||||
}
|
||||
val fos = FileOutputStream(file)
|
||||
try {
|
||||
@@ -52,15 +62,15 @@ class DownloadService : Service() {
|
||||
Result.success("File download successfully")
|
||||
} else {
|
||||
file.delete()
|
||||
Result.failure<Exception>(NetworkErrorException("Connection timed out"))
|
||||
Result.failure("Connection timed out")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Result.failure<Exception>(e)
|
||||
Result.failure(exception = e)
|
||||
} finally {
|
||||
fos.close()
|
||||
}
|
||||
|
||||
return@async Result.failure(Exception("Unknown error"))
|
||||
return@async Result.failure(message = "Unknown error")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,6 @@ class MainViewModel(private val repository: PostRepository, context: Context):Vi
|
||||
try {
|
||||
val newPosts = repository.fetchPostData(
|
||||
_uiState.value.nowSearchText.value,
|
||||
_uiState.value.isSafe,
|
||||
_uiState.value.nowPage
|
||||
)
|
||||
val currentPosts = _postList.value ?: arrayListOf()
|
||||
|
||||
@@ -28,20 +28,28 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.items
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
import androidx.compose.material.pullrefresh.pullRefresh
|
||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -62,6 +70,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -76,13 +85,16 @@ import coil.compose.AsyncImage
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.compose.SubcomposeAsyncImageContent
|
||||
import com.lsp.view.R
|
||||
import com.lsp.view.common.Config
|
||||
import com.lsp.view.service.DownloadService
|
||||
import com.lsp.view.ui.compose.widget.SearchBar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.random.Random
|
||||
|
||||
private const val TAG = "Compose_PostActivity"
|
||||
@@ -121,8 +133,8 @@ class PostActivity : ComponentActivity() {
|
||||
}
|
||||
|
||||
viewModel.downloadResult.observe(this){
|
||||
val message = it.getOrThrow()
|
||||
Toast.makeText(this,message.toString(),Toast.LENGTH_SHORT).show()
|
||||
val message = it.message
|
||||
Toast.makeText(this,message,Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
val serviceIntent = Intent(this, DownloadService::class.java)
|
||||
@@ -157,7 +169,9 @@ fun App(viewModel: PostViewModel = viewModel()) {
|
||||
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class,
|
||||
ExperimentalMaterialApi::class
|
||||
)
|
||||
@Composable
|
||||
fun PostListScreen(
|
||||
navController: NavController, onNavigateToDetail: (Post) -> Unit, viewModel: PostViewModel
|
||||
@@ -191,6 +205,19 @@ fun PostListScreen(
|
||||
mutableStateOf(24.dp)
|
||||
}
|
||||
|
||||
var showBottomSheet by remember { mutableStateOf(false) }
|
||||
|
||||
val refreshing by remember {
|
||||
uiState.refresh
|
||||
}
|
||||
|
||||
val pullRefreshState = rememberPullRefreshState(refreshing = refreshing, onRefresh = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
viewModel.fetchPost(refresh = true)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
LaunchedEffect(listState) {
|
||||
|
||||
snapshotFlow { listState.layoutInfo }.also{
|
||||
@@ -209,43 +236,50 @@ fun PostListScreen(
|
||||
}.distinctUntilChanged().collect { reachedEnd ->
|
||||
//避免初次加载数据时,list未绘制导致被判断为到达底部
|
||||
if (reachedEnd && listState.firstVisibleItemIndex != 0) {
|
||||
viewModel.fetchPost()
|
||||
withContext(Dispatchers.IO){
|
||||
viewModel.fetchPost()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
Column{
|
||||
LazyVerticalStaggeredGrid(
|
||||
state = listState,
|
||||
columns = StaggeredGridCells.Adaptive(200.dp),
|
||||
verticalItemSpacing = 4.dp,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
content = {
|
||||
//放置两个item将下面的内容顶下来
|
||||
items(count = 2, key = {
|
||||
Random.nextInt()
|
||||
}) {
|
||||
Box(modifier = Modifier
|
||||
.height(searchBarHeightSize + searchBarPadding)
|
||||
.fillMaxWidth())
|
||||
LazyVerticalStaggeredGrid(
|
||||
state = listState,
|
||||
columns = StaggeredGridCells.Adaptive(200.dp),
|
||||
verticalItemSpacing = 4.dp,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
content = {
|
||||
//放置两个item将下面的内容顶下来
|
||||
items(count = 2, key = {
|
||||
Random.nextInt()
|
||||
}) {
|
||||
Box(modifier = Modifier
|
||||
.height(searchBarHeightSize + searchBarPadding)
|
||||
.fillMaxWidth())
|
||||
}
|
||||
|
||||
items(items = postList, key = {
|
||||
it.postId//提供key以保持列表顺序稳定
|
||||
}) {
|
||||
Row(Modifier.animateItemPlacement(tween(durationMillis = 250))) {
|
||||
PostItem(it, clickable = {
|
||||
onNavigateToDetail.invoke(it)
|
||||
})
|
||||
}
|
||||
|
||||
items(items = postList, key = {
|
||||
it.postId//提供key以保持列表顺序稳定
|
||||
}) {
|
||||
Row(Modifier.animateItemPlacement(tween(durationMillis = 250))) {
|
||||
PostItem(it, clickable = {
|
||||
onNavigateToDetail.invoke(it)
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.background(Color.Transparent)
|
||||
.pullRefresh(pullRefreshState)
|
||||
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.background(Color.Transparent)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
PullRefreshIndicator(refreshing, pullRefreshState,
|
||||
Modifier
|
||||
.align(Alignment.TopCenter)
|
||||
.padding(searchBarHeightSize+searchBarPadding))
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = scrollDirectionState != -1,
|
||||
@@ -271,16 +305,37 @@ fun PostListScreen(
|
||||
it.size.height.toDp()
|
||||
}
|
||||
},
|
||||
searchTarget = uiState.searchTarget.value
|
||||
) {
|
||||
viewModel.fetchPost(it, refresh = true)
|
||||
scope.launch {
|
||||
listState.animateScrollToItem(index = 0)
|
||||
searchTarget = uiState.searchTarget.value,
|
||||
searchEvent = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
viewModel.fetchPost(it, refresh = true)
|
||||
listState.animateScrollToItem(index = 0)
|
||||
}
|
||||
}, menuButtonAction = {
|
||||
showBottomSheet = true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (showBottomSheet){
|
||||
var safeModel by remember {
|
||||
mutableStateOf(Config.getSafeMode())
|
||||
}
|
||||
ModalBottomSheet(onDismissRequest ={showBottomSheet = false}, modifier = Modifier.height(400.dp)){
|
||||
Row(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(text = "Safe mode", modifier = Modifier.wrapContentSize(), style = MaterialTheme.typography.bodyLarge)
|
||||
Switch(checked = safeModel, onCheckedChange = {
|
||||
safeModel = it
|
||||
Config.setSafeMode(it)
|
||||
})
|
||||
}
|
||||
MaterialTheme.shapes.large
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -329,6 +384,7 @@ fun DetailScreen(navController: NavController, viewModel: PostViewModel) {
|
||||
scale *= zoomChange
|
||||
rotation += rotationChange
|
||||
}
|
||||
val context = LocalContext.current
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(Color.Black)
|
||||
@@ -347,6 +403,7 @@ fun DetailScreen(navController: NavController, viewModel: PostViewModel) {
|
||||
.transformable(state = state)
|
||||
.background(Color.Black)
|
||||
)
|
||||
|
||||
Column {
|
||||
TopAppBar(
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
@@ -362,7 +419,10 @@ fun DetailScreen(navController: NavController, viewModel: PostViewModel) {
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
IconButton(onClick = { viewModel.actionDownload() }) {
|
||||
IconButton(onClick = {
|
||||
viewModel.actionDownload()
|
||||
Toast.makeText(context,"Start download",Toast.LENGTH_SHORT).show()
|
||||
}) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_twotone_arrow_downward_24),
|
||||
contentDescription = "Download"
|
||||
|
||||
@@ -5,10 +5,8 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import com.lsp.view.bean.Post
|
||||
|
||||
data class PostUiState(
|
||||
var refresh:Boolean = false,
|
||||
var refresh:MutableState<Boolean> = mutableStateOf(true),
|
||||
var searchTarget: MutableState<String> = mutableStateOf(""),
|
||||
val source: String = "",
|
||||
val safeModel: Boolean = false, //安全模式
|
||||
var page:Int = 1,
|
||||
var selectPost: Post? = null
|
||||
)
|
||||
@@ -6,11 +6,11 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.lsp.view.bean.YandPost
|
||||
import com.lsp.view.repository.exception.NetworkErrorException
|
||||
import com.lsp.view.repository.network.PostRepository
|
||||
import com.lsp.view.service.Result
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.Serializable
|
||||
|
||||
class PostViewModel:ViewModel() {
|
||||
private val _uiState = MutableStateFlow(PostUiState())
|
||||
@@ -20,42 +20,46 @@ class PostViewModel:ViewModel() {
|
||||
PostRepository()
|
||||
}
|
||||
val downloadAction = MutableLiveData<Unit>()
|
||||
val downloadResult = MutableLiveData<Result<Serializable>>()
|
||||
val downloadResult = MutableLiveData<Result>()
|
||||
|
||||
init {
|
||||
initData()
|
||||
}
|
||||
|
||||
private fun initData(){
|
||||
fetchPost()
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
fetchPost()
|
||||
}
|
||||
}
|
||||
|
||||
fun actionDownload(){
|
||||
downloadAction.postValue(Unit)
|
||||
}
|
||||
|
||||
fun fetchPost(searchTarget: String = _uiState.value.searchTarget.value,refresh:Boolean = false){
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
_uiState.value.searchTarget.value = searchTarget
|
||||
try {
|
||||
val data = repository.fetchPostData(
|
||||
searchTarget,
|
||||
_uiState.value.safeModel,
|
||||
_uiState.value.page
|
||||
)
|
||||
_uiState.value.page ++
|
||||
postData.value = if (refresh){
|
||||
data
|
||||
}else{
|
||||
postData.value + data
|
||||
}
|
||||
} catch (e: NetworkErrorException) {
|
||||
//todo network error
|
||||
suspend fun fetchPost(searchTarget: String = _uiState.value.searchTarget.value,refresh:Boolean = false){
|
||||
_uiState.value.refresh.value = true
|
||||
_uiState.value.searchTarget.value = searchTarget
|
||||
try {
|
||||
if (refresh){
|
||||
_uiState.value.page = 0
|
||||
}
|
||||
val data = repository.fetchPostData(
|
||||
searchTarget,
|
||||
_uiState.value.page
|
||||
)
|
||||
postData.value = if (refresh){
|
||||
data
|
||||
}else{
|
||||
_uiState.value.page ++
|
||||
postData.value + data
|
||||
}
|
||||
} catch (e: NetworkErrorException) {
|
||||
//todo network error
|
||||
}
|
||||
_uiState.value.refresh.value = false
|
||||
}
|
||||
|
||||
fun setDownloadResult(result: Result<Serializable>){
|
||||
fun setDownloadResult(result: Result){
|
||||
downloadResult.postValue(result)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.lsp.view.ui.compose.widget
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
@@ -32,7 +33,7 @@ import androidx.compose.ui.unit.sp
|
||||
|
||||
|
||||
@Composable
|
||||
fun SearchBar(modifier: Modifier = Modifier,searchTarget: String = "", searchEvent: (String) -> Unit) {
|
||||
fun SearchBar(modifier: Modifier = Modifier,searchTarget: String = "", searchEvent: (String) -> Unit,menuButtonAction: () -> Unit) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.background(MaterialTheme.colorScheme.onPrimary, shape = RoundedCornerShape(56.dp)),
|
||||
@@ -45,6 +46,9 @@ fun SearchBar(modifier: Modifier = Modifier,searchTarget: String = "", searchEve
|
||||
.padding(15.dp)
|
||||
.height(30.dp)
|
||||
.width(30.dp)
|
||||
.clickable {
|
||||
menuButtonAction.invoke()
|
||||
}
|
||||
)
|
||||
|
||||
var input: String by remember { mutableStateOf(searchTarget) }
|
||||
|
||||
Reference in New Issue
Block a user