Add move all feeds to target Group feature
This commit is contained in:
parent
4f7ebb7958
commit
890ee337a4
|
@ -5,6 +5,19 @@ import me.ash.reader.data.entity.Feed
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface FeedDao {
|
interface FeedDao {
|
||||||
|
@Query(
|
||||||
|
"""
|
||||||
|
UPDATE feed SET groupId = :targetGroupId
|
||||||
|
WHERE groupId = :groupId
|
||||||
|
AND accountId = :accountId
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
suspend fun updateTargetGroupIdByGroupId(
|
||||||
|
accountId: Int,
|
||||||
|
groupId: String,
|
||||||
|
targetGroupId: String
|
||||||
|
)
|
||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
"""
|
"""
|
||||||
UPDATE feed SET isFullContent = :isFullContent
|
UPDATE feed SET isFullContent = :isFullContent
|
||||||
|
|
|
@ -154,6 +154,10 @@ abstract class AbstractRssRepository constructor(
|
||||||
suspend fun groupAllowNotification(group: Group, isNotification: Boolean) {
|
suspend fun groupAllowNotification(group: Group, isNotification: Boolean) {
|
||||||
feedDao.updateIsNotificationByGroupId(context.currentAccountId, group.id, isNotification)
|
feedDao.updateIsNotificationByGroupId(context.currentAccountId, group.id, isNotification)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun groupMoveToTargetGroup(group: Group, targetGroup: Group) {
|
||||||
|
feedDao.updateTargetGroupIdByGroupId(context.currentAccountId, group.id, targetGroup.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@HiltWorker
|
@HiltWorker
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package me.ash.reader.ui.page.home.drawer.group
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.DriveFileMove
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||||
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.ui.component.Dialog
|
||||||
|
import me.ash.reader.ui.ext.collectAsStateValue
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPagerApi::class)
|
||||||
|
@Composable
|
||||||
|
fun AllMoveToGroupDialog(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
groupName: String,
|
||||||
|
viewModel: GroupOptionViewModel = hiltViewModel(),
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val viewState = viewModel.viewState.collectAsStateValue()
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val toastString =
|
||||||
|
stringResource(R.string.all_move_to_group_toast, viewState.targetGroup?.name ?: "")
|
||||||
|
|
||||||
|
Dialog(
|
||||||
|
visible = viewState.allMoveToGroupDialogVisible,
|
||||||
|
onDismissRequest = {
|
||||||
|
viewModel.dispatch(GroupOptionViewAction.HideAllMoveToGroupDialog)
|
||||||
|
},
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.DriveFileMove,
|
||||||
|
contentDescription = stringResource(R.string.move_to_group),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
title = {
|
||||||
|
Text(text = stringResource(R.string.move_to_group))
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
R.string.all_move_to_group_tip,
|
||||||
|
groupName,
|
||||||
|
viewState.targetGroup?.name ?: "",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
viewModel.dispatch(GroupOptionViewAction.AllMoveToGroup {
|
||||||
|
viewModel.dispatch(GroupOptionViewAction.HideAllMoveToGroupDialog)
|
||||||
|
viewModel.dispatch(GroupOptionViewAction.Hide(scope))
|
||||||
|
Toast.makeText(context, toastString, Toast.LENGTH_SHORT).show()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.confirm),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
viewModel.dispatch(GroupOptionViewAction.HideAllMoveToGroupDialog)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.cancel),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ package me.ash.reader.ui.page.home.drawer.group
|
||||||
|
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
@ -135,12 +137,48 @@ fun GroupOptionDrawer(
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(26.dp))
|
Spacer(modifier = Modifier.height(26.dp))
|
||||||
|
|
||||||
// AddToGroup(
|
Subtitle(text = stringResource(R.string.move_to_group))
|
||||||
// groups = groups,
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
// selectedGroupId = selectedGroupId,
|
|
||||||
// onGroupClick = onGroupClick,
|
if (viewState.groups.size > 6) {
|
||||||
// onAddNewGroup = onAddNewGroup,
|
LazyRow {
|
||||||
// )
|
items(viewState.groups) {
|
||||||
|
if (it.id != group?.id) {
|
||||||
|
SelectionChip(
|
||||||
|
modifier = Modifier.animateContentSize(),
|
||||||
|
content = it.name,
|
||||||
|
selected = false,
|
||||||
|
) {
|
||||||
|
GroupOptionViewModel.dispatch(
|
||||||
|
GroupOptionViewAction.ShowAllMoveToGroupDialog(it)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.width(10.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FlowRow(
|
||||||
|
mainAxisAlignment = MainAxisAlignment.Start,
|
||||||
|
crossAxisSpacing = 10.dp,
|
||||||
|
mainAxisSpacing = 10.dp,
|
||||||
|
) {
|
||||||
|
viewState.groups.forEach {
|
||||||
|
if (it.id != group?.id) {
|
||||||
|
SelectionChip(
|
||||||
|
modifier = Modifier.animateContentSize(),
|
||||||
|
content = it.name,
|
||||||
|
selected = false,
|
||||||
|
) {
|
||||||
|
GroupOptionViewModel.dispatch(
|
||||||
|
GroupOptionViewAction.ShowAllMoveToGroupDialog(it)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(6.dp))
|
Spacer(modifier = Modifier.height(6.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,4 +190,5 @@ fun GroupOptionDrawer(
|
||||||
DeleteGroupDialog(groupName = group?.name ?: "")
|
DeleteGroupDialog(groupName = group?.name ?: "")
|
||||||
AllAllowNotificationDialog(groupName = group?.name ?: "")
|
AllAllowNotificationDialog(groupName = group?.name ?: "")
|
||||||
AllParseFullContentDialog(groupName = group?.name ?: "")
|
AllParseFullContentDialog(groupName = group?.name ?: "")
|
||||||
|
AllMoveToGroupDialog(groupName = group?.name ?: "")
|
||||||
}
|
}
|
|
@ -49,18 +49,27 @@ class GroupOptionViewModel @Inject constructor(
|
||||||
is GroupOptionViewAction.ShowDeleteDialog -> changeDeleteDialogVisible(true)
|
is GroupOptionViewAction.ShowDeleteDialog -> changeDeleteDialogVisible(true)
|
||||||
is GroupOptionViewAction.HideDeleteDialog -> changeDeleteDialogVisible(false)
|
is GroupOptionViewAction.HideDeleteDialog -> changeDeleteDialogVisible(false)
|
||||||
is GroupOptionViewAction.Delete -> delete(action.callback)
|
is GroupOptionViewAction.Delete -> delete(action.callback)
|
||||||
|
|
||||||
is GroupOptionViewAction.ShowAllAllowNotificationDialog ->
|
is GroupOptionViewAction.ShowAllAllowNotificationDialog ->
|
||||||
changeAllAllowNotificationDialogVisible(true)
|
changeAllAllowNotificationDialogVisible(true)
|
||||||
is GroupOptionViewAction.HideAllAllowNotificationDialog ->
|
is GroupOptionViewAction.HideAllAllowNotificationDialog ->
|
||||||
changeAllAllowNotificationDialogVisible(false)
|
changeAllAllowNotificationDialogVisible(false)
|
||||||
is GroupOptionViewAction.AllAllowNotification ->
|
is GroupOptionViewAction.AllAllowNotification ->
|
||||||
allAllowNotification(action.isNotification, action.callback)
|
allAllowNotification(action.isNotification, action.callback)
|
||||||
|
|
||||||
is GroupOptionViewAction.ShowAllParseFullContentDialog ->
|
is GroupOptionViewAction.ShowAllParseFullContentDialog ->
|
||||||
changeAllParseFullContentDialogVisible(true)
|
changeAllParseFullContentDialogVisible(true)
|
||||||
is GroupOptionViewAction.HideAllParseFullContentDialog ->
|
is GroupOptionViewAction.HideAllParseFullContentDialog ->
|
||||||
changeAllParseFullContentDialogVisible(false)
|
changeAllParseFullContentDialogVisible(false)
|
||||||
is GroupOptionViewAction.AllParseFullContent ->
|
is GroupOptionViewAction.AllParseFullContent ->
|
||||||
allParseFullContent(action.isFullContent, action.callback)
|
allParseFullContent(action.isFullContent, action.callback)
|
||||||
|
|
||||||
|
is GroupOptionViewAction.ShowAllMoveToGroupDialog ->
|
||||||
|
changeAllMoveToGroupDialogVisible(action.targetGroup, true)
|
||||||
|
is GroupOptionViewAction.HideAllMoveToGroupDialog ->
|
||||||
|
changeAllMoveToGroupDialogVisible(visible = false)
|
||||||
|
is GroupOptionViewAction.AllMoveToGroup ->
|
||||||
|
allMoveToGroup(action.callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,15 +151,39 @@ class GroupOptionViewModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun allMoveToGroup(callback: () -> Unit) {
|
||||||
|
_viewState.value.group?.let { group ->
|
||||||
|
_viewState.value.targetGroup?.let { targetGroup ->
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
rssRepository.get().groupMoveToTargetGroup(group, targetGroup)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun changeAllMoveToGroupDialogVisible(targetGroup: Group? = null, visible: Boolean) {
|
||||||
|
_viewState.update {
|
||||||
|
it.copy(
|
||||||
|
targetGroup = if (visible) targetGroup else null,
|
||||||
|
allMoveToGroupDialogVisible = visible,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
data class GroupOptionViewState(
|
data class GroupOptionViewState(
|
||||||
var drawerState: ModalBottomSheetState = ModalBottomSheetState(ModalBottomSheetValue.Hidden),
|
var drawerState: ModalBottomSheetState = ModalBottomSheetState(ModalBottomSheetValue.Hidden),
|
||||||
val group: Group? = null,
|
val group: Group? = null,
|
||||||
|
val targetGroup: Group? = null,
|
||||||
val groups: List<Group> = emptyList(),
|
val groups: List<Group> = emptyList(),
|
||||||
val allAllowNotificationDialogVisible: Boolean = false,
|
val allAllowNotificationDialogVisible: Boolean = false,
|
||||||
val allParseFullContentDialogVisible: Boolean = false,
|
val allParseFullContentDialogVisible: Boolean = false,
|
||||||
|
val allMoveToGroupDialogVisible: Boolean = false,
|
||||||
val deleteDialogVisible: Boolean = false,
|
val deleteDialogVisible: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -186,4 +219,14 @@ sealed class GroupOptionViewAction {
|
||||||
|
|
||||||
object ShowAllAllowNotificationDialog : GroupOptionViewAction()
|
object ShowAllAllowNotificationDialog : GroupOptionViewAction()
|
||||||
object HideAllAllowNotificationDialog : GroupOptionViewAction()
|
object HideAllAllowNotificationDialog : GroupOptionViewAction()
|
||||||
|
|
||||||
|
data class AllMoveToGroup(
|
||||||
|
val callback: () -> Unit = {}
|
||||||
|
) : GroupOptionViewAction()
|
||||||
|
|
||||||
|
data class ShowAllMoveToGroupDialog(
|
||||||
|
val targetGroup: Group
|
||||||
|
) : GroupOptionViewAction()
|
||||||
|
|
||||||
|
object HideAllMoveToGroupDialog : GroupOptionViewAction()
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
<string name="all_parse_full_content_toast">全文解析 \"%1$s\" 分组中的文章</string>
|
<string name="all_parse_full_content_toast">全文解析 \"%1$s\" 分组中的文章</string>
|
||||||
<string name="all_deny_parse_full_content_toast">不再全文解析 \"%1$s\" 分组中的文章</string>
|
<string name="all_deny_parse_full_content_toast">不再全文解析 \"%1$s\" 分组中的文章</string>
|
||||||
<string name="add_to_group">添加到组</string>
|
<string name="add_to_group">添加到组</string>
|
||||||
|
<string name="move_to_group">移动到组</string>
|
||||||
|
<string name="all_move_to_group_tip">将 \"%1$s\" 分组中的所有订阅源移动至 \"%2$s\" 分组。</string>
|
||||||
|
<string name="all_move_to_group_toast">已全部移动至 \"%1$s\" 分组</string>
|
||||||
<string name="create_new_group">新建分组</string>
|
<string name="create_new_group">新建分组</string>
|
||||||
<string name="name">名称</string>
|
<string name="name">名称</string>
|
||||||
<string name="open_with">打开 %1$s</string>
|
<string name="open_with">打开 %1$s</string>
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
<string name="all_parse_full_content_toast">Full content parsing of all articles in the \"%1$s\" group</string>
|
<string name="all_parse_full_content_toast">Full content parsing of all articles in the \"%1$s\" group</string>
|
||||||
<string name="all_deny_parse_full_content_toast">No more full content parsing of all articles in the \"%1$s\" group</string>
|
<string name="all_deny_parse_full_content_toast">No more full content parsing of all articles in the \"%1$s\" group</string>
|
||||||
<string name="add_to_group">Add to Group</string>
|
<string name="add_to_group">Add to Group</string>
|
||||||
|
<string name="move_to_group">Move to Group</string>
|
||||||
|
<string name="all_move_to_group_tip">Move all feeds in the \"%1$s\" group to the \"%2$s\" group.</string>
|
||||||
|
<string name="all_move_to_group_toast">Moved all to \"%1$s\" group</string>
|
||||||
<string name="create_new_group">Create New Group</string>
|
<string name="create_new_group">Create New Group</string>
|
||||||
<string name="name">Name</string>
|
<string name="name">Name</string>
|
||||||
<string name="open_with">Open %1$s</string>
|
<string name="open_with">Open %1$s</string>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user