Compare commits
	
		
			140 Commits
		
	
	
		
			1.1c
			...
			d31a4c4c69
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d31a4c4c69 | ||
|  | 974f8a6738 | ||
|  | 934215723b | ||
|  | 546fbb55d6 | ||
|  | e1d05ba16f | ||
|  | 0ec542ef25 | ||
|  | b9203a4659 | ||
|  | c6ca8ef754 | ||
|  | 2bc3372db1 | ||
|  | 76cbdb7832 | ||
|  | 87ea1df4cd | ||
|  | ceffc79929 | ||
|  | 0914ebe475 | ||
|  | f57bb2b935 | ||
|  | d896124765 | ||
|  | a3e06eea84 | ||
|  | 01d206fb2b | ||
|  | d6824843f0 | ||
|  | 7635266a78 | ||
|  | 3b27d27c02 | ||
|  | 571f7d60cd | ||
|  | ce23372932 | ||
|  | 1024b8f4aa | ||
|  | 73e2e20398 | ||
|  | a95c6951f2 | ||
|  | 0966aa5054 | ||
|  | 8ca461ee0a | ||
|  | 6c7b1e2675 | ||
|  | 2359fdca81 | ||
|  | 998ed5abc0 | ||
|  | e4452160f6 | ||
|  | 8e67f2d885 | ||
|  | e3943b33ff | ||
|  | e26055afe7 | ||
|  | 587607f7dc | ||
|  | 262dc08881 | ||
|  | cea9c27d57 | ||
|  | 17a6526b29 | ||
|  | a931335a2b | ||
|  | aafd4f76d6 | ||
|  | 5d464826dc | ||
|  | 6eddd15d81 | ||
|  | 6fee471dec | ||
|  | 38727a239d | ||
|  | 83e2cf733e | ||
|  | 3214d772b2 | ||
|  | 40c3f39c49 | ||
|  | 6215ffa7b6 | ||
|  | bf073da67b | ||
|  | 49fe5ca037 | ||
|  | 62f854db27 | ||
|  | aea6fa6c69 | ||
|  | 029a1fcde7 | ||
|  | 92c99bec22 | ||
|  | 663c1236a4 | ||
|  | a9582ffb05 | ||
|  | b11fb89bd9 | ||
|  | 1e6bebe853 | ||
|  | 96904bce79 | ||
|  | 08675a5fc3 | ||
|  | 019046474c | ||
|  | 0e63b6a50d | ||
|  | 608ff610d8 | ||
| a009ce0c15 | |||
|  | 1ba95c54a2 | ||
|  | 51987f54e1 | ||
|  | efb3a436c4 | ||
|  | 8a22d3b66e | ||
|  | c404d498d5 | ||
|  | 10d35956b3 | ||
|  | 1de639dc46 | ||
|  | a297988d33 | ||
|  | e788d064a5 | ||
|  | d6692b5b7c | ||
|  | 5ac4ba1d43 | ||
|  | 50573a37c4 | ||
|  | 2528b7df5d | ||
|  | e6159f6f42 | ||
|  | f2982be549 | ||
|  | 0c5f7a658f | ||
|  | 9b90057f85 | ||
|  | a9192314de | ||
|  | aa08418109 | ||
|  | 5b239ace83 | ||
|  | 555cd8ada2 | ||
|  | b188313eb9 | ||
|  | 74ea62e8cd | ||
|  | a59d79aa0e | ||
|  | e8021f37dd | ||
|  | 4e179d8698 | ||
|  | a91f8545b0 | ||
|  | 94642047fb | ||
|  | e99f615fcd | ||
|  | 3ba61e87f9 | ||
|  | b798200883 | ||
|  | 2998362518 | ||
|  | 73e3add4a8 | ||
|  | 5b43db3ebd | ||
|  | f9535fe2da | ||
|  | aa20ec5a06 | ||
|  | 917a01b2ed | ||
|  | e7f55c2be2 | ||
|  | eb765e09e7 | ||
|  | 1cf4a6bc36 | ||
|  | 7f0212fc5d | ||
|  | 413d8bd7bf | ||
|  | 931adbb4dd | ||
|  | e6b2dfe37a | ||
|  | f73f9b5acf | ||
|  | ba2d0ac024 | ||
|  | f33b4672b0 | ||
|  | b6b69587fa | ||
| 06a006c0a2 | |||
|  | 8ae38f4250 | ||
|  | 3e1252cc0a | ||
|  | e4357a66e0 | ||
|  | 21f2c0d69f | ||
|  | 340789989c | ||
|  | 2428f4e50b | ||
| f4c9eddd22 | |||
|  | 6a5e971619 | ||
|  | 5829f18908 | ||
|  | 426d94ba81 | ||
| a58d208d49 | |||
|  | 069edaf6a2 | ||
| d0aa2fbeb9 | |||
| 17c75f27bc | |||
|  | 1738664f83 | ||
|  | a5b55fe214 | ||
| 0cd90413d1 | |||
|  | 653ee1ccc1 | ||
|  | 9b6a69e227 | ||
|  | e40305b680 | ||
|  | 668e9d653f | ||
| bcfcb85121 | |||
| 49c650c8a9 | |||
|  | b5f52c7e13 | ||
|  | d81922d2c9 | ||
| 84b2c2c455 | |||
| 841c3dea24 | 
							
								
								
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -32,7 +32,7 @@ jobs: | |||||||
|           gpg -d --passphrase "${{ secrets.RELEASE_KEYSTORE_PASSWORD }}" --batch keystore.asc > app/keystore.properties |           gpg -d --passphrase "${{ secrets.RELEASE_KEYSTORE_PASSWORD }}" --batch keystore.asc > app/keystore.properties | ||||||
|           gpg -d --passphrase "${{ secrets.RELEASE_KEYSTORE_PASSWORD }}" --batch key.asc > app/key.jks |           gpg -d --passphrase "${{ secrets.RELEASE_KEYSTORE_PASSWORD }}" --batch key.asc > app/key.jks | ||||||
|  |  | ||||||
|       - uses: gradle/wrapper-validation-action@v2 |       - uses: gradle/wrapper-validation-action@v3 | ||||||
|  |  | ||||||
|       - name: create and checkout branch |       - name: create and checkout branch | ||||||
|         if: github.event_name == 'pull_request' |         if: github.event_name == 'pull_request' | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @@ -1,10 +1,10 @@ | |||||||
| <!--suppress ALL --> | <!--suppress ALL --> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| <div align="center"> | <div align="center"> | ||||||
|   <h1>Keepass Fidelity</h1> |   <h1>Keepass Fidelity</h1> | ||||||
|  |   <img width="100px" src="./metadata/en-US/images/icon.png" alt="Logo"> | ||||||
|  |    | ||||||
|   <p>A minimalist fidelity/loyalty card plugin</p> |   <p>A minimalist fidelity/loyalty card plugin</p> | ||||||
|  |    | ||||||
|   <img src="https://forthebadge.com/images/badges/built-for-android.svg" alt="Built for Android"> |   <img src="https://forthebadge.com/images/badges/built-for-android.svg" alt="Built for Android"> | ||||||
|   <img src="https://forthebadge.com/images/badges/built-with-love.svg" alt="Built with love"> |   <img src="https://forthebadge.com/images/badges/built-with-love.svg" alt="Built with love"> | ||||||
|   <br> |   <br> | ||||||
| @@ -18,9 +18,9 @@ | |||||||
| <div align="center"> | <div align="center"> | ||||||
|   <table> |   <table> | ||||||
|     <tr> |     <tr> | ||||||
|       <td style="width: 33%; height: 100px;"><img src=".github/images/launcher.jpg" alt="Launcher" style="width: 100%; height: 100%;"></td> |       <td style="width: 33%; height: 100px;"><img src="./metadata/en-US/images/phoneScreenshots/launcher.jpg" alt="Launcher" style="width: 100%; height: 100%;"></td> | ||||||
|       <td style="width: 33%; height: 100px;"><img src=".github/images/view.jpg" alt="View" style="width: 100%; height: 100%;"></td> |       <td style="width: 33%; height: 100px;"><img src="./metadata/en-US/images/phoneScreenshots/view.jpg" alt="View" style="width: 100%; height: 100%;"></td> | ||||||
|       <td style="width: 33%; height: 100px;"><img src=".github/images/edit.jpg" alt="Edit" style="width: 100%; height: 100%;"></td> |       <td style="width: 33%; height: 100px;"><img src="./metadata/en-US/images/phoneScreenshots/edit.jpg" alt="Edit" style="width: 100%; height: 100%;"></td> | ||||||
|     </tr> |     </tr> | ||||||
|   </table> |   </table> | ||||||
| </div> | </div> | ||||||
| @@ -37,6 +37,9 @@ | |||||||
| ## 📳 Installation | ## 📳 Installation | ||||||
|  |  | ||||||
| <div style="display: flex; justify-content: center; align-items: center; flex-direction: row;"> | <div style="display: flex; justify-content: center; align-items: center; flex-direction: row;"> | ||||||
|  |     <a href="https://apt.izzysoft.de/fdroid/index/apk/net.helcel.fidelity"> | ||||||
|  |         <img width="200" height="80" alt="Izzy Download" src=".github/images/izzy.png"> | ||||||
|  |     </a> | ||||||
|     <a href="https://github.com/choelzl/keepass-fidelity/releases/latest"> |     <a href="https://github.com/choelzl/keepass-fidelity/releases/latest"> | ||||||
|         <img width="200" height="84" alt="APK Download" src=".github/images/apk.png"> |         <img width="200" height="84" alt="APK Download" src=".github/images/apk.png"> | ||||||
|     </a> |     </a> | ||||||
| @@ -44,7 +47,8 @@ | |||||||
|  |  | ||||||
| ## ⚙️ Permissions | ## ⚙️ Permissions | ||||||
|  |  | ||||||
| - `CAMERA`: necessary for the scanning of barcodes | - `CAMERA`: necessary for importing barcodes from camera | ||||||
|  | - `READ_MEDIA_VISUAL_USER_SELECTED`: necessary for the importing barcode from images | ||||||
|  |  | ||||||
| ## 📝 Contribute | ## 📝 Contribute | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| plugins { | plugins { | ||||||
|     id 'com.android.application' |     id 'com.android.application' | ||||||
|     id 'org.jetbrains.kotlin.android' |     id 'org.jetbrains.kotlin.android' | ||||||
|     id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.23' |     id 'org.jetbrains.kotlin.plugin.serialization' version '2.2.0' | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -34,6 +34,7 @@ android { | |||||||
|     buildTypes { |     buildTypes { | ||||||
|         debug { |         debug { | ||||||
|             debuggable true |             debuggable true | ||||||
|  |             signingConfig = signingConfigs.getByName("release") | ||||||
|         } |         } | ||||||
|         release { |         release { | ||||||
|             minifyEnabled true |             minifyEnabled true | ||||||
| @@ -71,13 +72,13 @@ android { | |||||||
|  |  | ||||||
|  |  | ||||||
| dependencies { | dependencies { | ||||||
|     coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.4' |     coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.1.5' | ||||||
|  |  | ||||||
|     implementation 'androidx.camera:camera-lifecycle:1.3.2' |     implementation 'androidx.camera:camera-lifecycle:1.4.2' | ||||||
|     implementation 'androidx.camera:camera-view:1.3.2' |     implementation 'androidx.camera:camera-view:1.4.2' | ||||||
|     runtimeOnly 'androidx.camera:camera-camera2:1.3.2' |     runtimeOnly 'androidx.camera:camera-camera2:1.4.2' | ||||||
|  |  | ||||||
|     implementation 'com.google.code.gson:gson:2.10.1' |     implementation 'com.google.code.gson:gson:2.13.1' | ||||||
|     implementation 'com.google.android.material:material:1.11.0' |     implementation 'com.google.android.material:material:1.12.0' | ||||||
|     implementation 'com.google.zxing:core:3.5.3' |     implementation 'com.google.zxing:core:3.5.3' | ||||||
| } | } | ||||||
| @@ -1,11 +1,14 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|     xmlns:tools="http://schemas.android.com/tools" |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|     android:versionCode="5" |     android:versionCode="8" | ||||||
|     android:versionName="1.1c"> |     android:versionName="1.2c"> | ||||||
|  |  | ||||||
|     <uses-feature android:name="android.hardware.camera" /> |     <uses-feature android:name="android.hardware.camera" /> | ||||||
|  |  | ||||||
|     <uses-permission android:name="android.permission.CAMERA" /> |     <uses-permission android:name="android.permission.CAMERA" /> | ||||||
|  |     <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" /> | ||||||
|  |  | ||||||
|     <application |     <application | ||||||
|         android:icon="@mipmap/ic_launcher_round" |         android:icon="@mipmap/ic_launcher_round" | ||||||
|         android:label="@string/app_name" |         android:label="@string/app_name" | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 11 KiB | 
| @@ -31,7 +31,6 @@ class MainActivity : AppCompatActivity() { | |||||||
|  |  | ||||||
|         binding = ActMainBinding.inflate(layoutInflater) |         binding = ActMainBinding.inflate(layoutInflater) | ||||||
|         setContentView(binding.root) |         setContentView(binding.root) | ||||||
|  |  | ||||||
|         onBackPressedDispatcher.addCallback(this) { |         onBackPressedDispatcher.addCallback(this) { | ||||||
|             if (supportFragmentManager.backStackEntryCount > 0) { |             if (supportFragmentManager.backStackEntryCount > 0) { | ||||||
|                 supportFragmentManager.popBackStackImmediate() |                 supportFragmentManager.popBackStackImmediate() | ||||||
|   | |||||||
| @@ -156,6 +156,11 @@ class CreateEntry : Fragment() { | |||||||
|             } catch (e: Exception) { |             } catch (e: Exception) { | ||||||
|                 e.printStackTrace() |                 e.printStackTrace() | ||||||
|             } |             } | ||||||
|  |             if (!binding.checkboxProtected.isChecked) { | ||||||
|  |                 val r = KeepassWrapper.entryExtract(kpEntry.first) | ||||||
|  |                 CacheManager.addFidelity(r) | ||||||
|  |             } | ||||||
|  |             activity?.supportFragmentManager?.popBackStack() | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -0,0 +1,107 @@ | |||||||
|  | package net.helcel.fidelity.activity.fragment | ||||||
|  |  | ||||||
|  | import android.Manifest | ||||||
|  | import android.graphics.BitmapFactory | ||||||
|  | import android.net.Uri | ||||||
|  | import android.os.Build | ||||||
|  | import android.os.Bundle | ||||||
|  | import android.view.LayoutInflater | ||||||
|  | import android.view.View | ||||||
|  | import android.view.ViewGroup | ||||||
|  | import androidx.activity.result.PickVisualMediaRequest | ||||||
|  | import androidx.activity.result.contract.ActivityResultContracts | ||||||
|  | import androidx.fragment.app.Fragment | ||||||
|  | import net.helcel.fidelity.R | ||||||
|  | import net.helcel.fidelity.tools.BarcodeScanner | ||||||
|  | import net.helcel.fidelity.tools.ErrorToaster | ||||||
|  | import net.helcel.fidelity.tools.KeepassWrapper | ||||||
|  | import java.io.FileNotFoundException | ||||||
|  |  | ||||||
|  | class FileScanner : Fragment() { | ||||||
|  |  | ||||||
|  |     private var code: String = "" | ||||||
|  |     private var fmt: String = "" | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     private val resultPermission = | ||||||
|  |         registerForActivityResult(ActivityResultContracts.RequestPermission()) { | ||||||
|  |             resultLauncherOpenMediaPick.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     private val resultLauncherOpenMediaBase = | ||||||
|  |         registerForActivityResult(ActivityResultContracts.GetContent()) { | ||||||
|  |             loadUri(it) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     private val resultLauncherOpenMediaPick = | ||||||
|  |         registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { | ||||||
|  |             loadUri(it) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     override fun onCreateView( | ||||||
|  |         inflater: LayoutInflater, | ||||||
|  |         container: ViewGroup?, | ||||||
|  |         savedInstanceState: Bundle? | ||||||
|  |     ): View { | ||||||
|  |         println(Build.VERSION.SDK_INT) | ||||||
|  |         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { | ||||||
|  |             resultPermission.launch(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED) | ||||||
|  |         } else { | ||||||
|  |             // resultLauncherOpenMediaBase.launch("image/*") | ||||||
|  |             resultLauncherOpenMediaPick.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) | ||||||
|  |         } | ||||||
|  |         return View(context) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun startCreateEntry() { | ||||||
|  |         val createEntryFragment = CreateEntry() | ||||||
|  |         createEntryFragment.arguments = | ||||||
|  |             KeepassWrapper.bundleCreate(null, this.code, this.fmt) | ||||||
|  |         requireActivity().supportFragmentManager.beginTransaction() | ||||||
|  |             .replace(R.id.container, createEntryFragment) | ||||||
|  |             .commit() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun scannerResult(code: String?, format: String?) { | ||||||
|  |         if (!code.isNullOrEmpty() && !format.isNullOrEmpty()) { | ||||||
|  |             this.code = code | ||||||
|  |             this.fmt = format | ||||||
|  |         } | ||||||
|  |         val isDone = this.code.isNotEmpty() && this.fmt.isNotEmpty() | ||||||
|  |         requireActivity().runOnUiThread { | ||||||
|  |             if (isDone) { | ||||||
|  |                 startCreateEntry() | ||||||
|  |             } else { | ||||||
|  |                 parentFragmentManager.popBackStack() | ||||||
|  |                 ErrorToaster.nothingFound(context) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun loadUri(it: Uri?) { | ||||||
|  |         try { | ||||||
|  |             run { | ||||||
|  |                 require(it != null) | ||||||
|  |  | ||||||
|  |                 val file = requireContext().contentResolver.openInputStream(it) | ||||||
|  |                 val image = BitmapFactory.decodeStream(file) | ||||||
|  |                 BarcodeScanner.bitmapUseCase(image) { code, format -> | ||||||
|  |                     scannerResult(code, format) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } catch (e: FileNotFoundException) { | ||||||
|  |             e.printStackTrace() | ||||||
|  |             println(e.message) | ||||||
|  |             println(it) | ||||||
|  |             ErrorToaster.noPermission(context) | ||||||
|  |             parentFragmentManager.popBackStack() | ||||||
|  |         } catch (e: IllegalArgumentException) { | ||||||
|  |             ErrorToaster.nothingFound(context) | ||||||
|  |             parentFragmentManager.popBackStack() | ||||||
|  |         } catch (e: SecurityException) { | ||||||
|  |             ErrorToaster.noPermission(context) | ||||||
|  |             parentFragmentManager.popBackStack() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -49,6 +49,11 @@ class Launcher : Fragment() { | |||||||
|             startScanner() |             startScanner() | ||||||
|             hideMenuAdd() |             hideMenuAdd() | ||||||
|         } |         } | ||||||
|  |         binding.btnOpen.setOnClickListener { | ||||||
|  |             startFileScanner() | ||||||
|  |             hideMenuAdd() | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         binding.btnManual.setOnClickListener { |         binding.btnManual.setOnClickListener { | ||||||
|             startCreateEntry() |             startCreateEntry() | ||||||
| @@ -96,6 +101,10 @@ class Launcher : Fragment() { | |||||||
|         startFragment(Scanner()) |         startFragment(Scanner()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private fun startFileScanner() { | ||||||
|  |         startFragment(FileScanner()) | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private fun startCreateEntry() { |     private fun startCreateEntry() { | ||||||
|         startFragment(CreateEntry()) |         startFragment(CreateEntry()) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -2,25 +2,23 @@ package net.helcel.fidelity.activity.fragment | |||||||
|  |  | ||||||
| import android.Manifest | import android.Manifest | ||||||
| import android.content.ContentValues | import android.content.ContentValues | ||||||
| import android.content.pm.PackageManager |  | ||||||
| import android.os.Bundle | import android.os.Bundle | ||||||
| import android.util.Log | import android.util.Log | ||||||
| import android.view.LayoutInflater | import android.view.LayoutInflater | ||||||
| import android.view.View | import android.view.View | ||||||
| import android.view.ViewGroup | import android.view.ViewGroup | ||||||
|  | import androidx.activity.result.contract.ActivityResultContracts | ||||||
| import androidx.camera.core.CameraSelector | import androidx.camera.core.CameraSelector | ||||||
| import androidx.camera.core.Preview | import androidx.camera.core.Preview | ||||||
| import androidx.camera.lifecycle.ProcessCameraProvider | import androidx.camera.lifecycle.ProcessCameraProvider | ||||||
| import androidx.core.app.ActivityCompat |  | ||||||
| import androidx.core.content.ContextCompat | import androidx.core.content.ContextCompat | ||||||
| import androidx.fragment.app.Fragment | import androidx.fragment.app.Fragment | ||||||
| import net.helcel.fidelity.R | import net.helcel.fidelity.R | ||||||
| import net.helcel.fidelity.databinding.FragScannerBinding | import net.helcel.fidelity.databinding.FragScannerBinding | ||||||
| import net.helcel.fidelity.tools.BarcodeScanner.getAnalysisUseCase | import net.helcel.fidelity.tools.BarcodeScanner.analysisUseCase | ||||||
|  | import net.helcel.fidelity.tools.ErrorToaster | ||||||
| import net.helcel.fidelity.tools.KeepassWrapper | import net.helcel.fidelity.tools.KeepassWrapper | ||||||
|  |  | ||||||
| private const val CAMERA_PERMISSION_REQUEST_CODE = 1 |  | ||||||
|  |  | ||||||
| class Scanner : Fragment() { | class Scanner : Fragment() { | ||||||
|  |  | ||||||
|     private lateinit var binding: FragScannerBinding |     private lateinit var binding: FragScannerBinding | ||||||
| @@ -28,6 +26,17 @@ class Scanner : Fragment() { | |||||||
|     private var code: String = "" |     private var code: String = "" | ||||||
|     private var fmt: String = "" |     private var fmt: String = "" | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     private val resultPermissionRequest = | ||||||
|  |         registerForActivityResult(ActivityResultContracts.RequestPermission()) { | ||||||
|  |             if (it) { | ||||||
|  |                 bindCameraUseCases() | ||||||
|  |             } else { | ||||||
|  |                 parentFragmentManager.popBackStack() | ||||||
|  |                 ErrorToaster.noPermission(context) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|     override fun onCreateView( |     override fun onCreateView( | ||||||
|         inflater: LayoutInflater, |         inflater: LayoutInflater, | ||||||
|         container: ViewGroup?, |         container: ViewGroup?, | ||||||
| @@ -37,11 +46,8 @@ class Scanner : Fragment() { | |||||||
|         binding.btnScanDone.setOnClickListener { |         binding.btnScanDone.setOnClickListener { | ||||||
|             startCreateEntry() |             startCreateEntry() | ||||||
|         } |         } | ||||||
|         when (hasCameraPermission()) { |  | ||||||
|             true -> bindCameraUseCases() |  | ||||||
|             else -> requestPermission() |  | ||||||
|         } |  | ||||||
|         binding.btnScanDone.isEnabled = false |         binding.btnScanDone.isEnabled = false | ||||||
|  |         resultPermissionRequest.launch(Manifest.permission.CAMERA) | ||||||
|         return binding.root |         return binding.root | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -55,26 +61,16 @@ class Scanner : Fragment() { | |||||||
|             .commit() |             .commit() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun hasCameraPermission() = |  | ||||||
|         ActivityCompat.checkSelfPermission( |  | ||||||
|             requireContext(), |  | ||||||
|             Manifest.permission.CAMERA |  | ||||||
|         ) == PackageManager.PERMISSION_GRANTED |  | ||||||
|  |  | ||||||
|     private fun requestPermission() { |     private fun scannerResult(code: String?, format: String?) { | ||||||
|         ActivityCompat.requestPermissions( |         if (!code.isNullOrEmpty() && !format.isNullOrEmpty()) { | ||||||
|             requireActivity(), |             this.code = code | ||||||
|             arrayOf(Manifest.permission.CAMERA), |             this.fmt = format | ||||||
|             CAMERA_PERMISSION_REQUEST_CODE |  | ||||||
|         ) |  | ||||||
|         ActivityCompat.OnRequestPermissionsResultCallback { c, p, i -> |  | ||||||
|             require(c == CAMERA_PERMISSION_REQUEST_CODE) |  | ||||||
|             require(p.contains(Manifest.permission.CAMERA)) |  | ||||||
|             val el = i[p.indexOf(Manifest.permission.CAMERA)] |  | ||||||
|             if (el != PackageManager.PERMISSION_GRANTED) { |  | ||||||
|                 startCreateEntry() |  | ||||||
|         } |         } | ||||||
|  |         val isDone = this.code.isNotEmpty() && this.fmt.isNotEmpty() | ||||||
|  |         activity?.runOnUiThread { | ||||||
|  |             binding.btnScanDone.isEnabled = isDone | ||||||
|  |             binding.ScanActive.isEnabled = !isDone | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -89,16 +85,8 @@ class Scanner : Fragment() { | |||||||
|                     it.setSurfaceProvider(binding.cameraView.surfaceProvider) |                     it.setSurfaceProvider(binding.cameraView.surfaceProvider) | ||||||
|                 } |                 } | ||||||
|             val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA |             val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA | ||||||
|             val analysisUseCase = getAnalysisUseCase { code, format -> |             val analysisUseCase = analysisUseCase { code, format -> | ||||||
|                 if (!code.isNullOrEmpty() && !format.isNullOrEmpty()) { |                 scannerResult(code, format) | ||||||
|                     this.code = code |  | ||||||
|                     this.fmt = format |  | ||||||
|                 } |  | ||||||
|                 val isDone = this.code.isNotEmpty() && this.fmt.isNotEmpty() |  | ||||||
|                 requireActivity().runOnUiThread { |  | ||||||
|                     binding.btnScanDone.isEnabled = isDone |  | ||||||
|                     binding.ScanActive.isEnabled = !isDone |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             try { |             try { | ||||||
|                 cameraProvider.bindToLifecycle( |                 cameraProvider.bindToLifecycle( | ||||||
|   | |||||||
| @@ -80,7 +80,7 @@ class ViewEntry : Fragment() { | |||||||
|         return (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) |         return (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun setScreenBrightness(brightness: Float?) { |     private fun setScreenBrightness(brightness: Float) { | ||||||
|         requireActivity().window?.attributes?.screenBrightness = brightness |         requireActivity().window?.attributes?.screenBrightness = brightness | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -7,15 +7,15 @@ import org.json.JSONObject | |||||||
| object Kp2aControl { | object Kp2aControl { | ||||||
|  |  | ||||||
|     fun getAddEntryIntent( |     fun getAddEntryIntent( | ||||||
|         fields: HashMap<String?, String?>, |         fields: HashMap<String, String>, | ||||||
|         protectedFields: ArrayList<String?>? |         protectedFields: ArrayList<String>? | ||||||
|     ): Intent { |     ): Intent { | ||||||
|         val outputData = JSONObject((fields as Map<*, *>)).toString() |         val outputData = JSONObject((fields as Map<*, *>)).toString() | ||||||
|         val startKp2aIntent = Intent(Strings.ACTION_START_WITH_TASK) |         val startKp2aIntent = Intent(Strings.ACTION_START_WITH_TASK) | ||||||
|         startKp2aIntent.addCategory(Intent.CATEGORY_DEFAULT) |         startKp2aIntent.addCategory(Intent.CATEGORY_DEFAULT) | ||||||
|         startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) |         startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) | ||||||
|         startKp2aIntent.putExtra("KP2A_APPTASK", "CreateEntryThenCloseTask") |         startKp2aIntent.putExtra("KP2A_APPTASK", "CreateEntryThenCloseTask") | ||||||
|         startKp2aIntent.putExtra("ShowUserNotifications", "false") |         startKp2aIntent.putExtra("ShowUserNotifications", "true") | ||||||
|         startKp2aIntent.putExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA, outputData) |         startKp2aIntent.putExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA, outputData) | ||||||
|         if (protectedFields != null) |         if (protectedFields != null) | ||||||
|             startKp2aIntent.putStringArrayListExtra( |             startKp2aIntent.putStringArrayListExtra( | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ object Strings { | |||||||
|     const val SCOPE_CURRENT_ENTRY = "keepass2android.SCOPE_CURRENT_ENTRY" |     const val SCOPE_CURRENT_ENTRY = "keepass2android.SCOPE_CURRENT_ENTRY" | ||||||
|     const val SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE = |     const val SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE = | ||||||
|         "keepass2android.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE" |         "keepass2android.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE" | ||||||
|  |     const val SCOPE_QUERY_CREDENTIALS = "keepass2android.SCOPE_QUERY_CREDENTIALS" | ||||||
|  |  | ||||||
|     const val EXTRA_SCOPES = "keepass2android.EXTRA_SCOPES" |     const val EXTRA_SCOPES = "keepass2android.EXTRA_SCOPES" | ||||||
|     const val EXTRA_PLUGIN_PACKAGE = "keepass2android.EXTRA_PLUGIN_PACKAGE" |     const val EXTRA_PLUGIN_PACKAGE = "keepass2android.EXTRA_PLUGIN_PACKAGE" | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ import android.graphics.Bitmap | |||||||
| import androidx.annotation.OptIn | import androidx.annotation.OptIn | ||||||
| import androidx.camera.core.ExperimentalGetImage | import androidx.camera.core.ExperimentalGetImage | ||||||
| import androidx.camera.core.ImageAnalysis | import androidx.camera.core.ImageAnalysis | ||||||
| import androidx.camera.core.ImageProxy |  | ||||||
| import com.google.zxing.BinaryBitmap | import com.google.zxing.BinaryBitmap | ||||||
| import com.google.zxing.MultiFormatReader | import com.google.zxing.MultiFormatReader | ||||||
| import com.google.zxing.NotFoundException | import com.google.zxing.NotFoundException | ||||||
| @@ -15,14 +14,13 @@ import net.helcel.fidelity.tools.BarcodeFormatConverter.formatToString | |||||||
| import java.util.concurrent.Executors | import java.util.concurrent.Executors | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @OptIn(ExperimentalGetImage::class) | ||||||
| object BarcodeScanner { | object BarcodeScanner { | ||||||
|  |  | ||||||
|     @OptIn(ExperimentalGetImage::class) |     private fun processImage( | ||||||
|     private fun processImageProxy( |         bitmap: Bitmap, | ||||||
|         imageProxy: ImageProxy, |  | ||||||
|         cb: (String?, String?) -> Unit |         cb: (String?, String?) -> Unit | ||||||
|     ) { |     ) { | ||||||
|         val bitmap = imageProxy.toBitmap() // Convert ImageProxy to Bitmap |  | ||||||
|         val binaryBitmap = createBinaryBitmap(bitmap) |         val binaryBitmap = createBinaryBitmap(bitmap) | ||||||
|         val reader = MultiFormatReader() |         val reader = MultiFormatReader() | ||||||
|         try { |         try { | ||||||
| @@ -32,8 +30,6 @@ object BarcodeScanner { | |||||||
|             cb(null, null) |             cb(null, null) | ||||||
|         } catch (e: ReaderException) { |         } catch (e: ReaderException) { | ||||||
|             cb(null, null) |             cb(null, null) | ||||||
|         } finally { |  | ||||||
|             imageProxy.close() |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -45,13 +41,21 @@ object BarcodeScanner { | |||||||
|         return BinaryBitmap(HybridBinarizer(source)) |         return BinaryBitmap(HybridBinarizer(source)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fun getAnalysisUseCase(cb: (String?, String?) -> Unit): ImageAnalysis { |     fun analysisUseCase(cb: (String?, String?) -> Unit): ImageAnalysis { | ||||||
|         val analysisUseCase = ImageAnalysis.Builder().build() |         val analysisUseCase = ImageAnalysis.Builder().build() | ||||||
|         analysisUseCase.setAnalyzer( |         analysisUseCase.setAnalyzer( | ||||||
|             Executors.newSingleThreadExecutor() |             Executors.newSingleThreadExecutor() | ||||||
|         ) { imageProxy -> |         ) { imageProxy -> | ||||||
|             processImageProxy(imageProxy, cb) |             val bitmap = imageProxy.toBitmap() | ||||||
|  |             imageProxy.close() | ||||||
|  |             bitmapUseCase(bitmap, cb) | ||||||
|         } |         } | ||||||
|         return analysisUseCase |         return analysisUseCase | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fun bitmapUseCase(bitmap: Bitmap, cb: (String?, String?) -> Unit) { | ||||||
|  |         processImage(bitmap, cb) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -20,4 +20,12 @@ object ErrorToaster { | |||||||
|     fun invalidFormat(activity: Context?) { |     fun invalidFormat(activity: Context?) { | ||||||
|         helper(activity, "Invalid Format", Toast.LENGTH_SHORT) |         helper(activity, "Invalid Format", Toast.LENGTH_SHORT) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fun nothingFound(activity: Context?) { | ||||||
|  |         helper(activity, "Nothing Found", Toast.LENGTH_SHORT) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun noPermission(activity: Context?) { | ||||||
|  |         helper(activity, "Missing Permission", Toast.LENGTH_LONG) | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,10 +21,10 @@ object KeepassWrapper { | |||||||
|         code: String, |         code: String, | ||||||
|         format: String, |         format: String, | ||||||
|         protectCode: Boolean, |         protectCode: Boolean, | ||||||
|     ): Pair<HashMap<String?, String?>, ArrayList<String?>> { |     ): Pair<HashMap<String, String>, ArrayList<String>> { | ||||||
|  |  | ||||||
|         val fields = HashMap<String?, String?>() |         val fields = HashMap<String, String>() | ||||||
|         val protected = ArrayList<String?>() |         val protected = ArrayList<String>() | ||||||
|         fields[KeepassDef.TitleField] = title |         fields[KeepassDef.TitleField] = title | ||||||
|         fields[KeepassDef.UrlField] = |         fields[KeepassDef.UrlField] = | ||||||
|             "androidapp://" + fragment.requireActivity().packageName |             "androidapp://" + fragment.requireActivity().packageName | ||||||
|   | |||||||
| @@ -1,5 +1,58 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|     <background android:drawable="@color/ic_launcher_background" /> |     android:width="108dp" | ||||||
|     <foreground android:drawable="@drawable/logo_g"/> |     android:height="108dp" | ||||||
| </adaptive-icon> |     android:viewportWidth="128" | ||||||
|  |     android:viewportHeight="128"> | ||||||
|  |   <group android:scaleX="1.2833333" | ||||||
|  |       android:scaleY="1.2833333" | ||||||
|  |       android:translateX="-16.612345" | ||||||
|  |       android:translateY="-16.612345"> | ||||||
|  |       <group | ||||||
|  |           android:translateX="34" | ||||||
|  |           android:translateY="26"> | ||||||
|  |           <group | ||||||
|  |               android:scaleX="0.8" | ||||||
|  |               android:scaleY="1.0" | ||||||
|  |               android:translateX="0" | ||||||
|  |               android:translateY="0"> | ||||||
|  |               <path | ||||||
|  |                   android:fillColor="@color/blue" | ||||||
|  |                   android:pathData="M59.959,52.794H12.041c-0.552,0 -1,-0.448 -1,-1v-29.547c0,-0.552 0.448,-1 1,-1h47.918c0.552,0 1,0.448 1,1v29.547C60.959,52.347 60.511,52.794 59.959,52.794z" | ||||||
|  |                   android:strokeWidth="2" | ||||||
|  |                   android:strokeColor="#000000" /> | ||||||
|  |           </group> | ||||||
|  |           <group | ||||||
|  |               android:scaleX="0.4" | ||||||
|  |               android:scaleY="0.5" | ||||||
|  |               android:translateX="27" | ||||||
|  |               android:translateY="15.75"> | ||||||
|  |               <path | ||||||
|  |                   android:fillColor="@color/red" | ||||||
|  |                   android:pathData="M46.5,56l-10,-11l-10,11l0,-45l20,0z" | ||||||
|  |                   android:strokeLineCap="round" | ||||||
|  |                   android:strokeLineJoin="round" /> | ||||||
|  |               <path | ||||||
|  |                   android:fillColor="@color/red2" | ||||||
|  |                   android:fillAlpha="1.0" | ||||||
|  |                   android:pathData="M41.5,11l0,39l5,6l0,-45z" | ||||||
|  |                   android:strokeColor="#00000000" /> | ||||||
|  |  | ||||||
|  |           </group> | ||||||
|  |           <group | ||||||
|  |               android:scaleX="0.75" | ||||||
|  |               android:scaleY="0.75" | ||||||
|  |               android:translateX="6" | ||||||
|  |               android:translateY="10"> | ||||||
|  |               <path | ||||||
|  |                   android:fillColor="#00000000" | ||||||
|  |                   android:pathData="M9,21V52 M12,21V52 M20,21V50 M28,21V50 M15,50V21H17V50H15 M23,50V21H25V50H23 M31,50V21H32V50H31 M35,21V52 M38,21V52" | ||||||
|  |                   android:strokeWidth="2" | ||||||
|  |                   android:strokeColor="#000" | ||||||
|  |                   android:strokeLineCap="round" | ||||||
|  |                   android:strokeLineJoin="round" /> | ||||||
|  |           </group> | ||||||
|  |  | ||||||
|  |       </group> | ||||||
|  |   </group> | ||||||
|  | </vector> | ||||||
| @@ -1,30 +0,0 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> |  | ||||||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |  | ||||||
|     <item |  | ||||||
|         android:width="256dp" |  | ||||||
|         android:height="256dp" |  | ||||||
|         android:viewportWidth="256" |  | ||||||
|         android:viewportHeight="256" |  | ||||||
|         android:gravity="center" |  | ||||||
|         > |  | ||||||
|     <layer-list> |  | ||||||
|     <item |  | ||||||
|         android:width="128dp" |  | ||||||
|         android:height="128dp" |  | ||||||
|         android:gravity="center" |  | ||||||
|         android:drawable="@drawable/card" /> |  | ||||||
|     <item |  | ||||||
|         android:width="64dp" |  | ||||||
|         android:height="64dp" |  | ||||||
|         android:drawable="@drawable/barcode" |  | ||||||
|         android:gravity="center" |  | ||||||
|         android:right="32dp" /> |  | ||||||
|     <item |  | ||||||
|         android:width="52dp" |  | ||||||
|         android:height="52dp" |  | ||||||
|         android:drawable="@drawable/bookmark" |  | ||||||
|         android:gravity="center" |  | ||||||
|         android:left="72dp" |  | ||||||
|         android:bottom="20dp" /> |  | ||||||
|     </layer-list></item> |  | ||||||
| </layer-list> |  | ||||||
| @@ -1,167 +1,53 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|     android:width="108dp" |     android:width="200dp" | ||||||
|     android:height="108dp" |     android:height="200dp" | ||||||
|     android:viewportWidth="128" |     android:viewportWidth="128" | ||||||
|     android:viewportHeight="128"> |     android:viewportHeight="128"> | ||||||
|     <group |     <group | ||||||
|         android:translateX="28" |         android:translateX="34" | ||||||
|         android:translateY="28"> |         android:translateY="26"> | ||||||
|         <group> |         <group | ||||||
|  |             android:scaleX="0.8" | ||||||
|  |             android:scaleY="1.0" | ||||||
|  |             android:translateX="0" | ||||||
|  |             android:translateY="0"> | ||||||
|             <path |             <path | ||||||
|                 android:fillColor="#92D3F5" |                 android:fillColor="@color/blue" | ||||||
|                 android:pathData="M59.959,52.794H12.041c-0.552,0 -1,-0.448 -1,-1v-29.547c0,-0.552 0.448,-1 1,-1h47.918c0.552,0 1,0.448 1,1v29.547C60.959,52.347 60.511,52.794 59.959,52.794z" |                 android:pathData="M59.959,52.794H12.041c-0.552,0 -1,-0.448 -1,-1v-29.547c0,-0.552 0.448,-1 1,-1h47.918c0.552,0 1,0.448 1,1v29.547C60.959,52.347 60.511,52.794 59.959,52.794z" | ||||||
|                 android:strokeWidth="2" |                 android:strokeWidth="2" | ||||||
|                 android:strokeColor="#000000" /> |                 android:strokeColor="#000000" /> | ||||||
|         </group> |         </group> | ||||||
|         <group |         <group | ||||||
|             android:scaleX="0.5" |             android:scaleX="0.4" | ||||||
|             android:scaleY="0.5" |             android:scaleY="0.5" | ||||||
|             android:translateX="32" |             android:translateX="27" | ||||||
|             android:translateY="16"> |             android:translateY="15.75"> | ||||||
|             <path |             <path | ||||||
|                 android:fillColor="#EA5A47" |                 android:fillColor="@color/red" | ||||||
|                 android:pathData="M46.5,56l-10,-11.151l-10,11.151l0,-45.042l20,0z" |                 android:pathData="M46.5,56l-10,-11l-10,11l0,-45l20,0z" | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#00000000" |  | ||||||
|                 android:strokeLineCap="round" |                 android:strokeLineCap="round" | ||||||
|                 android:strokeLineJoin="round" /> |                 android:strokeLineJoin="round" /> | ||||||
|             <path |             <path | ||||||
|                 android:fillColor="#D22F27" |                 android:fillColor="@color/red2" | ||||||
|                 android:pathData="M41.864,12.03l0,37.854l4.523,5.044l0,-42.898z" |                 android:fillAlpha="1.0" | ||||||
|  |                 android:pathData="M41.5,11l0,39l5,6l0,-45z" | ||||||
|                 android:strokeColor="#00000000" /> |                 android:strokeColor="#00000000" /> | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M46.5,56l-10,-11.151l-10,11.151l0,-45.042l20,0z" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M46.5,56l-10,-11.151l-10,11.151l0,-45.042l20,0z" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|         </group> |         </group> | ||||||
|         <group |         <group | ||||||
|             android:scaleX="0.5" |             android:scaleX="0.75" | ||||||
|             android:scaleY="0.5" |             android:scaleY="0.75" | ||||||
|             android:translateX="10" |             android:translateX="6" | ||||||
|             android:translateY="18"> |             android:translateY="10"> | ||||||
|             <path |             <path | ||||||
|                 android:fillColor="#00000000" |                 android:fillColor="#00000000" | ||||||
|                 android:pathData="M9,21V52" |                 android:pathData="M9,21V52 M12,21V52 M20,21V50 M28,21V50 M15,50V21H17V50H15 M23,50V21H25V50H23 M31,50V21H32V50H31 M35,21V52 M38,21V52" | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M12,21V52" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M20,21V50" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M28,21V50" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#000" |  | ||||||
|                 android:pathData="M15,50V21H17V50H15Z" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#000" |  | ||||||
|                 android:pathData="M23,50V21H25V50H23Z" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#000" |  | ||||||
|                 android:pathData="M31,50V21H32V50H31Z" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M46,21V50" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M49,21V50" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M57,21V50" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#000" |  | ||||||
|                 android:pathData="M41,50V21H43V50H41Z" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#000" |  | ||||||
|                 android:pathData="M52,50V21H54V50H52Z" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M60,21V52" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M63,21V52" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M35,21V52" |  | ||||||
|                 android:strokeWidth="2" |  | ||||||
|                 android:strokeColor="#000" |  | ||||||
|                 android:strokeLineCap="round" |  | ||||||
|                 android:strokeLineJoin="round" /> |  | ||||||
|             <path |  | ||||||
|                 android:fillColor="#00000000" |  | ||||||
|                 android:pathData="M38,21V52" |  | ||||||
|                 android:strokeWidth="2" |                 android:strokeWidth="2" | ||||||
|                 android:strokeColor="#000" |                 android:strokeColor="#000" | ||||||
|                 android:strokeLineCap="round" |                 android:strokeLineCap="round" | ||||||
|                 android:strokeLineJoin="round" /> |                 android:strokeLineJoin="round" /> | ||||||
|         </group> |         </group> | ||||||
|  |  | ||||||
|     </group> |     </group> | ||||||
| </vector> | </vector> | ||||||
							
								
								
									
										22
									
								
								app/src/main/res/drawable/open.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,22 @@ | |||||||
|  | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     android:width="72dp" | ||||||
|  |     android:height="72dp" | ||||||
|  |     android:viewportWidth="58" | ||||||
|  |     android:viewportHeight="58"> | ||||||
|  |   <group android:translateX="-10" android:translateY="-8"> | ||||||
|  |   <path | ||||||
|  |       android:pathData="m57.008,20.304v-3.356l-27.338,-0.002c-0.198,0 -0.359,-0.165 -0.359,-0.368l-0.069,-1.517c-0.116,-1.788 -1.34,-3.003 -2.997,-3.003h-11.287c-1.657,0 -3,1.343 -3,3v40.943" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="m17.027,55.568c-0.59,1.954 -2.972,4.139 -4.646,4.394l44.665,0.011c1.657,0 2.323,-0.439 3,-3s7,-31.657 7,-31.657c0,-0.552 -0.448,-1 -1,-1H24.965c-0.552,0 -1,0.448 -1,1 0,0 -6.348,28.299 -6.938,30.253Z" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   </group> | ||||||
|  | </vector> | ||||||
							
								
								
									
										302
									
								
								app/src/main/res/drawable/qr.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,302 @@ | |||||||
|  | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     android:width="72dp" | ||||||
|  |     android:height="72dp" | ||||||
|  |     android:viewportWidth="58" | ||||||
|  |     android:viewportHeight="58"> | ||||||
|  |   <group android:translateX="-8" android:translateY="-8"> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M20,20h4v4h-4z" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M20,48h4v4h-4z" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M48,20h4v4h-4z" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M18,40m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M16,38m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M20,38m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M34,46m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M40,38m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M40,28m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M32,16m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M46,32m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M52,32m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M52,44m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M54,48m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M56,56m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M32,56m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M44,56m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M46,54m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M44,52m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M16,32m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M40,54m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" | ||||||
|  |       android:fillColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M12,12h48v48h-48z" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M16,16h12v12h-12z" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M20,20h4v4h-4z" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M16,44h12v12h-12z" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M20,48h4v4h-4z" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M44,16h12v12h-12z" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M48,20h4v4h-4z" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M18,36V34H26" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M20,34V32" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M24,34V40" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M24,38H26" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M38,32V30" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M56,34H54" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M42,42H44V40" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M28,32H30" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M34,32H40" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M38,16V20H36V28" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M36,26H32V28" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M36,20H32" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M36,22H34V18" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M28,36H36" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M30,36V40H28" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M34,36V38" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M32,44V42H38V48H42V46H50V56" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M36,40V44H42M46,40H42V48H44" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M48,34V38H50V42H48V46" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M50,38V36H52" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M52,50H48V52" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M32,52H34V54H36V50" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M56,32V38H54" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M44,36V34" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M56,42V44" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M54,52H56" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   <path | ||||||
|  |       android:pathData="M40,22V24" | ||||||
|  |       android:strokeLineJoin="round" | ||||||
|  |       android:strokeWidth="2" | ||||||
|  |       android:fillColor="#00000000" | ||||||
|  |       android:strokeColor="#000" | ||||||
|  |       android:strokeLineCap="round"/> | ||||||
|  |   </group> | ||||||
|  | </vector> | ||||||
| @@ -11,6 +11,7 @@ | |||||||
|         android:id="@+id/container" |         android:id="@+id/container" | ||||||
|         android:layout_width="match_parent" |         android:layout_width="match_parent" | ||||||
|         android:layout_height="match_parent" |         android:layout_height="match_parent" | ||||||
|  |         android:background="@color/black" | ||||||
|         tools:ignore="MergeRootFrame" /> |         tools:ignore="MergeRootFrame" /> | ||||||
|  |  | ||||||
| </androidx.coordinatorlayout.widget.CoordinatorLayout> | </androidx.coordinatorlayout.widget.CoordinatorLayout> | ||||||
| @@ -3,6 +3,7 @@ | |||||||
|     xmlns:tools="http://schemas.android.com/tools" |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|     android:layout_width="match_parent" |     android:layout_width="match_parent" | ||||||
|     android:layout_height="match_parent" |     android:layout_height="match_parent" | ||||||
|  |     android:background="@color/black" | ||||||
|     android:orientation="vertical" |     android:orientation="vertical" | ||||||
|     tools:context=".activity.fragment.Launcher"> |     tools:context=".activity.fragment.Launcher"> | ||||||
|  |  | ||||||
| @@ -56,6 +57,16 @@ | |||||||
|                 app:maxImageSize="32dp" |                 app:maxImageSize="32dp" | ||||||
|                 app:srcCompat="@drawable/camera" /> |                 app:srcCompat="@drawable/camera" /> | ||||||
|  |  | ||||||
|  |             <com.google.android.material.floatingactionbutton.FloatingActionButton | ||||||
|  |                 android:id="@+id/btnOpen" | ||||||
|  |                 android:layout_width="wrap_content" | ||||||
|  |                 android:layout_height="wrap_content" | ||||||
|  |                 android:layout_margin="8dp" | ||||||
|  |                 android:contentDescription="@string/open" | ||||||
|  |                 app:fabCustomSize="46dp" | ||||||
|  |                 app:maxImageSize="32dp" | ||||||
|  |                 app:srcCompat="@drawable/open" /> | ||||||
|  |  | ||||||
|             <com.google.android.material.floatingactionbutton.FloatingActionButton |             <com.google.android.material.floatingactionbutton.FloatingActionButton | ||||||
|                 android:id="@+id/btnManual" |                 android:id="@+id/btnManual" | ||||||
|                 android:layout_width="wrap_content" |                 android:layout_width="wrap_content" | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-hdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.1 KiB | 
| Before Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-mdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.8 KiB | 
| Before Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.3 KiB | 
| Before Width: | Height: | Size: 2.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.8 KiB | 
| Before Width: | Height: | Size: 4.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 10 KiB | 
| Before Width: | Height: | Size: 6.1 KiB | 
							
								
								
									
										14
									
								
								app/src/main/res/values/colors.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,14 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <resources> | ||||||
|  |     <color name="black">#FF000000</color> | ||||||
|  |     <color name="darkgray">#FF0C1D2E</color> | ||||||
|  |     <color name="gray">#425F7C</color> | ||||||
|  |     <color name="lightgray">#FF93A9BE</color> | ||||||
|  |     <color name="white">#FFF0F3F7</color> | ||||||
|  |  | ||||||
|  |     <color name="blue">#7DB9F5</color> | ||||||
|  |     <color name="blue2">#3193F5</color> | ||||||
|  |     <color name="red">#F57D7D</color> | ||||||
|  |     <color name="red2">#F53131</color> | ||||||
|  |  | ||||||
|  | </resources> | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <resources> | <resources> | ||||||
|     <color name="ic_launcher_background">#393939</color> |     <color name="ic_launcher_background">#0C1D2E</color> | ||||||
| </resources> | </resources> | ||||||
| @@ -15,6 +15,7 @@ | |||||||
|     <string name="code">Code</string> |     <string name="code">Code</string> | ||||||
|     <string name="format">Format</string> |     <string name="format">Format</string> | ||||||
|     <string name="save">Save</string> |     <string name="save">Save</string> | ||||||
|  |     <string name="open">Open</string> | ||||||
|     <string-array name="format_array"> |     <string-array name="format_array"> | ||||||
|         <item>CODE_39</item> |         <item>CODE_39</item> | ||||||
|         <item>CODE_93</item> |         <item>CODE_93</item> | ||||||
|   | |||||||
| @@ -2,11 +2,10 @@ | |||||||
| <resources> | <resources> | ||||||
|  |  | ||||||
|     <style name="Theme.Fidelity" parent="Theme.MaterialComponents.DayNight.NoActionBar"> |     <style name="Theme.Fidelity" parent="Theme.MaterialComponents.DayNight.NoActionBar"> | ||||||
|  |         <item name="colorPrimary">@color/blue</item> | ||||||
|         <item name="colorPrimary">#7DB9F5</item> |         <item name="colorPrimaryVariant">@color/blue</item> | ||||||
|         <item name="colorPrimaryVariant">#7DB9F5</item> |         <item name="colorSecondary">@color/blue</item> | ||||||
|         <item name="colorSecondary">#7DB9F5</item> |         <item name="colorSecondaryVariant">@color/blue</item> | ||||||
|         <item name="colorSecondaryVariant">#7DB9F5</item> |         <item name="colorOnPrimary">@color/darkgray</item> | ||||||
|         <item name="colorOnPrimary">#030B12</item> |  | ||||||
|     </style> |     </style> | ||||||
| </resources> | </resources> | ||||||
| @@ -1,8 +1,8 @@ | |||||||
| // Top-level build file where you can add configuration options common to all sub-projects/modules. | // Top-level build file where you can add configuration options common to all sub-projects/modules. | ||||||
|  |  | ||||||
| plugins { | plugins { | ||||||
|     id 'com.android.application' version '8.3.1' apply false |     id 'com.android.application' version '8.11.0' apply false | ||||||
|     id 'com.android.library' version '8.3.1' apply false |     id 'com.android.library' version '8.11.0' apply false | ||||||
|     id 'org.jetbrains.kotlin.android' version '1.9.23' apply false |     id 'org.jetbrains.kotlin.android' version '2.1.21' apply false | ||||||
|     id 'com.autonomousapps.dependency-analysis' version '1.30.0' apply true |     id 'com.autonomousapps.dependency-analysis' version '2.19.0' apply true | ||||||
| } | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
								
							
							
						
						
							
								
								
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,6 +1,6 @@ | |||||||
| distributionBase=GRADLE_USER_HOME | distributionBase=GRADLE_USER_HOME | ||||||
| distributionPath=wrapper/dists | distributionPath=wrapper/dists | ||||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip | ||||||
| networkTimeout=10000 | networkTimeout=10000 | ||||||
| validateDistributionUrl=true | validateDistributionUrl=true | ||||||
| zipStoreBase=GRADLE_USER_HOME | zipStoreBase=GRADLE_USER_HOME | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								gradlew
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -15,6 +15,8 @@ | |||||||
| # See the License for the specific language governing permissions and | # See the License for the specific language governing permissions and | ||||||
| # limitations under the License. | # limitations under the License. | ||||||
| # | # | ||||||
|  | # SPDX-License-Identifier: Apache-2.0 | ||||||
|  | # | ||||||
|  |  | ||||||
| ############################################################################## | ############################################################################## | ||||||
| # | # | ||||||
| @@ -55,7 +57,7 @@ | |||||||
| #       Darwin, MinGW, and NonStop. | #       Darwin, MinGW, and NonStop. | ||||||
| # | # | ||||||
| #   (3) This script is generated from the Groovy template | #   (3) This script is generated from the Groovy template | ||||||
| #       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt | #       https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt | ||||||
| #       within the Gradle project. | #       within the Gradle project. | ||||||
| # | # | ||||||
| #       You can find Gradle at https://github.com/gradle/gradle/. | #       You can find Gradle at https://github.com/gradle/gradle/. | ||||||
| @@ -84,7 +86,7 @@ done | |||||||
| # shellcheck disable=SC2034 | # shellcheck disable=SC2034 | ||||||
| APP_BASE_NAME=${0##*/} | APP_BASE_NAME=${0##*/} | ||||||
| # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) | ||||||
| APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit | ||||||
|  |  | ||||||
| # Use the maximum available, or set MAX_FD != -1 to use that value. | # Use the maximum available, or set MAX_FD != -1 to use that value. | ||||||
| MAX_FD=maximum | MAX_FD=maximum | ||||||
| @@ -112,7 +114,7 @@ case "$( uname )" in                #( | |||||||
|   NONSTOP* )        nonstop=true ;; |   NONSTOP* )        nonstop=true ;; | ||||||
| esac | esac | ||||||
|  |  | ||||||
| CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | CLASSPATH="\\\"\\\"" | ||||||
|  |  | ||||||
|  |  | ||||||
| # Determine the Java command to use to start the JVM. | # Determine the Java command to use to start the JVM. | ||||||
| @@ -203,7 +205,7 @@ fi | |||||||
| DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | ||||||
|  |  | ||||||
| # Collect all arguments for the java command: | # Collect all arguments for the java command: | ||||||
| #   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, | #   * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, | ||||||
| #     and any embedded shellness will be escaped. | #     and any embedded shellness will be escaped. | ||||||
| #   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be | #   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be | ||||||
| #     treated as '${Hostname}' itself on the command line. | #     treated as '${Hostname}' itself on the command line. | ||||||
| @@ -211,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | |||||||
| set -- \ | set -- \ | ||||||
|         "-Dorg.gradle.appname=$APP_BASE_NAME" \ |         "-Dorg.gradle.appname=$APP_BASE_NAME" \ | ||||||
|         -classpath "$CLASSPATH" \ |         -classpath "$CLASSPATH" \ | ||||||
|         org.gradle.wrapper.GradleWrapperMain \ |         -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ | ||||||
|         "$@" |         "$@" | ||||||
|  |  | ||||||
| # Stop when "xargs" is not available. | # Stop when "xargs" is not available. | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								gradlew.bat
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -13,6 +13,8 @@ | |||||||
| @rem See the License for the specific language governing permissions and | @rem See the License for the specific language governing permissions and | ||||||
| @rem limitations under the License. | @rem limitations under the License. | ||||||
| @rem | @rem | ||||||
|  | @rem SPDX-License-Identifier: Apache-2.0 | ||||||
|  | @rem | ||||||
|  |  | ||||||
| @if "%DEBUG%"=="" @echo off | @if "%DEBUG%"=="" @echo off | ||||||
| @rem ########################################################################## | @rem ########################################################################## | ||||||
| @@ -68,11 +70,11 @@ goto fail | |||||||
| :execute | :execute | ||||||
| @rem Setup the command line | @rem Setup the command line | ||||||
|  |  | ||||||
| set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | set CLASSPATH= | ||||||
|  |  | ||||||
|  |  | ||||||
| @rem Execute Gradle | @rem Execute Gradle | ||||||
| "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* | ||||||
|  |  | ||||||
| :end | :end | ||||||
| @rem End local scope for the variables with windows NT shell | @rem End local scope for the variables with windows NT shell | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								metadata/en-US/full_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | <p><i>Keepass-Fidelity</i> adds an interface to view/save barcodes (QR included) to Keepass through the plugin interface of the Keepass2Android app.</p><p><br></p><ul><li><b>Launcher:</b> view and launch recent entries (a per entry flag can disable this behaviour)</li><li><b>View:</b> view entries from the history or queried from Keepass2Android</li><li><b>Create:</b> add entries from the camera, an image of by filling out a form. The entry is then created in the Keepass2Android app</li><li><b>Data:</b> the app uses the following data Title (entry name), barcode type (QR, UPC, ...), barcode content (number/text content) and a "secure" flag (enable/disable caching the entry).</li></ul> | ||||||
							
								
								
									
										
											BIN
										
									
								
								metadata/en-US/images/icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB | 
| Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB | 
| Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB | 
							
								
								
									
										1
									
								
								metadata/en-US/permission_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | <ul><li><b>CAMERA:</b> necessary for importing barcodes from camera</li><li><b>READ_MEDIA_VISUAL_USER_SELECTED:</b> necessary for the importing barcode from images</li></ul> | ||||||
							
								
								
									
										1
									
								
								metadata/en-US/short_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | Fidelity (Membership/Loyalty) Card plugin for Keepass2Android | ||||||