Skip to content

Commit

Permalink
[feature] Support #43, merge multiple stickers
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyD666 committed Feb 4, 2025
1 parent f15fcde commit c17219d
Show file tree
Hide file tree
Showing 20 changed files with 762 additions and 24 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ android {
minSdk = 24
targetSdk = 35
versionCode = 67
versionName = "2.3-rc12"
versionName = "2.3-rc13"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand Down
26 changes: 25 additions & 1 deletion app/src/main/java/com/skyd/rays/ext/CollectionExt.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.skyd.rays.ext

import androidx.compose.runtime.saveable.listSaver
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.toMutableStateList

inline fun <T> MutableCollection<T>.addIfAny(data: T, predicate: (T) -> Boolean) {
if (find { !predicate(it) } == null) {
this += data
Expand All @@ -12,4 +16,24 @@ fun <T> MutableCollection<T>.addAllDistinctly(newData: Collection<T>) {
add(item)
}
}
}
}

fun <T> List<T>.subList(step: Int, onEachSub: (List<T>) -> Unit) {
for (i in indices step step) {
onEachSub(
subList(
fromIndex = i,
toIndex = minOf(i + step, size),
)
)
}
}

fun <T> List<T>.safeDbVariableNumber(onEachSub: (List<T>) -> Unit) {
subList(900, onEachSub)
}

fun <T : Any> snapshotStateListSaver() = listSaver<SnapshotStateList<T>, T>(
save = { stateList -> stateList.toList() },
restore = { it.toMutableStateList() },
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.skyd.rays.appContext
import com.skyd.rays.base.BaseRepository
import com.skyd.rays.config.EXPORT_FILES_DIR
import com.skyd.rays.config.IMPORT_FILES_DIR
import com.skyd.rays.ext.safeDbVariableNumber
import com.skyd.rays.ext.toDateTimeString
import com.skyd.rays.model.bean.ImportExportInfo
import com.skyd.rays.model.bean.ImportExportResultInfo
Expand All @@ -22,7 +23,6 @@ import com.skyd.rays.util.unzip
import com.skyd.rays.util.zip
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import okio.use
Expand Down Expand Up @@ -125,15 +125,8 @@ class ImportExportFilesRepository @Inject constructor(
// the maximum value of a host parameter number is SQLITE_MAX_VARIABLE_NUMBER,
// which defaults to 999
mutableListOf<StickerWithTags>().apply {
for (i in exportStickers.indices step 900) {
addAll(
stickerDao.getAllStickerWithTagsList(
exportStickers.subList(
fromIndex = i,
toIndex = minOf(i + 900, exportStickers.size),
)
)
)
exportStickers.safeDbVariableNumber {
addAll(stickerDao.getAllStickerWithTagsList(it))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.skyd.rays.model.respository

import com.skyd.rays.base.BaseRepository
import com.skyd.rays.model.bean.StickerWithTags
import com.skyd.rays.model.db.dao.sticker.StickerDao
import com.skyd.rays.util.stickerUuidToFile
import com.skyd.rays.util.stickerUuidToUri
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import java.util.UUID
import javax.inject.Inject

class MergeStickersRepository @Inject constructor(
private val stickerDao: StickerDao,
private val addRepo: AddRepository,
private val searchRepo: SearchRepository,
) : BaseRepository() {
fun requestStickers(stickerUuids: List<String>): Flow<List<StickerWithTags>> = flow {
emit(stickerDao.getAllStickerWithTagsList(stickerUuids))
}.flowOn(Dispatchers.IO)

fun requestMerge(
oldStickerUuid: String,
sticker: StickerWithTags,
deleteUuids: List<String>,
): Flow<Unit> {
return flow {
val stickerFile = stickerUuidToFile(oldStickerUuid)
check(stickerFile.exists())
if (sticker.sticker.uuid == oldStickerUuid) {
sticker.sticker.uuid = UUID.randomUUID().toString()
}
val newStickerFile = stickerUuidToFile(sticker.sticker.uuid)
stickerFile.copyTo(newStickerFile)
check(newStickerFile.exists())

searchRepo.requestDeleteStickerWithTagsDetail(deleteUuids).collect()
addRepo.requestAddStickerWithTags(sticker, stickerUuidToUri(sticker.sticker.uuid))
.collect()

emit(Unit)
}.flowOn(Dispatchers.IO)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.skyd.rays.config.allSearchDomain
import com.skyd.rays.ext.catchMap
import com.skyd.rays.ext.dataStore
import com.skyd.rays.ext.getOrDefault
import com.skyd.rays.ext.safeDbVariableNumber
import com.skyd.rays.model.bean.STICKER_TABLE_NAME
import com.skyd.rays.model.bean.StickerBean
import com.skyd.rays.model.bean.StickerWithTags
Expand Down Expand Up @@ -126,7 +127,7 @@ class SearchRepository @Inject constructor(

fun requestDeleteStickerWithTagsDetail(stickerUuids: List<String>): Flow<List<String>> {
return flowOnIo {
stickerDao.deleteStickerWithTags(stickerUuids)
stickerUuids.safeDbVariableNumber { stickerDao.deleteStickerWithTags(it) }
emit(stickerUuids)
}
}
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/com/skyd/rays/ui/activity/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ import com.skyd.rays.ui.screen.fullimage.FULL_IMAGE_SCREEN_ROUTE
import com.skyd.rays.ui.screen.fullimage.FullImageScreen
import com.skyd.rays.ui.screen.main.MAIN_SCREEN_ROUTE
import com.skyd.rays.ui.screen.main.MainScreen
import com.skyd.rays.ui.screen.mergestickers.MERGE_STICKERS_SCREEN_ROUTE
import com.skyd.rays.ui.screen.mergestickers.MERGE_STICKERS_SCREEN_STICKER_UUIDS_KEY
import com.skyd.rays.ui.screen.mergestickers.MergeStickersScreenRoute
import com.skyd.rays.ui.screen.minitool.selfiesegmentation.SELFIE_SEGMENTATION_SCREEN_ROUTE
import com.skyd.rays.ui.screen.minitool.selfiesegmentation.SelfieSegmentationScreen
import com.skyd.rays.ui.screen.minitool.styletransfer.STYLE_TRANSFER_SCREEN_ROUTE
Expand Down Expand Up @@ -293,6 +296,13 @@ class MainActivity : BaseComposeActivity() {
exportStickers = it.arguments?.getStringArrayList("exportStickers")
)
}
composable(route = MERGE_STICKERS_SCREEN_ROUTE) {
MergeStickersScreenRoute(
stickerUuids = it.arguments?.getStringArrayList(
MERGE_STICKERS_SCREEN_STICKER_UUIDS_KEY
)
)
}
composable(route = IMPORT_FILES_SCREEN_ROUTE) {
ImportFilesScreen()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ fun EmptyPlaceholder(

@Composable
fun ErrorPlaceholder(
modifier: Modifier = Modifier,
text: String,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(),
) {
AnimatedPlaceholder(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import com.skyd.rays.ui.component.RaysLottieAnimation
@Composable
fun RaysDialog(
modifier: Modifier = Modifier,
visible: Boolean,
visible: Boolean = true,
properties: DialogProperties = DialogProperties(),
onDismissRequest: () -> Unit = {},
icon: @Composable (() -> Unit)? = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.skyd.rays.ui.screen.mergestickers

import com.skyd.rays.base.mvi.MviSingleEvent

sealed interface MergeStickersEvent : MviSingleEvent {
sealed interface MergeResult : MergeStickersEvent {
data object Success : MergeResult
data class Failed(val msg: String) : MergeResult
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.skyd.rays.ui.screen.mergestickers

import com.skyd.rays.base.mvi.MviIntent
import com.skyd.rays.model.bean.StickerWithTags

sealed interface MergeStickersIntent : MviIntent {
data class Init(val stickers: List<String>) : MergeStickersIntent
data class Merge(
val oldStickerUuid: String,
val sticker: StickerWithTags,
val deleteUuids: List<String>,
) : MergeStickersIntent
data class RemoveSelectedTag(val tag: String) : MergeStickersIntent
data class AddSelectedTag(val tag: String) : MergeStickersIntent
data class ReplaceAllSelectedTags(val tags: List<String>) : MergeStickersIntent
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.skyd.rays.ui.screen.mergestickers

import com.skyd.rays.model.bean.StickerWithTags

internal sealed interface MergeStickersPartialStateChange {
fun reduce(oldState: MergeStickersState): MergeStickersState

data object LoadingDialog : MergeStickersPartialStateChange {
override fun reduce(oldState: MergeStickersState) = oldState.copy(loadingDialog = true)
}

sealed interface Init : MergeStickersPartialStateChange {
override fun reduce(oldState: MergeStickersState): MergeStickersState {
return when (this) {
is Success -> oldState.copy(
stickersState = StickersState.Success(stickersList),
selectedTags = stickersList.map { sticker ->
sticker.tags.map { it.tag }
}.flatten().distinct(),
loadingDialog = false,
)

is Failed -> oldState.copy(
stickersState = StickersState.Failed(msg),
loadingDialog = false,
)
}
}

data class Success(val stickersList: List<StickerWithTags>) : Init
data class Failed(val msg: String) : Init
}

sealed interface Merge : MergeStickersPartialStateChange {
override fun reduce(oldState: MergeStickersState): MergeStickersState =
oldState.copy(loadingDialog = false)

data object Success : Merge
data class Failed(val msg: String) : Merge
}

data class RemoveSelectedTag(val tag: String) : MergeStickersPartialStateChange {
override fun reduce(oldState: MergeStickersState) = oldState.copy(
selectedTags = oldState.selectedTags.toMutableList().apply { remove(tag) }
)
}

data class AddSelectedTag(val tag: String) : MergeStickersPartialStateChange {
override fun reduce(oldState: MergeStickersState) = oldState.copy(
selectedTags = oldState.selectedTags.toMutableList().apply {
if (tag !in this) add(tag)
}
)
}

data class ReplaceAllSelectedTags(val tags: List<String>) : MergeStickersPartialStateChange {
override fun reduce(oldState: MergeStickersState) = oldState.copy(
selectedTags = tags
)
}
}
Loading

0 comments on commit c17219d

Please sign in to comment.