57 Commits

Author SHA1 Message Date
a5de6ae137 Version 2.1.2-beta1 versionCode 1008 2020-11-28 10:57:51 +01:00
b0fb52ea79 Merge branch 'ms/issue-18/change_new_attestation' into beta 2020-11-28 10:56:28 +01:00
1c7386e24b Correct not check boxes 2020-11-28 10:34:24 +01:00
747cae4d04 Version2.1.1-beta1 versionCode 1007 2020-11-28 03:54:34 +01:00
3811723df6 Merge branch 'ms/issue-18/change_new_attestation' into beta 2020-11-28 03:52:44 +01:00
8e3e1dd615 Update with the new attestation 2020-11-28 03:43:42 +01:00
8d69694ec3 Add twitch on the thanks page 2020-11-27 23:24:54 +01:00
ba3956bd2f Merge branch 'ms/issues-17/add_buy_me_a_coffee' into beta 2020-11-27 22:33:00 +01:00
31f2bf15b1 Move buy me a coffee from bottom to explication 2020-11-27 22:31:15 +01:00
d5c140e9e5 Version 2.0.2-beta1 et versionCode 1006 2020-10-31 15:15:15 +01:00
b037788708 Merge branch 'ms/issues-17/add_buy_me_a_coffee' into beta
# Conflicts:
#	app/build.gradle
2020-10-31 15:07:24 +01:00
8909908baa Issues-17: Add buy me a coffee and some text correction 2020-10-31 15:07:06 +01:00
eea7a7b27c Version 2.0.1 and versionCode 10 2020-10-31 10:00:53 +01:00
dd12a6a91e Merge remote-tracking branch 'origin/ms/issue-16/update_new_attestation' 2020-10-31 09:56:39 +01:00
6983af93d7 Version 2.0.1-beta2 and versionCode 1005 2020-10-31 09:54:38 +01:00
ee9b243902 Merge remote-tracking branch 'origin/ms/issue-16/update_new_attestation' into beta 2020-10-31 09:51:33 +01:00
c976c00ce4 Issue-16: Change name of the application 2020-10-31 09:51:22 +01:00
ae62c2ab7e Merge remote-tracking branch 'origin/ms/issue-16/update_new_attestation' 2020-10-31 09:33:23 +01:00
22732c42a3 Merge remote-tracking branch 'origin/ms/issue-14/adding-pickers'
# Conflicts:
#	app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/PdfUtils.kt
2020-10-31 09:32:51 +01:00
1530028f4b Version 2.0.1-beta1 version code 1004 2020-10-30 08:50:16 +01:00
20d41dec23 Merge branch 'ms/issue-16/update_new_attestation' into beta 2020-10-30 08:49:09 +01:00
3388de76b0 Issue-16: Update new attestation 2020-10-30 08:48:53 +01:00
b712c391ce Version 2.0.0-beta1 code 1003 2020-10-24 17:34:02 +02:00
b04cd541b4 Merge master in beta 2020-10-24 17:33:03 +02:00
055be5f968 Merge branch 'master' into beta
# Conflicts:
#	app/build.gradle
#	app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/PdfUtils.kt
2020-10-24 17:23:06 +02:00
8807105c06 Version 2.0.0 version code 9 2020-10-24 17:19:49 +02:00
849d6d4665 Version 2.0.0 version code 8 2020-10-24 17:05:10 +02:00
b5f8848f32 Issue-15: Add some warning and rename app name 2020-10-24 17:03:38 +02:00
a2e8a5e333 Issue-15: From attestation to get outside to attestation to move after curfew 2020-10-24 16:59:41 +02:00
af6cef0cd4 Version 1.0.5-beta1 version code 1002 2020-05-02 15:47:23 +02:00
3b2bf5f0ae Merge branch 'ms/issue-14/adding-pickers' into beta
# Conflicts:
#	app/build.gradle
2020-05-02 15:46:43 +02:00
5cb3478bb6 Adding pickers for date and time 2020-05-02 15:46:08 +02:00
52892c13d4 Version 1.0.5 version code 7 2020-05-02 14:54:18 +02:00
428759d30a Merge branch 'ms/issue-4/add-credits-libraries-used' 2020-05-02 14:50:13 +02:00
fac797ed32 Version 1.0.4-beta2 version code 1001 2020-05-02 14:47:57 +02:00
731920ca28 Merge branch 'ms/issue-4/add-credits-libraries-used' into beta 2020-05-02 14:46:45 +02:00
1d617e7678 Issue-4: Speeling correction 2020-05-02 14:46:30 +02:00
7d8c509e9c 1.0.4-beta1 version code 1000 2020-04-29 23:56:48 +02:00
ea6c9c4ee0 Merge pull request 'Adding config for alpha and beta build' (#13) from adding-config-alpha-beta into master 2020-04-29 21:49:09 +00:00
50cd345a53 Merge pull request 'Adding config for alpha and beta build' (#12) from adding-config-alpha-beta into beta 2020-04-29 21:48:52 +00:00
8f965e5322 Merge pull request 'Adding credits and correct spelling mistake' (#10) from ms/issue-4/add-credits-libraries-used into beta 2020-04-29 21:46:11 +00:00
a7993ed680 Adding credits and correct spelling mistake 2020-04-29 17:20:11 +02:00
f052470700 Adding config for alpha and beta build 2020-04-27 17:01:53 +02:00
41676a6b54 Version 1.0.4 version code 6 2020-04-26 17:14:00 +02:00
ff04fb3102 Issue-8: Downgrade PDF Viewer for Xiaomi error 2020-04-26 17:13:28 +02:00
514d1dff4e Adding error return if pdfUtils error 2020-04-26 17:12:38 +02:00
1f255951a0 Version 1.0.3 version code 5 2020-04-26 10:17:52 +02:00
a0e55683c6 Issue-8: Adding Keep class com.showckwave to proguard 2020-04-26 10:14:47 +02:00
75c0e004f6 Version 1.0.2 version code 4 2020-04-26 10:07:58 +02:00
9850c9fd08 Merge pull request 'Issue 2: Add config' (#7) from ms/issues-2/add-config-db into master 2020-04-25 20:37:12 +00:00
8494e9183e Issues-2: Optimize size app and remove warning 2020-04-25 22:33:22 +02:00
d316ede233 Issues-2: Correct saving Config when not existing 2020-04-25 22:15:34 +02:00
5b5a9c28f2 Issues-2: Adding Config Repository in the injectorUtils 2020-04-25 22:13:45 +02:00
148fd55e92 Add Config, ConfigDao et ConfigRepository
Change var to val in ProfileDao and AttestationDao
2020-04-25 09:28:00 +02:00
1f8fb61d6a Adding BuildConfig data and update dependencies 2020-04-25 09:20:02 +02:00
36e7818af5 Version 1.0.1 version code 3 2020-04-25 08:42:46 +02:00
49c92783cd Issues-1 : Correct birthday to reel birthday and not birth place 2020-04-25 08:42:29 +02:00
58 changed files with 508 additions and 321 deletions

View File

@ -4,19 +4,19 @@ apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
compileSdkVersion 30
buildToolsVersion "29.0.3"
dataBinding {
enabled = true
buildFeatures {
dataBinding = true
}
defaultConfig {
applicationId "fr.sanchezm.attestationsCovid19"
minSdkVersion 23
targetSdkVersion 29
versionCode 2
versionName "1.0"
targetSdkVersion 30
versionCode 1008
versionName "2.1.2-beta1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@ -27,8 +27,32 @@ android {
buildTypes {
release {
minifyEnabled false
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
buildConfigField "Integer", "DB_VERSION", db_version
buildConfigField "Boolean", "TEST", "false"
}
beta {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
buildConfigField "Integer", "DB_VERSION", db_version
buildConfigField "Boolean", "TEST", "false"
}
alpha {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
buildConfigField "Integer", "DB_VERSION", db_version
buildConfigField "Boolean", "TEST", "true"
}
debug {
buildConfigField "Integer", "DB_VERSION", db_version
buildConfigField "Boolean", "TEST", "true"
}
}
@ -49,27 +73,24 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.navigation:navigation-fragment-ktx:2.2.1'
implementation 'androidx.navigation:navigation-fragment:2.2.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.2.1'
implementation 'androidx.navigation:navigation-ui:2.2.1'
// Room
// implementation 'androidx.room:room-runtime:2.2.5'
// Android X
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
// kapt 'androidx.room:room-compiler:2.2.5'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
// Design
implementation 'com.google.android.material:material:1.2.1'
// PDF
implementation 'com.tom_roush:pdfbox-android:1.8.10.1'
implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'
//noinspection GradleDependency
implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'
// Gson
implementation 'com.google.code.gson:gson:2.8.6'
@ -79,8 +100,10 @@ dependencies {
//noinspection GradleDependency
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
implementation 'com.github.Ilhasoft:data-binding-validator:2.0.0'
// Test
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

View File

@ -19,3 +19,5 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class com.shockwave.*

View File

@ -8,12 +8,6 @@
<uses-permission
android:name="android.permission.CAMERA"
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
android:allowBackup="false"
@ -21,6 +15,7 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
tools:replace="android:allowBackup"
android:theme="@style/AppTheme.Light">
<activity android:name=".QrCodeActivity" />
<activity android:name=".PdfViewerActivity" />

Binary file not shown.

View File

@ -2,18 +2,22 @@ package fr.sanchezm.attestationsCovid19.data.db
import android.content.Context
import fr.sanchezm.attestationsCovid19.data.db.dao.AttestationDao
import fr.sanchezm.attestationsCovid19.data.db.dao.ConfigDao
import fr.sanchezm.attestationsCovid19.data.db.dao.ProfileDao
class MyDatabase private constructor(private val savePath: String, private val filesPath: String) {
private var _profileDao: ProfileDao? = null
private var _attestationDao: AttestationDao? = null
private var _configDao: ConfigDao? = null
fun profileDao(): ProfileDao = _profileDao ?: ProfileDao(savePath).also { _profileDao = it }
fun attestationDao(): AttestationDao =
_attestationDao ?: AttestationDao(savePath, filesPath).also { _attestationDao = it }
fun configDao(): ConfigDao = _configDao ?: ConfigDao(savePath).also { _configDao = it }
companion object {
@Volatile
private var instance: MyDatabase? = null
@ -24,40 +28,3 @@ class MyDatabase private constructor(private val savePath: String, private val f
}
}
}
/*
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import fr.sanchezm.attestationsCovid19.data.db.dao.AttestationDao
import fr.sanchezm.attestationsCovid19.data.db.dao.ProfileDao
import fr.sanchezm.attestationsCovid19.data.db.entity.Profile
@Database(
entities = [Profile::class],
version = 1
)
abstract class MyDatabase private constructor() : RoomDatabase() {
abstract fun profileDao(): ProfileDao
abstract fun attestationDao(): AttestationDao
companion object {
@Volatile
private var instance: MyDatabase? = null
private val LOCK = Any()
operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
instance ?: buildDatabase(context).also { instance = it }
}
private fun buildDatabase(context: Context) =
Room.databaseBuilder(
context.applicationContext,
MyDatabase::class.java, "data.db"
)
.build()
}
}
*/

View File

@ -11,8 +11,8 @@ import java.io.File
class AttestationDao(private val savePath: String, private val filesPath: String) {
private var _attestations = MutableLiveData<ArrayList<Attestation>>()
private var fileName = "attestation.db"
private val _attestations = MutableLiveData<ArrayList<Attestation>>()
private val fileName = "attestation.db"
private val type = object : TypeToken<ArrayList<Attestation>>() {}.type
@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) {
private var _profile = MutableLiveData<Profile>()
private var fileName = "profile.db"
private val _profile = MutableLiveData<Profile>()
private val fileName = "profile.db"
fun getProfile(): LiveData<Profile> =
_profile

View File

@ -3,7 +3,7 @@ package fr.sanchezm.attestationsCovid19.data.db.entity
import java.text.SimpleDateFormat
import java.util.*
const val PATTERN = "dd/MM/yyyy 'a' HH'h'mm"
const val PATTERN = "dd/MM/yyyy 'à' HH:mm"
//@Entity(tableName = "attestation")
data class Attestation(
@ -14,7 +14,7 @@ data class Attestation(
val reasons: List<Int>
) {
override fun toString(): String {
return "Cree le: ${getDate(createAt)}; $profile; Sortie: ${getExitDateFormatted()}; Motifs: ${getMotifsText()}"
return "Cree le: ${getDate(createAt)};\n$profile;\nSortie: ${getExitDateFormatted()};\nMotifs: ${getMotifsText()}"
}
fun getNameFormatted(): String = "${profile.firstName} ${profile.lastName}"
@ -28,21 +28,23 @@ data class Attestation(
private fun getMotifsText(): String {
val motifs = StringBuilder()
reasons.forEach { motifs.append(getMotifText(it), "-") }
return motifs.toString().dropLast(1)
reasons.forEach { motifs.append(getMotifText(it), ", ") }
return motifs.toString().dropLast(2)
}
private fun getDate(dateTime: Long): String = SimpleDateFormat(PATTERN, Locale.FRANCE).format(Date(dateTime))
private fun getMotifText(i: Int): String {
fun getMotifText(i: Int): String {
return when (i) {
1 -> "travail"
2 -> "courses"
2 -> "achats_culturel_culturel"
3 -> "sante"
4 -> "famille"
5 -> "sport"
6 -> "judiciare"
7 -> "missions"
5 -> "handicap"
6 -> "sport_animaux"
7 -> "convocation"
8 -> "missions"
9 -> "enfants"
else -> "Error $i not found"
}
}

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

@ -14,6 +14,6 @@ data class Profile(
// var id: Int = CURRENT_PROFILE_ID
override fun toString(): String {
return "Nom: $lastName; Prenom: $firstName; Naissance: $birthday a $birthPlace; Adresse: $address $postalCode $city"
return "Nom: $lastName;\nPrenom: $firstName;\nNaissance: $birthday a $birthPlace;\nAdresse: $address $postalCode $city"
}
}

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

@ -1,6 +1,9 @@
package fr.sanchezm.attestationsCovid19.ui.add
import android.annotation.SuppressLint
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.content.Context
import android.os.Build
import android.util.Log
import androidx.lifecycle.LiveData
@ -10,16 +13,20 @@ import fr.sanchezm.attestationsCovid19.R
import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation
import fr.sanchezm.attestationsCovid19.data.db.entity.Profile
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.utilities.Event
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.*
class AddViewModel(
private val configRepository: ConfigRepository,
private val profileRepository: ProfileRepository,
private val attestationRepository: AttestationRepository
private val attestationRepository: AttestationRepository,
private val app: Context
) : ViewModel() {
private val _errorMessage = MutableLiveData<Event<Int>>()
@ -53,10 +60,12 @@ class AddViewModel(
val reason5 = MutableLiveData(false)
val reason6 = MutableLiveData(false)
val reason7 = MutableLiveData(false)
val reason8 = MutableLiveData(false)
val reason9 = MutableLiveData(false)
// endregion
private val datePattern = "dd/MM/yyyy"
private val timePattern = "HH'h'mm"
private val timePattern = "HH:mm"
@SuppressLint("LongLogTag")
fun onGenerateAttestationClick() {
@ -73,6 +82,68 @@ class AddViewModel(
}
}
fun onBirthdayClick() {
val c = Calendar.getInstance().also { it.set(1970, 0, 1) }
if (!birthday.value.isNullOrBlank()) {
birthday.value?.let { birthday ->
DateFormat.getDateInstance(DateFormat.SHORT, Locale.FRANCE).parse(birthday)
?.let { c.time = it }
}
}
val year = c.get(Calendar.YEAR)
val month = c.get(Calendar.MONTH)
val day = c.get(Calendar.DAY_OF_MONTH)
val dpd = DatePickerDialog(
app,
{ _, yearPicked, monthOfYear, dayOfMonth ->
birthday.value =
"${getFormattedDayOrMonth(dayOfMonth)}/${getFormattedDayOrMonth(monthOfYear + 1)}/$yearPicked"
},
year,
month,
day
)
dpd.show()
}
fun onExitDateClick() {
val c = Calendar.getInstance()
val year = c.get(Calendar.YEAR)
val month = c.get(Calendar.MONTH)
val day = c.get(Calendar.DAY_OF_MONTH)
val dpd = DatePickerDialog(
app,
DatePickerDialog.OnDateSetListener { _, yearPicked, monthOfYear, dayOfMonth ->
exitDate.value =
"${getFormattedDayOrMonth(dayOfMonth)}/${getFormattedDayOrMonth(monthOfYear + 1)}/$yearPicked"
},
year,
month,
day
)
dpd.show()
}
fun onExitHourClick() {
val c = Calendar.getInstance()
val hour = c.get(Calendar.HOUR_OF_DAY)
val minute = c.get(Calendar.MINUTE)
val tpd = TimePickerDialog(
app,
TimePickerDialog.OnTimeSetListener { _, hourPicked, minutePicked ->
exitHour.value =
"${getFormattedDayOrMonth(hourPicked)}:${getFormattedDayOrMonth(minutePicked)}"
},
hour,
minute,
true
)
tpd.show()
}
init {
setProfileValue()
setDateHourToday()
@ -135,6 +206,8 @@ class AddViewModel(
if (reason5.value!!) reasons.add(5)
if (reason6.value!!) reasons.add(6)
if (reason7.value!!) reasons.add(7)
if (reason8.value!!) reasons.add(8)
if (reason9.value!!) reasons.add(9)
return reasons
}
@ -160,6 +233,17 @@ class AddViewModel(
|| reason5.value!!
|| reason6.value!!
|| reason7.value!!
|| reason8.value!!
|| reason9.value!!
}
private fun getFormattedDayOrMonth(date: Int): String {
var formattedDate: String = date.toString()
if (formattedDate.length <= 1) {
formattedDate = "0$formattedDate"
}
return formattedDate
}
}

View File

@ -1,18 +1,22 @@
package fr.sanchezm.attestationsCovid19.ui.add
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository
import fr.sanchezm.attestationsCovid19.data.repository.ConfigRepository
import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository
class AddViewModelFactory(
private val configRepository: ConfigRepository,
private val profileRepository: ProfileRepository,
private val attestationRepository: AttestationRepository
private val attestationRepository: AttestationRepository,
private val app: Context
) :
ViewModelProvider.NewInstanceFactory() {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return AddViewModel(profileRepository, attestationRepository) as T
return AddViewModel(configRepository, profileRepository, attestationRepository, app) as T
}
}

View File

@ -5,9 +5,14 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository
import fr.sanchezm.attestationsCovid19.data.repository.ConfigRepository
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 var _displayNoAttestation = MutableLiveData<Int>()

View File

@ -3,13 +3,16 @@ package fr.sanchezm.attestationsCovid19.ui.attestations
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
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() {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return AttestationsViewModel(attestationRepository) as T
return AttestationsViewModel(configRepository, attestationRepository) as T
}
}

View File

@ -1,15 +1,15 @@
package fr.sanchezm.attestationsCovid19.ui.info
import android.os.Bundle;
import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import fr.sanchezm.attestationsCovid19.BuildConfig
import fr.sanchezm.attestationsCovid19.R;
import fr.sanchezm.attestationsCovid19.R
import kotlinx.android.synthetic.main.fragment_info.view.*
class InfoFragment : Fragment() {
@ -20,13 +20,20 @@ class InfoFragment : Fragment() {
): View? {
val root = inflater.inflate(R.layout.fragment_info, container, false)
root.findViewById<TextView>(R.id.develop_by).movementMethod = LinkMovementMethod.getInstance()
root.findViewById<TextView>(R.id.version).text = getVersionText()
root.explication_4.movementMethod = LinkMovementMethod.getInstance()
root.credits_1.movementMethod = LinkMovementMethod.getInstance()
root.credits_2.movementMethod = LinkMovementMethod.getInstance()
root.credits_3.movementMethod = LinkMovementMethod.getInstance()
root.credits_4.movementMethod = LinkMovementMethod.getInstance()
root.credits_5.movementMethod = LinkMovementMethod.getInstance()
root.develop_by.movementMethod = LinkMovementMethod.getInstance()
root.version.text = getVersionText()
return root
}
private fun getVersionText(): String {
val versionText = getString(R.string.version_number);
val versionText = getString(R.string.version_number)
val versionName = BuildConfig.VERSION_NAME
return "$versionText $versionName"

View File

@ -5,12 +5,18 @@ import android.view.View
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import fr.sanchezm.attestationsCovid19.R
import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation
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.QRCodeUtils
class QrCodeViewModel(private val attestationRepository: AttestationRepository) : ViewModel() {
class QrCodeViewModel(
private val configRepository: ConfigRepository,
private val attestationRepository: AttestationRepository
) :
ViewModel() {
private val _attestation = MutableLiveData<Attestation>()
@ -23,6 +29,7 @@ class QrCodeViewModel(private val attestationRepository: AttestationRepository)
private val _startActivity = MutableLiveData<Event<Long>>()
private val _finish = MutableLiveData<Event<Boolean>>()
private val _error = MutableLiveData<Event<Int>>()
val attestation: LiveData<Attestation> = _attestation
@ -35,6 +42,7 @@ class QrCodeViewModel(private val attestationRepository: AttestationRepository)
val startActivity: LiveData<Event<Long>> = _startActivity
val finish: LiveData<Event<Boolean>> = _finish
val error: LiveData<Event<Int>> = _error
fun addData(createAt: Long, toCreate: Boolean) {
val att = attestationRepository.getAttestation(createAt)
@ -64,6 +72,8 @@ class QrCodeViewModel(private val attestationRepository: AttestationRepository)
) { success ->
if (success)
displayQrCode()
else
_error.value = Event(R.string.error_failed_create_pdf)
}
}
}

View File

@ -3,12 +3,16 @@ package fr.sanchezm.attestationsCovid19.ui.qrcode
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
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() {
@Suppress("UNCHECKED_CAST")
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 fr.sanchezm.attestationsCovid19.data.db.MyDatabase
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.ui.add.AddViewModelFactory
import fr.sanchezm.attestationsCovid19.ui.attestations.AttestationsViewModelFactory
@ -11,41 +12,43 @@ import fr.sanchezm.attestationsCovid19.ui.qrcode.QrCodeViewModelFactory
object InjectorUtils {
fun provideAddViewModelFactory(context: Context): AddViewModelFactory {
val profileRepository =
ProfileRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).profileDao()
)
val attestationRepository =
AttestationRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao()
)
fun provideAddViewModelFactory(context: Context): AddViewModelFactory =
AddViewModelFactory(
getConfigRepo(context),
getProfileRepo(context),
getAttestationRepo(context),
context
)
return AddViewModelFactory(profileRepository, attestationRepository)
}
fun provideAttestationViewModel(context: Context): AttestationsViewModelFactory =
AttestationsViewModelFactory(
getConfigRepo(context),
getAttestationRepo(context)
)
fun provideAttestationViewModel(context: Context): AttestationsViewModelFactory {
val attestationRepository =
AttestationRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao()
)
fun provideQrCodeViewModel(context: Context): QrCodeViewModelFactory =
QrCodeViewModelFactory(
getConfigRepo(context),
getAttestationRepo(context)
)
return AttestationsViewModelFactory(attestationRepository)
}
fun providePdfUtils(context: Context): PdfUtils =
PdfUtils.getInstance(context.assets, getMyFilesDir(context))
fun provideQrCodeViewModel(context: Context): QrCodeViewModelFactory {
val attestationRepository =
AttestationRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao()
)
private fun getMyFilesDir(context: Context): String =
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.path!!
return QrCodeViewModelFactory(attestationRepository)
}
private fun getAttestationRepo(context: Context): AttestationRepository =
AttestationRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao()
)
fun providePdfUtils(context: Context): PdfUtils {
return PdfUtils.getInstance(context.assets, getMyFilesDir(context))
}
private fun getProfileRepo(context: Context): ProfileRepository = ProfileRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).profileDao()
)
private fun getMyFilesDir(context: Context): String = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.path!!
private fun getConfigRepo(context: Context): ConfigRepository = ConfigRepository.getInstance(
MyDatabase.invoke(context, getMyFilesDir(context)).configDao()
)
}

View File

@ -21,8 +21,8 @@ class PdfUtils private constructor(
private val path: String
) {
private val checkboxListNames = ArrayList<String>()
private val font = PDType1Font.HELVETICA
// private val checkboxListNames = ArrayList<String>()
// private val font = PDType1Font.HELVETICA
fun fillForm(attestation: Attestation, callback: (Boolean) -> Unit) {
checkFolder()
@ -33,14 +33,17 @@ class PdfUtils private constructor(
val acroForm = docCatalog.acroForm
// Adding data
setFieldsData(acroForm, attestation)
setCheckboxFields(acroForm, attestation)
addPageWithQrCode(document, attestation)
if (setFieldsData(acroForm, attestation)) {
setCheckboxFields(acroForm, attestation)
addPageWithQrCode(document, attestation)
Log.v("PdfUtils", "Save File to ${getPath(attestation.createAt)}")
document.save(getPath(attestation.createAt))
document.close()
callback(true)
Log.v("PdfUtils", "Save File to ${getPath(attestation.createAt)}")
document.save(getPath(attestation.createAt))
document.close()
callback(true)
} else {
callback(false)
}
} catch (e: IOException) {
e.printStackTrace()
callback(false)
@ -51,7 +54,7 @@ class PdfUtils private constructor(
private fun addPageWithQrCode(document: PDDocument, attestation: Attestation) {
val size = 360
val margin = 40f
val margin = 25f
// Add QRCode on the first page
val page1: PDPage = document.pages.first()
@ -61,9 +64,8 @@ class PdfUtils private constructor(
page1,
attestation,
size / 3,
page1.mediaBox.upperRightX - margin - size / 3 - 30,
141f,
true
page1.mediaBox.upperRightX - margin - size / 3,
25f
)
// Add QRCode on a new page
@ -80,8 +82,7 @@ class PdfUtils private constructor(
attestation: Attestation,
size: Int,
x: Float,
y: Float,
addText: Boolean = false
y: Float
) {
val contentStream = PDPageContentStream(document, page, true, false)
@ -89,51 +90,39 @@ class PdfUtils private constructor(
LosslessFactory.createFromImage(document, QRCodeUtils.getQrCode(attestation, size))
contentStream.drawImage(alphaXimage, x, y)
if (addText) {
contentStream.beginText()
contentStream.setFont(font, 7f)
contentStream.newLineAtOffset(page.mediaBox.upperRightX - size - 20, 145f)
contentStream.showText("Date de création:")
contentStream.endText()
contentStream.beginText()
contentStream.setFont(font, 7f)
contentStream.newLineAtOffset(page.mediaBox.upperRightX - size - 27, 138f)
contentStream.showText(attestation.getCreatedAtFormattedDate())
contentStream.endText()
}
contentStream.close()
}
private fun setFieldsData(acroForm: PDAcroForm, attestation: Attestation) {
private fun setFieldsData(acroForm: PDAcroForm, attestation: Attestation): Boolean {
val profile = attestation.profile
// Init Fields
val namesField = acroForm.getField("Nom et prénom") as PDTextField
val birthdayField = acroForm.getField("Date de naissance") as PDTextField
val birthPlaceField = acroForm.getField("Lieu de naissance") as PDTextField
val addressField = acroForm.getField("Adresse actuelle") as PDTextField
val cityField = acroForm.getField("Ville") as PDTextField
val dateField = acroForm.getField("Date") as PDTextField
val hourField = acroForm.getField("Heure") as PDTextField
val minutesField = acroForm.getField("Minute") as PDTextField
// val signatureField = acroForm.getField("Signature") as PDTextField
namesField.value = "${profile.firstName} ${profile.lastName}"
birthdayField.value = profile.birthPlace
birthPlaceField.value = profile.birthPlace
addressField.value = "${profile.address} ${profile.postalCode} ${profile.city}"
cityField.value = profile.city
dateField.value = attestation.exitDate
hourField.value = attestation.exitHour.split("h")[0]
minutesField.value = attestation.exitHour.split("h")[1]
try {
// Init Fields
val namesField = acroForm.getField("Nom et prénom") as PDTextField
val birthdayField = acroForm.getField("Date de naissance") as PDTextField
val birthPlaceField = acroForm.getField("Lieu de naissance") as PDTextField
val addressField = acroForm.getField("Adresse") as PDTextField
val cityField = acroForm.getField("Ville") as PDTextField
val dateField = acroForm.getField("Date") as PDTextField
val exitField = acroForm.getField("Heure") as PDTextField
namesField.value = "${profile.firstName} ${profile.lastName}"
birthdayField.value = profile.birthday
birthPlaceField.value = profile.birthPlace
addressField.value = "${profile.address}, ${profile.city} ${profile.postalCode}"
cityField.value = profile.city
dateField.value = attestation.exitDate
exitField.value = attestation.exitHour.replace('h', ':')
return true
} catch (e: Exception) {
Log.e(TAG, "${e.message}")
}
return false
}
private fun setCheckboxFields(acroForm: PDAcroForm, attestation: Attestation) {
attestation.reasons.forEach {
(acroForm.getField(checkboxListNames[it - 1]) as PDCheckbox).check()
(acroForm.getField("distinction Motif $it") as PDCheckbox).check()
}
}
@ -150,24 +139,15 @@ class PdfUtils private constructor(
private var instance: PdfUtils? = null
private val LOCK = Any()
private const val folderPath = "attestations"
private val TAG = PdfUtils::class.simpleName
fun getInstance() = instance
fun getInstance(assetManager: AssetManager, path: String) = instance ?: synchronized(LOCK) {
instance ?: PdfUtils(assetManager, path).also { instance = it; it.initList() }
instance ?: PdfUtils(assetManager, path).also { instance = it }
}
fun getPath(path: String, createAt: Long): String = "$path/$folderPath/$createAt.pdf"
}
private fun initList() {
checkboxListNames.add("Déplacements entre domicile et travail")
checkboxListNames.add("Déplacements achats nécéssaires")
checkboxListNames.add("Consultations et soins")
checkboxListNames.add("Déplacements pour motif familial")
checkboxListNames.add("Déplacements brefs (activité physique et animaux)")
checkboxListNames.add("Convcation judiciaire ou administrative")
checkboxListNames.add("Mission d'intérêt général")
}
}

View File

@ -1,79 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="30dp"
android:paddingVertical="20dp">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:layout_marginTop="15dp"
android:textStyle="bold"
android:textColor="?attr/colorPrimaryDark"
android:text="@string/title_info"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/explication_1"
android:text="@string/explication_1"
android:layout_marginTop="40dp"
style="@style/TextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<TextView
android:id="@+id/explication_2"
android:text="@string/explication_2"
style="@style/TextView"
android:justificationMode="inter_word"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/explication_1" />
<TextView
android:id="@+id/explication_3"
android:text="@string/explication_3"
style="@style/TextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/explication_2" />
<TextView
android:id="@+id/explication_4"
android:text="@string/explication_4"
style="@style/TextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/explication_3" />
<TextView
android:id="@+id/develop_by"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="?attr/colorPrimaryDark"
android:text="@string/develop_by"
android:layout_marginBottom="5dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@+id/version" />
<TextView
android:id="@+id/version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/version_number"
android:textSize="12sp"
android:textColor="?attr/colorAccent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/custom_rectangle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:background="@drawable/custom_rectangle"
android:padding="15dp">
<TextView
@ -13,50 +13,50 @@
android:layout_height="wrap_content"
android:text="@string/people_item"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/date_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/date_item"
android:layout_marginTop="3dp"
android:text="@string/date_item"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@+id/people_item"
app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/people_item" />
<TextView
android:id="@+id/reason_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/reason_item"
android:layout_marginTop="3dp"
android:text="@string/reason_item"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@+id/date_item"
app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/date_item" />
<TextView
android:id="@+id/people_item_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/date_item_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
app:layout_constraintTop_toBottomOf="@id/people_item_data"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/people_item_data" />
<TextView
android:id="@+id/reason_item_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
app:layout_constraintTop_toBottomOf="@id/date_item_data"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/date_item_data" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.add.AddFragment">
<data>
@ -12,9 +12,9 @@
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintContext"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/constraintContext">
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
@ -34,10 +34,10 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@string/attestation_title"
android:textColor="?attr/colorPrimary"
android:textSize="25sp" />
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
@ -88,7 +88,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="date"
android:text="@={viewModel.birthday}" />
android:focusable="false"
android:onClick="@{() -> viewModel.onBirthdayClick()}"
android:text="@={viewModel.birthday}"
app:validateDate='@{"dd/MM/yyyy"}'
app:validateDateMessage="@{@string/date_error_message}" />
</com.google.android.material.textfield.TextInputLayout>
@ -162,8 +166,12 @@
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:inputType="date"
android:text="@={viewModel.exitDate}" />
android:onClick="@{() -> viewModel.onExitDateClick()}"
android:text="@={viewModel.exitDate}"
app:validateDate='@{"dd/MM/yyyy"}'
app:validateDateMessage="@{@string/date_error_message}" />
</com.google.android.material.textfield.TextInputLayout>
@ -177,7 +185,9 @@
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:inputType="time"
android:onClick="@{() -> viewModel.onExitHourClick()}"
android:text="@={viewModel.exitHour}" />
</com.google.android.material.textfield.TextInputLayout>
@ -246,6 +256,22 @@
android:checked="@={viewModel.reason7}"
android:text="@string/reason_7" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/reason_8"
style="@style/MaterialCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={viewModel.reason8}"
android:text="@string/reason_8" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/reason_9"
style="@style/MaterialCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={viewModel.reason9}"
android:text="@string/reason_9" />
<com.google.android.material.button.MaterialButton
android:id="@+id/generate_attestation"
android:layout_width="match_parent"
@ -253,7 +279,6 @@
android:layout_marginTop="20dp"
android:onClick="@{() -> viewModel.onGenerateAttestationClick()}"
android:text="@string/generate_attestation_button" />
<!-- android:enabled="false"-->
</LinearLayout>

View File

@ -22,7 +22,7 @@
<TextView
android:id="@+id/explication_1"
android:text="@string/explication_1"
android:layout_marginTop="40dp"
android:layout_marginTop="20dp"
style="@style/TextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@ -52,6 +52,58 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/explication_3" />
<TextView
android:layout_marginTop="20dp"
android:id="@+id/credits_title"
android:text="@string/credits_title"
android:textSize="17sp"
android:textStyle="bold"
style="@style/TextViewCredits"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/explication_4" />
<TextView
android:layout_marginTop="10dp"
android:id="@+id/credits_1"
android:text="@string/credits_1"
style="@style/TextViewCredits"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/credits_title" />
<TextView
android:id="@+id/credits_2"
android:text="@string/credits_2"
style="@style/TextViewCredits"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/credits_1" />
<TextView
android:id="@+id/credits_3"
android:text="@string/credits_3"
style="@style/TextViewCredits"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/credits_2" />
<TextView
android:id="@+id/credits_4"
android:text="@string/credits_4"
style="@style/TextViewCredits"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/credits_3" />
<TextView
android:id="@+id/credits_5"
android:text="@string/credits_5"
style="@style/TextViewCredits"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/credits_4" />
<TextView
android:id="@+id/develop_by"
android:layout_width="wrap_content"

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

View File

@ -4,7 +4,7 @@
<style name="TextView">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">@dimen/margin20dp</item>
<item name="android:layout_marginTop">@dimen/margin15dp</item>
<item name="android:textColor">@color/colorPrimary</item>
<item name="android:textSize">@dimen/textSize18sp</item>
<item name="android:justificationMode">inter_word</item>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Validator -->
<string name="date_error_message">Votre date doit être au format 01/01/1970</string>
<string name="error_cannot_create_attestation">Erreur lors de la génération de l\'attestation, tout les champs ne sont pas complétés</string>
<string name="error_failed_create_pdf">Erreur lors de la génération de l\'attestion, veuillez vérifiez vos champs ou contacter le développeur.</string>
</resources>

View File

@ -5,10 +5,9 @@
<string name="title_info">À Propos</string>
<!-- Attestation Fragment -->
<string name="attestation_title">Attestation de déplacement dérogatoire</string>
<string name="attestation_subtitle">#RestonsChezNous</string>
<string name="error_cannot_create_attestation">Erreur lors de la génération de l\'attestation, tout les champs ne sont pas compléter</string>
<string name="attestation_generated">Attestation générer</string>
<string name="attestation_title">@string/app_name</string>
<string name="attestation_subtitle">Restons chez nous pour nous protéger et protéger les autres</string>
<string name="attestation_generated">Attestation générée</string>
<string name="no_attestation">Aucune attestation, veuillez en générer une.</string>
<!-- Field for attestation -->
@ -19,26 +18,34 @@
<string name="address">Adresse</string>
<string name="city">Ville</string>
<string name="postal_code">Code Postal</string>
<string name="reason">Choisissez le ou les motif(s) de sortie</string>
<string name="exit_date">Date de sortie</string>
<string name="exit_hour">Heure de sortie</string>
<string name="generate_attestation_button">Générer l\'attestation</string>
<!-- Reasons for leaving house -->
<string name="reason_1">Déplacements entre le domicile et le lieu dexercice de lactivité professionnelle, lorsqu\'ils sont indispensables à l\'exercice dactivités ne pouvant être organisées sous forme de télétravail ou déplacements professionnels ne pouvant être différés.</string>
<string name="reason_2">Déplacements pour effectuer des achats de fournitures nécessaires à lactivité professionnelle et des achats de première nécessité dans des établissements dont les activités demeurent autorisées</string>
<string name="reason_3">Consultations et soins ne pouvant être assurés à distance et ne pouvant être différés ; consultations et soins des patients atteints d\'une affection de longue durée.</string>
<string name="reason_4">Déplacements pour motif familial impérieux, pour lassistance aux personnes vulnérables ou la garde denfants.</string>
<string name="reason_5">Déplacements brefs, dans la limite d\'une heure quotidienne et dans un rayon maximal d\'un kilomètre autour du domicile, liés soit à l\'activité physique individuelle des personnes, à l\'exclusion de toute pratique sportive collective et de toute proximité avec d\'autres personnes, soit à la promenade avec les seules personnes regroupées dans un même domicile, soit aux besoins des animaux de compagnie.</string>
<string name="reason_6">Convocation judiciaire ou administrative.</string>
<string name="reason_7">Participation à des missions dintérêt général sur demande de lautorité administrative.</string>
<string name="reason">Je certifie que mon déplacement est lié au(x) motif(s) suivant (cocher la case) autorisé en application des mesures générales nécessaires pour faire face à lépidémie de Covid19 dans le cadre de létat durgence sanitaire :</string>
<string name="reason_1">1. Déplacements entre le domicile et le lieu dexercice de lactivité professionnelle ou un établissement denseignement ou de formation ; déplacements professionnels ne pouvant être différés ; déplacements pour un concours ou un examen.</string>
<string name="reason_2">2. Déplacements pour se rendre dans un établissement culturel autorisé ou un lieu de culte ; déplacements pour effectuer des achats de biens, pour des services dont la fourniture est autorisée, pour les retraits de commandes et les livraisons à domicile.</string>
<string name="reason_3">3. Consultations, examens et soins ne pouvant être assurés à distance et lachat de médicaments.</string>
<string name="reason_4">4. Déplacements pour motif familial impérieux, pour lassistance aux personnes vulnérables et précaires ou la garde denfants.</string>
<string name="reason_5">5. Déplacements des personnes en situation de handicap et leur accompagnant.</string>
<string name="reason_6">6. Déplacements en plein air ou vers un lieu de plein air, sans changement du lieu de résidence, dans la limite de trois heures quotidiennes et dans un rayon maximal de vingt kilomètres autour du domicile, liés soit à lactivité physique ou aux loisirs individuels, à lexclusion de toute pratique sportive collective et de toute proximité avec dautres personnes, soit à la promenade avec les seules personnes regroupées dans un même domicile, soit aux besoins des animaux de compagnie.</string>
<string name="reason_7">7. Convocations judiciaires ou administratives et déplacements pour se rendre dans un service public.</string>
<string name="reason_8">8. Participation à des missions dintérêt général sur demande de lautorité administrative.</string>
<string name="reason_9">9. Déplacement pour chercher les enfants à lécole et à loccasion de leurs activités périscolaires.</string>
<!-- Info Fragment -->
<string name="explication_1">- Merci de n\'utiliser l\'application quand cas de nécessité.</string>
<string name="explication_2">- Cette application n\'aura jamais de publicité.</string>
<string name="explication_3">- Toutes les données sont stockées uniquement sur votre téléphone, utilisable hors ligne.</string>
<string name="explication_4">- Application non gouvernementale ni officiel, développer par un étudiant.</string>
<string name="develop_by">"Développer avec ❤️ par
<string name="explication_1">- Cette application n\'aura jamais de publicité.</string>
<string name="explication_2">- Toutes les données sont stockées uniquement sur votre téléphone, utilisable hors ligne.</string>
<string name="explication_3">- Application non gouvernementale ni officielle, développée par un jeune diplômé.</string>
<string name="explication_4">- Si vous souhaitez m\'offrir une bière ou un café, c\'est <a href="https://buymeacoff.ee/sanchezm/">ici</a> ou vous pouvez me suivre sur <a href="https://www.twitch.tv/mathdieu">twitch</a>.</string>
<string name="credits_title">Petit remerciement pour l\'aide apportée au développement de l\'application :</string>
<string name="credits_1">TomRoush: <a href="https://github.com/TomRoush/PdfBox-Android">PdfBox-Android</a></string>
<string name="credits_2">Barteksc: <a href="https://github.com/barteksc/AndroidPdfViewer">AndroidPdfViewer</a></string>
<string name="credits_3">Journeyapps: <a href="https://github.com/journeyapps/zxing-android-embedded">zxing-android-embedded</a></string>
<string name="credits_4">Ainsi que toutes les libraries fourni par google</string>
<string name="credits_5">Merci à <a href="https://www.linkedin.com/in/julienfabbro/">Fabbro J.</a> pour l\'aide sur l\'orthographe</string>
<string name="develop_by">"Développée avec ❤ par
<a href="https://www.sanchezm.fr/">Mathieu Sanchez</a>"</string>
<string name="version_number">Version :</string>

View File

@ -37,14 +37,20 @@
<style name="TextView" parent="Widget.MaterialComponents.TextView">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">@dimen/margin20dp</item>
<item name="android:layout_marginTop">@dimen/margin5dp</item>
<item name="android:textColor">@color/colorPrimary</item>
<item name="android:textSize">@dimen/textSize18sp</item>
<item name="android:textSize">@dimen/textSize14sp</item>
</style>
<style name="TextViewCredits" parent="TextView">
<item name="android:textSize">@dimen/textSize14sp</item>
<item name="android:layout_marginTop">@dimen/margin5dp</item>
</style>
<dimen name="textSize18sp">18sp</dimen>
<dimen name="textSize14sp">14sp</dimen>
<dimen name="textInputCornerRadius">20dp</dimen>
<dimen name="margin20dp">20dp</dimen>
<dimen name="margin15dp">15dp</dimen>
<dimen name="margin5dp">5dp</dimen>
<dimen name="emptySize">0dp</dimen>
</resources>

View File

@ -1,14 +1,19 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.3.72'
ext {
kotlin_version = '1.4.10'
db_version = '1'
}
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
@ -20,7 +25,7 @@ allprojects {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}

View File

@ -1,6 +1,6 @@
#Sun Apr 12 01:14:42 CEST 2020
#Sat Oct 24 15:33:39 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip