Skip to content

Commit

Permalink
[feature|optimize]支持多选表情包导出;优化“搜索结果数”的切换动画;优化推荐“常用标签”的计算方式
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyD666 committed Sep 24, 2023
1 parent e738cd7 commit 59f98cb
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 77 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ android {
applicationId "com.skyd.rays"
minSdk 24
targetSdk 34
versionCode 31
versionName "1.5-beta07"
versionCode 32
versionName "1.5"
flavorDimensions = ["versionName"]

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/com/skyd/rays/base/BaseViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ abstract class BaseViewModel<UiState : IUiState, UiEvent : IUiEvent, UiIntent :

fun sendUiIntent(uiIntent: UiIntent) {
viewModelScope.launch {
sendLoadUiIntent(LoadUiIntent.Loading(true))
if (uiIntent.showLoading) {
sendLoadUiIntent(LoadUiIntent.Loading(true))
}
_uiIntentFlow.emit(uiIntent)
}
}
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/java/com/skyd/rays/base/MVIInterface.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ interface IUiState : IUIChange
interface IUiEvent : IUIChange

@Keep
interface IUiIntent
interface IUiIntent {
// 是否触发 sendLoadUiIntent(LoadUiIntent.Loading(true))
val showLoading: Boolean
get() = true
}

sealed class LoadUiIntent {
data class Loading(var isShow: Boolean) : LoadUiIntent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,26 +68,44 @@ class HomeRepository @Inject constructor(private val stickerDao: StickerDao) : B
suspend fun requestPopularTags(count: Int): Flow<BaseData<List<Pair<String, Float>>>> {
return flow {
val popularStickersList = stickerDao.getPopularStickersList(count = count)
val tagsMap: MutableMap<String, Long> = mutableMapOf()
val tagsCountMap: MutableMap<String, Long> = mutableMapOf()
val tagsMap: MutableMap<Pair<String, String>, Long> = mutableMapOf()
val tagsCountMap: MutableMap<Pair<String, String>, Long> = mutableMapOf()
val stickerUuidCountMap: MutableMap<String, Long> = mutableMapOf()
popularStickersList.forEach {
it.tags.forEach { tag ->
val tagString = tag.tag
if (tagString.length < 6) {
tagsCountMap[tagString] = tagsCountMap.getOrDefault(tagString, 0) + 1
tagsMap[tagString] =
tagsMap.getOrDefault(tagString, 0) + it.sticker.shareCount
tagsCountMap[tagString to it.sticker.uuid] = tagsCountMap
.getOrDefault(tagString to it.sticker.uuid, 0) + 1
tagsMap[tagString to it.sticker.uuid] = tagsMap
.getOrDefault(tagString to it.sticker.uuid, 0) + it.sticker.shareCount
}
}
stickerUuidCountMap[it.sticker.uuid] = 0
}
tagsCountMap.forEach { (t, u) ->
tagsMap[t] = tagsMap.getOrDefault(t, 0) * u
}
val result = tagsMap.toList().sortedByDescending { (_, value) -> value }
var result = tagsMap.toList().sortedByDescending { (_, value) -> value }
result = result.filter {
val stickUuid = it.first.second
val cnt = stickerUuidCountMap[stickUuid]
if (cnt != null) {
// 限制每个表情包只能推荐两个标签
if (cnt >= 2) {
false
} else {
stickerUuidCountMap[stickUuid] = cnt + 1
true
}
} else {
false
}
}.distinctBy { it.first.first }
val maxPopularValue = result.getOrNull(0)?.second ?: 1
emitBaseData(BaseData<List<Pair<String, Float>>>().apply {
code = 0
data = result.map { it.first to it.second.toFloat() / maxPopularValue }
data = result.map { it.first.first to it.second.toFloat() / maxPopularValue }
})
}
}
Expand Down
15 changes: 11 additions & 4 deletions app/src/main/java/com/skyd/rays/ui/screen/home/HomeIntent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,24 @@ import com.skyd.rays.base.IUiIntent
import com.skyd.rays.model.bean.StickerWithTags

sealed class HomeIntent : IUiIntent {
override val showLoading: Boolean = false

data class UpdateThemeColor(val stickerUuid: String, val primaryColor: Int) : HomeIntent()
data class GetStickerDetails(val stickerUuid: String) :
HomeIntent()
data class GetStickerDetails(val stickerUuid: String) : HomeIntent()

data class DeleteStickerWithTags(val stickerUuids: List<String>) : HomeIntent() {
override val showLoading: Boolean = true
}

data class DeleteStickerWithTags(val stickerUuids: List<String>) : HomeIntent()
data class GetStickerWithTagsList(val keyword: String) : HomeIntent()
data class SortStickerWithTagsList(val data: List<StickerWithTags>) : HomeIntent()
data class ReverseStickerWithTagsList(val data: List<StickerWithTags>) : HomeIntent()
data class AddClickCountAndGetStickerDetails(val stickerUuid: String, val count: Int = 1) :
HomeIntent()

data class ExportStickers(val stickerUuids: List<String>) : HomeIntent()
data class ExportStickers(val stickerUuids: List<String>) : HomeIntent() {
override val showLoading: Boolean = true
}

object GetPopularTagsList : HomeIntent()
}
6 changes: 5 additions & 1 deletion app/src/main/java/com/skyd/rays/ui/screen/home/HomeScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import com.skyd.rays.ui.component.AnimatedPlaceholder
import com.skyd.rays.ui.component.RaysIconButton
import com.skyd.rays.ui.component.RaysIconButtonStyle
import com.skyd.rays.ui.component.RaysImage
import com.skyd.rays.ui.component.dialog.WaitingDialog
import com.skyd.rays.ui.local.LocalCurrentStickerUuid
import com.skyd.rays.ui.local.LocalHomeShareButtonAlignment
import com.skyd.rays.ui.local.LocalNavController
Expand All @@ -98,6 +99,7 @@ fun HomeScreen(viewModel: HomeViewModel = hiltViewModel()) {
val initQuery = LocalQuery.current
var active by rememberSaveable { mutableStateOf(false) }
var query by rememberSaveable(initQuery) { mutableStateOf(initQuery) }
var openWaitingDialog by rememberSaveable { mutableStateOf(false) }
val uiState by viewModel.uiStateFlow.collectAsStateWithLifecycle()
val uiEvent by viewModel.uiEventFlow.collectAsStateWithLifecycle(initialValue = null)
val loadUiIntent by viewModel.loadUiIntentFlow.collectAsStateWithLifecycle(initialValue = null)
Expand Down Expand Up @@ -218,9 +220,11 @@ fun HomeScreen(viewModel: HomeViewModel = hiltViewModel()) {
)
}

is LoadUiIntent.Loading -> Unit
is LoadUiIntent.Loading -> openWaitingDialog = loadUiIntent.isShow
}
}

WaitingDialog(visible = openWaitingDialog)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.skyd.rays.ui.screen.home.searchbar

import android.content.Intent
import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
Expand Down Expand Up @@ -33,7 +34,6 @@ import androidx.compose.material3.TextButton
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
Expand All @@ -57,6 +57,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.skyd.rays.R
import com.skyd.rays.config.refreshStickerData
import com.skyd.rays.ext.isCompact
import com.skyd.rays.model.bean.StickerWithTags
import com.skyd.rays.model.preference.ExportStickerDirPreference
import com.skyd.rays.model.preference.search.QueryPreference
Expand Down Expand Up @@ -91,10 +92,8 @@ fun RaysSearchBar(
var menuExpanded by rememberSaveable { mutableStateOf(false) }
var multiSelect by rememberSaveable { mutableStateOf(false) }
val selectedStickers = remember { mutableStateListOf<StickerWithTags>() }
val context = LocalContext.current
val windowSizeClass = LocalWindowSizeClass.current
val navController = LocalNavController.current
val scope = rememberCoroutineScope()
val currentStickerUuid = LocalCurrentStickerUuid.current
val keyboardController = LocalSoftwareKeyboardController.current
val searchBarHorizontalPadding: Dp by animateDpAsState(
Expand Down Expand Up @@ -234,16 +233,30 @@ fun RaysSearchBar(
enter = if (compact) expandVertically() else expandHorizontally(),
exit = if (compact) shrinkVertically() else shrinkHorizontally(),
) {
MultiSelectBar(
var openMultiStickersExportPathDialog by rememberSaveable {
mutableStateOf(false)
}
MultiSelectActionBar(
selectedStickers = selectedStickers,
onDeleteClick = {
openDeleteMultiStickersDialog =
searchResultUiState.stickerWithTagsList.toSet()
}
},
onExportClick = { openMultiStickersExportPathDialog = true },
)
ExportDialog(
visible = openMultiStickersExportPathDialog,
onDismissRequest = {
openMultiStickersExportPathDialog = false
},
onExport = {
val uuidList = selectedStickers.map { it.sticker.uuid }
viewModel.sendUiIntent(HomeIntent.ExportStickers(uuidList))
},
)
}
}
if (windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact) {
if (windowSizeClass.isCompact) {
Box(modifier = Modifier.weight(1f)) { searchResultList() }
multiSelectBar(compact = true)
} else {
Expand Down Expand Up @@ -311,61 +324,77 @@ fun RaysSearchBar(
}
)

val exportStickerDir = LocalExportStickerDir.current
val pickExportDirLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.OpenDocumentTree()
) { uri ->
if (uri != null) {
ExportStickerDirPreference.put(
context = context,
scope = scope,
value = uri.toString()
)
}
}
RaysDialog(
ExportDialog(
visible = openExportPathDialog,
title = { Text(text = stringResource(R.string.home_screen_export)) },
text = {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
modifier = Modifier.weight(1f),
text = exportStickerDir.ifBlank {
stringResource(id = R.string.home_screen_select_export_folder_tip)
}
)
RaysIconButton(
onClick = {
pickExportDirLauncher.launch(Uri.parse(exportStickerDir))
},
imageVector = Icons.Default.Folder,
contentDescription = stringResource(R.string.home_screen_select_export_folder)
)
}
},
onDismissRequest = {
openExportPathDialog = false
},
dismissButton = {
TextButton(onClick = { openExportPathDialog = false }) {
Text(text = stringResource(id = R.string.dialog_cancel))
}
},
confirmButton = {
TextButton(
enabled = exportStickerDir.isNotBlank(),
onClick = {
openExportPathDialog = false
viewModel.sendUiIntent(HomeIntent.ExportStickers(listOf(currentStickerUuid)))
}
) {
Text(text = stringResource(id = R.string.dialog_ok))
}
}
onDismissRequest = { openExportPathDialog = false },
onExport = { viewModel.sendUiIntent(HomeIntent.ExportStickers(listOf(currentStickerUuid))) },
)
}
}

@Composable
internal fun ExportDialog(
visible: Boolean,
onDismissRequest: () -> Unit = {},
onExport: () -> Unit,
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val exportStickerDir = LocalExportStickerDir.current
val pickExportDirLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.OpenDocumentTree()
) { uri ->
if (uri != null) {
context.contentResolver.takePersistableUriPermission(
uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
ExportStickerDirPreference.put(
context = context,
scope = scope,
value = uri.toString()
)
}
}
RaysDialog(
visible = visible,
title = { Text(text = stringResource(R.string.home_screen_export)) },
text = {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
modifier = Modifier.weight(1f),
text = exportStickerDir.ifBlank {
stringResource(id = R.string.home_screen_select_export_folder_tip)
}
)
RaysIconButton(
onClick = {
pickExportDirLauncher.launch(Uri.parse(exportStickerDir))
},
imageVector = Icons.Default.Folder,
contentDescription = stringResource(R.string.home_screen_select_export_folder)
)
}
},
onDismissRequest = onDismissRequest,
dismissButton = {
TextButton(onClick = onDismissRequest) {
Text(text = stringResource(id = R.string.dialog_cancel))
}
},
confirmButton = {
TextButton(
enabled = exportStickerDir.isNotBlank(),
onClick = {
onDismissRequest()
onExport()
}
) {
Text(text = stringResource(id = R.string.dialog_ok))
}
}
)
}

@Composable
fun TrailingIcon(
Expand Down
Loading

0 comments on commit 59f98cb

Please sign in to comment.