Combine a feed/folder filter with a main filter (all, new, stars)

This commit is contained in:
Shinokuni 2024-03-04 22:16:46 +01:00
parent e31ebe487f
commit 6664903532
14 changed files with 188 additions and 142 deletions

View File

@ -62,7 +62,7 @@ import com.readrops.db.entities.Feed;
import com.readrops.db.entities.Folder;
import com.readrops.db.entities.Item;
import com.readrops.db.entities.account.Account;
import com.readrops.db.filters.FilterType;
import com.readrops.db.filters.MainFilter;
import com.readrops.db.filters.ListSortType;
import com.readrops.db.pojo.ItemWithFeed;
@ -273,7 +273,7 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
switch (id) {
default:
case DrawerManager.ARTICLES_ITEM_ID:
viewModel.setFilterType(FilterType.NO_FILTER);
viewModel.setFilterType(MainFilter.ALL);
scrollToTop = true;
viewModel.invalidate();
setTitle(R.string.articles);
@ -284,7 +284,7 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
setTitle(R.string.read_later);
break;
case DrawerManager.STARS_ID:
viewModel.setFilterType(FilterType.STARS_FILTER);
viewModel.setFilterType(MainFilter.STARS);
viewModel.invalidate();
setTitle(R.string.favorites);
break;
@ -302,14 +302,14 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
drawer.closeDrawer();
viewModel.setFilterFeedId((int) drawerItem.getIdentifier());
viewModel.setFilterType(FilterType.FEED_FILTER);
viewModel.setFilterType(MainFilter.ALL);
viewModel.invalidate();
setTitle(((SecondaryDrawerItem) drawerItem).getName().getText());
} else if (drawerItem instanceof CustomExpandableBadgeDrawerItem) {
drawer.closeDrawer();
viewModel.setFilerFolderId((int) (drawerItem.getIdentifier() / 1000));
viewModel.setFilterType(FilterType.FOLDER_FILER);
viewModel.setFilterType(MainFilter.ALL);
viewModel.invalidate();
setTitle(((CustomExpandableBadgeDrawerItem) drawerItem).getName().getText());
}

View File

@ -17,7 +17,7 @@ import com.readrops.db.entities.Feed;
import com.readrops.db.entities.Folder;
import com.readrops.db.entities.Item;
import com.readrops.db.entities.account.Account;
import com.readrops.db.filters.FilterType;
import com.readrops.db.filters.MainFilter;
import com.readrops.db.filters.ListSortType;
import com.readrops.db.pojo.ItemWithFeed;
import com.readrops.db.queries.ItemsQueryBuilder;
@ -54,8 +54,8 @@ public class MainViewModel extends ViewModel {
itemsWithFeed = new MediatorLiveData<>();
queryFilters = new QueryFilters();
queryFilters.setShowReadItems(SharedPreferencesManager.readBoolean(
SharedPreferencesManager.SharedPrefKey.SHOW_READ_ARTICLES));
/* queryFilters.setShowReadItems(SharedPreferencesManager.readBoolean(
SharedPreferencesManager.SharedPrefKey.SHOW_READ_ARTICLES));*/
}
//region main query
@ -71,7 +71,7 @@ public class MainViewModel extends ViewModel {
}
DataSource.Factory<Integer, ItemWithFeed> items;
items = database.itemDao().selectAll(ItemsQueryBuilder.buildItemsQuery(queryFilters, currentAccount.getConfig().getUseSeparateState()));
items = database.itemDao().selectAll(ItemsQueryBuilder.INSTANCE.buildItemsQuery(queryFilters, currentAccount.getConfig().getUseSeparateState()));
lastFetch = new LivePagedListBuilder<>(new RoomFactoryWrapper<>(items),
new PagedList.Config.Builder()
@ -89,23 +89,23 @@ public class MainViewModel extends ViewModel {
}
public void setShowReadItems(boolean showReadItems) {
queryFilters.setShowReadItems(showReadItems);
//queryFilters.setShowReadItems(showReadItems);
}
public boolean showReadItems() {
return queryFilters.getShowReadItems();
}
public void setFilterType(FilterType filterType) {
queryFilters.setFilterType(filterType);
public void setFilterType(MainFilter filterType) {
//queryFilters.setMainFilter(filterType);
}
public FilterType getFilterType() {
return queryFilters.getFilterType();
public MainFilter getFilterType() {
return queryFilters.getMainFilter();
}
public void setSortType(ListSortType sortType) {
queryFilters.setSortType(sortType);
//queryFilters.setSortType(sortType);
}
public ListSortType getSortType() {
@ -113,11 +113,11 @@ public class MainViewModel extends ViewModel {
}
public void setFilterFeedId(int filterFeedId) {
queryFilters.setFilterFeedId(filterFeedId);
//queryFilters.setFilterFeedId(filterFeedId);
}
public void setFilerFolderId(int folderId) {
queryFilters.setFilterFolderId(folderId);
//queryFilters.setFilterFolderId(folderId);
}
public MediatorLiveData<PagedList<ItemWithFeed>> getItemsWithFeed() {
@ -128,7 +128,7 @@ public class MainViewModel extends ViewModel {
itemsWithFeed.removeSource(lastFetch);
// get current viewed feed
if (feeds == null && queryFilters.getFilterType() == FilterType.FEED_FILTER) {
if (feeds == null && queryFilters.getMainFilter() == MainFilter.ALL) {
return Single.<Feed>create(emitter -> emitter.onSuccess(database.feedDao()
.getFeedById(queryFilters.getFilterFeedId())))
.flatMapCompletable(feed -> repository.sync(Collections.singletonList(feed), update));
@ -181,7 +181,7 @@ public class MainViewModel extends ViewModel {
public void setCurrentAccount(Account currentAccount) {
this.currentAccount = currentAccount;
setRepository();
queryFilters.setAccountId(currentAccount.getId());
//queryFilters.setAccountId(currentAccount.getId());
buildPagedList();
// set the new account as the current one
@ -212,7 +212,7 @@ public class MainViewModel extends ViewModel {
currentAccountExists = true;
setRepository();
queryFilters.setAccountId(currentAccount.getId());
//queryFilters.setAccountId(currentAccount.getId());
buildPagedList();
break;
}
@ -252,7 +252,7 @@ public class MainViewModel extends ViewModel {
}
public Completable setAllItemsReadState(boolean read) {
if (queryFilters.getFilterType() == FilterType.FEED_FILTER)
if (queryFilters.getMainFilter() == MainFilter.ALL)
return repository.setAllFeedItemsReadState(queryFilters.getFilterFeedId(), read);
else
return repository.setAllItemsReadState(read);

View File

@ -10,7 +10,7 @@ import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
import com.readrops.db.entities.account.Account
import com.readrops.db.entities.account.AccountType
import com.readrops.db.filters.FilterType
import com.readrops.db.filters.MainFilter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.joda.time.LocalDateTime
@ -73,7 +73,7 @@ class GetFoldersWithFeedsTest {
@Test
fun getFoldersWithFeedsTest() = runTest {
getFoldersWithFeeds = GetFoldersWithFeeds(database)
val foldersAndFeeds = getFoldersWithFeeds.get(account.id, FilterType.NO_FILTER).first()
val foldersAndFeeds = getFoldersWithFeeds.get(account.id, MainFilter.ALL).first()
assertTrue { foldersAndFeeds.size == 4 }
assertTrue { foldersAndFeeds.entries.first().value.size == 2 }

View File

@ -11,7 +11,7 @@ import com.readrops.db.Database
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.entities.account.Account
import com.readrops.db.filters.FilterType
import com.readrops.db.filters.MainFilter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@ -47,7 +47,7 @@ class FeedScreenModel(
screenModelScope.launch(context = Dispatchers.IO) {
accountEvent
.flatMapConcat { account ->
getFoldersWithFeeds.get(account.id, FilterType.NO_FILTER)
getFoldersWithFeeds.get(account.id, MainFilter.ALL)
}
.catch { throwable ->
_feedState.update {

View File

@ -3,7 +3,7 @@ package com.readrops.app.compose.repositories
import com.readrops.db.Database
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.filters.FilterType
import com.readrops.db.filters.MainFilter
import com.readrops.db.queries.FoldersAndFeedsQueriesBuilder
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@ -12,11 +12,11 @@ class GetFoldersWithFeeds(
private val database: Database,
) {
fun get(accountId: Int, filterType: FilterType): Flow<Map<Folder?, List<Feed>>> {
fun get(accountId: Int, mainFilter: MainFilter): Flow<Map<Folder?, List<Feed>>> {
val foldersAndFeedsQuery =
FoldersAndFeedsQueriesBuilder.buildFoldersAndFeedsQuery(accountId, filterType)
FoldersAndFeedsQueriesBuilder.buildFoldersAndFeedsQuery(accountId, mainFilter)
val feedsWithoutFolderQuery =
FoldersAndFeedsQueriesBuilder.buildFeedsWithoutFolderQuery(accountId, filterType)
FoldersAndFeedsQueriesBuilder.buildFeedsWithoutFolderQuery(accountId, mainFilter)
return combine(
flow = database.newFolderDao()

View File

@ -14,8 +14,9 @@ import com.readrops.db.Database
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
import com.readrops.db.filters.FilterType
import com.readrops.db.filters.ListSortType
import com.readrops.db.filters.MainFilter
import com.readrops.db.filters.SubFilter
import com.readrops.db.pojo.ItemWithFeed
import com.readrops.db.queries.ItemsQueryBuilder
import com.readrops.db.queries.QueryFilters
@ -47,8 +48,7 @@ class TimelineScreenModel(
accountEvent,
filters
) { account, filters ->
filters.accountId = account.id
Pair(account, filters)
Pair(account, filters.copy(accountId = account.id))
}.collectLatest { (account, filters) ->
val query = ItemsQueryBuilder.buildItemsQuery(filters)
@ -67,7 +67,7 @@ class TimelineScreenModel(
)
}
getFoldersWithFeeds.get(account.id, filters.filterType)
getFoldersWithFeeds.get(account.id, filters.mainFilter)
.collect { foldersAndFeeds ->
_timelineState.update {
it.copy(
@ -103,12 +103,15 @@ class TimelineScreenModel(
_timelineState.update { it.copy(isDrawerOpen = false) }
}
fun updateDrawerDefaultItem(selection: FilterType) {
fun updateDrawerDefaultItem(selection: MainFilter) {
_timelineState.update {
it.copy(
filters = updateFilters {
it.filters.copy(
filterType = selection
mainFilter = selection,
subFilter = SubFilter.ALL,
filterFeedId = 0,
filterFolderId = 0
)
},
isDrawerOpen = false
@ -121,7 +124,7 @@ class TimelineScreenModel(
it.copy(
filters = updateFilters {
it.filters.copy(
filterType = FilterType.FOLDER_FILER,
subFilter = SubFilter.FOLDER,
filterFolderId = folder.id,
filterFeedId = 0
)
@ -137,7 +140,7 @@ class TimelineScreenModel(
it.copy(
filters = updateFilters {
it.filters.copy(
filterType = FilterType.FEED_FILTER,
subFilter = SubFilter.FEED,
filterFeedId = feed.id,
filterFolderId = 0
)
@ -187,21 +190,25 @@ class TimelineScreenModel(
fun setAllItemsRead() {
screenModelScope.launch(dispatcher) {
when (_timelineState.value.filters.filterType) {
FilterType.FEED_FILTER ->
when (_timelineState.value.filters.subFilter) {
SubFilter.FEED ->
repository?.setAllItemsReadByFeed(
_timelineState.value.filters.filterFeedId,
currentAccount!!.id
)
FilterType.FOLDER_FILER -> repository?.setAllItemsReadByFolder(
SubFilter.FOLDER -> repository?.setAllItemsReadByFolder(
_timelineState.value.filters.filterFolderId,
currentAccount!!.id
)
FilterType.STARS_FILTER -> repository?.setAllStarredItemsRead(currentAccount!!.id)
FilterType.NO_FILTER -> repository?.setAllItemsRead(currentAccount!!.id)
FilterType.NEW -> TODO()
else -> when (_timelineState.value.filters.mainFilter) {
MainFilter.STARS -> repository?.setAllStarredItemsRead(currentAccount!!.id)
MainFilter.ALL -> repository?.setAllItemsRead(currentAccount!!.id)
MainFilter.NEW -> TODO()
}
}
}
}

View File

@ -49,7 +49,8 @@ import com.readrops.app.compose.timelime.drawer.TimelineDrawer
import com.readrops.app.compose.util.components.CenteredColumn
import com.readrops.app.compose.util.components.TwoChoicesDialog
import com.readrops.app.compose.util.theme.spacing
import com.readrops.db.filters.FilterType
import com.readrops.db.filters.MainFilter
import com.readrops.db.filters.SubFilter
object TimelineTab : Tab {
@ -168,12 +169,14 @@ object TimelineTab : Tab {
TopAppBar(
title = {
Text(
text = when (state.filters.filterType) {
FilterType.FEED_FILTER -> state.filterFeedName
FilterType.FOLDER_FILER -> state.filterFolderName
FilterType.STARS_FILTER -> stringResource(R.string.favorites)
FilterType.NO_FILTER -> stringResource(R.string.articles)
FilterType.NEW -> stringResource(R.string.new_articles)
text = when (state.filters.subFilter) {
SubFilter.FEED -> state.filterFeedName
SubFilter.FOLDER -> state.filterFolderName
else -> when (state.filters.mainFilter) {
MainFilter.STARS -> stringResource(R.string.favorites)
MainFilter.ALL -> stringResource(R.string.articles)
MainFilter.NEW -> stringResource(R.string.new_articles)
}
},
maxLines = 1,
overflow = TextOverflow.Ellipsis
@ -213,7 +216,7 @@ object TimelineTab : Tab {
floatingActionButton = {
FloatingActionButton(
onClick = {
if (state.filters.filterType == FilterType.NO_FILTER) {
if (state.filters.mainFilter == MainFilter.ALL) {
viewModel.openDialog(DialogState.ConfirmDialog)
} else {
viewModel.setAllItemsRead()

View File

@ -51,7 +51,7 @@ fun DrawerFolderItem(
) {
val colors = NavigationDrawerItemDefaults.colors()
var isExpanded by remember { mutableStateOf(false) }
var isExpanded by remember { mutableStateOf(feeds.any { it.id == selectedFeed }) }
val rotationState by animateFloatAsState(
targetValue = if (isExpanded) 180f else 0f,
label = "drawer item arrow rotation"

View File

@ -28,12 +28,12 @@ import com.readrops.app.compose.timelime.TimelineState
import com.readrops.app.compose.util.theme.spacing
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.filters.FilterType
import com.readrops.db.filters.MainFilter
@Composable
fun TimelineDrawer(
state: TimelineState,
onClickDefaultItem: (FilterType) -> Unit,
onClickDefaultItem: (MainFilter) -> Unit,
onFolderClick: (Folder) -> Unit,
onFeedClick: (Feed) -> Unit,
) {
@ -47,7 +47,7 @@ fun TimelineDrawer(
Spacer(modifier = Modifier.size(MaterialTheme.spacing.drawerSpacing))
DrawerDefaultItems(
selectedItem = state.filters.filterType,
selectedItem = state.filters.mainFilter,
onClick = { onClickDefaultItem(it) }
)
@ -116,8 +116,8 @@ fun TimelineDrawer(
@Composable
fun DrawerDefaultItems(
selectedItem: FilterType,
onClick: (FilterType) -> Unit,
selectedItem: MainFilter,
onClick: (MainFilter) -> Unit,
) {
NavigationDrawerItem(
label = { Text(text = stringResource(R.string.articles)) },
@ -127,8 +127,8 @@ fun DrawerDefaultItems(
contentDescription = null
)
},
selected = selectedItem == FilterType.NO_FILTER,
onClick = { onClick(FilterType.NO_FILTER) },
selected = selectedItem == MainFilter.ALL,
onClick = { onClick(MainFilter.ALL) },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
@ -140,8 +140,8 @@ fun DrawerDefaultItems(
contentDescription = null
)
},
selected = selectedItem == FilterType.NEW,
onClick = { onClick(FilterType.NEW) },
selected = selectedItem == MainFilter.NEW,
onClick = { onClick(MainFilter.NEW) },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
@ -153,8 +153,8 @@ fun DrawerDefaultItems(
contentDescription = null
)
},
selected = selectedItem == FilterType.STARS_FILTER,
onClick = { onClick(FilterType.STARS_FILTER) },
selected = selectedItem == MainFilter.STARS,
onClick = { onClick(MainFilter.STARS) },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
}

View File

@ -4,8 +4,9 @@ import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.readrops.db.filters.FilterType
import com.readrops.db.filters.ListSortType
import com.readrops.db.filters.MainFilter
import com.readrops.db.filters.SubFilter
import com.readrops.db.queries.ItemsQueryBuilder
import com.readrops.db.queries.QueryFilters
import junit.framework.TestCase.assertFalse
@ -51,7 +52,7 @@ class ItemsQueryBuilderTest {
@Test
fun feedFilterCaseTest() {
val queryFilters = QueryFilters(accountId = 1, filterType = FilterType.FEED_FILTER,
val queryFilters = QueryFilters(accountId = 1, subFilter = SubFilter.FEED,
filterFeedId = 15)
val query = ItemsQueryBuilder.buildItemsQuery(queryFilters)
@ -62,7 +63,7 @@ class ItemsQueryBuilderTest {
@Test
fun starsFilterCaseTest() {
val queryFilters = QueryFilters(accountId = 1, filterType = FilterType.STARS_FILTER)
val queryFilters = QueryFilters(accountId = 1, mainFilter = MainFilter.STARS)
val query = ItemsQueryBuilder.buildItemsQuery(queryFilters)
database.query(query)
@ -72,7 +73,7 @@ class ItemsQueryBuilderTest {
@Test
fun folderFilterCaseTest() {
val queryFilters = QueryFilters(accountId = 1, filterType = FilterType.FOLDER_FILER, filterFolderId = 1)
val queryFilters = QueryFilters(accountId = 1, subFilter = SubFilter.FOLDER, filterFolderId = 1)
val query = ItemsQueryBuilder.buildItemsQuery(queryFilters)
database.query(query)
@ -97,7 +98,7 @@ class ItemsQueryBuilderTest {
@Test
fun separateStateTest() {
val queryFilters = QueryFilters(accountId = 1, showReadItems = false, filterType = FilterType.STARS_FILTER)
val queryFilters = QueryFilters(accountId = 1, showReadItems = false, mainFilter = MainFilter.STARS)
val query = ItemsQueryBuilder.buildItemsQuery(queryFilters, true)
database.query(query)
@ -117,7 +118,7 @@ class ItemsQueryBuilderTest {
@Test(expected = IllegalArgumentException::class)
fun filterFeedIdExceptionTest() {
val queryFilters = QueryFilters(accountId = 1, filterType = FilterType.FEED_FILTER)
val queryFilters = QueryFilters(accountId = 1, subFilter = SubFilter.FEED)
ItemsQueryBuilder.buildItemsQuery(queryFilters)
}
}

View File

@ -1,9 +0,0 @@
package com.readrops.db.filters;
enum class FilterType {
FEED_FILTER,
FOLDER_FILER,
STARS_FILTER,
NO_FILTER,
NEW
}

View File

@ -0,0 +1,13 @@
package com.readrops.db.filters
enum class MainFilter {
STARS,
NEW,
ALL
}
enum class SubFilter {
FEED,
FOLDER,
ALL
}

View File

@ -2,15 +2,15 @@ package com.readrops.db.queries
import androidx.sqlite.db.SimpleSQLiteQuery
import androidx.sqlite.db.SupportSQLiteQuery
import com.readrops.db.filters.FilterType
import com.readrops.db.filters.MainFilter
import org.intellij.lang.annotations.Language
object FoldersAndFeedsQueriesBuilder {
fun buildFoldersAndFeedsQuery(accountId: Int, filterType: FilterType): SupportSQLiteQuery {
val filter = when (filterType) {
FilterType.STARS_FILTER -> "And Item.starred = 1"
FilterType.NEW -> "And DateTime(Round(Item.pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\") "
fun buildFoldersAndFeedsQuery(accountId: Int, mainFilter: MainFilter): SupportSQLiteQuery {
val filter = when (mainFilter) {
MainFilter.STARS -> "And Item.starred = 1"
MainFilter.NEW -> "And DateTime(Round(Item.pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\") "
else -> ""
}
@ -29,10 +29,10 @@ object FoldersAndFeedsQueriesBuilder {
return query
}
fun buildFeedsWithoutFolderQuery(accountId: Int, filterType: FilterType): SupportSQLiteQuery {
val filter = when (filterType) {
FilterType.STARS_FILTER -> "And Item.starred = 1 "
FilterType.NEW -> "And DateTime(Round(Item.pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\") "
fun buildFeedsWithoutFolderQuery(accountId: Int, mainFilter: MainFilter): SupportSQLiteQuery {
val filter = when (mainFilter) {
MainFilter.STARS -> "And Item.starred = 1 "
MainFilter.NEW -> "And DateTime(Round(Item.pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\") "
else -> ""
}

View File

@ -2,90 +2,121 @@ package com.readrops.db.queries
import androidx.sqlite.db.SupportSQLiteQuery
import androidx.sqlite.db.SupportSQLiteQueryBuilder
import com.readrops.db.filters.FilterType
import com.readrops.db.filters.ListSortType
import com.readrops.db.filters.MainFilter
import com.readrops.db.filters.SubFilter
object ItemsQueryBuilder {
private val COLUMNS = arrayOf("Item.id", "Item.remoteId", "title", "clean_description", "image_link", "pub_date", "link",
"read_it_later", "Feed.name", "text_color", "background_color", "icon_url", "read_time",
"Feed.id as feedId", "Feed.account_id", "Folder.id as folder_id", "Folder.name as folder_name")
private val COLUMNS = arrayOf(
"Item.id",
"Item.remoteId",
"title",
"clean_description",
"image_link",
"pub_date",
"link",
"read_it_later",
"Feed.name",
"text_color",
"background_color",
"icon_url",
"read_time",
"Feed.id as feedId",
"Feed.account_id",
"Folder.id as folder_id",
"Folder.name as folder_name"
)
private val SEPARATE_STATE_COLUMNS = arrayOf("case When ItemState.remote_id is NULL Or ItemState.read = 1 Then 1 else 0 End read",
"case When ItemState.remote_id is NULL or ItemState.starred = 1 Then 1 else 0 End starred")
private val SEPARATE_STATE_COLUMNS = arrayOf(
"case When ItemState.remote_id is NULL Or ItemState.read = 1 Then 1 else 0 End read",
"case When ItemState.remote_id is NULL or ItemState.starred = 1 Then 1 else 0 End starred"
)
private val OTHER_COLUMNS = arrayOf("read", "starred")
private val SELECT_ALL_JOIN = """Item INNER JOIN Feed on Item.feed_id = Feed.id
LEFT JOIN Folder on Feed.folder_id = Folder.id """.trimIndent()
private const val SEPARATE_STATE_JOIN = "LEFT JOIN ItemState On Item.remoteId = ItemState.remote_id"
private const val SEPARATE_STATE_JOIN =
"LEFT JOIN ItemState On Item.remoteId = ItemState.remote_id"
private const val ORDER_BY_ASC = "pub_date DESC"
private const val ORDER_BY_DESC = "pub_date ASC"
@JvmStatic
fun buildItemsQuery(queryFilters: QueryFilters, separateState: Boolean): SupportSQLiteQuery =
buildQuery(queryFilters, separateState)
buildQuery(queryFilters, separateState)
@JvmStatic
fun buildItemsQuery(queryFilters: QueryFilters): SupportSQLiteQuery =
buildQuery(queryFilters, false)
buildQuery(queryFilters, false)
private fun buildQuery(queryFilters: QueryFilters, separateState: Boolean): SupportSQLiteQuery = with(queryFilters) {
if (accountId == 0)
throw IllegalArgumentException("AccountId must be greater than 0")
private fun buildQuery(queryFilters: QueryFilters, separateState: Boolean): SupportSQLiteQuery =
with(queryFilters) {
if (accountId == 0)
throw IllegalArgumentException("AccountId must be greater than 0")
if (filterType == FilterType.FEED_FILTER && filterFeedId == 0)
throw IllegalArgumentException("FeedId must be greater than 0 if current filter is FEED_FILTER")
if (queryFilters.subFilter == SubFilter.FEED && filterFeedId == 0)
throw IllegalArgumentException("FeedId must be greater than 0 if current filter is FEED_FILTER")
val columns = if (separateState) COLUMNS.plus(SEPARATE_STATE_COLUMNS) else COLUMNS.plus(OTHER_COLUMNS)
val selectAllJoin = if (separateState) SELECT_ALL_JOIN + SEPARATE_STATE_JOIN else SELECT_ALL_JOIN
SupportSQLiteQueryBuilder.builder(selectAllJoin).run {
columns(columns)
selection(buildWhereClause(this@with, separateState), null)
orderBy(if (sortType == ListSortType.NEWEST_TO_OLDEST) ORDER_BY_ASC else ORDER_BY_DESC)
create()
}
}
private fun buildWhereClause(queryFilters: QueryFilters, separateState: Boolean): String = StringBuilder(500).run {
append("Feed.account_id = ${queryFilters.accountId} And ")
if (!queryFilters.showReadItems) {
if (separateState)
append("ItemState.read = 0 And ")
val columns = if (separateState)
COLUMNS.plus(SEPARATE_STATE_COLUMNS)
else
append("Item.read = 0 And ")
}
COLUMNS.plus(OTHER_COLUMNS)
when (queryFilters.filterType) {
FilterType.FEED_FILTER -> append("feed_id = ${queryFilters.filterFeedId} And read_it_later = 0")
FilterType.FOLDER_FILER -> append("folder_id = ${queryFilters.filterFolderId} And read_it_later = 0")
FilterType.STARS_FILTER -> {
if (separateState) {
append("ItemState.starred = 1 And read_it_later = 0")
} else {
append("starred = 1 And read_it_later = 0")
}
val selectAllJoin =
if (separateState) SELECT_ALL_JOIN + SEPARATE_STATE_JOIN else SELECT_ALL_JOIN
SupportSQLiteQueryBuilder.builder(selectAllJoin).run {
columns(columns)
selection(buildWhereClause(this@with, separateState), null)
orderBy(if (sortType == ListSortType.NEWEST_TO_OLDEST) ORDER_BY_ASC else ORDER_BY_DESC)
create()
}
FilterType.NEW -> append("DateTime(Round(pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\") ")
else -> append("read_it_later = 0")
}
toString()
}
private fun buildWhereClause(queryFilters: QueryFilters, separateState: Boolean): String =
StringBuilder(500).run {
append("Feed.account_id = ${queryFilters.accountId} And ")
if (!queryFilters.showReadItems) {
if (separateState)
append("ItemState.read = 0 And ")
else
append("Item.read = 0 And ")
}
when (queryFilters.mainFilter) {
MainFilter.STARS -> {
if (separateState) {
append("ItemState.starred = 1 And read_it_later = 0 ")
} else {
append("starred = 1 And read_it_later = 0 ")
}
}
MainFilter.NEW -> append("DateTime(Round(pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\") ")
else -> append("read_it_later = 0 ")
}
when (queryFilters.subFilter) {
SubFilter.FEED -> append("And feed_id = ${queryFilters.filterFeedId} And read_it_later = 0")
SubFilter.FOLDER -> append("And folder_id = ${queryFilters.filterFolderId} And read_it_later = 0")
else -> {}
}
toString()
}
}
data class QueryFilters(
var showReadItems: Boolean = true,
var filterFeedId: Int = 0,
var filterFolderId: Int = 0,
var accountId: Int = 0,
var filterType: FilterType = FilterType.NO_FILTER,
var sortType: ListSortType = ListSortType.NEWEST_TO_OLDEST,
val showReadItems: Boolean = true,
val filterFeedId: Int = 0,
val filterFolderId: Int = 0,
val accountId: Int = 0,
val mainFilter: MainFilter = MainFilter.ALL,
val subFilter: SubFilter = SubFilter.ALL,
val sortType: ListSortType = ListSortType.NEWEST_TO_OLDEST,
)