Merge pull request 'Issue 2: Add config' (#7) from ms/issues-2/add-config-db into master

This commit is contained in:
Mathieu Sanchez 2020-04-25 20:37:12 +00:00
commit 9850c9fd08
42 changed files with 143 additions and 48 deletions

View File

@ -27,7 +27,8 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
buildConfigField "Integer", "DB_VERSION", "1" buildConfigField "Integer", "DB_VERSION", "1"
buildConfigField "Boolean", "TEST", "false" buildConfigField "Boolean", "TEST", "false"

View File

@ -8,12 +8,6 @@
<uses-permission <uses-permission
android:name="android.permission.CAMERA" android:name="android.permission.CAMERA"
tools:node="remove" /> tools:node="remove" />
<uses-permission
android:name="android.permission.READ_PHONE_STATE"
tools:node="remove" />
<uses-permission
android:name="android.permission.INTERNET"
tools:node="remove" />
<application <application
android:allowBackup="false" android:allowBackup="false"

View File

@ -2,18 +2,22 @@ package fr.sanchezm.attestationsCovid19.data.db
import android.content.Context import android.content.Context
import fr.sanchezm.attestationsCovid19.data.db.dao.AttestationDao import fr.sanchezm.attestationsCovid19.data.db.dao.AttestationDao
import fr.sanchezm.attestationsCovid19.data.db.dao.ConfigDao
import fr.sanchezm.attestationsCovid19.data.db.dao.ProfileDao import fr.sanchezm.attestationsCovid19.data.db.dao.ProfileDao
class MyDatabase private constructor(private val savePath: String, private val filesPath: String) { class MyDatabase private constructor(private val savePath: String, private val filesPath: String) {
private var _profileDao: ProfileDao? = null private var _profileDao: ProfileDao? = null
private var _attestationDao: AttestationDao? = null private var _attestationDao: AttestationDao? = null
private var _configDao: ConfigDao? = null
fun profileDao(): ProfileDao = _profileDao ?: ProfileDao(savePath).also { _profileDao = it } fun profileDao(): ProfileDao = _profileDao ?: ProfileDao(savePath).also { _profileDao = it }
fun attestationDao(): AttestationDao = fun attestationDao(): AttestationDao =
_attestationDao ?: AttestationDao(savePath, filesPath).also { _attestationDao = it } _attestationDao ?: AttestationDao(savePath, filesPath).also { _attestationDao = it }
fun configDao(): ConfigDao = _configDao ?: ConfigDao(savePath).also { _configDao = it }
companion object { companion object {
@Volatile @Volatile
private var instance: MyDatabase? = null private var instance: MyDatabase? = null

View File

@ -11,8 +11,8 @@ import java.io.File
class AttestationDao(private val savePath: String, private val filesPath: String) { class AttestationDao(private val savePath: String, private val filesPath: String) {
private var _attestations = MutableLiveData<ArrayList<Attestation>>() private val _attestations = MutableLiveData<ArrayList<Attestation>>()
private var fileName = "attestation.db" private val fileName = "attestation.db"
private val type = object : TypeToken<ArrayList<Attestation>>() {}.type private val type = object : TypeToken<ArrayList<Attestation>>() {}.type
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")

View File

@ -0,0 +1,45 @@
package fr.sanchezm.attestationsCovid19.data.db.dao
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.google.gson.Gson
import fr.sanchezm.attestationsCovid19.BuildConfig
import fr.sanchezm.attestationsCovid19.data.db.entity.Config
import java.io.File
class ConfigDao(private val savePath: String) {
private val _config = MutableLiveData<Config>()
private val fileName = "config.db"
fun getConfig(): LiveData<Config> =
_config
fun updateConfig(config: Config) {
_config.value = config
save()
}
init {
load()
}
private fun load() {
val file = File("$savePath/$fileName")
if (file.exists()) {
_config.value = Gson().fromJson(file.readText(Charsets.UTF_8), Config::class.java)
_config.value?.versionCode = BuildConfig.VERSION_CODE
_config.value?.versionName = BuildConfig.VERSION_NAME
} else {
_config.value =
Config(BuildConfig.DB_VERSION, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)
save()
}
}
private fun save() {
File("$savePath/$fileName").writeText(Gson().toJson(_config.value))
}
}

View File

@ -8,8 +8,8 @@ import java.io.File
class ProfileDao(private val path: String) { class ProfileDao(private val path: String) {
private var _profile = MutableLiveData<Profile>() private val _profile = MutableLiveData<Profile>()
private var fileName = "profile.db" private val fileName = "profile.db"
fun getProfile(): LiveData<Profile> = fun getProfile(): LiveData<Profile> =
_profile _profile

View File

@ -0,0 +1,7 @@
package fr.sanchezm.attestationsCovid19.data.db.entity
data class Config(
val dbVersion: Int,
var versionName: String,
var versionCode: Int
)

View File

@ -0,0 +1,21 @@
package fr.sanchezm.attestationsCovid19.data.repository
import fr.sanchezm.attestationsCovid19.data.db.dao.ConfigDao
import fr.sanchezm.attestationsCovid19.data.db.entity.Config
class ConfigRepository private constructor(private val configDao: ConfigDao) {
fun getConfig() = configDao.getConfig()
fun updateConfig(config: Config) = configDao.updateConfig(config)
companion object {
@Volatile
private var instance: ConfigRepository? = null
fun getInstance(configDao: ConfigDao) =
instance ?: synchronized(this) {
instance ?: ConfigRepository(configDao).also { instance = it }
}
}
}

View File

@ -10,6 +10,7 @@ import fr.sanchezm.attestationsCovid19.R
import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation
import fr.sanchezm.attestationsCovid19.data.db.entity.Profile import fr.sanchezm.attestationsCovid19.data.db.entity.Profile
import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository
import fr.sanchezm.attestationsCovid19.data.repository.ConfigRepository
import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository
import fr.sanchezm.attestationsCovid19.utilities.Event import fr.sanchezm.attestationsCovid19.utilities.Event
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -18,6 +19,7 @@ import java.time.format.DateTimeFormatter
import java.util.* import java.util.*
class AddViewModel( class AddViewModel(
private val configRepository: ConfigRepository,
private val profileRepository: ProfileRepository, private val profileRepository: ProfileRepository,
private val attestationRepository: AttestationRepository private val attestationRepository: AttestationRepository
) : ViewModel() { ) : ViewModel() {

View File

@ -3,9 +3,11 @@ package fr.sanchezm.attestationsCovid19.ui.add
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository
import fr.sanchezm.attestationsCovid19.data.repository.ConfigRepository
import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository
class AddViewModelFactory( class AddViewModelFactory(
private val configRepository: ConfigRepository,
private val profileRepository: ProfileRepository, private val profileRepository: ProfileRepository,
private val attestationRepository: AttestationRepository private val attestationRepository: AttestationRepository
) : ) :
@ -13,6 +15,6 @@ class AddViewModelFactory(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T { override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return AddViewModel(profileRepository, attestationRepository) as T return AddViewModel(configRepository, profileRepository, attestationRepository) as T
} }
} }

View File

@ -5,9 +5,14 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository
import fr.sanchezm.attestationsCovid19.data.repository.ConfigRepository
import fr.sanchezm.attestationsCovid19.utilities.Event import fr.sanchezm.attestationsCovid19.utilities.Event
class AttestationsViewModel(attestationRepository: AttestationRepository) : ViewModel() { class AttestationsViewModel(
private val configRepository: ConfigRepository,
attestationRepository: AttestationRepository
) :
ViewModel() {
private val _startActivity = MutableLiveData<Event<Long>>() private val _startActivity = MutableLiveData<Event<Long>>()
private var _displayNoAttestation = MutableLiveData<Int>() private var _displayNoAttestation = MutableLiveData<Int>()

View File

@ -3,13 +3,16 @@ package fr.sanchezm.attestationsCovid19.ui.attestations
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository
import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository import fr.sanchezm.attestationsCovid19.data.repository.ConfigRepository
class AttestationsViewModelFactory(private val attestationRepository: AttestationRepository) : class AttestationsViewModelFactory(
private val configRepository: ConfigRepository,
private val attestationRepository: AttestationRepository
) :
ViewModelProvider.NewInstanceFactory() { ViewModelProvider.NewInstanceFactory() {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T { override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return AttestationsViewModel(attestationRepository) as T return AttestationsViewModel(configRepository, attestationRepository) as T
} }
} }

View File

@ -7,10 +7,15 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation
import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository
import fr.sanchezm.attestationsCovid19.data.repository.ConfigRepository
import fr.sanchezm.attestationsCovid19.utilities.Event import fr.sanchezm.attestationsCovid19.utilities.Event
import fr.sanchezm.attestationsCovid19.utilities.QRCodeUtils import fr.sanchezm.attestationsCovid19.utilities.QRCodeUtils
class QrCodeViewModel(private val attestationRepository: AttestationRepository) : ViewModel() { class QrCodeViewModel(
private val configRepository: ConfigRepository,
private val attestationRepository: AttestationRepository
) :
ViewModel() {
private val _attestation = MutableLiveData<Attestation>() private val _attestation = MutableLiveData<Attestation>()

View File

@ -3,12 +3,16 @@ package fr.sanchezm.attestationsCovid19.ui.qrcode
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository
import fr.sanchezm.attestationsCovid19.data.repository.ConfigRepository
class QrCodeViewModelFactory(private val attestationRepository: AttestationRepository) : class QrCodeViewModelFactory(
private val configRepository: ConfigRepository,
private val attestationRepository: AttestationRepository
) :
ViewModelProvider.NewInstanceFactory() { ViewModelProvider.NewInstanceFactory() {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T { override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return QrCodeViewModel(attestationRepository) as T return QrCodeViewModel(configRepository, attestationRepository) as T
} }
} }

View File

@ -4,6 +4,7 @@ import android.content.Context
import android.os.Environment import android.os.Environment
import fr.sanchezm.attestationsCovid19.data.db.MyDatabase import fr.sanchezm.attestationsCovid19.data.db.MyDatabase
import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository
import fr.sanchezm.attestationsCovid19.data.repository.ConfigRepository
import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository
import fr.sanchezm.attestationsCovid19.ui.add.AddViewModelFactory import fr.sanchezm.attestationsCovid19.ui.add.AddViewModelFactory
import fr.sanchezm.attestationsCovid19.ui.attestations.AttestationsViewModelFactory import fr.sanchezm.attestationsCovid19.ui.attestations.AttestationsViewModelFactory
@ -11,41 +12,42 @@ import fr.sanchezm.attestationsCovid19.ui.qrcode.QrCodeViewModelFactory
object InjectorUtils { object InjectorUtils {
fun provideAddViewModelFactory(context: Context): AddViewModelFactory { fun provideAddViewModelFactory(context: Context): AddViewModelFactory =
val profileRepository = AddViewModelFactory(
ProfileRepository.getInstance( getConfigRepo(context),
getProfileRepo(context),
getAttestationRepo(context)
)
fun provideAttestationViewModel(context: Context): AttestationsViewModelFactory =
AttestationsViewModelFactory(
getConfigRepo(context),
getAttestationRepo(context)
)
fun provideQrCodeViewModel(context: Context): QrCodeViewModelFactory =
QrCodeViewModelFactory(
getConfigRepo(context),
getAttestationRepo(context)
)
fun providePdfUtils(context: Context): PdfUtils =
PdfUtils.getInstance(context.assets, getMyFilesDir(context))
private fun getMyFilesDir(context: Context): String =
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.path!!
private fun getAttestationRepo(context: Context): AttestationRepository =
AttestationRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao()
)
private fun getProfileRepo(context: Context): ProfileRepository = ProfileRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).profileDao() MyDatabase.invoke(context, getMyFilesDir(context)).profileDao()
) )
val attestationRepository =
AttestationRepository.getInstance( private fun getConfigRepo(context: Context): ConfigRepository = ConfigRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao() MyDatabase.invoke(context, getMyFilesDir(context)).configDao()
) )
return AddViewModelFactory(profileRepository, attestationRepository)
}
fun provideAttestationViewModel(context: Context): AttestationsViewModelFactory {
val attestationRepository =
AttestationRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao()
)
return AttestationsViewModelFactory(attestationRepository)
}
fun provideQrCodeViewModel(context: Context): QrCodeViewModelFactory {
val attestationRepository =
AttestationRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao()
)
return QrCodeViewModelFactory(attestationRepository)
}
fun providePdfUtils(context: Context): PdfUtils {
return PdfUtils.getInstance(context.assets, getMyFilesDir(context))
}
private fun getMyFilesDir(context: Context): String = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.path!!
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB