1
0
mirror of https://github.com/AllanWang/Frost-for-Facebook.git synced 2024-11-10 04:52:38 +01:00

Replace tab dao with generic dao

This commit is contained in:
Allan Wang 2019-03-07 19:36:09 -05:00
parent cac563f6c6
commit 3f5d2cf2a5
No known key found for this signature in database
GPG Key ID: C93E3F9C679D7A56
9 changed files with 89 additions and 142 deletions

View File

@ -1,34 +0,0 @@
package com.pitchedapps.frost.db
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.defaultTabs
import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
class FbTabsDbTest : BaseDbTest() {
private val dao get() = db.tabDao()
/**
* Note that order is also preserved here
*/
@Test
fun save() {
val tabs = listOf(FbItem.ACTIVITY_LOG, FbItem.BIRTHDAYS, FbItem.EVENTS, FbItem.MARKETPLACE, FbItem.ACTIVITY_LOG)
runBlocking {
dao.save(tabs)
assertEquals(tabs, dao.selectAll(), "Tab saving failed")
val newTabs = listOf(FbItem.PAGES, FbItem.MENU)
dao.save(newTabs)
assertEquals(newTabs, dao.selectAll(), "Tab saving does not delete preexisting items")
}
}
@Test
fun defaultRetrieve() {
runBlocking {
assertEquals(defaultTabs(), dao.selectAll(), "Default retrieval failed")
}
}
}

View File

@ -0,0 +1,46 @@
package com.pitchedapps.frost.db
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.defaultTabs
import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
class GenericDbTest : BaseDbTest() {
private val dao get() = db.genericDao()
/**
* Note that order is also preserved here
*/
@Test
fun save() {
val tabs = listOf(FbItem.ACTIVITY_LOG, FbItem.BIRTHDAYS, FbItem.EVENTS, FbItem.MARKETPLACE, FbItem.ACTIVITY_LOG)
runBlocking {
dao.saveTabs(tabs)
assertEquals(tabs, dao.getTabs(), "Tab saving failed")
val newTabs = listOf(FbItem.PAGES, FbItem.MENU)
dao.saveTabs(newTabs)
assertEquals(newTabs, dao.getTabs(), "Tab overwrite failed")
}
}
@Test
fun defaultRetrieve() {
runBlocking {
assertEquals(defaultTabs(), dao.getTabs(), "Default retrieval failed")
}
}
@Test
fun ignoreErrors() {
runBlocking {
dao.save(GenericEntity(GenericDao.TYPE_TABS, "${FbItem.ACTIVITY_LOG.name},unknown,${FbItem.EVENTS.name}"))
assertEquals(
listOf(FbItem.ACTIVITY_LOG, FbItem.EVENTS),
dao.getTabs(),
"Tab fetching does not ignore unknown names"
)
}
}
}

View File

@ -35,10 +35,10 @@ import com.pitchedapps.frost.activities.SelectorActivity
import com.pitchedapps.frost.db.CookieDao
import com.pitchedapps.frost.db.CookieEntity
import com.pitchedapps.frost.db.CookieModel
import com.pitchedapps.frost.db.FbTabDao
import com.pitchedapps.frost.db.FbTabModel
import com.pitchedapps.frost.db.save
import com.pitchedapps.frost.db.selectAll
import com.pitchedapps.frost.db.GenericDao
import com.pitchedapps.frost.db.getTabs
import com.pitchedapps.frost.db.saveTabs
import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.utils.EXTRA_COOKIES
import com.pitchedapps.frost.utils.L
@ -59,7 +59,7 @@ import java.util.ArrayList
class StartActivity : KauBaseActivity() {
private val cookieDao: CookieDao by inject()
private val tabDao: FbTabDao by inject()
private val genericDao: GenericDao by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -114,8 +114,8 @@ class StartActivity : KauBaseActivity() {
}
val tabs = (select from FbTabModel::class).queryList().map(FbTabModel::tab)
if (tabs.isNotEmpty()) {
tabDao.save(tabs)
L._d { "Migrated tabs ${tabDao.selectAll()}" }
genericDao.saveTabs(tabs)
L._d { "Migrated tabs ${genericDao.getTabs()}" }
}
deleteDatabase("Cookies.db")
deleteDatabase("FrostTabs.db")

View File

@ -70,9 +70,9 @@ import com.pitchedapps.frost.contracts.FileChooserDelegate
import com.pitchedapps.frost.contracts.MainActivityContract
import com.pitchedapps.frost.contracts.VideoViewHolder
import com.pitchedapps.frost.db.CookieDao
import com.pitchedapps.frost.db.FbTabDao
import com.pitchedapps.frost.db.GenericDao
import com.pitchedapps.frost.db.currentCookie
import com.pitchedapps.frost.db.selectAll
import com.pitchedapps.frost.db.getTabs
import com.pitchedapps.frost.enums.MainActivityLayout
import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.facebook.FbItem
@ -129,7 +129,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
override val frameWrapper: FrameLayout get() = frame_wrapper
val viewPager: FrostViewPager get() = container
val cookieDao: CookieDao by inject()
val tabDao: FbTabDao by inject()
val genericDao: GenericDao by inject()
/*
* Components with the same id in multiple layout files
@ -165,7 +165,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
onNestedCreate(savedInstanceState)
L.i { "Main finished loading UI in ${System.currentTimeMillis() - start} ms" }
launch {
adapter.setPages(tabDao.selectAll())
adapter.setPages(genericDao.getTabs())
}
controlWebview = WebView(this)
if (BuildConfig.VERSION_CODE > Prefs.versionCode) {

View File

@ -34,10 +34,10 @@ import com.mikepenz.fastadapter_extensions.drag.ItemTouchCallback
import com.mikepenz.fastadapter_extensions.drag.SimpleDragCallback
import com.mikepenz.google_material_typeface_library.GoogleMaterial
import com.pitchedapps.frost.R
import com.pitchedapps.frost.db.FbTabDao
import com.pitchedapps.frost.db.GenericDao
import com.pitchedapps.frost.db.TAB_COUNT
import com.pitchedapps.frost.db.save
import com.pitchedapps.frost.db.selectAll
import com.pitchedapps.frost.db.getTabs
import com.pitchedapps.frost.db.saveTabs
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.iitems.TabIItem
import com.pitchedapps.frost.utils.L
@ -54,7 +54,7 @@ import java.util.Collections
*/
class TabCustomizerActivity : BaseActivity() {
private val tabDao: FbTabDao by inject()
private val genericDao: GenericDao by inject()
private val adapter = FastItemAdapter<TabIItem>()
@ -74,7 +74,7 @@ class TabCustomizerActivity : BaseActivity() {
instructions.setTextColor(Prefs.textColor)
launch {
val tabs = tabDao.selectAll().toMutableList()
val tabs = genericDao.getTabs().toMutableList()
L.d { "Tabs $tabs" }
val remaining = FbItem.values().filter { it.name[0] != '_' }.toMutableList()
remaining.removeAll(tabs)
@ -94,7 +94,7 @@ class TabCustomizerActivity : BaseActivity() {
fab_save.setOnClickListener {
launchMain(NonCancellable) {
val tabs = adapter.adapterItems.subList(0, TAB_COUNT).map(TabIItem::item)
tabDao.save(tabs)
genericDao.saveTabs(tabs)
setResult(Activity.RESULT_OK)
finish()
}

View File

@ -27,11 +27,10 @@ abstract class FrostPrivateDatabase : RoomDatabase(), FrostPrivateDao {
}
interface FrostPublicDao {
fun tabDao(): FbTabDao
fun genericDao(): GenericDao
}
@Database(entities = [FbTabEntity::class], version = 1, exportSchema = true)
@TypeConverters(FbItemConverter::class)
@Database(entities = [GenericEntity::class], version = 1, exportSchema = true)
abstract class FrostPublicDatabase : RoomDatabase(), FrostPublicDao {
companion object {
const val DATABASE_NAME = "frost-db"
@ -71,9 +70,9 @@ class FrostDatabase(private val privateDb: FrostPrivateDatabase, private val pub
fun module(context: Context) = module {
single { create(context) }
single { get<FrostDatabase>().cookieDao() }
single { get<FrostDatabase>().tabDao() }
single { get<FrostDatabase>().cacheDao() }
single { get<FrostDatabase>().notifDao() }
single { get<FrostDatabase>().genericDao() }
}
/**

View File

@ -16,79 +16,16 @@
*/
package com.pitchedapps.frost.db
import androidx.room.Dao
import androidx.room.Entity
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.defaultTabs
import com.raizlabs.android.dbflow.annotation.Database
import com.raizlabs.android.dbflow.annotation.PrimaryKey
import com.raizlabs.android.dbflow.annotation.Table
import com.raizlabs.android.dbflow.structure.BaseModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
/**
* Created by Allan Wang on 2017-05-30.
*/
@Entity(tableName = "tabs")
data class FbTabEntity(@androidx.room.PrimaryKey val position: Int, val tab: FbItem)
@Dao
interface FbTabDao {
@Query("SELECT * FROM tabs ORDER BY position ASC")
fun _selectAll(): List<FbTabEntity>
@Query("DELETE FROM tabs")
fun _deleteAll()
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun _insertAll(items: List<FbTabEntity>)
@Transaction
fun _save(items: List<FbTabEntity>) {
_deleteAll()
_insertAll(items)
}
}
/**
* Saving tabs operates by deleting all db items and saving the new list.
* Transactions can't be done with suspensions in room as switching threads during the process
* may result in a deadlock.
* That's why we disallow thread switching within the transaction, but wrap the entire thing in a coroutine
*/
suspend fun FbTabDao.save(items: List<FbItem>) {
withContext(Dispatchers.IO) {
val entities = (items.takeIf { it.isNotEmpty() } ?: defaultTabs()).mapIndexed { index, fbItem ->
FbTabEntity(
index,
fbItem
)
}
_save(entities)
}
}
suspend fun FbTabDao.selectAll(): List<FbItem> = withContext(Dispatchers.IO) {
_selectAll().map { it.tab }.takeIf { it.isNotEmpty() } ?: defaultTabs()
}
object FbItemConverter {
@androidx.room.TypeConverter
@JvmStatic
fun fromItem(item: FbItem): String = item.name
@androidx.room.TypeConverter
@JvmStatic
fun toItem(value: String): FbItem = FbItem.valueOf(value)
}
const val TAB_COUNT = 4
@Database(version = FbTabsDb.VERSION)

View File

@ -24,7 +24,6 @@ import androidx.room.PrimaryKey
import androidx.room.Query
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.defaultTabs
import com.pitchedapps.frost.utils.L
/**
* Created by Allan Wang on 2017-05-30.
@ -52,21 +51,21 @@ interface GenericDao {
@Query("DELETE FROM frost_generic WHERE type = :type")
suspend fun delete(type: String)
suspend fun saveTabs(tabs: List<FbItem>) {
val content = tabs.joinToString(",") { it.name }
save(GenericEntity(TYPE_TABS, content))
}
suspend fun getTabs(): List<FbItem> {
val allTabs = FbItem.values.map { it.name to it }.toMap()
return select(TYPE_TABS)
?.split(",")
?.mapNotNull { allTabs[it] }
?.takeIf { it.isNotEmpty() }
?: defaultTabs()
}
companion object {
const val TYPE_TABS = "generic_tabs"
}
}
suspend fun GenericDao.saveTabs(tabs: List<FbItem>) {
val content = tabs.joinToString(",") { it.name }
save(GenericEntity(GenericDao.TYPE_TABS, content))
}
suspend fun GenericDao.getTabs(): List<FbItem> {
val allTabs = FbItem.values.map { it.name to it }.toMap()
return select(GenericDao.TYPE_TABS)
?.split(",")
?.mapNotNull { allTabs[it] }
?.takeIf { it.isNotEmpty() }
?: defaultTabs()
}

View File

@ -2,28 +2,28 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "fde868470836ff9230f1d406922d7563",
"identityHash": "ee4d2fe4052ad3a1892be17681816c2c",
"entities": [
{
"tableName": "tabs",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`position` INTEGER NOT NULL, `tab` TEXT NOT NULL, PRIMARY KEY(`position`))",
"tableName": "frost_generic",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `contents` TEXT NOT NULL, PRIMARY KEY(`type`))",
"fields": [
{
"fieldPath": "position",
"columnName": "position",
"affinity": "INTEGER",
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "tab",
"columnName": "tab",
"fieldPath": "contents",
"columnName": "contents",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"position"
"type"
],
"autoGenerate": false
},
@ -34,7 +34,7 @@
"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, \"fde868470836ff9230f1d406922d7563\")"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"ee4d2fe4052ad3a1892be17681816c2c\")"
]
}
}