diff --git a/app/build.gradle b/app/build.gradle index 97379d7..789e616 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,6 +56,7 @@ dependencies { 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' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 21022a2..abd690e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,8 +12,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme.Light"> - - + >() private var fileName = "attestation.db" private val type = object : TypeToken>() {}.type - fun getAttestations() : LiveData> = - _attestations + @Suppress("UNCHECKED_CAST") + fun getAttestations(): LiveData> = + _attestations as LiveData> fun getAttestation(id: Int): Attestation? = _attestations.value?.elementAt(id) fun addAttestation(attestation: Attestation) { + _attestations.value = _attestations.value ?: ArrayList() + _attestations.value?.add(attestation) + Log.d(TAG, "Add Attestation : $attestation") save() } @@ -33,36 +38,50 @@ class AttestationDao(private val path: String) { return null } + fun deleteAttestation(attestation: Attestation) { + deleteFile(attestation) + delete(attestation) + } + init { load() } + private fun delete(attestation: Attestation) { + _attestations.value?.remove(attestation) + } + + private fun deleteFile(attestation: Attestation) { + File(PdfUtils.getPath(filesPath, attestation.createAt)).also { + if (it.exists()) + it.delete() + } + _attestations.value = _attestations.value + + } + private fun load() { - val file = File("$path/$fileName") + val file = File("$savePath/$fileName") + val removeList = ArrayList() if (file.exists()) { _attestations.value = Gson().fromJson(file.readText(Charsets.UTF_8), type) } _attestations.value?.forEach { - val filePath = PdfUtils.getInstance()?.getPath(it.createAt) + val filePath = PdfUtils.getPath(filesPath, it.createAt) - if (filePath != null && !File(filePath).exists()) { - _attestations.value!!.remove(it) + if (!File(filePath).exists()) { + removeList.add(it) } - } + }.also { _attestations.value?.removeAll(removeList) } } private fun save() { - File("$path/$fileName").writeText(Gson().toJson(_attestations.value)) + Log.d(TAG, "Save : ${Gson().toJson(_attestations.value)}") + File("$savePath/$fileName").writeText(Gson().toJson(_attestations.value)) } -} - -//@Dao -//interface AttestationDao { -// @Insert -// fun insert(attestation: Attestation) -// -// @Query(value = "SELECT * FROM attestation WHERE id = $CURRENT_ATTESTATION_ID") -// fun getAttestation(): LiveData -//} \ No newline at end of file + companion object { + private val TAG = AttestationDao::class.simpleName + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/entity/Attestation.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/entity/Attestation.kt index 6e0397c..5971e30 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/entity/Attestation.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/entity/Attestation.kt @@ -14,12 +14,18 @@ data class Attestation( val reasons: List ) { override fun toString(): String { - return "Cree le: ${getDate(createAt)}; $profile; Sortie: $exitDate a $exitHour; Motifs: ${getMotifsText()}" + return "Cree le: ${getDate(createAt)}; $profile; Sortie: ${getExitDateFormatted()}; Motifs: ${getMotifsText()}" } - fun getCreatedAtFormatedDate(): String = getDate(createAt) + fun getNameFormatted(): String = "${profile.firstName} ${profile.lastName}" - fun getMotifsText(): String { + fun getCreatedAtFormattedDate(): String = getDate(createAt) + + fun getExitDateFormatted(): String = "$exitDate a $exitHour" + + fun getMotifsFormatted(): String = getMotifsText().replace("-", " ") + + private fun getMotifsText(): String { val motifs = StringBuilder() reasons.forEach { motifs.append(getMotifText(it), "-") } diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/data/repository/AttestationRepository.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/repository/AttestationRepository.kt index 4c0486d..cb6e819 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/data/repository/AttestationRepository.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/repository/AttestationRepository.kt @@ -6,8 +6,8 @@ import fr.sanchezm.attestationsCovid19.utilities.PdfUtils class AttestationRepository private constructor(private val attestationDao: AttestationDao) { - fun generateAttestation(attestation: Attestation) = - PdfUtils.getInstance()?.fillForm(attestation) + fun generateAttestation(attestation: Attestation, callback: (Boolean) -> Unit) = + PdfUtils.getInstance()?.fillForm(attestation, callback) fun getAttestations() = attestationDao.getAttestations() @@ -17,6 +17,8 @@ class AttestationRepository private constructor(private val attestationDao: Atte fun addAttestation(attestation: Attestation) = attestationDao.addAttestation(attestation) + fun deleteAttestation(attestation: Attestation) = attestationDao.deleteAttestation(attestation) + companion object { @Volatile private var instance: AttestationRepository? = null diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddFragment.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddFragment.kt index 5573713..412093a 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddFragment.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddFragment.kt @@ -53,8 +53,8 @@ class AddFragment : Fragment() { } }) - addViewModel.startActivity.observe(viewLifecycleOwner, Observer { - it.getContentIfNotHandled()?.let { + addViewModel.startActivity.observe(viewLifecycleOwner, Observer { event -> + event.getContentIfNotHandled()?.let { val intent = Intent(context, QrCodeActivity::class.java).apply { putExtra("createAt", it) putExtra("toCreate", true) diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModel.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModel.kt index ca22aa9..b8249d8 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModel.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModel.kt @@ -67,8 +67,6 @@ class AddViewModel( attestationRepository.addAttestation(attestation) _startActivity.value = Event(attestation.createAt) -// attestationRepository.generateAttestation(attestation) -// _dataMessage.value = Event(R.string.attestation_generated) } else { _errorMessage.value = Event(R.string.error_cannot_create_attestation) Log.e("onGenerateAttestationClick", "Cannot generate Attestation") diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsAdapter.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsAdapter.kt index 3ab0a65..cd56d23 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsAdapter.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsAdapter.kt @@ -41,13 +41,10 @@ class AttestationsAdapter( private val reasonItem = view.reason_item_data fun bind(attestation: Attestation) { - peopleItem.text = getName(attestation) - dateItem.text = attestation.getCreatedAtFormatedDate() - reasonItem.text = attestation.getMotifsText() + peopleItem.text = attestation.getNameFormatted() + dateItem.text = attestation.getExitDateFormatted() + reasonItem.text = attestation.getMotifsFormatted() view.setOnClickListener { itemClickListener.onItemClick(attestation) } } - - private fun getName(attestation: Attestation) = - "${attestation.profile.firstName} ${attestation.profile.lastName}" } } \ No newline at end of file diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsFragment.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsFragment.kt index 4fad307..8f9fd27 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsFragment.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsFragment.kt @@ -11,6 +11,7 @@ import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import fr.sanchezm.attestationsCovid19.PdfViewerActivity +import fr.sanchezm.attestationsCovid19.QrCodeActivity import fr.sanchezm.attestationsCovid19.R import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation import fr.sanchezm.attestationsCovid19.databinding.FragmentAttestationsBinding @@ -24,8 +25,9 @@ class AttestationsFragment : Fragment() { private val attestationsAdapter = AttestationsAdapter(arrayListOf(), object : ItemClickListener { override fun onItemClick(item: Attestation) { - val intent = Intent(context, PdfViewerActivity::class.java).apply { + val intent = Intent(context, QrCodeActivity::class.java).apply { putExtra("createAt", item.createAt) + putExtra("toCreate", false) } startActivity(intent) } @@ -56,8 +58,8 @@ class AttestationsFragment : Fragment() { } private fun bindMessage() { - attestationsViewModel.startActivity.observe(viewLifecycleOwner, Observer { - it.getContentIfNotHandled()?.let { createAtPdf -> + attestationsViewModel.startActivity.observe(viewLifecycleOwner, Observer { event -> + event.getContentIfNotHandled()?.let { createAtPdf -> val intent = Intent(context, PdfViewerActivity::class.java).apply { putExtra("createAt", createAtPdf) } diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsViewModel.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsViewModel.kt index 4d277bb..4a23ca4 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsViewModel.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/attestations/AttestationsViewModel.kt @@ -4,29 +4,20 @@ import android.view.View import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository import fr.sanchezm.attestationsCovid19.utilities.Event class AttestationsViewModel(attestationRepository: AttestationRepository) : ViewModel() { private val _startActivity = MutableLiveData>() - - private var _attestations = attestationRepository.getAttestations() as MutableLiveData> - private var _displayNoAttestation = MutableLiveData() - val attestations: LiveData> = - _attestations - - val startActivity: LiveData> = - _startActivity - - val displayNoAttestation: LiveData = - _displayNoAttestation + val attestations = attestationRepository.getAttestations() + val startActivity: LiveData> = _startActivity + val displayNoAttestation: LiveData = _displayNoAttestation init { - if (_attestations.value == null || _attestations.value?.size == 0) { + if (attestations.value == null || attestations.value?.size == 0) { _displayNoAttestation.value = View.VISIBLE } else { _displayNoAttestation.value = View.GONE diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/qrcode/QrCodeFragment.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/qrcode/QrCodeFragment.kt index a9f8afe..1c86cbe 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/qrcode/QrCodeFragment.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/qrcode/QrCodeFragment.kt @@ -1,15 +1,19 @@ package fr.sanchezm.attestationsCovid19.ui.qrcode +import android.content.Intent import android.os.Bundle -import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.databinding.DataBindingUtil +import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider +import fr.sanchezm.attestationsCovid19.PdfViewerActivity import fr.sanchezm.attestationsCovid19.R import fr.sanchezm.attestationsCovid19.databinding.QrCodeFragmentBinding import fr.sanchezm.attestationsCovid19.utilities.InjectorUtils +import kotlinx.android.synthetic.main.qr_code_fragment.* class QrCodeFragment : Fragment() { @@ -41,10 +45,11 @@ class QrCodeFragment : Fragment() { this.viewModel = qrCodeViewModel } + bindingData() + return binding.root } - private fun initializeUi(createAt: Long, toCreate: Boolean) { val factory = context?.let { InjectorUtils.provideQrCodeViewModel(it) } qrCodeViewModel = factory?.let { @@ -54,4 +59,28 @@ class QrCodeFragment : Fragment() { qrCodeViewModel.addData(createAt, toCreate) } + private fun bindingData() { + qrCodeViewModel.qrCodeBitmap.observe(viewLifecycleOwner, Observer { + qrcode_image.setImageBitmap(it) + }) + + qrCodeViewModel.finish.observe(viewLifecycleOwner, Observer { event -> + event.getContentIfNotHandled()?.let { + if (it) { + activity?.finish() + } + } + }) + + qrCodeViewModel.startActivity.observe(viewLifecycleOwner, Observer { event -> + event.getContentIfNotHandled()?.let { + val intent = Intent(context, PdfViewerActivity::class.java).apply { + putExtra("createAt", it) + putExtra("toCreate", true) + } + startActivity(intent) + } + }) + } + } diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/qrcode/QrCodeViewModel.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/qrcode/QrCodeViewModel.kt index 345a8bf..7a3e6b9 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/qrcode/QrCodeViewModel.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/qrcode/QrCodeViewModel.kt @@ -1,24 +1,85 @@ package fr.sanchezm.attestationsCovid19.ui.qrcode +import android.graphics.Bitmap +import android.view.View +import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation import fr.sanchezm.attestationsCovid19.data.repository.AttestationRepository +import fr.sanchezm.attestationsCovid19.utilities.Event +import fr.sanchezm.attestationsCovid19.utilities.QRCodeUtils class QrCodeViewModel(private val attestationRepository: AttestationRepository) : ViewModel() { private val _attestation = MutableLiveData() - private var toCreate: Boolean = false + + private val _loading = MutableLiveData(View.GONE) + private val _displayQrCode = MutableLiveData(View.GONE) + private val _qrCodeBitmap = MutableLiveData() + private val _peopleItem = MutableLiveData() + private val _dateItem = MutableLiveData() + private val _reasonItem = MutableLiveData() + + private val _startActivity = MutableLiveData>() + private val _finish = MutableLiveData>() + + val attestation: LiveData = _attestation + + val loading: LiveData = _loading + val displayQrCode: LiveData = _displayQrCode + val qrCodeBitmap: LiveData = _qrCodeBitmap + val peopleItem: LiveData = _peopleItem + val dateItem: LiveData = _dateItem + val reasonItem: LiveData = _reasonItem + + val startActivity: LiveData> = _startActivity + val finish: LiveData> = _finish fun addData(createAt: Long, toCreate: Boolean) { - this.toCreate = toCreate - _attestation.value = attestationRepository.getAttestation(createAt) + val att = attestationRepository.getAttestation(createAt) + + _attestation.value = att if (toCreate) { + _loading.value = View.VISIBLE createPdf() + } else { + displayQrCode() } } - fun createPdf() { + fun displayAttestation() { + _startActivity.value = Event(_attestation.value!!.createAt) + } + fun deleteAttestation() { + attestationRepository.deleteAttestation(_attestation.value!!) + _finish.value = Event(true) + } + + private fun createPdf() { + _attestation.value?.let { attesattion -> + attestationRepository.generateAttestation( + attesattion + ) { success -> + if (success) + displayQrCode() + } + } + } + + private fun displayQrCode() { + _qrCodeBitmap.value = _attestation.value?.let { QRCodeUtils.getQrCode(it, 300) } + + _peopleItem.value = attestation.value?.getNameFormatted() + _dateItem.value = attestation.value?.getExitDateFormatted() + _reasonItem.value = attestation.value?.getMotifsFormatted() + + _loading.value = View.GONE + _displayQrCode.value = View.VISIBLE + } + + companion object { + private val TAG = QrCodeViewModel::class.simpleName } } diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/InjectorUtils.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/InjectorUtils.kt index e75ac3d..0da4f76 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/InjectorUtils.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/InjectorUtils.kt @@ -13,23 +13,31 @@ object InjectorUtils { fun provideAddViewModelFactory(context: Context): AddViewModelFactory { val profileRepository = - ProfileRepository.getInstance(MyDatabase.invoke(context).profileDao()) + ProfileRepository.getInstance( + MyDatabase.invoke(context, getMyFilesDir(context)).profileDao() + ) val attestationRepository = - AttestationRepository.getInstance(MyDatabase.invoke(context).attestationDao()) + AttestationRepository.getInstance( + MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao() + ) return AddViewModelFactory(profileRepository, attestationRepository) } fun provideAttestationViewModel(context: Context): AttestationsViewModelFactory { val attestationRepository = - AttestationRepository.getInstance(MyDatabase.invoke(context).attestationDao()) + AttestationRepository.getInstance( + MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao() + ) return AttestationsViewModelFactory(attestationRepository) } fun provideQrCodeViewModel(context: Context): QrCodeViewModelFactory { val attestationRepository = - AttestationRepository.getInstance(MyDatabase.invoke(context).attestationDao()) + AttestationRepository.getInstance( + MyDatabase.invoke(context, getMyFilesDir(context)).attestationDao() + ) return QrCodeViewModelFactory(attestationRepository) } diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/PdfUtils.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/PdfUtils.kt index dce3eb4..4278ae2 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/PdfUtils.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/PdfUtils.kt @@ -14,8 +14,6 @@ import com.tom_roush.pdfbox.pdmodel.interactive.form.PDTextField import fr.sanchezm.attestationsCovid19.data.db.entity.Attestation import java.io.File import java.io.IOException -import java.util.* -import kotlin.collections.ArrayList class PdfUtils private constructor( @@ -23,11 +21,10 @@ class PdfUtils private constructor( private val path: String ) { - private val folderPath = "attestations" private val checkboxListNames = ArrayList() private val font = PDType1Font.HELVETICA - fun fillForm(attestation: Attestation) { + fun fillForm(attestation: Attestation, callback: (Boolean) -> Unit) { checkFolder() try { // Load the document and get the AcroForm @@ -43,12 +40,14 @@ class PdfUtils private constructor( Log.v("PdfUtils", "Save File to ${getPath(attestation.createAt)}") document.save(getPath(attestation.createAt)) document.close() + callback(true) } catch (e: IOException) { e.printStackTrace() + callback(false) } } - fun getPath(createAt: Long): String = "$path/$folderPath/$createAt.pdf" + fun getPath(createAt: Long): String = getPath(path, createAt) private fun addPageWithQrCode(document: PDDocument, attestation: Attestation) { val size = 360 @@ -100,7 +99,7 @@ class PdfUtils private constructor( contentStream.beginText() contentStream.setFont(font, 7f) contentStream.newLineAtOffset(page.mediaBox.upperRightX - size - 27, 138f) - contentStream.showText(attestation.getCreatedAtFormatedDate()) + contentStream.showText(attestation.getCreatedAtFormattedDate()) contentStream.endText() } contentStream.close() @@ -150,12 +149,16 @@ class PdfUtils private constructor( @Volatile private var instance: PdfUtils? = null private val LOCK = Any() + private const val folderPath = "attestations" fun getInstance() = instance fun getInstance(assetManager: AssetManager, path: String) = instance ?: synchronized(LOCK) { instance ?: PdfUtils(assetManager, path).also { instance = it; it.initList() } } + + fun getPath(path: String, createAt: Long): String = "$path/$folderPath/$createAt.pdf" + } private fun initList() { diff --git a/app/src/main/res/layout/qr_code_fragment.xml b/app/src/main/res/layout/qr_code_fragment.xml index 936ee0e..61fc287 100644 --- a/app/src/main/res/layout/qr_code_fragment.xml +++ b/app/src/main/res/layout/qr_code_fragment.xml @@ -1,9 +1,10 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> + @@ -15,13 +16,132 @@ android:layout_height="match_parent" tools:context=".ui.qrcode.QrCodeFragment"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bcb5e31..32ff0bc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,4 +46,10 @@ Personne : Date de sortie : Raison(s) : + + + Création de votre attesation + QrCode Attestation + Afficher l\'attestation + Supprimer l\'attestation diff --git a/build.gradle b/build.gradle index f31f8bb..84b783e 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.6.2' + classpath 'com.android.tools.build:gradle:3.6.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong