Add move all feeds to target Group feature

This commit is contained in:
Ash 2022-04-07 03:12:18 +08:00
parent 4f7ebb7958
commit 890ee337a4
7 changed files with 195 additions and 7 deletions

View File

@ -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

View File

@ -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

View File

@ -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),
)
}
},
)
}

View File

@ -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 ?: "")
}

View File

@ -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()
} }

View File

@ -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>

View File

@ -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>