@ -4,6 +4,7 @@
package com.fox2code.mmm.repo
package com.fox2code.mmm.repo
import android.net.Uri
import android.net.Uri
import androidx.room.Room
import com.fox2code.mmm.AppUpdateManager.Companion.shouldForceHide
import com.fox2code.mmm.AppUpdateManager.Companion.shouldForceHide
import com.fox2code.mmm.BuildConfig
import com.fox2code.mmm.BuildConfig
import com.fox2code.mmm.MainActivity
import com.fox2code.mmm.MainActivity
@ -13,16 +14,13 @@ import com.fox2code.mmm.XRepo
import com.fox2code.mmm.manager.ModuleInfo
import com.fox2code.mmm.manager.ModuleInfo
import com.fox2code.mmm.utils.io.Files.Companion.write
import com.fox2code.mmm.utils.io.Files.Companion.write
import com.fox2code.mmm.utils.io.PropUtils.Companion.readProperties
import com.fox2code.mmm.utils.io.PropUtils.Companion.readProperties
import com.fox2code.mmm.utils.realm.ModuleListCache
import com.fox2code.mmm.utils.room.ModuleListCacheDatabase
import com.fox2code.mmm.utils.realm.ReposList
import com.fox2code.mmm.utils.room.ReposListDatabase
import io.realm.Realm
import io.realm.RealmConfiguration
import org.json.JSONException
import org.json.JSONException
import org.json.JSONObject
import org.json.JSONObject
import timber.log.Timber
import timber.log.Timber
import java.io.File
import java.io.File
import java.io.IOException
import java.io.IOException
import java.util.concurrent.atomic.AtomicBoolean
@Suppress ( " LeakingThis " , " SENSELESS_COMPARISON " , " RedundantSetter " )
@Suppress ( " LeakingThis " , " SENSELESS_COMPARISON " , " RedundantSetter " )
open class RepoData ( url : String , cacheRoot : File ) : XRepo ( ) {
open class RepoData ( url : String , cacheRoot : File ) : XRepo ( ) {
@ -150,40 +148,20 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
defaultName = url // Set url as default name
defaultName = url // Set url as default name
val tempVarForPreferenceId = preferenceId !!
val tempVarForPreferenceId = preferenceId !!
isForceHide = shouldForceHide ( tempVarForPreferenceId )
isForceHide = shouldForceHide ( tempVarForPreferenceId )
// this.enable is set from the database
// basically same as above but for room database
val realmConfiguration = RealmConfiguration . Builder ( ) . name ( " ReposList.realm " ) . encryptionKey (
val db = Room . databaseBuilder (
INSTANCE !! . key
INSTANCE !! . applicationContext ,
) . allowQueriesOnUiThread ( true ) . allowWritesOnUiThread ( true ) . directory (
ReposListDatabase :: class . java ,
INSTANCE !! . getDataDirWithPath ( " realms " )
" repo_database "
) . schemaVersion ( 1 ) . build ( )
) . allowMainThreadQueries ( ) . build ( )
val realm = Realm . getInstance ( realmConfiguration )
val reposListRoom = db . reposListDao ( )
val reposList = realm . where ( ReposList :: class . java ) . equalTo ( " id " , preferenceId ) . findFirst ( )
val reposListRoomList = reposListRoom . getById ( preferenceId !! )
if ( reposList == null ) {
enabled = !is ForceHide && reposListRoomList != null && reposListRoomList . enabled
Timber . d ( " RepoData for %s not found in database " , preferenceId )
// log every repo in db
val fullList : Array < Any > = realm . where ( ReposList :: class . java ) . findAll ( ) . toTypedArray ( )
Timber . d ( " RepoData: " + preferenceId + " . repos in database: " + fullList . size )
for ( repo in fullList ) {
val r = repo as ReposList
Timber . d ( " RepoData: " + preferenceId + " . repo: " + r . id + " " + r . name + " " + r . website + " " + r . support + " " + r . donate + " " + r . submitModule + " " + r . isEnabled )
}
} else {
Timber . d ( " RepoData for %s found in database " , preferenceId )
}
Timber . d (
" RepoData: $preferenceId . record in database: " + ( reposList ?. toString ( )
?: " none " )
)
enabled = !is ForceHide && reposList != null && reposList . isEnabled
defaultWebsite = " https:// " + Uri . parse ( url ) . host + " / "
defaultWebsite = " https:// " + Uri . parse ( url ) . host + " / "
// open realm database
// open realm database
// load metadata from realm database
// load metadata from realm database
if ( enabled ) {
if ( enabled ) {
try {
try {
metaDataCache = ModuleListCache . getRepoModulesAsJson ( preferenceId )
// log count of modules in the database
val tempMetaDataCacheVar = metaDataCache !!
Timber . d ( " RepoData: $preferenceId . modules in database: ${tempMetaDataCacheVar.length()} " )
// load repo metadata from ReposList unless it's a built-in repo
// load repo metadata from ReposList unless it's a built-in repo
if ( RepoManager . isBuiltInRepo ( preferenceId ) ) {
if ( RepoManager . isBuiltInRepo ( preferenceId ) ) {
name = defaultName
name = defaultName
@ -192,28 +170,25 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
donate = defaultDonate
donate = defaultDonate
submitModule = defaultSubmitModule
submitModule = defaultSubmitModule
} else {
} else {
// get everything from ReposList realm database
// get everything from the database
name = realm . where (
name = reposListRoomList . name
ReposList :: class . java
website = reposListRoomList . website
) . equalTo ( " id " , preferenceId ) . findFirst ( ) ?. name
support = reposListRoomList . support
website = realm . where (
donate = reposListRoomList . donate
ReposList :: class . java
submitModule = reposListRoomList . submitModule
) . equalTo ( " id " , preferenceId ) . findFirst ( ) ?. website
// if name is null return defaultName and if defaultName is null return url
support = realm . where (
if ( name == null ) {
ReposList :: class . java
name = if ( defaultName == null ) {
) . equalTo ( " id " , preferenceId ) . findFirst ( ) ?. support
url
donate = realm . where (
} else {
ReposList :: class . java
defaultName
) . equalTo ( " id " , preferenceId ) . findFirst ( ) ?. donate
}
submitModule = realm . where (
}
ReposList :: class . java
) . equalTo ( " id " , preferenceId ) . findFirst ( ) ?. submitModule
}
}
} catch ( e : Exception ) {
} catch ( e : Exception ) {
Timber . w ( " Failed to load repo metadata from database: " + e . message + " . If this is a first time run, this is normal. " )
Timber . w ( " Failed to load repo metadata from database: " + e . message + " . If this is a first time run, this is normal. " )
}
}
}
}
realm . close ( )
}
}
open fun prepare ( ) : Boolean {
open fun prepare ( ) : Boolean {
@ -330,27 +305,14 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
get ( ) = if ( field ) {
get ( ) = if ( field ) {
field
field
} else {
} else {
val realmConfiguration2 =
val db = Room . databaseBuilder (
RealmConfiguration . Builder ( ) . name ( " ReposList.realm " ) . encryptionKey (
INSTANCE !! . applicationContext ,
INSTANCE !! . key
ReposListDatabase :: class . java ,
) . allowQueriesOnUiThread ( true ) . allowWritesOnUiThread ( true ) . directory (
" ReposList.db " ,
INSTANCE !! . getDataDirWithPath ( " realms " )
) . build ( )
) . schemaVersion ( 1 ) . build ( )
val reposList = db . reposListDao ( ) . getById ( preferenceId !! )
val realm2 = Realm . getInstance ( realmConfiguration2 )
val dbEnabled = AtomicBoolean ( false )
realm2 . executeTransaction { realm : Realm ->
val reposList =
realm . where ( ReposList :: class . java ) . equalTo ( " id " , preferenceId ) . findFirst ( )
if ( reposList != null ) {
dbEnabled . set ( reposList . isEnabled )
} else {
// should never happen but for safety
dbEnabled . set ( false )
}
}
realm2 . close ( )
// should never happen but for safety
// should never happen but for safety
if ( dbEnabled. get ( ) ) {
if ( reposList . enabled ) {
!is ForceHide
!is ForceHide
} else {
} else {
false
false
@ -359,22 +321,13 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
set ( value ) {
set ( value ) {
field = value
field = value
this . enabled = enabled && !is ForceHide
this . enabled = enabled && !is ForceHide
// reposlist realm
val db = Room . databaseBuilder (
val realmConfiguration2 =
INSTANCE !! . applicationContext ,
RealmConfiguration . Builder ( ) . name ( " ReposList.realm " ) . encryptionKey (
ReposListDatabase :: class . java ,
INSTANCE !! . key
" ReposList.db " ,
) . allowQueriesOnUiThread ( true ) . allowWritesOnUiThread ( true ) . directory (
) . build ( )
INSTANCE !! . getDataDirWithPath ( " realms " )
val reposList = db . reposListDao ( ) . getById ( preferenceId !! )
) . schemaVersion ( 1 ) . build ( )
db . reposListDao ( ) . update ( name = reposList . name , enabled = value , id = reposList . id , donate = reposList . donate , support = reposList . support , website = reposList . website , submitModule = reposList . submitModule , lastUpdate = reposList . lastUpdate . toLong ( ) , url = reposList . url )
val realm2 = Realm . getInstance ( realmConfiguration2 )
realm2 . executeTransaction { realm : Realm ->
val reposList =
realm . where ( ReposList :: class . java ) . equalTo ( " id " , preferenceId ) . findFirst ( )
if ( reposList != null ) {
reposList . isEnabled = enabled
}
}
realm2 . close ( )
}
}
@Throws ( IOException :: class )
@Throws ( IOException :: class )
@ -423,24 +376,17 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
}
}
// if repo starts with repo_, it's always enabled bc custom repos can't be disabled without being deleted.
// if repo starts with repo_, it's always enabled bc custom repos can't be disabled without being deleted.
isForceHide = shouldForceHide ( preferenceId !! )
isForceHide = shouldForceHide ( preferenceId !! )
// reposlist realm
val db = Room . databaseBuilder (
val realmConfiguration2 =
INSTANCE !! . applicationContext ,
RealmConfiguration . Builder ( ) . name ( " ReposList.realm " ) . encryptionKey (
ReposListDatabase :: class . java ,
INSTANCE !! . key
" ReposList.db " ,
) . allowQueriesOnUiThread ( true ) . allowWritesOnUiThread ( true ) . directory (
) . allowMainThreadQueries ( ) . build ( )
INSTANCE !! . getDataDirWithPath ( " realms " )
val reposList = db . reposListDao ( ) . getById ( preferenceId !! )
) . schemaVersion ( 1 ) . build ( )
enabled = if ( reposList . enabled ) {
val realm2 = Realm . getInstance ( realmConfiguration2 )
!is ForceHide
var dbEnabled = false
} else {
try {
false
dbEnabled = realm2 . where (
ReposList :: class . java
) . equalTo ( " id " , preferenceId ) . findFirst ( ) ?. isEnabled == true
} catch ( e : Exception ) {
Timber . e ( e , " Error while updating enabled state for repo %s " , preferenceId )
}
}
realm2 . close ( )
enabled = !is ForceHide && dbEnabled
}
}
open fun getUrl ( ) : String ? {
open fun getUrl ( ) : String ? {
@ -467,42 +413,35 @@ open class RepoData(url: String, cacheRoot: File) : XRepo() {
// should update (lastUpdate > 15 minutes)
// should update (lastUpdate > 15 minutes)
fun shouldUpdate ( ) : Boolean {
fun shouldUpdate ( ) : Boolean {
Timber . d ( " Repo $preferenceId should update check called " )
Timber . d ( " Repo $preferenceId should update check called " )
val realmConfiguration2 =
val db = Room . databaseBuilder (
RealmConfiguration . Builder ( ) . name ( " ReposList.realm " ) . encryptionKey (
INSTANCE !! . applicationContext ,
INSTANCE !! . key
ReposListDatabase :: class . java ,
) . allowQueriesOnUiThread ( true ) . allowWritesOnUiThread ( true ) . directory (
" ReposList.db " ,
INSTANCE !! . getDataDirWithPath ( " realms " )
) . allowMainThreadQueries ( ) . build ( )
) . schemaVersion ( 1 ) . build ( )
val repo = db . reposListDao ( ) . getById ( preferenceId !! )
val realm2 = Realm . getInstance ( realmConfiguration2 )
// get modulelistcache
val repo = realm2 . where ( ReposList :: class . java ) . equalTo ( " id " , preferenceId ) . findFirst ( )
val db2 = Room . databaseBuilder (
// Make sure ModuleListCache for repoId is not null
INSTANCE !! . applicationContext ,
val cacheRoot = INSTANCE !! . getDataDirWithPath ( " realms/repos/ $preferenceId " )
ModuleListCacheDatabase :: class . java ,
val realmConfiguration =
" ModuleListCache.db " ,
RealmConfiguration . Builder ( ) . name ( " ModuleListCache.realm " ) . encryptionKey (
) . allowMainThreadQueries ( ) . build ( )
INSTANCE !! . key
val moduleListCache = db2 . moduleListCacheDao ( ) . getByRepoId ( preferenceId !! )
) . schemaVersion ( 1 ) . deleteRealmIfMigrationNeeded ( ) . allowWritesOnUiThread ( true )
. allowQueriesOnUiThread ( true ) . directory ( cacheRoot ) . build ( )
val realm = Realm . getInstance ( realmConfiguration )
val moduleListCache = realm . where (
ModuleListCache :: class . java
) . equalTo ( " repoId " , preferenceId ) . findAll ( )
if ( repo != null ) {
if ( repo != null ) {
return if ( repo . lastUpdate != 0 && moduleListCache . size != 0 ) {
return if ( repo . lastUpdate != 0 && moduleListCache . isNotEmpty ( ) ) {
val lastUpdate = repo . lastUpdate . toLong ( )
val lastUpdate = repo . lastUpdate . toLong ( )
val currentTime = System . currentTimeMillis ( )
val currentTime = System . currentTimeMillis ( )
val diff = currentTime - lastUpdate
val diff = currentTime - lastUpdate
val diffMinutes = diff / ( 60 * 1000 ) % 60
val diffMinutes = diff / ( 60 * 1000 ) % 60
Timber . d ( " Repo $preferenceId updated: $diffMinutes minutes ago " )
Timber . d ( " Repo $preferenceId updated: $diffMinutes minutes ago " )
realm . close ( )
diffMinutes > if ( BuildConfig . DEBUG ) 15 else 30
diffMinutes > if ( BuildConfig . DEBUG ) 15 else 30
} else {
} else {
Timber . d ( " Repo $preferenceId should update could not find repo in database " )
Timber . d ( " Repo $preferenceId should update could not find repo in database " )
Timber . d ( " This is probably an error, please report this to the developer " )
Timber . d ( " This is probably an error, please report this to the developer " )
realm . close ( )
true
true
}
}
} else {
} else {
realm . close ( )
db . close ( )
db2 . close ( )
}
}
return true
return true
}
}