diff --git a/app/build.gradle b/app/build.gradle index cb12243..74f12e9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,8 +21,8 @@ android { applicationId "com.skyd.rays" minSdk 24 targetSdk 34 - versionCode 42 - versionName "1.6-beta24" + versionCode 43 + versionName "1.6-beta25" flavorDimensions = ["versionName"] testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -85,7 +85,7 @@ android { compose true } composeOptions { - kotlinCompilerExtensionVersion '1.5.3' + kotlinCompilerExtensionVersion '1.5.4' } packagingOptions { resources { diff --git a/app/src/main/java/com/skyd/rays/ui/component/RaysIconButton.kt b/app/src/main/java/com/skyd/rays/ui/component/RaysIconButton.kt index 0030ca3..7eb653b 100644 --- a/app/src/main/java/com/skyd/rays/ui/component/RaysIconButton.kt +++ b/app/src/main/java/com/skyd/rays/ui/component/RaysIconButton.kt @@ -1,7 +1,21 @@ package com.skyd.rays.ui.component import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.material3.* +import androidx.compose.material3.FilledIconButton +import androidx.compose.material3.FilledTonalIconButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonColors +import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.IconToggleButton +import androidx.compose.material3.IconToggleButtonColors +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.OutlinedIconButton +import androidx.compose.material3.PlainTooltip +import androidx.compose.material3.Text +import androidx.compose.material3.TooltipBox +import androidx.compose.material3.TooltipDefaults +import androidx.compose.material3.rememberTooltipState import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -43,6 +57,7 @@ fun RaysIconButton( interactionSource = interactionSource, content = icon, ) + RaysIconButtonStyle.Filled -> FilledIconButton( modifier = it, onClick = onClick, @@ -51,6 +66,7 @@ fun RaysIconButton( interactionSource = interactionSource, content = icon, ) + RaysIconButtonStyle.FilledTonal -> FilledTonalIconButton( modifier = it, onClick = onClick, @@ -59,6 +75,7 @@ fun RaysIconButton( interactionSource = interactionSource, content = icon, ) + RaysIconButtonStyle.Outlined -> OutlinedIconButton( modifier = it, onClick = onClick, @@ -112,3 +129,43 @@ fun RaysIconButton( interactionSource = interactionSource, ) } + +@Composable +fun RaysIconToggleButton( + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonColors(), + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + contentDescription: String? = null, + content: @Composable () -> Unit +) { + val iconButton: @Composable (modifier: Modifier) -> Unit = { + IconToggleButton( + checked = checked, + onCheckedChange = onCheckedChange, + modifier = it, + enabled = enabled, + colors = colors, + interactionSource = interactionSource, + content = content, + ) + } + if (contentDescription.isNullOrEmpty()) { + iconButton(modifier) + } else { + TooltipBox( + modifier = modifier, + positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(), + tooltip = { + PlainTooltip { + Text(contentDescription) + } + }, + state = rememberTooltipState() + ) { + iconButton(Modifier) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/skyd/rays/ui/screen/add/AddScreen.kt b/app/src/main/java/com/skyd/rays/ui/screen/add/AddScreen.kt index 336f713..b14ff67 100644 --- a/app/src/main/java/com/skyd/rays/ui/screen/add/AddScreen.kt +++ b/app/src/main/java/com/skyd/rays/ui/screen/add/AddScreen.kt @@ -36,17 +36,26 @@ import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos +import androidx.compose.material.icons.automirrored.filled.ArrowForward import androidx.compose.material.icons.automirrored.filled.Help +import androidx.compose.material.icons.filled.AddPhotoAlternate import androidx.compose.material.icons.filled.AddToPhotos import androidx.compose.material.icons.filled.Cancel +import androidx.compose.material.icons.filled.CancelScheduleSend import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material.icons.filled.DeleteOutline import androidx.compose.material.icons.filled.Done +import androidx.compose.material.icons.filled.EditOff import androidx.compose.material.icons.filled.ExpandLess import androidx.compose.material.icons.filled.ExpandMore +import androidx.compose.material.icons.filled.Image +import androidx.compose.material.icons.filled.Save +import androidx.compose.material.icons.filled.SkipNext import androidx.compose.material3.AssistChipDefaults import androidx.compose.material3.CardDefaults import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.InputChip import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField @@ -77,11 +86,15 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -93,20 +106,21 @@ import com.skyd.rays.config.refreshStickerData import com.skyd.rays.ext.addAllDistinctly import com.skyd.rays.ext.addIfAny import com.skyd.rays.ext.navigate +import com.skyd.rays.ext.plus import com.skyd.rays.ext.popBackStackWithLifecycle import com.skyd.rays.ext.showSnackbar import com.skyd.rays.ext.showSnackbarWithLaunchedEffect -import com.skyd.rays.model.bean.EmptyUriWithStickerUuidBean import com.skyd.rays.model.bean.StickerBean import com.skyd.rays.model.bean.StickerWithTags import com.skyd.rays.model.bean.TagBean import com.skyd.rays.model.bean.UriWithStickerUuidBean import com.skyd.rays.ui.component.AnimatedPlaceholder import com.skyd.rays.ui.component.RaysCard +import com.skyd.rays.ui.component.RaysFloatingActionButton +import com.skyd.rays.ui.component.RaysFloatingActionButtonStyle import com.skyd.rays.ui.component.RaysIconButton import com.skyd.rays.ui.component.RaysImage import com.skyd.rays.ui.component.RaysTopBar -import com.skyd.rays.ui.component.TopBarIcon import com.skyd.rays.ui.component.dialog.RaysDialog import com.skyd.rays.ui.local.LocalNavController import com.skyd.rays.util.stickerUuidToUri @@ -147,43 +161,90 @@ fun AddScreen( var stickerCreateTime by remember { mutableLongStateOf(System.currentTimeMillis()) } val tagsToAllWaitingStickers = remember { mutableStateListOf() } val tags = remember { mutableStateListOf() } - var currentSticker by remember { mutableStateOf(EmptyUriWithStickerUuidBean) } val stickersWaitingList = remember { mutableStateListOf() } val suggestedTags = remember { mutableStateListOf() } val loadUiIntent by viewModel.loadUiIntentFlow.collectAsStateWithLifecycle(initialValue = null) val uiEvent by viewModel.uiEventFlow.collectAsStateWithLifecycle(initialValue = null) + fun currentSticker(): UriWithStickerUuidBean? = stickersWaitingList.firstOrNull() + + // 添加/修改完成后重设页面数据 + fun resetStickerData() { + titleText = "" + currentTagText = "" + stickerCreateTime = System.currentTimeMillis() + suggestedTags.clear() + tags.clear() + tags.addAll(tagsToAllWaitingStickers) + if (stickersWaitingList.isNotEmpty()) { + stickersWaitingList.removeAt(0) + } + } + LaunchedEffect(Unit) { - initStickers.firstOrNull()?.let { firstSticker -> - currentSticker = firstSticker - stickersWaitingList.addAll(initStickers.subList(1, initStickers.size)) - if (firstSticker.stickerUuid.isNotBlank()) { - viewModel.sendUiIntent(AddIntent.GetStickerWithTags(firstSticker.stickerUuid)) + stickersWaitingList.addAll(initStickers) + currentSticker()?.let { currentSticker -> + if (currentSticker.stickerUuid.isNotBlank()) { + viewModel.sendUiIntent(AddIntent.GetStickerWithTags(currentSticker.stickerUuid)) + } + } + } + + LaunchedEffect(currentSticker()) { + val currentSticker = currentSticker() + if (currentSticker != null) { + currentSticker.uri?.let { uri -> + viewModel.sendUiIntent(AddIntent.GetSuggestTags(uri)) + } + } else { + resetStickerData() + if (isEdit) { + navController.popBackStackWithLifecycle() } } } + val pickStickerLauncher = rememberLauncherForActivityResult( + ActivityResultContracts.GetContent() + ) { result -> + if (result != null) stickersWaitingList[0] = UriWithStickerUuidBean(uri = result) + } + val pickStickersLauncher = rememberLauncherForActivityResult( + ActivityResultContracts.GetMultipleContents() + ) { result -> + if (result.isEmpty()) return@rememberLauncherForActivityResult + stickersWaitingList.addAllDistinctly(result.map { UriWithStickerUuidBean(uri = it) }) + } + Scaffold( snackbarHost = { SnackbarHost(snackbarHostState) }, topBar = { RaysTopBar( title = { Text( - text = stringResource( - if (isEdit) R.string.add_screen_name_edit else R.string.add_screen_name + stringResource( + if (isEdit) R.string.add_screen_name_edit + else R.string.add_screen_name ) ) }, actions = { - TopBarIcon( - imageVector = if (stickersWaitingList.isEmpty()) { - Icons.Default.Done - } else { - Icons.AutoMirrored.Default.ArrowForwardIos + RaysIconButton( + onClick = { + (if (isEdit) pickStickerLauncher else pickStickersLauncher) + .launch("image/*") }, - contentDescription = stringResource(R.string.add_screen_add), + contentDescription = stringResource(R.string.add_screen_select_sticker), + imageVector = if (isEdit) Icons.Default.Image else Icons.Default.AddPhotoAlternate, + ) + RaysIconButton( + onClick = { resetStickerData() }, + contentDescription = stringResource(R.string.add_screen_skip_current_sticker), + imageVector = Icons.Default.EditOff, + ) + RaysIconButton( onClick = { - if (currentSticker.isEmpty()) { + if (currentSticker() == null) { snackbarHostState.showSnackbar( scope = scope, message = appContext.getString(R.string.add_screen_sticker_is_not_set), @@ -195,40 +256,25 @@ fun AddScreen( sticker = StickerBean( title = titleText, createTime = stickerCreateTime - ).apply { uuid = currentSticker.stickerUuid }, + ).apply { uuid = currentSticker()!!.stickerUuid }, tags = tags.distinct() ) viewModel.sendUiIntent( AddIntent.AddNewStickerWithTags( stickerWithTags, - currentSticker.uri!! + currentSticker()!!.uri!! ) ) } - } + }, + contentDescription = stringResource(R.string.add_screen_save), + imageVector = Icons.Default.Save, ) } ) - } - ) { paddingValues -> - val pickStickerLauncher = rememberLauncherForActivityResult( - ActivityResultContracts.GetContent() - ) { result -> - if (result != null) currentSticker = UriWithStickerUuidBean(uri = result) - } - val pickStickersLauncher = rememberLauncherForActivityResult( - ActivityResultContracts.GetMultipleContents() - ) { result -> - if (result.isEmpty()) return@rememberLauncherForActivityResult - if (currentSticker.isEmpty()) { - currentSticker = UriWithStickerUuidBean(uri = result.first()) - stickersWaitingList.addAllDistinctly(result.subList(1, result.size) - .map { UriWithStickerUuidBean(uri = it) }) - } else { - stickersWaitingList.addAllDistinctly(result.map { UriWithStickerUuidBean(uri = it) }) - stickersWaitingList.removeIf { it.uri == currentSticker.uri } - } - } + }, + + ) { paddingValues -> LazyColumn(contentPadding = paddingValues) { item { AnimatedVisibility( @@ -280,31 +326,22 @@ fun AddScreen( tags.addIfAny(TagBean(tag = text)) { it.tag != text } }) } - item { - StickerCard( - stickerUri = currentSticker.uri, - pickLauncher = if (isEdit) pickStickerLauncher else pickStickersLauncher, - onGetSuggestTags = { stickerUri -> - viewModel.sendUiIntent(AddIntent.GetSuggestTags(stickerUri)) - } - ) - } } RaysDialog( visible = openDialog, - title = { Text(text = stringResource(R.string.dialog_tip)) }, + title = { Text(text = stringResource(R.string.info)) }, text = { Text(text = stringResource(R.string.add_screen_success)) }, onDismissRequest = { openDialog = false - if (stickersWaitingList.isEmpty() && currentSticker.isEmpty()) { + if (stickersWaitingList.isEmpty()) { navController.popBackStackWithLifecycle() } }, confirmButton = { TextButton(onClick = { openDialog = false - if (stickersWaitingList.isEmpty() && currentSticker.isEmpty()) { + if (stickersWaitingList.isEmpty()) { navController.popBackStackWithLifecycle() } }) { @@ -315,7 +352,7 @@ fun AddScreen( RaysDialog( visible = openDuplicateDialog, - title = { Text(text = stringResource(R.string.dialog_tip)) }, + title = { Text(text = stringResource(R.string.info)) }, text = { Text(text = stringResource(R.string.add_screen_sticker_duplicate)) }, onDismissRequest = { openDuplicateDialog = false }, confirmButton = { @@ -326,30 +363,18 @@ fun AddScreen( ) } - // 添加/修改完成后重设页面数据 - fun resetStickerData() { - titleText = "" - currentTagText = "" - stickerCreateTime = System.currentTimeMillis() - suggestedTags.clear() - tags.clear() - tags.addAll(tagsToAllWaitingStickers) - if (stickersWaitingList.isEmpty()) { - currentSticker = EmptyUriWithStickerUuidBean - } else { - currentSticker = stickersWaitingList.first() - stickersWaitingList.removeAt(0) - } - } - uiEvent?.apply { when (getStickersWithTagsUiEvent) { is GetStickersWithTagsUiEvent.Success -> { val stickerBean = getStickersWithTagsUiEvent.stickerWithTags.sticker - currentSticker = currentSticker.copy( - uri = stickerUuidToUri(stickerBean.uuid), - stickerUuid = stickerBean.uuid - ) + val stickerIndex = stickersWaitingList + .indexOfFirst { it.stickerUuid == stickerBean.uuid } + if (stickerIndex > -1) { + stickersWaitingList[stickerIndex] = UriWithStickerUuidBean( + uri = stickerUuidToUri(stickerBean.uuid), + stickerUuid = stickerBean.uuid + ) + } titleText = stickerBean.title stickerCreateTime = stickerBean.createTime tags.clear() @@ -424,7 +449,10 @@ private fun LazyListScope.titleInputFieldItem( ) } }, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Done, + keyboardType = KeyboardType.Uri + ), keyboardActions = KeyboardActions(onDone = { focusManager.moveFocus(FocusDirection.Next) }) @@ -598,37 +626,6 @@ private fun WaitingRow( } } -@Composable -private fun StickerCard( - stickerUri: Uri?, - pickLauncher: ManagedActivityResultLauncher, - onGetSuggestTags: (Uri) -> Unit, -) { - RaysCard( - modifier = Modifier.padding(horizontal = 16.dp, vertical = 7.dp), - colors = CardDefaults.cardColors(Color.Transparent), - onClick = { pickLauncher.launch("image/*") }, - ) { - if (stickerUri == null) { - Box(modifier = Modifier.aspectRatio(1.6f)) { - AnimatedPlaceholder( - resId = R.raw.lottie_genshin_impact_klee_1, - sizeFraction = 0.9f, - tip = stringResource(R.string.add_screen_select_sticker) - ) - } - } else { - LaunchedEffect(stickerUri) { - onGetSuggestTags(stickerUri) - } - RaysImage( - model = stickerUri, - modifier = Modifier.fillMaxWidth() - ) - } - } -} - @Composable private fun AddedTags(tags: List, onClick: (Int) -> Unit) { FlowRow( diff --git a/app/src/main/java/com/skyd/rays/ui/screen/home/searchbar/RaysSearchBar.kt b/app/src/main/java/com/skyd/rays/ui/screen/home/searchbar/RaysSearchBar.kt index e85ee9e..371b6ed 100644 --- a/app/src/main/java/com/skyd/rays/ui/screen/home/searchbar/RaysSearchBar.kt +++ b/app/src/main/java/com/skyd/rays/ui/screen/home/searchbar/RaysSearchBar.kt @@ -218,16 +218,14 @@ fun RaysSearchBar( val searchResultUiState = uiState.searchResultUiState if (searchResultUiState is SearchResultUiState.Success) { val searchResultList = @Composable { + if (!active) multiSelect = false SearchResultList( state = searchResultListState, dataList = searchResultUiState.stickerWithTagsList, onItemClickListener = { data, selected -> if (multiSelect) { - if (selected) { - selectedStickers.add(data) - } else { - selectedStickers.remove(data) - } + if (selected) selectedStickers.add(data) + else selectedStickers.remove(data) } else { onActiveChange(false) viewModel.sendUiIntent( @@ -244,9 +242,11 @@ fun RaysSearchBar( selectedStickers.clear() } }, - onSelectAllClick = { + onInvertSelectClick = { + val newSelectedStickers = + searchResultUiState.stickerWithTagsList - selectedStickers selectedStickers.clear() - selectedStickers.addAll(searchResultUiState.stickerWithTagsList) + selectedStickers.addAll(newSelectedStickers) }, selectedStickers = selectedStickers, ) diff --git a/app/src/main/java/com/skyd/rays/ui/screen/home/searchbar/SearchResultList.kt b/app/src/main/java/com/skyd/rays/ui/screen/home/searchbar/SearchResultList.kt index bc50a3c..d26d0d2 100644 --- a/app/src/main/java/com/skyd/rays/ui/screen/home/searchbar/SearchResultList.kt +++ b/app/src/main/java/com/skyd/rays/ui/screen/home/searchbar/SearchResultList.kt @@ -1,5 +1,6 @@ package com.skyd.rays.ui.screen.home.searchbar +import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedContent import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn @@ -31,19 +32,18 @@ import androidx.compose.material.icons.filled.ArrowDropDown import androidx.compose.material.icons.filled.ArrowDropUp import androidx.compose.material.icons.filled.ArrowUpward import androidx.compose.material.icons.filled.Delete -import androidx.compose.material.icons.filled.Done import androidx.compose.material.icons.filled.Save import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.outlined.CheckCircle import androidx.compose.material3.AssistChipDefaults import androidx.compose.material3.Badge import androidx.compose.material3.FilterChip -import androidx.compose.material3.FilterChipDefaults import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.SuggestionChip import androidx.compose.material3.Text +import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -86,7 +86,7 @@ fun SearchResultList( onItemClickListener: ((data: StickerWithTags, selected: Boolean) -> Unit)? = null, multiSelect: Boolean, onMultiSelectChanged: (Boolean) -> Unit, - onSelectAllClick: () -> Unit, + onInvertSelectClick: () -> Unit, selectedStickers: List, viewModel: HomeViewModel = hiltViewModel() ) { @@ -107,7 +107,7 @@ fun SearchResultList( stickersCount = dataList.size, multiSelect = multiSelect, onMultiSelectChanged = onMultiSelectChanged, - onSelectAllClick = onSelectAllClick, + onInvertSelectClick = onInvertSelectClick, ) if (dataList.isEmpty()) { AnimatedPlaceholder( @@ -162,13 +162,17 @@ fun SearchResultConfigBar( stickersCount: Int, multiSelect: Boolean, onMultiSelectChanged: (Boolean) -> Unit, - onSelectAllClick: () -> Unit, + onInvertSelectClick: () -> Unit, ) { val searchResultReverse = LocalSearchResultReverse.current val context = LocalContext.current val scope = rememberCoroutineScope() var expandMenu by rememberSaveable { mutableStateOf(false) } + BackHandler(multiSelect) { + onMultiSelectChanged(false) + } + LazyRow( contentPadding = PaddingValues(horizontal = 16.dp), horizontalArrangement = Arrangement.spacedBy(6.dp), @@ -193,6 +197,8 @@ fun SearchResultConfigBar( } } + item { VerticalDivider(modifier = Modifier.height(16.dp)) } + item { Box { FilterChip( @@ -225,40 +231,24 @@ fun SearchResultConfigBar( ) }, label = { Text(text = stringResource(R.string.search_result_reverse)) }, - leadingIcon = { - if (searchResultReverse) { - Icon( - imageVector = Icons.Default.Done, - contentDescription = null, - modifier = Modifier.size(FilterChipDefaults.IconSize), - ) - } - } ) } + item { VerticalDivider(modifier = Modifier.height(16.dp)) } + item { FilterChip( selected = multiSelect, onClick = { onMultiSelectChanged(!multiSelect) }, label = { Text(text = stringResource(R.string.search_result_multi_select)) }, - leadingIcon = { - if (multiSelect) { - Icon( - imageVector = Icons.Default.Done, - contentDescription = null, - modifier = Modifier.size(FilterChipDefaults.IconSize), - ) - } - } ) } item { if (multiSelect) { SuggestionChip( - onClick = onSelectAllClick, - label = { Text(text = stringResource(R.string.search_result_select_all)) }, + onClick = onInvertSelectClick, + label = { Text(text = stringResource(R.string.search_result_invert_selection)) }, ) } } diff --git a/app/src/main/java/com/skyd/rays/ui/screen/minitool/MiniToolScreen.kt b/app/src/main/java/com/skyd/rays/ui/screen/minitool/MiniToolScreen.kt index bad4ba3..52459c0 100644 --- a/app/src/main/java/com/skyd/rays/ui/screen/minitool/MiniToolScreen.kt +++ b/app/src/main/java/com/skyd/rays/ui/screen/minitool/MiniToolScreen.kt @@ -2,13 +2,10 @@ package com.skyd.rays.ui.screen.minitool import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Egg import androidx.compose.material.icons.filled.Extension import androidx.compose.material.icons.filled.PeopleAlt import androidx.compose.material.icons.filled.Style -import androidx.compose.material3.Icon import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState @@ -70,13 +67,11 @@ fun MiniToolScreen() { MiniTool1Bean( title = stringResource(R.string.style_transfer_screen_name), icon = Icons.Default.Style, - experimental = false, action = { navController.navigate(STYLE_TRANSFER_SCREEN_ROUTE) } ), MiniTool1Bean( title = stringResource(R.string.selfie_segmentation_screen_name), icon = Icons.Default.PeopleAlt, - experimental = true, action = { navController.navigate(SELFIE_SEGMENTATION_SCREEN_ROUTE) } ), ) diff --git a/app/src/main/java/com/skyd/rays/ui/screen/settings/appearance/style/HomeScreenPreview.kt b/app/src/main/java/com/skyd/rays/ui/screen/settings/appearance/style/HomeScreenPreview.kt index c583323..1abc1fe 100644 --- a/app/src/main/java/com/skyd/rays/ui/screen/settings/appearance/style/HomeScreenPreview.kt +++ b/app/src/main/java/com/skyd/rays/ui/screen/settings/appearance/style/HomeScreenPreview.kt @@ -182,7 +182,7 @@ private fun RaysSearchBarPreview() { onItemClickListener = { _, _ -> active = false }, multiSelect = false, onMultiSelectChanged = {}, - onSelectAllClick = {}, + onInvertSelectClick = {}, selectedStickers = emptyList() ) } diff --git a/app/src/main/java/com/skyd/rays/ui/screen/settings/data/importexport/cloud/webdav/WebDavScreen.kt b/app/src/main/java/com/skyd/rays/ui/screen/settings/data/importexport/cloud/webdav/WebDavScreen.kt index 666afbb..92b3270 100644 --- a/app/src/main/java/com/skyd/rays/ui/screen/settings/data/importexport/cloud/webdav/WebDavScreen.kt +++ b/app/src/main/java/com/skyd/rays/ui/screen/settings/data/importexport/cloud/webdav/WebDavScreen.kt @@ -15,10 +15,10 @@ import androidx.compose.material.icons.filled.CloudDownload import androidx.compose.material.icons.filled.CloudUpload import androidx.compose.material.icons.filled.DeleteForever import androidx.compose.material.icons.filled.Dns +import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Key import androidx.compose.material.icons.filled.Recycling import androidx.compose.material.icons.filled.RestoreFromTrash -import androidx.compose.material.icons.filled.Warning import androidx.compose.material3.Button import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.ListItem @@ -65,6 +65,7 @@ import com.skyd.rays.ui.component.RaysIconButton import com.skyd.rays.ui.component.RaysLottieAnimation import com.skyd.rays.ui.component.RaysTopBar import com.skyd.rays.ui.component.RaysTopBarStyle +import com.skyd.rays.ui.component.TipSettingsItem import com.skyd.rays.ui.component.dialog.DeleteWarningDialog import com.skyd.rays.ui.component.dialog.RaysDialog import com.skyd.rays.ui.component.dialog.TextFieldDialog @@ -104,7 +105,8 @@ fun WebDavScreen(viewModel: WebDavViewModel = hiltViewModel()) { actions = { RaysIconButton( onClick = { openWarningDialog = true }, - imageVector = Icons.Default.Warning + imageVector = Icons.Default.Info, + contentDescription = stringResource(R.string.info) ) }, ) @@ -512,6 +514,13 @@ private fun LazyListScope.syncItem( onClick = onRemoteRecycleBinItemClick ) } + item { + TipSettingsItem( + text = stringResource(R.string.webdav_screen_download_tip) + "\n\n" + + stringResource(R.string.webdav_screen_upload_tip) + "\n\n" + + stringResource(R.string.webdav_screen_remote_recycle_bin_tip) + ) + } } private fun checkWebDavInfo( diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 09b2576..f1aa21a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -4,19 +4,20 @@ 首页 输入关键词搜索 添加 - 添加 + 保存 标题(可选) 添加标签(可选) 添加表情包 修改表情包 返回 操作成功 - 待添加(点击可移除) + 处理列表 表情包图片未设置! 按下回车以添加 为待添加列表中的所有表情包加入此标签 全局标签 待添加列表中的所有表情包都会加入这些标签。 + 放弃当前编辑 搜索 关闭 清除文字 @@ -27,7 +28,7 @@ 编辑 删除 导出 - 提示 + 提示 确定 关闭 取消 @@ -54,7 +55,7 @@ 亮色 跟随系统 通过云 - 通过文件(实验性) + 通过文件 从文件导入 从本地文件导入表情包、标签等信息 选择备份文件 @@ -98,10 +99,12 @@ 服务器 请输入 WebDAV 服务器网址 同步 - 推送到远端 - 将本地数据推送到远端,冲突时会覆盖远端内容。若某表情包本地没有,而远端有,则该表情包会被移动到远端回收站 - 从远端拉取 - 从远端拉取数据,冲突时会覆盖本地内容。若某表情包既在本地,也在远端回收站内,则本地的该表情包会被删除。若某表情包本地有,而远端没有,则该表情包不会被修改 + 推送 + 将本地数据推送到远端 + 将本地数据推送到远端时,若遇到冲突,则会覆盖远端内容。若某表情包本地没有,而远端有,则该表情包会被移动到远端回收站内。 + 拉取 + 从远端拉取数据 + 从远端拉取数据时,若遇到冲突,则会覆盖本地内容。若某表情包既在本地,也在远端回收站内,则该本地的表情包会被删除。若本地有某个表情包,而远端没有,则该表情包不会被修改。 拉取成功,耗时 %1$.2f 秒,更新 %2$d 条 @@ -114,7 +117,8 @@ 账号 密码 远端回收站 - 查看远端回收站的内容,有哪些表情包被逻辑删除了。该项包含的操作仅会影响远端内容,不会修改本地内容 + 查看远端回收站的内容 + 远端回收站里的内容是被逻辑删除的表情包。对远端回收站的操作仅会影响远端内容,不会修改本地内容。 清空回收站 上次修改时间:%s 删除 @@ -191,7 +195,7 @@ 排序 逆序 多选 - 全选 + 反选 到顶部 分享按钮位置 水平 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 943db9e..4cb571a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,19 +4,20 @@ Home Search Add - Add + Save Title (Optional) Add tags (Optional) Add sticker Edit sticker Back Operation successful - Waiting list (Click to remove) + Waiting list Please select a sticker! Press Enter to add Add to all stickers in the waiting list Global tags Global tags will be added to all stickers in the waiting list. + Drop current editing content Search Close Clear query @@ -27,7 +28,7 @@ Edit Delete Export - Info + Info OK Close Cancel @@ -55,7 +56,7 @@ Light mode System default Via cloud - Via files (Beta) + Via files Import from files Import stickers, tags, and other information from the local files Select backup file @@ -102,9 +103,11 @@ Please input the WebDAV server URL Sync Push - Push the local data to remote, overwrite the remote content in case of conflict. If a sticker is not available locally but is available at the remote, the sticker will be moved to the remote recycle bin + Push the local data to remote + When pushing local data to the remote, local stickers will overwrite the remote content if there is a conflict. If a sticker is not existing in local but in remote, the sticker will be moved to the remote recycle bin. Pull - Pull data from remote, overwrite local content in case of conflict. If a sticker is both local and in the remote recycle bin, the local sticker will be deleted. If a sticker is local but not in the remote, the sticker will not be modified + Pull data from remote + When pulling data from the remote, local content is overwritten if there is a conflict. If a sticker is both local and in the remote recycle bin, that local sticker will be deleted. If a sticker is in the local and not in the remote, the sticker will not be modified. Pull successful, spent %1$.2fs, update %2$d sticker Pull successful, spent %1$.2fs, update %2$d stickers @@ -119,7 +122,8 @@ Account Password Remote recycle bin - View the contents of the remote recycle bin (logically deleted). This operation will only affect the remote content and will not modify the local content + View the remote recycle bin (logically deleted) + Contents in the remote recycle bin are stickers that were logically deleted. Operations on the remote recycle bin will only affect the remote contents and will not modify the local contents. Clear Last modified on: %s Delete @@ -199,8 +203,8 @@ Title Sort Reverse - Multi-select - All + Select + Invert To the top Share button position Horizontal diff --git a/build.gradle b/build.gradle index 83f3335..d1b80d4 100644 --- a/build.gradle +++ b/build.gradle @@ -11,10 +11,10 @@ buildscript { } }// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.1.2' apply false - id 'com.android.library' version '8.1.2' apply false - id 'org.jetbrains.kotlin.android' version '1.9.10' apply false - id 'com.google.dagger.hilt.android' version '2.48' apply false - id 'com.google.devtools.ksp' version '1.9.10-1.0.13' apply false - id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.10' + id 'com.android.application' version '8.1.3' apply false + id 'com.android.library' version '8.1.3' apply false + id 'org.jetbrains.kotlin.android' version '1.9.20' apply false + id 'com.google.dagger.hilt.android' version '2.48.1' apply false + id 'com.google.devtools.ksp' version '1.9.20-1.0.14' apply false + id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.20' } diff --git a/settings.gradle b/settings.gradle index 9f7f0ff..ab7b879 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,7 @@ pluginManagement { repositories { google() - maven { url 'https://maven.aliyun.com/repository/public' } +// maven { url 'https://maven.aliyun.com/repository/public' } mavenCentral() maven { url 'https://jitpack.io' } gradlePluginPortal() @@ -11,7 +11,7 @@ dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() - maven { url 'https://maven.aliyun.com/repository/public' } +// maven { url 'https://maven.aliyun.com/repository/public' } mavenCentral() maven { url 'https://jitpack.io' } }