Skip to content

Commit

Permalink
fix: wrong index display and add animation while open setting
Browse files Browse the repository at this point in the history
  • Loading branch information
jelychow committed Jan 21, 2025
1 parent e7bc06d commit 5484b3b
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 54 deletions.
4 changes: 2 additions & 2 deletions app/src/main/java/me/grey/picquery/common/AppModules.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ private val dataModules = module {
AppDatabase::class.java, "app-db"
).build()
}

single { get<AppDatabase>().embeddingDao() }
single { AlbumRepository(androidContext().contentResolver, database = get()) }
single { EmbeddingRepository(database = get()) }
single { EmbeddingRepository(dataSource = get()) }
single { PhotoRepository(androidContext()) }
single { PreferenceRepository() }
}
Expand Down
36 changes: 19 additions & 17 deletions app/src/main/java/me/grey/picquery/common/AssetUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package me.grey.picquery.common
import android.content.Context
import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.io.*

Expand Down Expand Up @@ -37,7 +35,12 @@ object AssetUtil {
}
}

private suspend fun copyAssets(context: Context, sourceAsset: String, targetFolder: File, assets: Array<String>) {
private suspend fun copyAssets(
context: Context,
sourceAsset: String,
targetFolder: File,
assets: Array<String>
) {
val assetManager = context.assets
for (itemInFolder in assets) {
val currentAssetPath = "$sourceAsset/$itemInFolder"
Expand All @@ -54,25 +57,24 @@ object AssetUtil {
}

@Throws(IOException::class)
suspend fun copyAssetFile(context: Context, sourceAsset: String, target: File) {
fun copyAssetFile(context: Context, sourceAsset: String, target: File) {
if (target.exists() && target.length() > 0) {
return
}

coroutineScope {
val inputStream: InputStream = context.assets.open(sourceAsset)
val outputStream: OutputStream = FileOutputStream(target)
val inputStream: InputStream = context.assets.open(sourceAsset)
val outputStream: OutputStream = FileOutputStream(target)

inputStream.use { inputs ->
outputStream.use { os ->
val buffer = ByteArray(4 * 1024)
var read: Int
while (inputs.read(buffer).also { read = it } != -1) {
os.write(buffer, 0, read)
}
os.flush()
inputStream.use { inputs ->
outputStream.use { os ->
val buffer = ByteArray(4 * 1024)
var read: Int
while (inputs.read(buffer).also { read = it } != -1) {
os.write(buffer, 0, read)
}
os.flush()
}

}
}

Expand All @@ -98,7 +100,7 @@ object AssetUtil {
}

return try {
runBlocking { copyAssetFile(context, assetName, file) }
copyAssetFile(context, assetName, file)
file.absolutePath
} catch (_: Exception) {
""
Expand Down Expand Up @@ -127,7 +129,7 @@ object AssetUtil {
}

return try {
runBlocking { copyAssetFile(context, assetName, file) }
copyAssetFile(context, assetName, file)
file
} catch (_: Exception) {
null
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/me/grey/picquery/common/UiUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -45,6 +47,9 @@ object Animation {
val navigateInAnimation = fadeIn(tween(DEFAULT_NAVIGATION_ANIMATION_DURATION))
val navigateUpAnimation = fadeOut(tween(DEFAULT_NAVIGATION_ANIMATION_DURATION))

val popInAnimation = slideInHorizontally { width -> width }
val popUpAnimation = slideOutHorizontally { width -> -width }

fun enterAnimation(durationMillis: Int): EnterTransition =
fadeIn(tween(durationMillis))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ class AlbumRepository(
private val albumCollection: Uri =
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)

// 查询相册
// 本质上其实是还是遍历所有的图片,但是手动将他们归类和统计数量
fun getAllAlbums(): List<Album> {
val queryAlbums = contentResolver.query(
albumCollection,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
package me.grey.picquery.data.data_source

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.flow
import me.grey.picquery.data.AppDatabase
import me.grey.picquery.data.dao.EmbeddingDao
import me.grey.picquery.data.model.Album
import me.grey.picquery.data.model.Embedding
import java.util.concurrent.LinkedBlockingDeque

class EmbeddingRepository(
private val database: AppDatabase
private val dataSource: EmbeddingDao
) {
companion object {
private const val TAG = "EmbeddingRepo"
}

fun getAll(): List<Embedding> {
return database.embeddingDao().getAll()
return dataSource.getAll()
}

fun getAllEmbeddingsPaginated(batchSize: Int): Flow<List<Embedding>> = flow {
var offset = 0
while (true) {
val embeddings = database.embeddingDao().getEmbeddingsPaginated(batchSize, offset)
val embeddings = dataSource.getEmbeddingsPaginated(batchSize, offset)
if (embeddings.isEmpty()) {
emit(emptyList())
break
Expand All @@ -33,21 +32,21 @@ class EmbeddingRepository(
}

fun getTotalCount(): Long {
return database.embeddingDao().getTotalCount()
return dataSource.getTotalCount()
}

fun getByAlbumId(albumId: Long): List<Embedding> {
return database.embeddingDao().getAllByAlbumId(albumId)
return dataSource.getAllByAlbumId(albumId)
}

fun getByAlbumList(albumList: List<Album>): List<Embedding> {
return database.embeddingDao().getByAlbumIdList(albumList.map { it.id })
return dataSource.getByAlbumIdList(albumList.map { it.id })
}

fun getEmbeddingsByAlbumIdsPaginated(albumIds: List<Long>, batchSize: Int): Flow<List<Embedding>> = flow {
var offset = 0
while (true) {
val embeddings = database.embeddingDao().getByAlbumIdList(albumIds, batchSize, offset)
val embeddings = dataSource.getByAlbumIdList(albumIds, batchSize, offset)
if (embeddings.isEmpty()) {
emit(emptyList())
break
Expand All @@ -58,28 +57,28 @@ class EmbeddingRepository(
}

fun update(emb: Embedding) {
return database.embeddingDao().upsertAll(listOf(emb))
return dataSource.upsertAll(listOf(emb))
}

fun updateList(e: Embedding) {
cacheLinkedBlockingDeque.add(e)
if (cacheLinkedBlockingDeque.size >= 300) {
val toUpdate = cacheLinkedBlockingDeque.toList()
cacheLinkedBlockingDeque.clear()
return database.embeddingDao().upsertAll(toUpdate)
return dataSource.upsertAll(toUpdate)
}
}

fun updateCache() {
if (cacheLinkedBlockingDeque.isNotEmpty()) {
val toUpdate = cacheLinkedBlockingDeque.toList()
cacheLinkedBlockingDeque.clear()
return database.embeddingDao().upsertAll(toUpdate)
return dataSource.upsertAll(toUpdate)
}
}

private val cacheLinkedBlockingDeque = LinkedBlockingDeque<Embedding>()
fun updateAll(list: List<Embedding>) {
return database.embeddingDao().upsertAll(list)
return dataSource.upsertAll(list)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package me.grey.picquery.feature.mobileclip2
import android.content.Context
import android.graphics.Bitmap
import android.util.Log
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.grey.picquery.PicQueryApplication
import me.grey.picquery.common.AssetUtil
import me.grey.picquery.feature.base.ImageEncoder
import org.tensorflow.lite.DataType
Expand All @@ -29,6 +32,7 @@ class ImageEncoderMobileCLIPv2(context: Context, private val preprocessor: Prepr
}

init {

val modelFile = AssetUtil.assetFile(context, MODEL_PATH)
?: throw FileNotFoundException("Model: $MODEL_PATH not exist.")

Expand Down
16 changes: 10 additions & 6 deletions app/src/main/java/me/grey/picquery/ui/AppNavHost.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package me.grey.picquery.ui

import android.net.Uri
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import me.grey.picquery.common.Animation.navigateInAnimation
import me.grey.picquery.common.Animation.navigateUpAnimation
import me.grey.picquery.common.Animation.popInAnimation
import me.grey.picquery.common.Routes
import me.grey.picquery.ui.display.DisplayScreen
import me.grey.picquery.ui.home.HomeScreen
Expand All @@ -26,7 +26,6 @@ fun AppNavHost(
NavHost(
navController,
startDestination = startDestination,
// TODO: Animation when switching screens
enterTransition = { navigateInAnimation },
exitTransition = { navigateUpAnimation },
) {
Expand All @@ -49,23 +48,28 @@ fun AppNavHost(
initialQuery = queryText,
onNavigateBack = { navController.popBackStack() },
onClickPhoto = { _, index ->
Log.d("AppNavHost", "onClickPhoto: $index")
navController.navigate("${Routes.Display.name}/${index}")
},
)
}
composable(
"${Routes.Display.name}/{index}",
arguments = listOf(navArgument("index") { type = NavType.IntType })
) {
val initialIndex: Int = it.arguments?.getInt("index") ?: 0
val initialIndex: Int = it.arguments?.getString("index")?.toInt() ?: 0
DisplayScreen(
initialPage = initialIndex,
onNavigateBack = {
navController.popBackStack()
},
)
}
composable(Routes.Setting.name) {
composable(
Routes.Setting.name,
enterTransition = { popInAnimation },
popEnterTransition = { popInAnimation },
exitTransition = { navigateUpAnimation },
) {
SettingScreen(
onNavigateBack = { navController.popBackStack() },
)
Expand Down
20 changes: 15 additions & 5 deletions app/src/main/java/me/grey/picquery/ui/display/DisplayScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand All @@ -44,7 +45,6 @@ import androidx.compose.ui.unit.dp
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
import com.bumptech.glide.integration.compose.GlideImage
import me.grey.picquery.R
import me.grey.picquery.common.InitializeEffect
import me.grey.picquery.data.model.Photo
import net.engawapg.lib.zoomable.rememberZoomState
import net.engawapg.lib.zoomable.zoomable
Expand All @@ -64,10 +64,20 @@ fun DisplayScreen(
initialPageOffsetFraction = 0f,
pageCount = { photoList.size }
)
InitializeEffect {
displayViewModel.loadPhotos(initialPage)
pagerState.scrollToPage(initialPage)

LaunchedEffect(initialPage) {
displayViewModel.loadPhotos()
if (photoList.isNotEmpty()) {
pagerState.scrollToPage(initialPage)
}
}

LaunchedEffect(photoList) {
if (photoList.isNotEmpty()) {
pagerState.scrollToPage(initialPage)
}
}

Scaffold(
topBar = {
if (pagerState.currentPage + 1 <= photoList.size) {
Expand Down Expand Up @@ -146,7 +156,7 @@ private fun TopPhotoInfoBar(currentPhoto: Photo) {
}


// TODO 标明出处

@OptIn(
ExperimentalFoundationApi::class, ExperimentalGlideComposeApi::class,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package me.grey.picquery.ui.display

import androidx.compose.runtime.mutableIntStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
Expand All @@ -17,10 +16,8 @@ class DisplayViewModel(

private val _photoList = MutableStateFlow<MutableList<Photo>>(mutableListOf())
val photoList:StateFlow<MutableList<Photo>> = _photoList
private val currentIndex = mutableIntStateOf(0)

fun loadPhotos(initialPage: Int) {
currentIndex.intValue = initialPage
fun loadPhotos() {
viewModelScope.launch {
val ids = imageSearcher.searchResultIds
val list = reorderList(photoRepository.getPhotoListByIds(ids),ids)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ fun SearchResultGrid(
state: SearchState,
onClickPhoto: (Photo, Int) -> Unit,
) {
fun onClickPhotoResult(index: Int) {
onClickPhoto(resultList[index], index)
}

when (state) {
SearchState.NO_INDEX -> UnReadyText()
Expand All @@ -63,7 +60,7 @@ fun SearchResultGrid(
Box(padding) {
PhotoResultRecommend(
photo = resultList[0],
onItemClick = { onClickPhotoResult(0) },
onItemClick = { onClickPhoto(resultList[0], 0) },
)
}
}
Expand All @@ -79,7 +76,7 @@ fun SearchResultGrid(
resultList[index + 1],
onItemClick = {
Log.e("SearchResultGrid", "click: $index")
onClickPhotoResult(index + 1)
onClickPhoto(resultList[index+1], index+1)
},
)
}
Expand Down

0 comments on commit 5484b3b

Please sign in to comment.