Implement full text search
This commit is contained in:
@@ -12,4 +12,6 @@ interface RecipeRepo {
|
|||||||
suspend fun refreshRecipeInfo(recipeSlug: String): Result<Unit>
|
suspend fun refreshRecipeInfo(recipeSlug: String): Result<Unit>
|
||||||
|
|
||||||
suspend fun loadRecipeInfo(recipeId: String): FullRecipeEntity?
|
suspend fun loadRecipeInfo(recipeId: String): FullRecipeEntity?
|
||||||
|
|
||||||
|
fun setSearchName(name: String?)
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
|||||||
interface RecipeStorage {
|
interface RecipeStorage {
|
||||||
suspend fun saveRecipes(recipes: List<RecipeSummaryInfo>)
|
suspend fun saveRecipes(recipes: List<RecipeSummaryInfo>)
|
||||||
|
|
||||||
fun queryRecipes(): PagingSource<Int, RecipeSummaryEntity>
|
fun queryRecipes(query: String?): PagingSource<Int, RecipeSummaryEntity>
|
||||||
|
|
||||||
suspend fun refreshAll(recipes: List<RecipeSummaryInfo>)
|
suspend fun refreshAll(recipes: List<RecipeSummaryInfo>)
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,11 @@ class RecipeStorageImpl @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun queryRecipes(): PagingSource<Int, RecipeSummaryEntity> {
|
override fun queryRecipes(query: String?): PagingSource<Int, RecipeSummaryEntity> {
|
||||||
logger.v { "queryRecipes() called" }
|
logger.v { "queryRecipes() called with: query = $query" }
|
||||||
return recipeDao.queryRecipesByPages()
|
return if (query == null) recipeDao.queryRecipesByPages()
|
||||||
|
else recipeDao.queryRecipesByPages(query)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun refreshAll(recipes: List<RecipeSummaryInfo>) {
|
override suspend fun refreshAll(recipes: List<RecipeSummaryInfo>) {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package gq.kirmanak.mealient.data.recipes.impl
|
||||||
|
|
||||||
|
import androidx.paging.PagingSource
|
||||||
|
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
||||||
|
|
||||||
|
interface RecipePagingSourceFactory : () -> PagingSource<Int, RecipeSummaryEntity> {
|
||||||
|
fun setQuery(newQuery: String?)
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package gq.kirmanak.mealient.data.recipes.impl
|
||||||
|
|
||||||
|
import androidx.paging.PagingSource
|
||||||
|
import gq.kirmanak.mealient.data.recipes.db.RecipeStorage
|
||||||
|
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
||||||
|
import gq.kirmanak.mealient.logging.Logger
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class RecipePagingSourceFactoryImpl @Inject constructor(
|
||||||
|
private val recipeStorage: RecipeStorage,
|
||||||
|
private val logger: Logger,
|
||||||
|
) : RecipePagingSourceFactory {
|
||||||
|
|
||||||
|
private val query = AtomicReference<String>(null)
|
||||||
|
|
||||||
|
override fun invoke(): PagingSource<Int, RecipeSummaryEntity> {
|
||||||
|
val currentQuery = query.get()
|
||||||
|
logger.d { "Creating paging source, query is $currentQuery" }
|
||||||
|
return recipeStorage.queryRecipes(currentQuery)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setQuery(newQuery: String?) {
|
||||||
|
logger.v { "setQuery() called with: newQuery = $newQuery" }
|
||||||
|
query.set(newQuery)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,10 +19,12 @@ import javax.inject.Singleton
|
|||||||
class RecipeRepoImpl @Inject constructor(
|
class RecipeRepoImpl @Inject constructor(
|
||||||
private val mediator: RecipesRemoteMediator,
|
private val mediator: RecipesRemoteMediator,
|
||||||
private val storage: RecipeStorage,
|
private val storage: RecipeStorage,
|
||||||
private val pagingSourceFactory: InvalidatingPagingSourceFactory<Int, RecipeSummaryEntity>,
|
private val pagingSourceFactory: RecipePagingSourceFactory,
|
||||||
|
private val invalidatingPagingSourceFactory: InvalidatingPagingSourceFactory<Int, RecipeSummaryEntity>,
|
||||||
private val dataSource: RecipeDataSource,
|
private val dataSource: RecipeDataSource,
|
||||||
private val logger: Logger,
|
private val logger: Logger,
|
||||||
) : RecipeRepo {
|
) : RecipeRepo {
|
||||||
|
|
||||||
override fun createPager(): Pager<Int, RecipeSummaryEntity> {
|
override fun createPager(): Pager<Int, RecipeSummaryEntity> {
|
||||||
logger.v { "createPager() called" }
|
logger.v { "createPager() called" }
|
||||||
val pagingConfig = PagingConfig(pageSize = 5, enablePlaceholders = true)
|
val pagingConfig = PagingConfig(pageSize = 5, enablePlaceholders = true)
|
||||||
@@ -53,4 +55,10 @@ class RecipeRepoImpl @Inject constructor(
|
|||||||
logger.v { "loadRecipeInfo() returned: $recipeInfo" }
|
logger.v { "loadRecipeInfo() returned: $recipeInfo" }
|
||||||
return recipeInfo
|
return recipeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setSearchName(name: String?) {
|
||||||
|
logger.v { "setSearchName() called with: name = $name" }
|
||||||
|
pagingSourceFactory.setQuery(name)
|
||||||
|
invalidatingPagingSourceFactory.invalidate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,9 +13,7 @@ import gq.kirmanak.mealient.data.network.MealieDataSourceWrapper
|
|||||||
import gq.kirmanak.mealient.data.recipes.RecipeRepo
|
import gq.kirmanak.mealient.data.recipes.RecipeRepo
|
||||||
import gq.kirmanak.mealient.data.recipes.db.RecipeStorage
|
import gq.kirmanak.mealient.data.recipes.db.RecipeStorage
|
||||||
import gq.kirmanak.mealient.data.recipes.db.RecipeStorageImpl
|
import gq.kirmanak.mealient.data.recipes.db.RecipeStorageImpl
|
||||||
import gq.kirmanak.mealient.data.recipes.impl.RecipeImageUrlProvider
|
import gq.kirmanak.mealient.data.recipes.impl.*
|
||||||
import gq.kirmanak.mealient.data.recipes.impl.RecipeImageUrlProviderImpl
|
|
||||||
import gq.kirmanak.mealient.data.recipes.impl.RecipeRepoImpl
|
|
||||||
import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource
|
import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource
|
||||||
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
||||||
import gq.kirmanak.mealient.ui.recipes.images.RecipeModelLoaderFactory
|
import gq.kirmanak.mealient.ui.recipes.images.RecipeModelLoaderFactory
|
||||||
@@ -46,13 +44,17 @@ interface RecipeModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
fun bindModelLoaderFactory(recipeModelLoaderFactory: RecipeModelLoaderFactory): ModelLoaderFactory<RecipeSummaryEntity, InputStream>
|
fun bindModelLoaderFactory(recipeModelLoaderFactory: RecipeModelLoaderFactory): ModelLoaderFactory<RecipeSummaryEntity, InputStream>
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
fun bindRecipePagingSourceFactory(recipePagingSourceFactoryImpl: RecipePagingSourceFactoryImpl): RecipePagingSourceFactory
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideRecipePagingSourceFactory(
|
fun provideRecipePagingSourceFactory(
|
||||||
recipeStorage: RecipeStorage
|
factory: RecipePagingSourceFactory,
|
||||||
) = InvalidatingPagingSourceFactory { recipeStorage.queryRecipes() }
|
) = InvalidatingPagingSourceFactory(factory)
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import gq.kirmanak.mealient.R
|
|||||||
import gq.kirmanak.mealient.data.auth.AuthRepo
|
import gq.kirmanak.mealient.data.auth.AuthRepo
|
||||||
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
|
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
|
||||||
import gq.kirmanak.mealient.data.disclaimer.DisclaimerStorage
|
import gq.kirmanak.mealient.data.disclaimer.DisclaimerStorage
|
||||||
|
import gq.kirmanak.mealient.data.recipes.RecipeRepo
|
||||||
import gq.kirmanak.mealient.logging.Logger
|
import gq.kirmanak.mealient.logging.Logger
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
@@ -18,6 +19,7 @@ class MainActivityViewModel @Inject constructor(
|
|||||||
private val logger: Logger,
|
private val logger: Logger,
|
||||||
private val disclaimerStorage: DisclaimerStorage,
|
private val disclaimerStorage: DisclaimerStorage,
|
||||||
private val serverInfoRepo: ServerInfoRepo,
|
private val serverInfoRepo: ServerInfoRepo,
|
||||||
|
private val recipeRepo: RecipeRepo,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val _uiState = MutableLiveData(MainActivityUiState())
|
private val _uiState = MutableLiveData(MainActivityUiState())
|
||||||
@@ -55,5 +57,6 @@ class MainActivityViewModel @Inject constructor(
|
|||||||
|
|
||||||
fun onSearchQuery(query: String) {
|
fun onSearchQuery(query: String) {
|
||||||
logger.v { "onSearchQuery() called with: query = $query" }
|
logger.v { "onSearchQuery() called with: query = $query" }
|
||||||
|
recipeRepo.setSearchName(query)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
201
database/schemas/gq.kirmanak.mealient.database.AppDb/7.json
Normal file
201
database/schemas/gq.kirmanak.mealient.database.AppDb/7.json
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 7,
|
||||||
|
"identityHash": "1def22b22cb1f09a27de1b3188b857d2",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "recipe_summaries",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`remote_id` TEXT NOT NULL, `name` TEXT NOT NULL, `slug` TEXT NOT NULL, `description` TEXT NOT NULL, `date_added` INTEGER NOT NULL, `date_updated` INTEGER NOT NULL, `image_id` TEXT, PRIMARY KEY(`remote_id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "remoteId",
|
||||||
|
"columnName": "remote_id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "slug",
|
||||||
|
"columnName": "slug",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "description",
|
||||||
|
"columnName": "description",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "dateAdded",
|
||||||
|
"columnName": "date_added",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "dateUpdated",
|
||||||
|
"columnName": "date_updated",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "imageId",
|
||||||
|
"columnName": "image_id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"remote_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "recipe",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`remote_id` TEXT NOT NULL, `recipe_yield` TEXT NOT NULL, PRIMARY KEY(`remote_id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "remoteId",
|
||||||
|
"columnName": "remote_id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "recipeYield",
|
||||||
|
"columnName": "recipe_yield",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"remote_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "recipe_ingredient",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`local_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `recipe_id` TEXT NOT NULL, `note` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "localId",
|
||||||
|
"columnName": "local_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "recipeId",
|
||||||
|
"columnName": "recipe_id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "note",
|
||||||
|
"columnName": "note",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"local_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "recipe_instruction",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`local_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `recipe_id` TEXT NOT NULL, `text` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "localId",
|
||||||
|
"columnName": "local_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "recipeId",
|
||||||
|
"columnName": "recipe_id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "text",
|
||||||
|
"columnName": "text",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"local_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ftsVersion": "FTS4",
|
||||||
|
"ftsOptions": {
|
||||||
|
"tokenizer": "simple",
|
||||||
|
"tokenizerArgs": [],
|
||||||
|
"contentTable": "recipe_summaries",
|
||||||
|
"languageIdColumnName": "",
|
||||||
|
"matchInfo": "FTS4",
|
||||||
|
"notIndexedColumns": [],
|
||||||
|
"prefixSizes": [],
|
||||||
|
"preferredOrder": "ASC"
|
||||||
|
},
|
||||||
|
"contentSyncTriggers": [
|
||||||
|
"CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_recipe_summaries_fts_BEFORE_UPDATE BEFORE UPDATE ON `recipe_summaries` BEGIN DELETE FROM `recipe_summaries_fts` WHERE `docid`=OLD.`rowid`; END",
|
||||||
|
"CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_recipe_summaries_fts_BEFORE_DELETE BEFORE DELETE ON `recipe_summaries` BEGIN DELETE FROM `recipe_summaries_fts` WHERE `docid`=OLD.`rowid`; END",
|
||||||
|
"CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_recipe_summaries_fts_AFTER_UPDATE AFTER UPDATE ON `recipe_summaries` BEGIN INSERT INTO `recipe_summaries_fts`(`docid`, `remote_id`, `name`) VALUES (NEW.`rowid`, NEW.`remote_id`, NEW.`name`); END",
|
||||||
|
"CREATE TRIGGER IF NOT EXISTS room_fts_content_sync_recipe_summaries_fts_AFTER_INSERT AFTER INSERT ON `recipe_summaries` BEGIN INSERT INTO `recipe_summaries_fts`(`docid`, `remote_id`, `name`) VALUES (NEW.`rowid`, NEW.`remote_id`, NEW.`name`); END"
|
||||||
|
],
|
||||||
|
"tableName": "recipe_summaries_fts",
|
||||||
|
"createSql": "CREATE VIRTUAL TABLE IF NOT EXISTS `${TABLE_NAME}` USING FTS4(`remote_id` TEXT NOT NULL, `name` TEXT NOT NULL, content=`recipe_summaries`)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "remoteId",
|
||||||
|
"columnName": "remote_id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1def22b22cb1f09a27de1b3188b857d2')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,12 +6,13 @@ import gq.kirmanak.mealient.database.recipe.RecipeDao
|
|||||||
import gq.kirmanak.mealient.database.recipe.entity.*
|
import gq.kirmanak.mealient.database.recipe.entity.*
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
version = 6,
|
version = 7,
|
||||||
entities = [
|
entities = [
|
||||||
RecipeSummaryEntity::class,
|
RecipeSummaryEntity::class,
|
||||||
RecipeEntity::class,
|
RecipeEntity::class,
|
||||||
RecipeIngredientEntity::class,
|
RecipeIngredientEntity::class,
|
||||||
RecipeInstructionEntity::class
|
RecipeInstructionEntity::class,
|
||||||
|
RecipeSummaryFtsEntity::class,
|
||||||
],
|
],
|
||||||
exportSchema = true,
|
exportSchema = true,
|
||||||
autoMigrations = [
|
autoMigrations = [
|
||||||
@@ -19,6 +20,7 @@ import gq.kirmanak.mealient.database.recipe.entity.*
|
|||||||
AutoMigration(from = 3, to = 4),
|
AutoMigration(from = 3, to = 4),
|
||||||
AutoMigration(from = 4, to = 5, spec = AppDb.From4To5Migration::class),
|
AutoMigration(from = 4, to = 5, spec = AppDb.From4To5Migration::class),
|
||||||
AutoMigration(from = 5, to = 6, spec = AppDb.From5To6Migration::class),
|
AutoMigration(from = 5, to = 6, spec = AppDb.From5To6Migration::class),
|
||||||
|
AutoMigration(from = 6, to = 7),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@TypeConverters(RoomTypeConverters::class)
|
@TypeConverters(RoomTypeConverters::class)
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ interface RecipeDao {
|
|||||||
@Query("SELECT * FROM recipe_summaries ORDER BY date_added DESC")
|
@Query("SELECT * FROM recipe_summaries ORDER BY date_added DESC")
|
||||||
fun queryRecipesByPages(): PagingSource<Int, RecipeSummaryEntity>
|
fun queryRecipesByPages(): PagingSource<Int, RecipeSummaryEntity>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM recipe_summaries JOIN recipe_summaries_fts ON recipe_summaries_fts.remote_id == recipe_summaries.remote_id WHERE recipe_summaries_fts.name MATCH :query ORDER BY date_added DESC")
|
||||||
|
fun queryRecipesByPages(query: String): PagingSource<Int, RecipeSummaryEntity>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun insertRecipe(recipeSummaryEntity: RecipeSummaryEntity)
|
suspend fun insertRecipe(recipeSummaryEntity: RecipeSummaryEntity)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package gq.kirmanak.mealient.database.recipe.entity
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.Fts4
|
||||||
|
|
||||||
|
|
||||||
|
@Entity(tableName = "recipe_summaries_fts")
|
||||||
|
@Fts4(contentEntity = RecipeSummaryEntity::class)
|
||||||
|
data class RecipeSummaryFtsEntity(
|
||||||
|
@ColumnInfo(name = "remote_id") val remoteId: String,
|
||||||
|
@ColumnInfo(name = "name") val name: String,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user