diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..312d1eb --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,43 @@ +name: Android Pull Request & main CI + +on: + pull_request: + branches: + - main + - dev + push: + branches: + - main + - dev + +jobs: + test: + name: Run Unit Tests + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Unit tests + run: bash ./gradlew test --stacktrace + + apk: + name: Generate APK + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build debug APK + run: bash ./gradlew assembleDebug --stacktrace + - name: Upload APK + uses: actions/upload-artifact@v1 + with: + name: app + path: app/build/outputs/apk/debug/app-debug.apk \ No newline at end of file diff --git a/.github/workflows/signed_release.yml b/.github/workflows/signed_release.yml new file mode 100644 index 0000000..61bcc5d --- /dev/null +++ b/.github/workflows/signed_release.yml @@ -0,0 +1,48 @@ +name: Android Release Signed + +on: + push: + branches: + - main + - dev + +jobs: + test: + name: Run Unit Tests + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Unit tests + run: bash ./gradlew test --stacktrace + + apk: + name: Generate APK + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build release APK + run: bash ./gradlew assembleRelease --stacktrace + + - uses: jobobby04/sign-android-release@v1.0.3 + with: + releaseDirectory: app/build/outputs/apk/release + signingKeyBase64: ${{ secrets.signingKeyBase64 }} + alias: ${{ secrets.alias }} + keyStorePassword: ${{ secrets.keyStorePassword }} + keyPassword: ${{ secrets.keyPassword }} + + - name: Upload APK + uses: actions/upload-artifact@v1 + with: + name: app + path: ${{ env.SIGNED_RELEASE_FILE }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index d6205cd..f8651f0 100644 --- a/.gitignore +++ b/.gitignore @@ -455,3 +455,4 @@ fabric.properties .externalNativeBuild .cxx local.properties +/app/release/output-metadata.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..4cc37c0 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Auto Attestation +<img src="https://raw.githubusercontent.com/maxisoft/AutoAttestation/dev/app/src/main/res/raw/web_hi_res_512.png" alt="logo" width="100"/> +Application Android libre pour faire une attestation simplement, sans tracker et sans internet + +## Disclaimer +- Cette application n'est **pas officielle**. +- Aucune garantie sur le fait que les données (e.g. *documents pdf*, *codes qr*) produits par cette application soient valides et/ou conformes à quoi que ça soit. +- Voir le fichier *LICENSE* pour d'autres disclaimers effectifs. + +## Fonctionalitées +- Générer une attestation en mode qrcode similaire à l'application [TousAntiCovid](https://play.google.com/store/apps/details?id=fr.gouv.android.stopcovid) +- Générer une attestation PDF similaire au site [Générateur de certificat de déplacement](https://media.interieur.gouv.fr/deplacement-covid-19/) + +## Design et philosophie +Le but principal de cette application est de pouvoir créer des attestations au moins aussi simplement que l'application [TousAntiCovid](https://play.google.com/store/apps/details?id=fr.gouv.android.stopcovid) et ce sans contenir de code directement lié à la communication réseau / pistage. +Pour ce faire l'application est conçue pour utiliser exclusivement des logiciels/librairies [FLOSS](https://fr.wikipedia.org/wiki/Free/Libre_Open_Source_Software) tout en étant elle même publiée sous licence libre. +De plus l'application ne possede pas l'autorisation de communiquer en réseau. +Enfin l'application enregistre comme information personelle le strict minimum nécessaire à son fonctionement. La totalité des informations enregistrées sont à tout moment supprimables en utilisant la fonctionalité native "Effacer données application" d'Android. + +## Captures d'écran diff --git a/app/build.gradle b/app/build.gradle index 468fc62..3d032f6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -32,6 +32,11 @@ android { kotlinOptions { jvmTarget = '1.8' } + + testOptions { + unitTests.includeAndroidResources = true + } + } dependencies { @@ -42,7 +47,10 @@ dependencies { implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' - implementation 'androidx.preference:preference:1.1.1' + implementation 'androidx.preference:preference-ktx:1.1.1' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.cardview:cardview:1.0.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' @@ -52,5 +60,7 @@ dependencies { implementation 'com.google.zxing:core:3.3.2' implementation 'com.tom_roush:pdfbox-android:1.8.10.1' implementation "com.squareup.moshi:moshi-kotlin:1.11.0" - + implementation "com.squareup.moshi:moshi-adapters:1.11.0" + implementation 'com.takisoft.preferencex:preferencex:1.1.0' + implementation 'com.takisoft.preferencex:preferencex-datetimepicker:1.1.0' } \ No newline at end of file diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json deleted file mode 100644 index 7938e36..0000000 --- a/app/release/output-metadata.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": 2, - "artifactType": { - "type": "APK", - "kind": "Directory" - }, - "applicationId": "io.github.maxisoft.autoattestation", - "variantName": "processReleaseResources", - "elements": [ - { - "type": "SINGLE", - "filters": [], - "versionCode": 1, - "versionName": "1.0", - "outputFile": "app-release.apk" - } - ] -} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2895862..da90768 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,25 +1,44 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" package="io.github.maxisoft.autoattestation"> - <uses-permission - android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> + + <uses-sdk tools:overrideLibrary="com.dr1009.app.chronodialogpreference" /> <application android:name=".Application" android:allowBackup="false" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" - android:supportsRtl="true" + android:supportsRtl="false" android:theme="@style/Theme.AutoAttestation"> + <provider + android:name="androidx.core.content.FileProvider" + android:authorities="${applicationId}.provider" + android:exported="false" + android:grantUriPermissions="true"> + + <meta-data + android:name="android.support.FILE_PROVIDER_PATHS" + android:resource="@xml/fileprovider" /> + </provider> + + <activity + android:name=".AttestationSummary" + android:screenOrientation="portrait" + android:theme="@style/Theme.AutoAttestationSummary"/> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - </application> + </manifest> \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/Application.kt b/app/src/main/java/io/github/maxisoft/autoattestation/Application.kt index 872d0cf..e16942b 100644 --- a/app/src/main/java/io/github/maxisoft/autoattestation/Application.kt +++ b/app/src/main/java/io/github/maxisoft/autoattestation/Application.kt @@ -1,7 +1,11 @@ package io.github.maxisoft.autoattestation import androidx.multidex.MultiDexApplication +import com.squareup.moshi.Moshi +import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import com.tom_roush.pdfbox.util.PDFBoxResourceLoader +import java.util.* class Application : MultiDexApplication() { @@ -9,4 +13,13 @@ class Application : MultiDexApplication() { super.onCreate() PDFBoxResourceLoader.init(this) } + + companion object { + val moshi: Moshi by lazy { + Moshi.Builder() + .add(Date::class.java, Rfc3339DateJsonAdapter()) + .addLast(KotlinJsonAdapterFactory()) + .build() + } + } } \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/AttestationSummary.kt b/app/src/main/java/io/github/maxisoft/autoattestation/AttestationSummary.kt new file mode 100644 index 0000000..25774df --- /dev/null +++ b/app/src/main/java/io/github/maxisoft/autoattestation/AttestationSummary.kt @@ -0,0 +1,130 @@ +package io.github.maxisoft.autoattestation + +import android.content.Context +import android.content.Intent +import android.graphics.Paint +import android.graphics.Point +import android.os.AsyncTask +import android.os.Bundle +import android.util.TypedValue +import android.view.View +import android.view.WindowManager +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.TextView +import androidmads.library.qrgenearator.QRGEncoder +import androidx.appcompat.app.AppCompatActivity +import com.squareup.moshi.JsonAdapter +import io.github.maxisoft.autoattestation.Application.Companion.moshi +import io.github.maxisoft.autoattestation.attestation.AttestationGenerator +import io.github.maxisoft.autoattestation.attestation.AttestationSettings +import java.lang.ref.WeakReference +import kotlin.math.min + + +class AttestationSummary : AppCompatActivity() { + private var settings: AttestationSettings? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + intent.extras?.getString("payload")?.let { + settings = adapter.fromJson(it) + } + setContentView(R.layout.activity_attestation_summary) + + settings?.let { + findViewById<ImageView>(R.id.qrcode).apply { + visibility = View.INVISIBLE + val dim = (getSystemService(WINDOW_SERVICE) as WindowManager).let { wm -> + Point().also { pt -> wm.defaultDisplay.getSize(pt) } + .let { pt -> min(pt.x, pt.y) } + } + GenQrTask(it, WeakReference(this)).execute(dim.coerceAtLeast(150)) + } + + findViewById<TextView>(R.id.qrtranscription).apply { + text = it.qrData + resizeTextToFit(this) + } + } + + findViewById<View>(R.id.backButton).apply { + setOnClickListener { + packageManager.getLaunchIntentForPackage("fr.gouv.android.stopcovid")?.let { + startActivity(it) + return@setOnClickListener + } + finish() + } + + setOnLongClickListener { + finish() + true + } + } + } + + + private fun resizeTextToFit(textView: TextView) { + val text = textView.text.toString() + + val minTextSize = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + 7f, + resources.displayMetrics + ) + + val measurePaint = Paint(textView.paint) + var width: Float = measurePaint.measureText(text) + val labelWidth: Float = textView.width.toFloat() + val maxLines: Int = textView.maxLines + + while (labelWidth > 0 && width / maxLines > labelWidth - 20) { + val textSize: Float = measurePaint.textSize + measurePaint.textSize = textSize - 1 + width = measurePaint.measureText(text) + if (textSize < minTextSize) break + } + + textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, measurePaint.textSize) + } + + private class GenQrTask( + val settings: AttestationSettings, + val imageView: WeakReference<ImageView> + ) : AsyncTask<Int, Void, QRGEncoder>() { + override fun doInBackground(vararg params: Int?): QRGEncoder { + return AttestationGenerator(settings).genQRCode(params[0]!!) + } + + override fun onPostExecute(result: QRGEncoder?) { + result?.let { + imageView.get()?.apply { + setImageBitmap(it.bitmap!!) + visibility = View.VISIBLE + invalidate() + } + } + } + + override fun onCancelled() { + imageView.get()?.apply { + visibility = View.GONE + } + } + } + + companion object { + fun create(context: Context, attestationSettings: AttestationSettings): Intent { + return Intent(context, AttestationSummary::class.java).also { + it.putExtras(Bundle().apply { + putString("payload", adapter.toJson(attestationSettings)) + }) + } + } + + private val adapter: JsonAdapter<AttestationSettings> by lazy { + moshi.adapter(AttestationSettings::class.java) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/MainActivity.kt b/app/src/main/java/io/github/maxisoft/autoattestation/MainActivity.kt index a0a9bd1..690b00a 100644 --- a/app/src/main/java/io/github/maxisoft/autoattestation/MainActivity.kt +++ b/app/src/main/java/io/github/maxisoft/autoattestation/MainActivity.kt @@ -1,27 +1,49 @@ package io.github.maxisoft.autoattestation import android.app.Activity +import android.content.ActivityNotFoundException import android.content.Intent import android.content.res.Resources +import android.net.Uri import android.os.AsyncTask +import android.os.Build import android.os.Bundle import android.os.Environment import android.util.Log +import android.util.SparseIntArray import android.view.Menu import android.view.MenuItem +import android.view.View +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.FileProvider +import androidx.core.net.toFile +import androidx.core.net.toUri +import androidx.core.util.containsKey +import androidx.core.util.set +import androidx.preference.DialogPreference import androidx.preference.EditTextPreference import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreferenceCompat -import io.github.maxisoft.autoattestation.attestation.AttestationGenerator +import com.google.android.material.snackbar.Snackbar +import com.takisoft.preferencex.DatePickerPreference +import com.takisoft.preferencex.PreferenceFragmentCompat +import com.takisoft.preferencex.TimePickerPreference +import io.github.maxisoft.autoattestation.android.AsyncTaskEzAny +import io.github.maxisoft.autoattestation.android.showAsActionFlag +import io.github.maxisoft.autoattestation.attestation.AttestationRepository import io.github.maxisoft.autoattestation.attestation.AttestationSettings import io.github.maxisoft.autoattestation.attestation.dateFormat import io.github.maxisoft.autoattestation.attestation.form.FormDataAdapterService -import io.github.maxisoft.autoattestation.attestation.timeFormat +import io.github.maxisoft.autoattestation.attestation.localTimeFormat +import io.github.maxisoft.autoattestation.attestation.task.GeneratePdfTask +import io.github.maxisoft.autoattestation.attestation.task.QuickSavePdfTask +import io.github.maxisoft.autoattestation.attestation.task.SaveAsPdfTask import java.io.File import java.io.FileOutputStream +import java.lang.ref.WeakReference import java.util.* +import kotlin.collections.ArrayDeque class MainActivity : AppCompatActivity() { @@ -29,6 +51,9 @@ class MainActivity : AppCompatActivity() { private var pendingPdf: GeneratePdfTask? = null private lateinit var settingsFragment: SettingsFragment private lateinit var formDataAdapterService: FormDataAdapterService + internal val attestationRepository: AttestationRepository by lazy { + AttestationRepository(this) + } override fun onStart() { resources.openRawResource(R.raw.form_data_adapter).use { @@ -37,160 +62,434 @@ class MainActivity : AppCompatActivity() { super.onStart() } + val content: View + get() = findViewById<View>(android.R.id.content) + + val rootView: View + get() = content.rootView + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) - if (savedInstanceState == null) { + if (savedInstanceState == null || supportFragmentManager.findFragmentByTag(SettingsFragment::class.simpleName) !is SettingsFragment) { supportFragmentManager .beginTransaction() - .replace(R.id.settings, SettingsFragment().also { settingsFragment = it }) + .replace( + R.id.settings, + SettingsFragment().also { settingsFragment = it }, + SettingsFragment::class.simpleName + ) .commit() + } else { + settingsFragment = + supportFragmentManager.findFragmentByTag(SettingsFragment::class.simpleName) as SettingsFragment } - supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setDisplayHomeAsUpEnabled(false) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { val inflater = menuInflater inflater.inflate(R.menu.mainmenu, menu) + if (menu != null) { + doUpdateActions(menu) + } return super.onCreateOptionsMenu(menu) } + private val actionVisibilityMap: SparseIntArray = SparseIntArray(8) + + private fun doUpdateActions(menu: Menu) { + + fun getOriginalVisibility(id: Int): Int { + return if (actionVisibilityMap.containsKey(id)) { + actionVisibilityMap[id] + } else { + menu.findItem(id).showAsActionFlag.also { + actionVisibilityMap[id] = it + } + } + } + + menu.findItem(R.id.action_open_prev).apply { + val original = getOriginalVisibility(itemId) + val visible = attestationRepository.hasLatestPdf + setShowAsAction(if (visible) MenuItem.SHOW_AS_ACTION_IF_ROOM else original) + } + + val actionVisibility = settingsFragment.changeCounter > 0 + + arrayOf( + R.id.action_show_qr, + R.id.action_save, + R.id.action_save_as, + R.id.action_create_shortcut + ).forEach { + val original = getOriginalVisibility(it) + menu.findItem(it).apply { + setShowAsAction(if (actionVisibility) original else MenuItem.SHOW_AS_ACTION_NEVER) + } + } + + menu.findItem(R.id.action_create_shortcut).isVisible = false // TODO remove once it's impl + } + + override fun onPrepareOptionsMenu(menu: Menu): Boolean { + doUpdateActions(menu) + return super.onPrepareOptionsMenu(menu) + } + + private fun shortcutIcon() { + val shortcutIntent = Intent(applicationContext, MainActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + } + val addIntent = Intent().apply { + putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent) + putExtra(Intent.EXTRA_SHORTCUT_NAME, "Test") + putExtra( + Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext( + applicationContext, R.drawable.ic_launcher_foreground + ) + ) + putExtra("duplicate", false) + action = "com.android.launcher.action.INSTALL_SHORTCUT" + } + applicationContext.sendBroadcast(addIntent) + } + override fun onOptionsItemSelected(item: MenuItem): Boolean { + fun checkFirstUse(continuation: () -> Unit = {}) { + if (settingsFragment.changeCounter > 0) { + continuation() + } else { + Snackbar.make( + content, + getString(R.string.please_complete_form), + Snackbar.LENGTH_SHORT + ) + .apply { + setAction(getString(R.string.ignore).capitalize(Locale.getDefault())) { continuation() } + show() + } + } + } + when (item.itemId) { R.id.action_save -> { - fun getTextPref(key: String, default: String = ""): String { - val pref = - settingsFragment.preferenceManager.findPreference<EditTextPreference>(key) - ?: error("unable to find pref with key $key") - val ret = pref.text?.trim() - return if (ret.isNullOrBlank()) default else ret - } - - val birthday = dateFormat.parse(getTextPref("birthdate")) - ?: error("unable to parse birth date") - val dateSortie = - dateFormat.parse(getTextPref("date")) ?: error("unable to parse date") - val heureSortie = - timeFormat.parse(getTextPref("hour")) ?: error("unable to parse time part") - val calendar = Calendar.getInstance().apply { - time = dateSortie - Calendar.getInstance().also { - it.time = heureSortie - arrayOf(Calendar.HOUR, Calendar.MINUTE, Calendar.SECOND).forEach { field -> - set(field, it.get(field)) + checkFirstUse { startPdfGeneration { QuickSavePdfTask(it, WeakReference(this)) } } + } + R.id.action_save_as -> { + checkFirstUse { startPdfGeneration { SaveAsPdfTask(it, WeakReference(this)) } } + } + R.id.action_show_qr -> { + checkFirstUse { + startActivity(AttestationSummary.create(this, getAttestationSettings())) + } + } + R.id.action_open_prev -> { + if (attestationRepository.hasLatestPdf) { + openPdf(attestationRepository.latestPdfFile.toUri()) + } else { + Snackbar.make(content, getString(R.string.no_pdf_found), Snackbar.LENGTH_SHORT) + .apply { + setAction(getString(R.string.generate)) { + startPdfGeneration { + QuickSavePdfTask(it, WeakReference(this@MainActivity)) + } + dismiss() + } + show() } - } } - - val reasons = formDataAdapterService.listReasons().filter { (key, _) -> - val pref = - settingsFragment.preferenceManager.findPreference<SwitchPreferenceCompat>( - key - ) - ?: throw Resources.NotFoundException("unable to find pref with key $key") - pref.isChecked - }.map { (_, reason) -> reason } - - val attestationSettings = AttestationSettings( - creationDate = Date().coerceAtMost(calendar.time), - firstName = getTextPref("firstname"), - lastName = getTextPref("lastname"), - birthDay = birthday, - lieuNaissance = getTextPref("birthplace"), - address = getTextPref("address"), - zipCode = getTextPref("zipcode"), - city = getTextPref("town"), - dateSortie = calendar.time, - reasons = reasons.toList() - ) - Log.d("Attestation", "using settings: $attestationSettings") - - pendingPdf = GeneratePdfTask(this).apply { execute(attestationSettings) } + } + R.id.action_create_shortcut -> { + shortcutIcon() } } return super.onOptionsItemSelected(item) } - private class GeneratePdfTask(private val context: MainActivity) : - AsyncTask<AttestationSettings, Void, ByteArray>() { - override fun doInBackground(vararg params: AttestationSettings?): ByteArray { - return try { - context.resources.openRawResource(R.raw.certificate).use { - AttestationGenerator(params[0]!!, context.formDataAdapterService).generate(it) + private fun <T : GeneratePdfTask> startPdfGeneration(factory: (AttestationSettings) -> T) { + pendingPdf?.let { + if (it.status != AsyncTask.Status.FINISHED) { + Log.d("Attestation", "cancelling previous pdf gen task") + it.cancel(true) + } + } + val attestationSettings = getAttestationSettings() + Log.d("Attestation", "using settings: $attestationSettings") + pendingPdf = factory(attestationSettings).apply { + execute( + attestationSettings + ) + } + } + + private fun getAttestationSettings(): AttestationSettings { + fun getTextPref(key: String, default: String = ""): String { + val pref = + settingsFragment.preferenceManager.findPreference<DialogPreference>(key) + ?: error("unable to find pref with key $key") + + val ret = when (pref) { + is EditTextPreference -> { + pref.text?.trim() + } + is DatePickerPreference -> { + dateFormat.format(pref.date!!) + } + is TimePickerPreference -> { + localTimeFormat.format(pref.time!!) + } + else -> { + "" } - } catch (e: InterruptedException) { - ByteArray(0) } + + return if (ret.isNullOrBlank()) default else ret } - override fun onPostExecute(result: ByteArray?) { - context.createFile(result) - super.onPostExecute(result) + val birthday = dateFormat.parse(getTextPref("birthday")) + ?: error("unable to parse birth date") + val leavingDate = + dateFormat.parse(getTextPref("date")) ?: error("unable to parse date") + val leavingTime = + localTimeFormat.parse(getTextPref("hour")) ?: error("unable to parse time part") + val calendar = Calendar.getInstance().apply { + time = leavingDate + Calendar.getInstance().also { + it.time = leavingTime + arrayOf( + Calendar.HOUR_OF_DAY, + Calendar.MINUTE, + Calendar.SECOND, + Calendar.MILLISECOND + ).forEach { field -> + set(field, it.get(field)) + } + } } + + Log.i("Attestation", "parsed calendar: $calendar") + + val reasons = formDataAdapterService.listReasons().filter { (key, _) -> + val pref = + settingsFragment.preferenceManager.findPreference<SwitchPreferenceCompat>( + key + ) + ?: throw Resources.NotFoundException("unable to find pref with key $key") + pref.isChecked + }.map { (_, reason) -> reason } + + + val maxCreationDate = (calendar.clone() as Calendar).apply { + val seed = listOf<Any>( + calendar, + birthday, + leavingTime, + reasons.map { it.hashCode() }.reduce { acc, reason -> acc * 31 + reason }) + .map { it.hashCode().toLong() } + .reduce { acc, it -> + 31 * acc + it + } + val minutes = Random(seed).run { + var m: Double + do { + m = nextGaussian() * 3 + 5 + } while (m.toInt() !in 1..59) + m + } + add(Calendar.SECOND, (minutes * -60).toInt()) + } + + return AttestationSettings( + creationDate = Date().coerceAtMost(maxCreationDate.time), + firstName = getTextPref("firstname"), + lastName = getTextPref("lastname"), + birthDay = birthday, + birthplace = getTextPref("birthplace"), + address = getTextPref("address"), + zipCode = getTextPref("zipcode"), + city = getTextPref("city"), + leavingDate = calendar.time, + reasons = reasons.toList() + ) } - private fun createFile(result: ByteArray?) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { - val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = "application/pdf" - putExtra(Intent.EXTRA_TITLE, "attestation.pdf") + private val bufferQueue: ArrayDeque<Pair<ByteArray, AttestationSettings>> = ArrayDeque() + + internal fun createFile(result: ByteArray, settings: AttestationSettings) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + synchronized(bufferQueue) { + bufferQueue.addLast(Pair(result, settings)) + try { + startActivityForResult(Intent(Intent.ACTION_CREATE_DOCUMENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + type = "application/pdf" + putExtra(Intent.EXTRA_TITLE, "attestation.pdf") + }, CREATE_FILE) + } catch (e: Exception) { + bufferQueue.removeLast() + throw e + } } - startActivityForResult(intent, CREATE_FILE) + } else { - try { - val target = - if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()) { - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath - } else { - getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)!!.absolutePath - } + val target = + if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()) { + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath + } else { + getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)!!.absolutePath + } + + val path = File(File(target), "/attestation.pdf") - FileOutputStream(File(File(target), "/attestation.pdf")).use { stream -> - stream.write(pendingPdf?.get()!!) + AsyncTaskEzAny { + FileOutputStream(path).use { stream -> + attestationRepository.saveInto(result, settings, stream) } - } finally { - pendingPdf = null + }.executeAndThen { + invalidateOptionsMenu() + createOpenPdfSnackbar() } } + } + + internal fun createOpenPdfSnackbar(show: Boolean = true): Snackbar { + require(attestationRepository.hasLatestPdf) + return createOpenPdfSnackbar(attestationRepository.latestPdfFile.toUri(), show) + } + + private fun createOpenPdfSnackbar(uri: Uri, show: Boolean = true): Snackbar { + return Snackbar.make(content, getString(R.string.pdf_created), Snackbar.LENGTH_LONG).also { + it.setAction(getString(R.string.open)) { runOnUiThread { openPdf(uri) } } + if (show) it.show() + } + } + + private fun openPdf(uri: Uri) { + val shareIntent = Intent(Intent.ACTION_VIEW) + var effectiveUri = uri + if (uri.scheme == "file") { + effectiveUri = FileProvider.getUriForFile( + this, + "${application.packageName}.provider", + uri.toFile() + ) + } + shareIntent.setDataAndType(effectiveUri, "application/pdf") + shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + + if (shareIntent.resolveActivity(packageManager) != null) { + startActivity(shareIntent) + } else { + openWithPdf(uri) + } + } + + private fun openWithPdf(uri: Uri) { + val target = Intent(Intent.ACTION_VIEW) + var effectiveUri = uri + if (uri.scheme == "file") { + effectiveUri = FileProvider.getUriForFile( + this, + "${application.packageName}.provider", + uri.toFile() + ) + } + target.setDataAndType(effectiveUri, "application/pdf") + target.flags = + target.flags or Intent.FLAG_ACTIVITY_NO_HISTORY or Intent.FLAG_GRANT_READ_URI_PERMISSION + val intent = Intent.createChooser(target, "Open File") + try { + startActivity(intent) + } catch (e: ActivityNotFoundException) { + Log.e("Attestation", "unable to find a pdf reader", e) + Toast.makeText(this, getString(R.string.no_pdf_reader_app), Toast.LENGTH_SHORT).show() + } } override fun onDestroy() { pendingPdf?.cancel(true) pendingPdf = null + synchronized(bufferQueue) { + bufferQueue.clear() + } super.onDestroy() } override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) { - if (requestCode == CREATE_FILE - && resultCode == Activity.RESULT_OK - ) { - try { + if (requestCode == CREATE_FILE) { + val (buff, settings) = synchronized(bufferQueue) { + bufferQueue.removeFirst() + } + if (resultCode == Activity.RESULT_OK) { resultData?.data?.also { uri -> - contentResolver.openFileDescriptor(uri, "w")?.use { - FileOutputStream(it.fileDescriptor).use { stream -> - stream.write(pendingPdf?.get()!!) + AsyncTaskEzAny { + contentResolver.openOutputStream(uri)?.use { stream -> + attestationRepository.saveInto(buff, settings, stream) } + }.executeAndThen { + invalidateOptionsMenu() + createOpenPdfSnackbar() } } - } finally { - pendingPdf = null } - } else { super.onActivityResult(requestCode, resultCode, resultData) } - - } class SettingsFragment : PreferenceFragmentCompat() { - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.root_preferences, rootKey) updateDateTimeFields() - attachDateTimeValidators() + attachValidators() + attachChangeCounter() + if (changeCounter > 0) { + scrollToPreference("date") + } + } + + internal val changeCounter: Long + get() = preferenceManager.sharedPreferences.getLong("change_counter", 0) + + private fun attachChangeCounter() { + arrayOf( + "address", + "city", + "zipcode", + "birthday", + "birthplace", + "firstname", + "lastname" + ).forEach { + findPreference<DialogPreference>(it)!!.let { pref -> + val prev = pref.onPreferenceChangeListener + pref.onPreferenceChangeListener = + Preference.OnPreferenceChangeListener { preference, newValue -> + if (prev != null && !prev.onPreferenceChange(preference, newValue)) { + false + } + else { + preferenceManager.sharedPreferences.apply { + val counter = getLong("change_counter", 0) + edit().putLong( + "change_counter", + counter + 1 + ).apply() + + if (counter <= 0) { + activity?.invalidateOptionsMenu() + } + } + true + } + } + } + } } private fun updateDateTimeFields() { @@ -199,46 +498,44 @@ class MainActivity : AppCompatActivity() { it.add(Calendar.SECOND, (rnd * -60).toInt()) } - findPreference<EditTextPreference>("date")?.apply { - val today = dateFormat.format(calendar.time) - setDefaultValue(today) - if ((text ?: "") != today) text = today + findPreference<DatePickerPreference>("date")!!.apply { + date = calendar.time + pickerDate = date } - findPreference<EditTextPreference>("hour")?.apply { - val time = timeFormat.format(calendar.time) - setDefaultValue(time) - if ((text ?: "") != time) text = time + findPreference<TimePickerPreference>("hour")!!.apply { + setDefaultValue(localTimeFormat.format(calendar.time)) + time = calendar.time + pickerTime = time } } - private fun attachDateTimeValidators() { - arrayOf("date", "birthdate").forEach { key -> - findPreference<EditTextPreference>(key)?.apply { - onPreferenceChangeListener = - Preference.OnPreferenceChangeListener { _, value -> - try { - dateFormat.parse(value.toString()) - true - } catch (e: Exception) { - // TODO warn - false + private fun attachValidators() { + arrayOf("lastname", "firstname", "birthplace", "address", "city").forEach { key -> + findPreference<DialogPreference>(key)!!.apply { + val prev = onPreferenceChangeListener + setOnPreferenceChangeListener { pref, value -> + if (prev != null && !prev.onPreferenceChange(pref, value)) false + else + value.toString().run { + isNotEmpty() && !contains("\n") && length < 255 } - } + } } } - arrayOf("hour").forEach { key -> - findPreference<EditTextPreference>(key)?.apply { - onPreferenceChangeListener = - Preference.OnPreferenceChangeListener { _, value -> - try { - timeFormat.parse(value.toString()) - true - } catch (e: Exception) { - // TODO warn - false - } + arrayOf("date", "birthday").forEach { key -> + findPreference<DatePickerPreference>(key)!!.apply { + maxDate = Calendar.getInstance().apply { + add(Calendar.YEAR, 1) + }.time + + minDate = dateFormat.parse( + when (key) { + "birthday" -> "01/01/1900" + "date" -> "01/01/2020" + else -> error("unknown key $key") } + ) } } } diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/android/AsyncTaskEz.kt b/app/src/main/java/io/github/maxisoft/autoattestation/android/AsyncTaskEz.kt new file mode 100644 index 0000000..cb51a88 --- /dev/null +++ b/app/src/main/java/io/github/maxisoft/autoattestation/android/AsyncTaskEz.kt @@ -0,0 +1,31 @@ +package io.github.maxisoft.autoattestation.android + +import android.os.AsyncTask + +open class AsyncTaskEz<Params, Progress, Result>(val background: (params: Array<out Params>) -> Result): AsyncTask<Params, Progress, Result>() { + var post: ((Result) -> Unit)? = null + + override fun onPostExecute(result: Result) { + post?.invoke(result) + } + + override fun doInBackground(vararg params: Params): Result { + return background(params) + } + + fun executeAndThen(postAction: ((Result) -> Unit)) { + require(post == null) + post = postAction + execute() + } + + fun executeAndThen(postAction: ((Result) -> Unit), vararg params: Params) { + require(post == null) + post = postAction + execute(*params) + } +} + +class AsyncTaskEzAny(background: () -> Unit): AsyncTaskEz<Any, Any, Any>({ background() } +) { +} \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/android/Extensions.kt b/app/src/main/java/io/github/maxisoft/autoattestation/android/Extensions.kt new file mode 100644 index 0000000..7be7e76 --- /dev/null +++ b/app/src/main/java/io/github/maxisoft/autoattestation/android/Extensions.kt @@ -0,0 +1,17 @@ +package io.github.maxisoft.autoattestation.android + +import android.annotation.SuppressLint +import android.view.MenuItem +import androidx.appcompat.view.menu.MenuItemImpl + +val MenuItem.showAsActionFlag: Int + @SuppressLint("RestrictedApi") + get() { + this as MenuItemImpl + return when { + requiresActionButton() -> MenuItemImpl.SHOW_AS_ACTION_ALWAYS + requestsActionButton() -> MenuItemImpl.SHOW_AS_ACTION_IF_ROOM + showsTextAsAction() -> MenuItemImpl.SHOW_AS_ACTION_WITH_TEXT + else -> MenuItemImpl.SHOW_AS_ACTION_NEVER + } + } \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationGenerator.kt b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationGenerator.kt index a50dc4d..7b70eb5 100644 --- a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationGenerator.kt +++ b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationGenerator.kt @@ -10,14 +10,12 @@ import com.tom_roush.pdfbox.pdmodel.font.PDFont import com.tom_roush.pdfbox.pdmodel.font.PDType1Font import com.tom_roush.pdfbox.pdmodel.graphics.image.LosslessFactory import com.tom_roush.pdfbox.pdmodel.graphics.image.PDImageXObject -import io.github.maxisoft.autoattestation.attestation.form.FormDataAdapterService import java.io.ByteArrayOutputStream import java.io.InputStream class AttestationGenerator( - private val settings: AttestationSettings, - private val formDataAdapterService: FormDataAdapterService + private val settings: AttestationSettings ) { fun generate(buff: InputStream): ByteArray { @@ -51,9 +49,10 @@ class AttestationGenerator( } } + // magic numbers extracted from official javascript drawText("${settings.firstName} ${settings.lastName}", 119f, 696f) drawText(settings.formattedBirthDay, 119f, 674f) - drawText(settings.lieuNaissance, 297f, 674f) + drawText(settings.birthplace, 297f, 674f) drawText("${settings.address} ${settings.zipCode} ${settings.city}", 133f, 652f) val locationSize = getIdealFontSize(settings.city, 83f, 7f, 11f) drawText(settings.city, 105f, 177f, locationSize ?: 7f) @@ -86,7 +85,7 @@ class AttestationGenerator( private fun printQRCode( pdf: PDDocument ) { - val code = GenQRCode(settings.qrData, pdf) + val code = genQRCode(settings.qrData, pdf) val page1 = pdf.pages.first() PDPageContentStream(pdf, page1, true, true, true).use { @@ -103,7 +102,11 @@ class AttestationGenerator( } } - private fun GenQRCode(payload: String, pdf: PDDocument): PDImageXObject? { + fun genQRCode(dimention: Int = 300): QRGEncoder { + return QRGEncoder(settings.qrData, null, QRGContents.Type.TEXT, dimention) + } + + private fun genQRCode(payload: String, pdf: PDDocument): PDImageXObject? { Log.d("Attestation", "encoding $payload") val qrgEncoder = QRGEncoder(payload, null, QRGContents.Type.TEXT, 300) val bitmap = qrgEncoder.bitmap!! diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationRepository.kt b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationRepository.kt new file mode 100644 index 0000000..993038f --- /dev/null +++ b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationRepository.kt @@ -0,0 +1,65 @@ +package io.github.maxisoft.autoattestation.attestation + +import android.content.Context +import android.net.Uri +import androidx.core.net.toUri +import io.github.maxisoft.autoattestation.BuildConfig +import java.io.File +import java.io.OutputStream + +class AttestationRepository(val context: Context) { + private val pdfDir: File by lazy { + context.getDir("pdf", Context.MODE_PRIVATE) + } + + val latestPdfFile: File by lazy { + File(context.cacheDir, "latest.pdf") + } + + private fun genPdfFilename(attestationSettings: AttestationSettings): File { + return File(pdfDir, datetimeFileFormat.format(attestationSettings.leavingDate) + ".pdf") + } + + val hasLatestPdf: Boolean + get() = latestPdfFile.exists() + + fun save(pdf: ByteArray, attestationSettings: AttestationSettings): Uri { + genPdfFilename(attestationSettings).let { outputFile -> + File(outputFile.parent!!).let { + if (!it.exists()) { + it.mkdirs() + } + } + + if (BuildConfig.DEBUG) { + outputFile.outputStream().use { + it.write(pdf) + } + } + + + latestPdfFile.outputStream().use { + it.write(pdf) + } + + + return outputFile.toUri() + } + } + + fun saveInto( + pdf: ByteArray, + attestationSettings: AttestationSettings, + outputStream: OutputStream, + cache: Boolean = true + ) { + + outputStream.write(pdf) + + if (cache) { + latestPdfFile.outputStream().use { + it.write(pdf) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationSettings.kt b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationSettings.kt index 50b3269..246a29d 100644 --- a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationSettings.kt +++ b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/AttestationSettings.kt @@ -8,11 +8,11 @@ data class AttestationSettings( val lastName: String, val firstName: String, val birthDay: Date, - val lieuNaissance: String, + val birthplace: String, val address: String, val zipCode: String, val city: String, - val dateSortie: Date, + val leavingDate: Date, val reasons: List<Reason> ) { @@ -23,12 +23,12 @@ data class AttestationSettings( val formattedDateSortie: String get() { - return dateFormat.format(dateSortie) + return dateFormat.format(leavingDate) } val formattedHeureSortie: String get() { - return timeFormat.format(dateSortie) + return timeFormat.format(leavingDate) } val formattedReasons: String @@ -57,7 +57,7 @@ data class AttestationSettings( append("Naissance: ") append(formattedBirthDay) append(" a ") - append(lieuNaissance) + append(birthplace) append(lineSep) append("Adresse: ") @@ -68,7 +68,7 @@ data class AttestationSettings( append(city) append(lineSep) - append("Sortie :") + append("Sortie: ") append(formattedDateSortie) append(" a ") append(formattedHeureSortie) diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/Formaters.kt b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/Formaters.kt index 10196e0..b81d7e9 100644 --- a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/Formaters.kt +++ b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/Formaters.kt @@ -8,5 +8,14 @@ val dateFormat: SimpleDateFormat by lazy { } val timeFormat: SimpleDateFormat by lazy { + SimpleDateFormat("hh:mm aa", Locale.CANADA) +} + + +val localTimeFormat: SimpleDateFormat by lazy { SimpleDateFormat("HH:mm", Locale.FRANCE) +} + +val datetimeFileFormat : SimpleDateFormat by lazy { + SimpleDateFormat("yyyy_MM_dd.HH_mm", Locale.FRANCE) } \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/form/FormDataAdapterService.kt b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/form/FormDataAdapterService.kt index efe4501..2f4ebe5 100644 --- a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/form/FormDataAdapterService.kt +++ b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/form/FormDataAdapterService.kt @@ -2,7 +2,9 @@ package io.github.maxisoft.autoattestation.attestation.form import com.squareup.moshi.JsonReader import com.squareup.moshi.Moshi +import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import io.github.maxisoft.autoattestation.Application import okio.Okio import java.io.InputStream import java.util.* @@ -26,6 +28,7 @@ class FormDataAdapterService(private val data: FormDataAdapter) { } companion object { + @JvmStatic fun createFromStream(inputStream: InputStream): FormDataAdapterService { val adapter = moshi.adapter(FormDataAdapter::class.java) JsonReader.of(Okio.buffer(Okio.source(inputStream))).use { buffer -> @@ -34,10 +37,7 @@ class FormDataAdapterService(private val data: FormDataAdapter) { } } - val moshi: Moshi by lazy { - Moshi.Builder() - .addLast(KotlinJsonAdapterFactory()) - .build() - } + val moshi: Moshi + get() = Application.moshi } } \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/task/GeneratePdfTask.kt b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/task/GeneratePdfTask.kt new file mode 100644 index 0000000..3ffc5c0 --- /dev/null +++ b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/task/GeneratePdfTask.kt @@ -0,0 +1,54 @@ +package io.github.maxisoft.autoattestation.attestation.task + +import android.os.AsyncTask +import com.google.android.material.snackbar.Snackbar +import io.github.maxisoft.autoattestation.MainActivity +import io.github.maxisoft.autoattestation.R +import io.github.maxisoft.autoattestation.attestation.AttestationGenerator +import io.github.maxisoft.autoattestation.attestation.AttestationSettings +import java.lang.ref.WeakReference + +internal abstract class GeneratePdfTask( + val settings: AttestationSettings, + private val weakcontext: WeakReference<MainActivity> +) : + AsyncTask<AttestationSettings, Void, ByteArray>() { + + protected var snackbar: Snackbar? = null + + val context: MainActivity + get() = weakcontext.get() ?: error("activity is gone") + + override fun onPreExecute() { + snackbar = + Snackbar.make(context.content, context.getString(R.string.generating_pdf), Snackbar.LENGTH_INDEFINITE) + .also { + it.setAction(context.getString(R.string.cancel)) { this.cancel(true) } + it.show() + } + } + + override fun doInBackground(vararg params: AttestationSettings?): ByteArray { + return try { + context.resources.openRawResource(R.raw.certificate).use { + AttestationGenerator(settings).generate(it) + } + } catch (e: InterruptedException) { + ByteArray(0) + } finally { + closeDialogs() + } + } + + protected fun closeDialogs() { + snackbar?.let { + if (it.isShown) it.dismiss() + } + } + + abstract override fun onPostExecute(result: ByteArray?) + + override fun onCancelled() { + closeDialogs() + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/task/QuickSavePdfTask.kt b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/task/QuickSavePdfTask.kt new file mode 100644 index 0000000..1a4fee3 --- /dev/null +++ b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/task/QuickSavePdfTask.kt @@ -0,0 +1,21 @@ +package io.github.maxisoft.autoattestation.attestation.task + +import io.github.maxisoft.autoattestation.MainActivity +import io.github.maxisoft.autoattestation.attestation.AttestationSettings +import java.lang.ref.WeakReference + +internal class QuickSavePdfTask( + settings: AttestationSettings, + weakcontext: WeakReference<MainActivity> +) : GeneratePdfTask(settings, weakcontext) { + + override fun onPostExecute(result: ByteArray?) { + result?.let { buff -> + context.attestationRepository.save(buff, settings).also { + context.createOpenPdfSnackbar() + } + } + + closeDialogs() + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/maxisoft/autoattestation/attestation/task/SaveAsPdfTask.kt b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/task/SaveAsPdfTask.kt new file mode 100644 index 0000000..5cc7943 --- /dev/null +++ b/app/src/main/java/io/github/maxisoft/autoattestation/attestation/task/SaveAsPdfTask.kt @@ -0,0 +1,18 @@ +package io.github.maxisoft.autoattestation.attestation.task + +import io.github.maxisoft.autoattestation.MainActivity +import io.github.maxisoft.autoattestation.attestation.AttestationSettings +import java.lang.ref.WeakReference + +internal class SaveAsPdfTask( + settings: AttestationSettings, + weakcontext: WeakReference<MainActivity> +) : GeneratePdfTask(settings, weakcontext) { + + override fun onPostExecute(result: ByteArray?) { + result?.let { + context.createFile(it, settings) + } + closeDialogs() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_18.png b/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_18.png new file mode 100644 index 0000000..a55469b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_24.png b/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_24.png new file mode 100644 index 0000000..190067c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_36.png b/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_36.png new file mode 100644 index 0000000..3069c75 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_48.png b/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_48.png new file mode 100644 index 0000000..0dee40c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_arrow_back_black_48.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_18.png b/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_18.png new file mode 100644 index 0000000..1ded0e1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_24.png b/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_24.png new file mode 100644 index 0000000..42d4a89 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_36.png b/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_36.png new file mode 100644 index 0000000..3f4e931 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_48.png b/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_48.png new file mode 100644 index 0000000..4f9ac0a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_arrow_back_white_48.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_18.png b/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_18.png new file mode 100644 index 0000000..400c4b2 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_24.png b/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_24.png new file mode 100644 index 0000000..d8055e0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_36.png b/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_36.png new file mode 100644 index 0000000..8907b30 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_48.png b/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_48.png new file mode 100644 index 0000000..8edc409 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_picture_as_pdf_white_48.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_18.png b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_18.png new file mode 100644 index 0000000..a0ce184 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_20.png b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_20.png new file mode 100644 index 0000000..7d7d78c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_20.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_24.png b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_24.png new file mode 100644 index 0000000..0183ae4 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_36.png b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_36.png new file mode 100644 index 0000000..717587d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_48.png b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_48.png new file mode 100644 index 0000000..5f42a51 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_qr_code_2_white_48.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_qr_code_white_18.png b/app/src/main/res/drawable-hdpi/baseline_qr_code_white_18.png new file mode 100644 index 0000000..6421669 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_qr_code_white_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_qr_code_white_24.png b/app/src/main/res/drawable-hdpi/baseline_qr_code_white_24.png new file mode 100644 index 0000000..d350a47 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_qr_code_white_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_qr_code_white_36.png b/app/src/main/res/drawable-hdpi/baseline_qr_code_white_36.png new file mode 100644 index 0000000..6483331 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_qr_code_white_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_qr_code_white_48.png b/app/src/main/res/drawable-hdpi/baseline_qr_code_white_48.png new file mode 100644 index 0000000..a1623be Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_qr_code_white_48.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_restore_page_white_18.png b/app/src/main/res/drawable-hdpi/baseline_restore_page_white_18.png new file mode 100644 index 0000000..c7760be Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_restore_page_white_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_restore_page_white_24.png b/app/src/main/res/drawable-hdpi/baseline_restore_page_white_24.png new file mode 100644 index 0000000..b6dc0af Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_restore_page_white_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_restore_page_white_36.png b/app/src/main/res/drawable-hdpi/baseline_restore_page_white_36.png new file mode 100644 index 0000000..15c9a14 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_restore_page_white_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_restore_page_white_48.png b/app/src/main/res/drawable-hdpi/baseline_restore_page_white_48.png new file mode 100644 index 0000000..794f444 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_restore_page_white_48.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_save_black_18.png b/app/src/main/res/drawable-hdpi/baseline_save_black_18.png new file mode 100644 index 0000000..dad358f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_save_black_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_save_black_24.png b/app/src/main/res/drawable-hdpi/baseline_save_black_24.png new file mode 100644 index 0000000..7b8b90b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_save_black_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_save_black_36.png b/app/src/main/res/drawable-hdpi/baseline_save_black_36.png new file mode 100644 index 0000000..f907a66 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_save_black_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_save_black_48.png b/app/src/main/res/drawable-hdpi/baseline_save_black_48.png new file mode 100644 index 0000000..5375097 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_save_black_48.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_18.png b/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_18.png new file mode 100644 index 0000000..27f4deb Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_24.png b/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_24.png new file mode 100644 index 0000000..c84896e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_36.png b/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_36.png new file mode 100644 index 0000000..c2d92e7 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_48.png b/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_48.png new file mode 100644 index 0000000..c73e1b9 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_text_snippet_black_48.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_18.png b/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_18.png new file mode 100644 index 0000000..654035a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_18.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_24.png b/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_24.png new file mode 100644 index 0000000..7e885fe Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_24.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_36.png b/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_36.png new file mode 100644 index 0000000..6a805b3 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_36.png differ diff --git a/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_48.png b/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_48.png new file mode 100644 index 0000000..16b1b91 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/baseline_text_snippet_white_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_18.png b/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_18.png new file mode 100644 index 0000000..aecb930 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_24.png b/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_24.png new file mode 100644 index 0000000..65dcd94 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_36.png b/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_36.png new file mode 100644 index 0000000..190067c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_48.png b/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_48.png new file mode 100644 index 0000000..7411bef Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_arrow_back_black_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_18.png b/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_18.png new file mode 100644 index 0000000..529c2d5 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_24.png b/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_24.png new file mode 100644 index 0000000..5d878f4 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_36.png b/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_36.png new file mode 100644 index 0000000..42d4a89 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_48.png b/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_48.png new file mode 100644 index 0000000..95cdab2 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_arrow_back_white_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_18.png b/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_18.png new file mode 100644 index 0000000..76c2820 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_24.png b/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_24.png new file mode 100644 index 0000000..f1394f5 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_36.png b/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_36.png new file mode 100644 index 0000000..d8055e0 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_48.png b/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_48.png new file mode 100644 index 0000000..0d8a46f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_picture_as_pdf_white_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_18.png b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_18.png new file mode 100644 index 0000000..72d9e9a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_20.png b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_20.png new file mode 100644 index 0000000..7c6bc50 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_20.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_24.png b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_24.png new file mode 100644 index 0000000..ccba539 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_36.png b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_36.png new file mode 100644 index 0000000..0183ae4 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_48.png b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_48.png new file mode 100644 index 0000000..41b2b3d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_qr_code_2_white_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_qr_code_white_18.png b/app/src/main/res/drawable-mdpi/baseline_qr_code_white_18.png new file mode 100644 index 0000000..e6f2e43 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_qr_code_white_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_qr_code_white_24.png b/app/src/main/res/drawable-mdpi/baseline_qr_code_white_24.png new file mode 100644 index 0000000..d2c3c8e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_qr_code_white_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_qr_code_white_36.png b/app/src/main/res/drawable-mdpi/baseline_qr_code_white_36.png new file mode 100644 index 0000000..d350a47 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_qr_code_white_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_qr_code_white_48.png b/app/src/main/res/drawable-mdpi/baseline_qr_code_white_48.png new file mode 100644 index 0000000..7429ef8 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_qr_code_white_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_restore_page_white_18.png b/app/src/main/res/drawable-mdpi/baseline_restore_page_white_18.png new file mode 100644 index 0000000..49675c1 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_restore_page_white_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_restore_page_white_24.png b/app/src/main/res/drawable-mdpi/baseline_restore_page_white_24.png new file mode 100644 index 0000000..92b3bba Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_restore_page_white_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_restore_page_white_36.png b/app/src/main/res/drawable-mdpi/baseline_restore_page_white_36.png new file mode 100644 index 0000000..b6dc0af Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_restore_page_white_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_restore_page_white_48.png b/app/src/main/res/drawable-mdpi/baseline_restore_page_white_48.png new file mode 100644 index 0000000..c658694 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_restore_page_white_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_save_black_18.png b/app/src/main/res/drawable-mdpi/baseline_save_black_18.png new file mode 100644 index 0000000..91ca3d4 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_save_black_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_save_black_24.png b/app/src/main/res/drawable-mdpi/baseline_save_black_24.png new file mode 100644 index 0000000..4f2fbf6 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_save_black_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_save_black_36.png b/app/src/main/res/drawable-mdpi/baseline_save_black_36.png new file mode 100644 index 0000000..7b8b90b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_save_black_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_save_black_48.png b/app/src/main/res/drawable-mdpi/baseline_save_black_48.png new file mode 100644 index 0000000..7c97d2f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_save_black_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_18.png b/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_18.png new file mode 100644 index 0000000..5ff4eaf Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_24.png b/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_24.png new file mode 100644 index 0000000..69bdbfd Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_36.png b/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_36.png new file mode 100644 index 0000000..c84896e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_48.png b/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_48.png new file mode 100644 index 0000000..5ec020b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_text_snippet_black_48.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_18.png b/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_18.png new file mode 100644 index 0000000..2ea8621 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_18.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_24.png b/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_24.png new file mode 100644 index 0000000..0d14ac1 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_24.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_36.png b/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_36.png new file mode 100644 index 0000000..7e885fe Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_36.png differ diff --git a/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_48.png b/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_48.png new file mode 100644 index 0000000..4132e3c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/baseline_text_snippet_white_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_18.png b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_18.png new file mode 100644 index 0000000..190067c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_24.png b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_24.png new file mode 100644 index 0000000..7411bef Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_36.png b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_36.png new file mode 100644 index 0000000..0dee40c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_48.png b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_48.png new file mode 100644 index 0000000..ababe7c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_black_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_18.png b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_18.png new file mode 100644 index 0000000..42d4a89 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_24.png b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_24.png new file mode 100644 index 0000000..95cdab2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_36.png b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_36.png new file mode 100644 index 0000000..4f9ac0a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_48.png b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_48.png new file mode 100644 index 0000000..ea1bda3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_arrow_back_white_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_18.png b/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_18.png new file mode 100644 index 0000000..d8055e0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_24.png b/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_24.png new file mode 100644 index 0000000..0d8a46f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_36.png b/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_36.png new file mode 100644 index 0000000..8edc409 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_48.png b/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_48.png new file mode 100644 index 0000000..25a7dde Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_picture_as_pdf_white_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_18.png b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_18.png new file mode 100644 index 0000000..0183ae4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_20.png b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_20.png new file mode 100644 index 0000000..bcf8c45 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_20.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_24.png b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_24.png new file mode 100644 index 0000000..41b2b3d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_36.png b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_36.png new file mode 100644 index 0000000..5f42a51 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_48.png b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_48.png new file mode 100644 index 0000000..e7aa047 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_qr_code_2_white_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_18.png b/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_18.png new file mode 100644 index 0000000..d350a47 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_24.png b/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_24.png new file mode 100644 index 0000000..7429ef8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_36.png b/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_36.png new file mode 100644 index 0000000..a1623be Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_48.png b/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_48.png new file mode 100644 index 0000000..cd31c2a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_qr_code_white_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_18.png b/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_18.png new file mode 100644 index 0000000..b6dc0af Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_24.png b/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_24.png new file mode 100644 index 0000000..c658694 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_36.png b/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_36.png new file mode 100644 index 0000000..794f444 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_48.png b/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_48.png new file mode 100644 index 0000000..53bed98 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_restore_page_white_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_save_black_18.png b/app/src/main/res/drawable-xhdpi/baseline_save_black_18.png new file mode 100644 index 0000000..7b8b90b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_save_black_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_save_black_24.png b/app/src/main/res/drawable-xhdpi/baseline_save_black_24.png new file mode 100644 index 0000000..7c97d2f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_save_black_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_save_black_36.png b/app/src/main/res/drawable-xhdpi/baseline_save_black_36.png new file mode 100644 index 0000000..5375097 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_save_black_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_save_black_48.png b/app/src/main/res/drawable-xhdpi/baseline_save_black_48.png new file mode 100644 index 0000000..9e8f393 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_save_black_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_18.png b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_18.png new file mode 100644 index 0000000..c84896e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_24.png b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_24.png new file mode 100644 index 0000000..5ec020b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_36.png b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_36.png new file mode 100644 index 0000000..c73e1b9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_48.png b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_48.png new file mode 100644 index 0000000..ffb6055 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_black_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_18.png b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_18.png new file mode 100644 index 0000000..7e885fe Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_24.png b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_24.png new file mode 100644 index 0000000..4132e3c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_36.png b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_36.png new file mode 100644 index 0000000..16b1b91 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_48.png b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_48.png new file mode 100644 index 0000000..97be1dd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/baseline_text_snippet_white_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_18.png b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_18.png new file mode 100644 index 0000000..3069c75 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_24.png b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_24.png new file mode 100644 index 0000000..0dee40c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_36.png b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_36.png new file mode 100644 index 0000000..8738b87 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_48.png b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_48.png new file mode 100644 index 0000000..f8b2870 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_black_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_18.png b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_18.png new file mode 100644 index 0000000..3f4e931 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_24.png b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_24.png new file mode 100644 index 0000000..4f9ac0a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_36.png b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_36.png new file mode 100644 index 0000000..d6e520b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_48.png b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_48.png new file mode 100644 index 0000000..0ca4231 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_arrow_back_white_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_18.png b/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_18.png new file mode 100644 index 0000000..8907b30 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_24.png b/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_24.png new file mode 100644 index 0000000..8edc409 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_36.png b/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_36.png new file mode 100644 index 0000000..79cbd5f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_48.png b/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_48.png new file mode 100644 index 0000000..972938f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_picture_as_pdf_white_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_18.png b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_18.png new file mode 100644 index 0000000..717587d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_20.png b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_20.png new file mode 100644 index 0000000..07c1405 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_20.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_24.png b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_24.png new file mode 100644 index 0000000..5f42a51 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_36.png b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_36.png new file mode 100644 index 0000000..f34a5bc Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_48.png b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_48.png new file mode 100644 index 0000000..5c10b49 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_2_white_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_18.png b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_18.png new file mode 100644 index 0000000..6483331 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_24.png b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_24.png new file mode 100644 index 0000000..a1623be Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_36.png b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_36.png new file mode 100644 index 0000000..98a45be Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_48.png b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_48.png new file mode 100644 index 0000000..d75a7c5 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_qr_code_white_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_18.png b/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_18.png new file mode 100644 index 0000000..15c9a14 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_24.png b/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_24.png new file mode 100644 index 0000000..794f444 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_36.png b/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_36.png new file mode 100644 index 0000000..6f1fce3 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_48.png b/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_48.png new file mode 100644 index 0000000..fd7ed09 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_restore_page_white_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_save_black_18.png b/app/src/main/res/drawable-xxhdpi/baseline_save_black_18.png new file mode 100644 index 0000000..f907a66 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_save_black_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_save_black_24.png b/app/src/main/res/drawable-xxhdpi/baseline_save_black_24.png new file mode 100644 index 0000000..5375097 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_save_black_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_save_black_36.png b/app/src/main/res/drawable-xxhdpi/baseline_save_black_36.png new file mode 100644 index 0000000..0b20056 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_save_black_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_save_black_48.png b/app/src/main/res/drawable-xxhdpi/baseline_save_black_48.png new file mode 100644 index 0000000..33b5a9d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_save_black_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_18.png b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_18.png new file mode 100644 index 0000000..c2d92e7 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_24.png b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_24.png new file mode 100644 index 0000000..c73e1b9 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_36.png b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_36.png new file mode 100644 index 0000000..7087378 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_48.png b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_48.png new file mode 100644 index 0000000..015c4cd Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_black_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_18.png b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_18.png new file mode 100644 index 0000000..6a805b3 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_24.png b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_24.png new file mode 100644 index 0000000..16b1b91 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_36.png b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_36.png new file mode 100644 index 0000000..06b0432 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_48.png b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_48.png new file mode 100644 index 0000000..46018e9 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/baseline_text_snippet_white_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_18.png new file mode 100644 index 0000000..0dee40c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_24.png new file mode 100644 index 0000000..ababe7c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_36.png new file mode 100644 index 0000000..f8b2870 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_48.png new file mode 100644 index 0000000..bd5d128 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_black_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_18.png new file mode 100644 index 0000000..4f9ac0a Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_24.png new file mode 100644 index 0000000..ea1bda3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_36.png new file mode 100644 index 0000000..0ca4231 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_48.png new file mode 100644 index 0000000..a0ab1cc Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_arrow_back_white_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_18.png new file mode 100644 index 0000000..8edc409 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_24.png new file mode 100644 index 0000000..25a7dde Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_36.png new file mode 100644 index 0000000..972938f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_48.png new file mode 100644 index 0000000..426e323 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_picture_as_pdf_white_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_18.png new file mode 100644 index 0000000..5f42a51 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_20.png b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_20.png new file mode 100644 index 0000000..3af0346 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_20.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_24.png new file mode 100644 index 0000000..e7aa047 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_36.png new file mode 100644 index 0000000..5c10b49 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_48.png new file mode 100644 index 0000000..8ac95a3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_2_white_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_18.png new file mode 100644 index 0000000..a1623be Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_24.png new file mode 100644 index 0000000..cd31c2a Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_36.png new file mode 100644 index 0000000..d75a7c5 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_48.png new file mode 100644 index 0000000..7b993af Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_qr_code_white_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_18.png new file mode 100644 index 0000000..794f444 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_24.png new file mode 100644 index 0000000..53bed98 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_36.png new file mode 100644 index 0000000..fd7ed09 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_48.png new file mode 100644 index 0000000..acb50f6 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_restore_page_white_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_save_black_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_save_black_18.png new file mode 100644 index 0000000..5375097 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_save_black_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_save_black_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_save_black_24.png new file mode 100644 index 0000000..9e8f393 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_save_black_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_save_black_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_save_black_36.png new file mode 100644 index 0000000..33b5a9d Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_save_black_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_save_black_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_save_black_48.png new file mode 100644 index 0000000..c1ec1d4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_save_black_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_18.png new file mode 100644 index 0000000..c73e1b9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_24.png new file mode 100644 index 0000000..ffb6055 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_36.png new file mode 100644 index 0000000..015c4cd Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_48.png new file mode 100644 index 0000000..b91cbb9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_black_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_18.png b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_18.png new file mode 100644 index 0000000..16b1b91 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_24.png b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_24.png new file mode 100644 index 0000000..97be1dd Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_36.png b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_36.png new file mode 100644 index 0000000..46018e9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_48.png b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_48.png new file mode 100644 index 0000000..81a087b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/baseline_text_snippet_white_48.png differ diff --git a/app/src/main/res/drawable/baseline_arrow_back_24.xml b/app/src/main/res/drawable/baseline_arrow_back_24.xml new file mode 100644 index 0000000..bab545a --- /dev/null +++ b/app/src/main/res/drawable/baseline_arrow_back_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/> +</vector> diff --git a/app/src/main/res/drawable/baseline_picture_as_pdf_24.xml b/app/src/main/res/drawable/baseline_picture_as_pdf_24.xml new file mode 100644 index 0000000..81f1015 --- /dev/null +++ b/app/src/main/res/drawable/baseline_picture_as_pdf_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM11.5,9.5c0,0.83 -0.67,1.5 -1.5,1.5L9,11v2L7.5,13L7.5,7L10,7c0.83,0 1.5,0.67 1.5,1.5v1zM16.5,11.5c0,0.83 -0.67,1.5 -1.5,1.5h-2.5L12.5,7L15,7c0.83,0 1.5,0.67 1.5,1.5v3zM20.5,8.5L19,8.5v1h1.5L20.5,11L19,11v2h-1.5L17.5,7h3v1.5zM9,9.5h1v-1L9,8.5v1zM4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6zM14,11.5h1v-3h-1v3z"/> +</vector> diff --git a/app/src/main/res/drawable/baseline_qr_code_24.xml b/app/src/main/res/drawable/baseline_qr_code_24.xml new file mode 100644 index 0000000..e9366bf --- /dev/null +++ b/app/src/main/res/drawable/baseline_qr_code_24.xml @@ -0,0 +1,40 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M3,11h8V3H3V11zM5,5h4v4H5V5z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M3,21h8v-8H3V21zM5,15h4v4H5V15z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M13,3v8h8V3H13zM19,9h-4V5h4V9z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M19,19h2v2h-2z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M13,13h2v2h-2z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M15,15h2v2h-2z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M13,17h2v2h-2z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M15,19h2v2h-2z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M17,17h2v2h-2z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M17,13h2v2h-2z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M19,15h2v2h-2z"/> +</vector> diff --git a/app/src/main/res/drawable/baseline_qr_code_2_24.xml b/app/src/main/res/drawable/baseline_qr_code_2_24.xml new file mode 100644 index 0000000..6918603 --- /dev/null +++ b/app/src/main/res/drawable/baseline_qr_code_2_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M15,21h-2v-2h2V21zM13,14h-2v5h2V14zM21,12h-2v4h2V12zM19,10h-2v2h2V10zM7,12H5v2h2V12zM5,10H3v2h2V10zM12,5h2V3h-2V5zM4.5,4.5v3h3v-3H4.5zM9,9H3V3h6V9zM4.5,16.5v3h3v-3H4.5zM9,21H3v-6h6V21zM16.5,4.5v3h3v-3H16.5zM21,9h-6V3h6V9zM19,19v-3l-4,0v2h2v3h4v-2H19zM17,12l-4,0v2h4V12zM13,10H7v2h2v2h2v-2h2V10zM14,9V7h-2V5h-2v4L14,9zM6.75,5.25h-1.5v1.5h1.5V5.25zM6.75,17.25h-1.5v1.5h1.5V17.25zM18.75,5.25h-1.5v1.5h1.5V5.25z"/> +</vector> diff --git a/app/src/main/res/drawable/baseline_restore_page_24.xml b/app/src/main/res/drawable/baseline_restore_page_24.xml new file mode 100644 index 0000000..f0495ca --- /dev/null +++ b/app/src/main/res/drawable/baseline_restore_page_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M14,2L6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6zM12,18c-2.05,0 -3.81,-1.24 -4.58,-3h1.71c0.63,0.9 1.68,1.5 2.87,1.5 1.93,0 3.5,-1.57 3.5,-3.5S13.93,9.5 12,9.5c-1.35,0 -2.52,0.78 -3.1,1.9l1.6,1.6h-4L6.5,9l1.3,1.3C8.69,8.92 10.23,8 12,8c2.76,0 5,2.24 5,5s-2.24,5 -5,5z"/> +</vector> diff --git a/app/src/main/res/drawable/baseline_save_24.xml b/app/src/main/res/drawable/baseline_save_24.xml new file mode 100644 index 0000000..1a8d86d --- /dev/null +++ b/app/src/main/res/drawable/baseline_save_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/> +</vector> diff --git a/app/src/main/res/drawable/baseline_text_snippet_24.xml b/app/src/main/res/drawable/baseline_text_snippet_24.xml new file mode 100644 index 0000000..074fe0f --- /dev/null +++ b/app/src/main/res/drawable/baseline_text_snippet_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M20.41,8.41l-4.83,-4.83C15.21,3.21 14.7,3 14.17,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V9.83C21,9.3 20.79,8.79 20.41,8.41zM7,7h7v2H7V7zM17,17H7v-2h10V17zM17,13H7v-2h10V13z"/> +</vector> diff --git a/app/src/main/res/font/marianne_bold.otf b/app/src/main/res/font/marianne_bold.otf new file mode 100644 index 0000000..4a051bc Binary files /dev/null and b/app/src/main/res/font/marianne_bold.otf differ diff --git a/app/src/main/res/layout/activity_attestation_summary.xml b/app/src/main/res/layout/activity_attestation_summary.xml new file mode 100644 index 0000000..7225c4d --- /dev/null +++ b/app/src/main/res/layout/activity_attestation_summary.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:isScrollContainer="false" + android:orientation="vertical" + android:fitsSystemWindows="true" + tools:context=".AttestationSummary"> + + + <FrameLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="0"> + + + <androidx.cardview.widget.CardView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:clickable="false" + android:clipToPadding="false" + android:scaleX="1.2" + android:scaleY="1.2" + android:translationY="-6dp" + app:cardCornerRadius="1dp" + app:cardElevation="4dp" + app:cardPreventCornerOverlap="false" + app:cardUseCompatPadding="true"> + + <!-- put whatever you want --> + + <ImageView + android:id="@+id/backButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="25dp" + android:layout_marginLeft="25dp" + android:layout_marginTop="4dp" + android:scaleType="fitCenter" + android:scaleX="0.8" + android:scaleY="0.8" + android:translationX="16dp" + app:srcCompat="@drawable/baseline_arrow_back_black_36" + app:tint="#5770BE" + tools:layout_editor_absoluteX="14dp" + tools:layout_editor_absoluteY="35dp" /> + </androidx.cardview.widget.CardView> + + </FrameLayout> + + <ImageView + android:id="@+id/qrcode" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_gravity="center" + android:layout_marginHorizontal="0dp" + android:layout_marginStart="4dp" + android:layout_marginLeft="4dp" + android:layout_marginTop="1dp" + android:layout_marginEnd="4dp" + android:layout_marginRight="4dp" + android:layout_weight="0.5" + android:minWidth="150dp" + android:minHeight="150dp" + android:scaleType="fitCenter" + android:scaleX="1" + android:scaleY="1" + app:srcCompat="@mipmap/ic_launcher" /> + + <TextView + android:id="@+id/qrtranscription" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginHorizontal="16dp" + android:layout_marginTop="8dp" + android:layout_marginBottom="16dp" + android:layout_weight="0.4" + android:fontFamily="@font/marianne_bold" + android:gravity="center_horizontal" + android:maxLines="8" + android:minHeight="400dp" + android:minLines="7" + android:text="@string/qr_transcription_example" + android:textColor="@color/black" + android:textIsSelectable="false" + android:textSize="18sp" + android:textStyle="bold" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/main_activity.xml b/app/src/main/res/layout/main_activity.xml index de6591a..6ccbf38 100644 --- a/app/src/main/res/layout/main_activity.xml +++ b/app/src/main/res/layout/main_activity.xml @@ -1,9 +1,12 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:orientation="vertical"> <FrameLayout android:id="@+id/settings" android:layout_width="match_parent" - android:layout_height="match_parent" /> + android:layout_height="match_parent"> + </FrameLayout> + </LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/menu/mainmenu.xml b/app/src/main/res/menu/mainmenu.xml index 8d53f8c..f97a886 100644 --- a/app/src/main/res/menu/mainmenu.xml +++ b/app/src/main/res/menu/mainmenu.xml @@ -2,10 +2,40 @@ <menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"> + + <item + android:id="@+id/action_show_qr" + android:icon="@drawable/baseline_qr_code_2_24" + android:orderInCategory="10" + android:title="@string/qr_code" + app:showAsAction="ifRoom" /> + + <item android:id="@+id/action_save" - android:icon="@android:drawable/ic_menu_save" - android:orderInCategory="100" - android:title="Save" - app:showAsAction="always" /> + android:icon="@drawable/baseline_picture_as_pdf_24" + android:orderInCategory="15" + android:title="@string/create_pdf" + app:showAsAction="ifRoom" /> + + <item + android:id="@+id/action_save_as" + android:icon="@drawable/baseline_save_24" + android:orderInCategory="20" + android:title="@string/save_pdf" + app:showAsAction="withText" /> + + <item + android:id="@+id/action_open_prev" + android:icon="@drawable/baseline_restore_page_24" + android:orderInCategory="30" + android:title="@string/open_previous_pdf" + app:showAsAction="never" /> + + <item + android:id="@+id/action_create_shortcut" + android:icon="@android:drawable/btn_star_big_on" + android:orderInCategory="40" + android:title="@string/create_shortcut" + app:showAsAction="withText" /> </menu> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index eca70cf..0000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@drawable/ic_launcher_background" /> - <foreground android:drawable="@drawable/ic_launcher_foreground" /> -</adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index eca70cf..0000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@drawable/ic_launcher_background" /> - <foreground android:drawable="@drawable/ic_launcher_foreground" /> -</adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index a571e60..1a52366 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index 61da551..c441ad3 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index c41dd28..ef6dac8 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index db5080a..caf4932 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 6dba46d..ca27024 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index da31a87..977ca39 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 15ac681..a7cd14a 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index b216f2d..de4d457 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index f25a419..484ce4f 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index e96783c..28a7ffb 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/raw/ic_launcher_circle.png b/app/src/main/res/raw/ic_launcher_circle.png new file mode 100644 index 0000000..4219dbd Binary files /dev/null and b/app/src/main/res/raw/ic_launcher_circle.png differ diff --git a/app/src/main/res/raw/web_hi_res_512.png b/app/src/main/res/raw/web_hi_res_512.png new file mode 100644 index 0000000..1a0f99d Binary files /dev/null and b/app/src/main/res/raw/web_hi_res_512.png differ diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml new file mode 100644 index 0000000..dd6e1e4 --- /dev/null +++ b/app/src/main/res/values-fr/strings.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_name">Auto Attestation</string> + <string name="title_activity_settings">Paramètres</string> + <string name="create_pdf">Créer le pdf</string> + <string name="save_pdf">Enregistrer le pdf…</string> + <string name="open_previous_pdf">Ouvrir le dernier pdf</string> + <string name="create_shortcut">Créer un racourci</string> + <string name="firstname">Prénom</string> + <string name="lastname">Nom</string> + <string name="birthday">Date de naissance</string> + <string name="birthplace">Lieu de naissance</string> + <string name="address">Adresse</string> + <string name="city">Ville</string> + <string name="leaving_date">Date de sortie</string> + <string name="leaving_hour">Heure de sortie</string> + <string name="work">Travail</string> + <string name="shopping">Achats</string> + <string name="health">Santé</string> + <string name="familly">Famille</string> + <string name="handicap">Handicap</string> + <string name="sport_and_pets">Sport / Animaux</string> + <string name="summon">Convocation</string> + <string name="mission">Mission</string> + <string name="children">Enfants</string> + <string name="please_complete_form">Veuillez completer les données</string> + <string name="ignore">Ignorer</string> + <string name="no_pdf_found">Aucun pdf trouvé</string> + <string name="generate">Générer</string> + <string name="pdf_created">Pdf crée</string> + <string name="open">Ouvrir</string> + <string name="no_pdf_reader_app">Pas de lecteur pdf trouvé</string> + <string name="generating_pdf">Generation du pdf…</string> + <string name="cancel">Annuler</string> + <string name="postal_code">Code Postal</string> + <string name="name_category">Nom</string> + <string name="birth_category">Info de naissance</string> + <string name="address_category">Adresse</string> + <string name="leaving_datetime_category">Sortie</string> + <string name="why_category">Motif de déplacement</string> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 39e4e54..7e9959d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,20 +1,43 @@ <resources> - <string name="app_name">AutoAttestation</string> + <string name="app_name">Auto Attestation</string> <!-- Settings Activity Title --> <string name="title_activity_settings">Settings</string> - - <!-- Preference Titles --> - <string name="messages_header">Messages</string> - <string name="sync_header">Sync</string> - - <!-- Messages Preferences --> - <string name="signature_title">Your signature</string> - <string name="reply_title">Default reply action</string> - - <!-- Sync Preferences --> - <string name="sync_title">Sync email periodically</string> - <string name="attachment_title">Download incoming attachments</string> - <string name="attachment_summary_on">Automatically download attachments for incoming emails - </string> - <string name="attachment_summary_off">Only download attachments when manually requested</string> + <string name="qr_code" translatable="false">Qr code</string> + <string name="create_pdf">Create a pdf file</string> + <string name="save_pdf">Save as pdf…</string> + <string name="open_previous_pdf">Open previous pdf file</string> + <string name="create_shortcut">Create a shortcut</string> + <string name="qr_transcription_example" translatable="false">Cree le 06/11/2020 a 10:38AM;\nNom: M;\nPrenom: M;\nNaissance x;\nAdresse: x;\nSortie: 06/11/2020 a 12h00 AM;\nMotifs: sport animaux</string> + <string name="firstname">First name</string> + <string name="lastname">Last name</string> + <string name="birthday">Birthday</string> + <string name="birthplace">Birthplace</string> + <string name="address">Addresse</string> + <string name="city">City</string> + <string name="leaving_date">Leaving date</string> + <string name="leaving_hour">Leaving hour</string> + <string name="work">Work</string> + <string name="shopping">Shopping</string> + <string name="health">Health</string> + <string name="familly">Familly</string> + <string name="handicap">Handicap</string> + <string name="sport_and_pets">Sport / Pets</string> + <string name="summon">Convocation</string> + <string name="mission">Mission</string> + <string name="children">Children</string> + <string name="please_complete_form">Please complete the form</string> + <string name="ignore">Ignore</string> + <string name="no_pdf_found">No pdf file found</string> + <string name="generate">Generate</string> + <string name="pdf_created">Pdf file created</string> + <string name="open">Open</string> + <string name="no_pdf_reader_app">No pdf reader app found</string> + <string name="generating_pdf">Generating a pdf file…</string> + <string name="cancel">Cancel</string> + <string name="postal_code">Postal code</string> + <string name="name_category">Name</string> + <string name="birth_category">Birth info</string> + <string name="address_category">Address</string> + <string name="leaving_datetime_category">Leaving date and time</string> + <string name="why_category">Why ?</string> </resources> \ No newline at end of file diff --git a/app/src/main/res/values/summary_themes.xml b/app/src/main/res/values/summary_themes.xml new file mode 100644 index 0000000..834972f --- /dev/null +++ b/app/src/main/res/values/summary_themes.xml @@ -0,0 +1,23 @@ +<resources xmlns:tools="http://schemas.android.com/tools"> + <!-- Base application theme. --> + <style name="Theme.AutoAttestationSummary" parent="Theme.MaterialComponents.DayNight.NoActionBar"> + + <!--<item name="android:statusBarColor" tools:targetApi="l">@android:color/transparent</item>--> + <item name="android:statusBarColor" tools:targetApi="lollipop">#5770BE</item> + <item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">false</item> + <item name="android:windowLightStatusBar" tools:targetApi="m">true</item> + <item name="android:windowTranslucentNavigation" tools:targetApi="kitkat">true</item> + <item name="appBarLayoutStyle">@style/Widget.MaterialComponents.AppBarLayout.Surface</item> + + <!-- Primary brand color. --> + <item name="colorPrimary">#5770BE</item> + <item name="colorPrimaryVariant">@color/purple_700</item> + <item name="colorOnPrimary">@color/white</item> + <!-- Secondary brand color. --> + <item name="colorSecondary">@color/teal_200</item> + <item name="colorSecondaryVariant">@color/teal_700</item> + <item name="colorOnSecondary">@color/black</item> + <!-- Status bar color. --> + <!-- Customize your theme here. --> + </style> +</resources> \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index d977771..2efb63f 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,13 +1,13 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!-- Base application theme. --> - <style name="Theme.AutoAttestation" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> + <style name="Theme.AutoAttestation" parent="Theme.AppCompat"> <!-- Primary brand color. --> - <item name="colorPrimary">@color/purple_500</item> + <item name="colorPrimary">@color/purple_200</item> <item name="colorPrimaryVariant">@color/purple_700</item> - <item name="colorOnPrimary">@color/white</item> + <item name="colorOnPrimary">@color/black</item> <!-- Secondary brand color. --> <item name="colorSecondary">@color/teal_200</item> - <item name="colorSecondaryVariant">@color/teal_700</item> + <item name="colorSecondaryVariant">@color/teal_200</item> <item name="colorOnSecondary">@color/black</item> <!-- Status bar color. --> <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> diff --git a/app/src/main/res/xml/fileprovider.xml b/app/src/main/res/xml/fileprovider.xml new file mode 100644 index 0000000..4187ff6 --- /dev/null +++ b/app/src/main/res/xml/fileprovider.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<paths xmlns:android="http://schemas.android.com/apk/res/android"> + <cache-path name="all_cache" path="."/> +</paths> \ No newline at end of file diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 9aa29ac..76ba4e3 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -1,114 +1,129 @@ -<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"> +<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:android="http://schemas.android.com/apk/res/android"> - <PreferenceCategory app:title="Nom"> - <EditTextPreference + <PreferenceCategory app:title="@string/name_category"> + <com.takisoft.preferencex.EditTextPreference + android:maxLines="1" + android:inputType="textPersonName" app:defaultValue="Dominique" app:key="firstname" - app:title="Prénom" + app:title="@string/firstname" app:useSimpleSummaryProvider="true" /> - <EditTextPreference + <com.takisoft.preferencex.EditTextPreference + android:maxLines="1" + android:inputType="textPersonName" app:defaultValue="Dupont" app:key="lastname" - app:title="Nom" + app:title="@string/lastname" app:useSimpleSummaryProvider="true" /> </PreferenceCategory> - <PreferenceCategory app:title="Info de naissance"> - <EditTextPreference - app:defaultValue="01/01/1970" - app:key="birthdate" - app:title="Date de naissance (au format jj/mm/aaaa)" - app:useSimpleSummaryProvider="true" /> - <EditTextPreference + <PreferenceCategory app:title="@string/birth_category"> + <com.takisoft.preferencex.DatePickerPreference + android:defaultValue="1/1/2000" + android:key="birthday" + android:persistent="true" + android:title="@string/birthday" /> + <com.takisoft.preferencex.EditTextPreference + android:maxLines="1" + android:inputType="textPostalAddress" app:defaultValue="Lyon" app:key="birthplace" - app:title="Lieu de naissance" + app:title="@string/birthplace" app:useSimpleSummaryProvider="true" /> </PreferenceCategory> - <PreferenceCategory app:title="Addresse"> - <EditTextPreference + <PreferenceCategory app:title="@string/address_category"> + <com.takisoft.preferencex.EditTextPreference + android:maxLines="1" + android:inputType="textPostalAddress" app:defaultValue="999 avenue de france" app:key="address" - app:title="Adresse" + app:title="@string/address" app:useSimpleSummaryProvider="true" /> - <EditTextPreference + <com.takisoft.preferencex.EditTextPreference + android:maxLines="1" + android:inputType="textPostalAddress" app:defaultValue="Paris" - app:key="town" - app:title="Ville" + app:key="city" + app:title="@string/city" app:useSimpleSummaryProvider="true" /> - <EditTextPreference + <com.takisoft.preferencex.EditTextPreference + android:maxLines="1" + android:inputType="number" app:defaultValue="75001" app:key="zipcode" - app:title="Code Postal" + app:title="@string/postal_code" app:useSimpleSummaryProvider="true" /> </PreferenceCategory> - <PreferenceCategory app:title="Sortie"> - <EditTextPreference - app:defaultValue="31/10/2020" + <PreferenceCategory app:title="@string/leaving_datetime_category"> + <com.takisoft.preferencex.DatePickerPreference + android:defaultValue="10/31/2020" + app:pref_minDate="01/01/2019" + app:pref_maxDate="01/01/2030" app:key="date" - app:title="Date de sortie" - app:useSimpleSummaryProvider="true" /> - <EditTextPreference - app:defaultValue="10:23" + app:title="@string/leaving_date" /> + <com.takisoft.preferencex.TimePickerPreference + android:defaultValue="10:23" + android:persistent="false" app:key="hour" - app:title="Heure de sortie" + app:title="@string/leaving_hour" app:useSimpleSummaryProvider="true" /> </PreferenceCategory> - <PreferenceCategory app:title="Motif de déplacement" + <PreferenceCategory app:title="@string/why_category" app:summary="certifie que mon déplacement est lié au motif suivant (cocher la case) autorisé par le décret n°2020-1310 du 29 octobre 2020 prescrivant les mesures générales nécessaires pour faire face à l'épidémie de Covid19 dans le cadre de l'état d'urgence sanitaire [1] :"> <SwitchPreferenceCompat app:key="working" app:summary="Déplacements entre le domicile et le lieu d’exercice de l’activité professionnelle ou un établissement d’enseignement ou de formation, déplacements professionnels ne pouvant être différés [2], déplacements pour un concours ou un examen." - app:title="Travail" /> + app:title="@string/work" /> <SwitchPreferenceCompat app:key="buying" app:summary="Déplacements pour effectuer des achats de fournitures nécessaires à l'activité professionnelle, des achats de première nécessité [3] dans des établissements dont les activités demeurent autorisées, le retrait de commande et les livraisons à domicile ;" - app:title="Achats" /> + app:title="@string/shopping" /> <SwitchPreferenceCompat app:key="health" app:summary="Consultations, examens et soins ne pouvant être assurés à distance et l’achat de médicaments ;" - app:title="Santé" /> + app:title="@string/health" /> <SwitchPreferenceCompat app:key="familly" app:summary="Déplacements pour motif familial impérieux, pour l'assistance aux personnes vulnérables et précaires ou la garde d'enfants ;" - app:title="Famille" /> + app:title="@string/familly" /> <SwitchPreferenceCompat app:key="handicap" app:summary="Déplacement des personnes en situation de handicap et leur accompagnant ;" - app:title="Handicap" /> + app:title="@string/handicap" /> <SwitchPreferenceCompat app:key="sport" app:summary="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 ;" app:defaultValue="true" - app:title="Sport / Animaux" /> + app:title="@string/sport_and_pets" /> <SwitchPreferenceCompat app:key="summon" app:summary="Convocation judiciaire ou administrative et pour se rendre dans un service public ;" - app:title="Convocation" /> + app:title="@string/summon" /> <SwitchPreferenceCompat app:key="mission" app:summary="Participation à des missions d'intérêt général sur demande de l'autorité administrative ;" - app:title="Mission" /> + app:title="@string/mission" /> <SwitchPreferenceCompat app:key="child" app:summary="Déplacement pour chercher les enfants à l’école et à l’occasion de leurs activités périscolaires ;" - app:title="Enfants" /> + app:title="@string/children" /> </PreferenceCategory> diff --git a/build.gradle b/build.gradle index 24d1382..df78d78 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ buildscript { repositories { google() jcenter() + maven { url 'https://jitpack.io' } } dependencies { classpath "com.android.tools.build:gradle:4.1.0" @@ -18,6 +19,7 @@ allprojects { repositories { google() jcenter() + maven { url "https://jitpack.io" } } }