diff --git a/app/src/main/java/me/ash/reader/data/repository/AbstractRssRepository.kt b/app/src/main/java/me/ash/reader/data/repository/AbstractRssRepository.kt index 8a425cf..f91bb8c 100644 --- a/app/src/main/java/me/ash/reader/data/repository/AbstractRssRepository.kt +++ b/app/src/main/java/me/ash/reader/data/repository/AbstractRssRepository.kt @@ -145,16 +145,23 @@ abstract class AbstractRssRepository constructor( } suspend fun deleteGroup(group: Group) { - articleDao.deleteByGroupId(context.currentAccountId, group.id) + deleteArticles(group = group) feedDao.deleteByGroupId(context.currentAccountId, group.id) groupDao.delete(group) } suspend fun deleteFeed(feed: Feed) { - articleDao.deleteByFeedId(context.currentAccountId, feed.id) + deleteArticles(feed = feed) feedDao.delete(feed) } + suspend fun deleteArticles(group: Group? = null, feed: Feed? = null) { + when { + group != null -> articleDao.deleteByGroupId(context.currentAccountId, group.id) + feed != null -> articleDao.deleteByFeedId(context.currentAccountId, feed.id) + } + } + suspend fun groupParseFullContent(group: Group, isFullContent: Boolean) { feedDao.updateIsFullContentByGroupId(context.currentAccountId, group.id, isFullContent) } diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt index 538f6bf..4ceb989 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt @@ -253,8 +253,8 @@ fun FeedsPage( // } } item { - Spacer(modifier = Modifier.height(64.dp)) - Spacer(modifier = Modifier.height(64.dp)) + Spacer(modifier = Modifier.height(128.dp)) + Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars)) } } }, diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/ClearFeedDialog.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/ClearFeedDialog.kt new file mode 100644 index 0000000..cad233b --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/ClearFeedDialog.kt @@ -0,0 +1,76 @@ +package me.ash.reader.ui.page.home.feeds.option.feed + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.DeleteForever +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 +import me.ash.reader.ui.ext.showToast + +@OptIn(ExperimentalPagerApi::class) +@Composable +fun ClearFeedDialog( + modifier: Modifier = Modifier, + feedName: String, + viewModel: FeedOptionViewModel = hiltViewModel(), +) { + val context = LocalContext.current + val viewState = viewModel.viewState.collectAsStateValue() + val scope = rememberCoroutineScope() + val toastString = stringResource(R.string.clear_articles_in_feed_toast, feedName) + + Dialog( + visible = viewState.clearDialogVisible, + onDismissRequest = { + viewModel.dispatch(FeedOptionViewAction.HideClearDialog) + }, + icon = { + Icon( + imageVector = Icons.Outlined.DeleteForever, + contentDescription = stringResource(R.string.clear_articles), + ) + }, + title = { + Text(text = stringResource(R.string.clear_articles)) + }, + text = { + Text(text = stringResource(R.string.clear_articles_feed_tips, feedName)) + }, + confirmButton = { + TextButton( + onClick = { + viewModel.dispatch(FeedOptionViewAction.Clear { + viewModel.dispatch(FeedOptionViewAction.HideClearDialog) + viewModel.dispatch(FeedOptionViewAction.Hide(scope)) + context.showToast(toastString) + }) + } + ) { + Text( + text = stringResource(R.string.clear), + ) + } + }, + dismissButton = { + TextButton( + onClick = { + viewModel.dispatch(FeedOptionViewAction.HideClearDialog) + } + ) { + Text( + text = stringResource(R.string.cancel), + ) + } + }, + ) +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/DeleteFeedDialog.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/DeleteFeedDialog.kt index bee258e..22c8a8e 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/DeleteFeedDialog.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/DeleteFeedDialog.kt @@ -44,7 +44,7 @@ fun DeleteFeedDialog( Text(text = stringResource(R.string.unsubscribe)) }, text = { - Text(text = stringResource(R.string.unsubscribe_tip, feedName)) + Text(text = stringResource(R.string.unsubscribe_tips, feedName)) }, confirmButton = { TextButton( diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/FeedOptionDrawer.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/FeedOptionDrawer.kt index fbdbab4..4fd85e0 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/FeedOptionDrawer.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/FeedOptionDrawer.kt @@ -89,6 +89,9 @@ fun FeedOptionDrawer( parseFullContentPresetOnClick = { feedOptionViewModel.dispatch(FeedOptionViewAction.ChangeParseFullContentPreset) }, + clearArticlesOnClick = { + feedOptionViewModel.dispatch(FeedOptionViewAction.ShowClearDialog) + }, unsubscribeOnClick = { feedOptionViewModel.dispatch(FeedOptionViewAction.ShowDeleteDialog) }, @@ -110,6 +113,8 @@ fun FeedOptionDrawer( DeleteFeedDialog(feedName = feed?.name ?: "") + ClearFeedDialog(feedName = feed?.name ?: "") + TextFieldDialog( visible = viewState.newGroupDialogVisible, title = stringResource(R.string.create_new_group), diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/FeedOptionViewModel.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/FeedOptionViewModel.kt index e2656f1..d31c510 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/FeedOptionViewModel.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/feed/FeedOptionViewModel.kt @@ -54,6 +54,9 @@ class FeedOptionViewModel @Inject constructor( is FeedOptionViewAction.ShowDeleteDialog -> showDeleteDialog() is FeedOptionViewAction.HideDeleteDialog -> hideDeleteDialog() is FeedOptionViewAction.Delete -> delete(action.callback) + is FeedOptionViewAction.ShowClearDialog -> showClearDialog() + is FeedOptionViewAction.HideClearDialog -> hideClearDialog() + is FeedOptionViewAction.Clear -> clear(action.callback) is FeedOptionViewAction.AddNewGroup -> addNewGroup() is FeedOptionViewAction.ShowNewGroupDialog -> changeNewGroupDialogVisible(true) is FeedOptionViewAction.HideNewGroupDialog -> changeNewGroupDialogVisible(false) @@ -183,6 +186,33 @@ class FeedOptionViewModel @Inject constructor( } } + private fun showClearDialog() { + _viewState.update { + it.copy( + clearDialogVisible = true, + ) + } + } + + private fun hideClearDialog() { + _viewState.update { + it.copy( + clearDialogVisible = false, + ) + } + } + + private fun clear(callback: () -> Unit = {}) { + _viewState.value.feed?.let { + viewModelScope.launch(Dispatchers.IO) { + rssRepository.get().deleteArticles(feed = it) + withContext(Dispatchers.Main) { + callback() + } + } + } + } + private fun rename() { _viewState.value.feed?.let { viewModelScope.launch { @@ -261,6 +291,7 @@ data class FeedOptionViewState( val newGroupDialogVisible: Boolean = false, val groups: List = emptyList(), val deleteDialogVisible: Boolean = false, + val clearDialogVisible: Boolean = false, val newName: String = "", val renameDialogVisible: Boolean = false, val newUrl: String = "", @@ -295,6 +326,13 @@ sealed class FeedOptionViewAction { object ShowDeleteDialog : FeedOptionViewAction() object HideDeleteDialog : FeedOptionViewAction() + data class Clear( + val callback: () -> Unit = {} + ) : FeedOptionViewAction() + + object ShowClearDialog : FeedOptionViewAction() + object HideClearDialog : FeedOptionViewAction() + object ShowNewGroupDialog : FeedOptionViewAction() object HideNewGroupDialog : FeedOptionViewAction() object AddNewGroup : FeedOptionViewAction() diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllAllowNotificationDialog.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllAllowNotificationDialog.kt index 4375629..32b599d 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllAllowNotificationDialog.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllAllowNotificationDialog.kt @@ -45,7 +45,7 @@ fun AllAllowNotificationDialog( Text(text = stringResource(R.string.allow_notification)) }, text = { - Text(text = stringResource(R.string.all_allow_notification_tip, groupName)) + Text(text = stringResource(R.string.all_allow_notification_tips, groupName)) }, confirmButton = { TextButton( diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllMoveToGroupDialog.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllMoveToGroupDialog.kt index 8898407..e5ddb62 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllMoveToGroupDialog.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllMoveToGroupDialog.kt @@ -47,7 +47,7 @@ fun AllMoveToGroupDialog( text = { Text( text = stringResource( - R.string.all_move_to_group_tip, + R.string.all_move_to_group_tips, groupName, viewState.targetGroup?.name ?: "", ) diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllParseFullContentDialog.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllParseFullContentDialog.kt index f71799f..c5db1da 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllParseFullContentDialog.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/AllParseFullContentDialog.kt @@ -45,7 +45,7 @@ fun AllParseFullContentDialog( Text(text = stringResource(R.string.parse_full_content)) }, text = { - Text(text = stringResource(R.string.all_parse_full_content_tip, groupName)) + Text(text = stringResource(R.string.all_parse_full_content_tips, groupName)) }, confirmButton = { TextButton( diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/ClearGroupDialog.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/ClearGroupDialog.kt new file mode 100644 index 0000000..b02403a --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/ClearGroupDialog.kt @@ -0,0 +1,76 @@ +package me.ash.reader.ui.page.home.feeds.option.group + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.DeleteForever +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 +import me.ash.reader.ui.ext.showToast + +@OptIn(ExperimentalPagerApi::class) +@Composable +fun ClearGroupDialog( + 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.clear_articles_in_group_toast, groupName) + + Dialog( + visible = viewState.clearDialogVisible, + onDismissRequest = { + viewModel.dispatch(GroupOptionViewAction.HideClearDialog) + }, + icon = { + Icon( + imageVector = Icons.Outlined.DeleteForever, + contentDescription = stringResource(R.string.clear_articles), + ) + }, + title = { + Text(text = stringResource(R.string.clear_articles)) + }, + text = { + Text(text = stringResource(R.string.clear_articles_group_tips, groupName)) + }, + confirmButton = { + TextButton( + onClick = { + viewModel.dispatch(GroupOptionViewAction.Clear { + viewModel.dispatch(GroupOptionViewAction.HideClearDialog) + viewModel.dispatch(GroupOptionViewAction.Hide(scope)) + context.showToast(toastString) + }) + } + ) { + Text( + text = stringResource(R.string.clear), + ) + } + }, + dismissButton = { + TextButton( + onClick = { + viewModel.dispatch(GroupOptionViewAction.HideClearDialog) + } + ) { + Text( + text = stringResource(R.string.cancel), + ) + } + }, + ) +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/DeleteGroupDialog.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/DeleteGroupDialog.kt index 6f0793d..8c39dc4 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/DeleteGroupDialog.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/DeleteGroupDialog.kt @@ -44,7 +44,7 @@ fun DeleteGroupDialog( Text(text = stringResource(R.string.delete_group)) }, text = { - Text(text = stringResource(R.string.delete_group_tip, groupName)) + Text(text = stringResource(R.string.delete_group_tips, groupName)) }, confirmButton = { TextButton( diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/GroupOptionDrawer.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/GroupOptionDrawer.kt index 3742131..480aa1f 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/GroupOptionDrawer.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/GroupOptionDrawer.kt @@ -93,7 +93,7 @@ fun GroupOptionDrawer( horizontalArrangement = Arrangement.Center ) { Text( - text = stringResource(R.string.group_option_tip), + text = stringResource(R.string.group_option_tips), color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f), style = MaterialTheme.typography.bodyMedium, textAlign = TextAlign.Center, @@ -126,6 +126,7 @@ fun GroupOptionDrawer( content() } + ClearGroupDialog(groupName = group?.name ?: "") DeleteGroupDialog(groupName = group?.name ?: "") AllAllowNotificationDialog(groupName = group?.name ?: "") AllParseFullContentDialog(groupName = group?.name ?: "") @@ -194,6 +195,13 @@ private fun Preset( ) { groupOptionViewModel.dispatch(GroupOptionViewAction.ShowAllParseFullContentDialog) } + SelectionChip( + modifier = Modifier.animateContentSize(), + content = stringResource(R.string.clear_articles), + selected = false, + ) { + groupOptionViewModel.dispatch(GroupOptionViewAction.ShowClearDialog) + } if (group?.id != context.currentAccountId.getDefaultGroupId()) { SelectionChip( modifier = Modifier.animateContentSize(), diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/GroupOptionViewModel.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/GroupOptionViewModel.kt index cc7b1cb..b696c8d 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/GroupOptionViewModel.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/option/group/GroupOptionViewModel.kt @@ -50,6 +50,10 @@ class GroupOptionViewModel @Inject constructor( is GroupOptionViewAction.HideDeleteDialog -> changeDeleteDialogVisible(false) is GroupOptionViewAction.Delete -> delete(action.callback) + is GroupOptionViewAction.ShowClearDialog -> showClearDialog() + is GroupOptionViewAction.HideClearDialog -> hideClearDialog() + is GroupOptionViewAction.Clear -> clear(action.callback) + is GroupOptionViewAction.ShowAllAllowNotificationDialog -> changeAllAllowNotificationDialogVisible(true) is GroupOptionViewAction.HideAllAllowNotificationDialog -> @@ -157,6 +161,33 @@ class GroupOptionViewModel @Inject constructor( } } + private fun showClearDialog() { + _viewState.update { + it.copy( + clearDialogVisible = true, + ) + } + } + + private fun hideClearDialog() { + _viewState.update { + it.copy( + clearDialogVisible = false, + ) + } + } + + private fun clear(callback: () -> Unit = {}) { + _viewState.value.group?.let { + viewModelScope.launch(Dispatchers.IO) { + rssRepository.get().deleteArticles(group = it) + withContext(Dispatchers.Main) { + callback() + } + } + } + } + private fun allMoveToGroup(callback: () -> Unit) { _viewState.value.group?.let { group -> _viewState.value.targetGroup?.let { targetGroup -> @@ -224,6 +255,7 @@ data class GroupOptionViewState( val allParseFullContentDialogVisible: Boolean = false, val allMoveToGroupDialogVisible: Boolean = false, val deleteDialogVisible: Boolean = false, + val clearDialogVisible: Boolean = false, val newName: String = "", val renameDialogVisible: Boolean = false, ) @@ -245,6 +277,13 @@ sealed class GroupOptionViewAction { object ShowDeleteDialog : GroupOptionViewAction() object HideDeleteDialog : GroupOptionViewAction() + data class Clear( + val callback: () -> Unit = {} + ) : GroupOptionViewAction() + + object ShowClearDialog : GroupOptionViewAction() + object HideClearDialog : GroupOptionViewAction() + data class AllParseFullContent( val isFullContent: Boolean, val callback: () -> Unit = {} diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/subscribe/ResultView.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/subscribe/ResultView.kt index ecdd5a4..65894e6 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/subscribe/ResultView.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/subscribe/ResultView.kt @@ -47,6 +47,7 @@ fun ResultView( selectedGroupId: String = "", allowNotificationPresetOnClick: () -> Unit = {}, parseFullContentPresetOnClick: () -> Unit = {}, + clearArticlesOnClick: () -> Unit = {}, unsubscribeOnClick: () -> Unit = {}, onGroupClick: (groupId: String) -> Unit = {}, onAddNewGroup: () -> Unit = {}, @@ -68,6 +69,7 @@ fun ResultView( showUnsubscribe = showUnsubscribe, allowNotificationPresetOnClick = allowNotificationPresetOnClick, parseFullContentPresetOnClick = parseFullContentPresetOnClick, + clearArticlesOnClick = clearArticlesOnClick, unsubscribeOnClick = unsubscribeOnClick, ) Spacer(modifier = Modifier.height(26.dp)) @@ -114,6 +116,7 @@ private fun Preset( showUnsubscribe: Boolean = false, allowNotificationPresetOnClick: () -> Unit = {}, parseFullContentPresetOnClick: () -> Unit = {}, + clearArticlesOnClick: () -> Unit = {}, unsubscribeOnClick: () -> Unit = {}, ) { Subtitle(text = stringResource(R.string.preset)) @@ -159,6 +162,13 @@ private fun Preset( parseFullContentPresetOnClick() } if (showUnsubscribe) { + SelectionChip( + modifier = Modifier.animateContentSize(), + content = stringResource(R.string.clear_articles), + selected = false, + ) { + clearArticlesOnClick() + } SelectionChip( modifier = Modifier.animateContentSize(), content = stringResource(R.string.unsubscribe), diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 2d0ad90..e84b160 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -31,16 +31,21 @@ 预设 已选择 允许通知 - 允许 \"%1$s\" 分组中的所有订阅源发出通知。 + 允许 \"%1$s\" 分组中的所有订阅源发出通知。 已全部允许 \"%1$s\" 分组中的通知 已全部拒绝 \"%1$s\" 分组中的通知 全文解析 - 对 \"%1$s\" 分组中的所有文章进行全文解析。 + 对 \"%1$s\" 分组中的所有文章进行全文解析。 全文解析 \"%1$s\" 分组中的文章 不再全文解析 \"%1$s\" 分组中的文章 + 清空文章 + 已清空 \"%1$s\" 订阅源中所有已归档的文章。 + 已清空 \"%1$s\" 分组中所有已归档的文章。 + 清空 \"%1$s\" 订阅源中所有已归档的文章。 + 清空 \"%1$s\" 分组中所有已归档的文章。 添加到组 移动到组 - 将 \"%1$s\" 分组中的所有订阅源移动至 \"%2$s\" 分组。 + 将 \"%1$s\" 分组中的所有订阅源移动至 \"%2$s\" 分组。 已全部移动至 \"%1$s\" 分组 重命名 更改链接 @@ -52,10 +57,10 @@ 删除 \"%1$s\" 已被删除 取消订阅 - 不再订阅 \"%1$s\",同时删除其中所有已归档的文章。 + 不再订阅 \"%1$s\",同时删除其中所有已归档的文章。 删除分组 - 删除 \"%1$s\" 分组,同时删除其中所有订阅源和已归档的文章。 - 以下选项将应用到该分组中的所有订阅源。 + 删除 \"%1$s\" 分组,同时删除其中所有订阅源和已归档的文章。 + 以下选项将应用到该分组中的所有订阅源。 今天 昨天 %1$s %2$s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 423803c..0c43184 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,16 +31,21 @@ Preset Selected Allow Notification - Allow all feeds in the \"%1$s\" group to send notifications. + Allow all feeds in the \"%1$s\" group to send notifications. All notifications in the \"%1$s\" group are allowed All notifications in the \"%1$s\" group are denied Parse Full Content - Full content parsing of all articles in the \"%1$s\" group. + Full content parsing of all articles in the \"%1$s\" group. Full content parsing of all articles in the \"%1$s\" group No more full content parsing of all articles in the \"%1$s\" group + Clear Articles + All archived of articles in the \"%1$s\" Feed has been cleaned + All archived of articles in the \"%1$s\" group has been cleaned + Clear all archived of articles in \"%1$s\" feed. + Clear all archived of articles in \"%1$s\" group. Add to Group Move to Group - Move all feeds in the \"%1$s\" group to the \"%2$s\" group. + Move all feeds in the \"%1$s\" group to the \"%2$s\" group. Moved all to \"%1$s\" group Rename Change URL @@ -53,10 +58,10 @@ Delete \"%1$s\" has been deleted Unsubscribe - Unsubscribe \"%1$s\" and delete all archived articles in it. + Unsubscribe \"%1$s\" and delete all archived articles in it. Delete Group - Delete the \"%1$s\" group, and delete all feeds and archived articles in it. - The following options will be applied to all feeds in this group. + Delete the \"%1$s\" group, and delete all feeds and archived articles in it. + The following options will be applied to all feeds in this group. Today Yesterday %1$s At %2$s