2 Commits
v1.0.5 ... main

Author SHA1 Message Date
2d705457f8 animate lock and eye icons in action bar (top)
All checks were successful
Auto Tag on Version Change / check-version (push) Successful in 3s
2026-05-21 01:37:37 +05:00
f03e23062b you can now hold to copy text from recipts even in full screen mode
All checks were successful
Auto Tag on Version Change / check-version (push) Successful in 6s
2026-05-21 01:04:23 +05:00
6 changed files with 234 additions and 33 deletions

View File

@@ -427,14 +427,24 @@ fun applyNavLabelVisibility() {
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.action_lock) { if (item.itemId == R.id.action_lock) {
lock() val avd = getDrawable(R.drawable.avd_lock) as? android.graphics.drawable.AnimatedVectorDrawable
if (avd != null) {
item.icon = avd
avd.start()
Handler(Looper.getMainLooper()).postDelayed({ lock() }, 200)
} else {
lock()
}
return true return true
} }
if (item.itemId == R.id.action_hide_amounts) { if (item.itemId == R.id.action_hide_amounts) {
val newHidden = !(viewModel.hideAmounts.value ?: false) val newHidden = !(viewModel.hideAmounts.value ?: false)
viewModel.hideAmounts.value = newHidden viewModel.hideAmounts.value = newHidden
getSharedPreferences("prefs", MODE_PRIVATE).edit().putBoolean("hide_amounts", newHidden).apply() getSharedPreferences("prefs", MODE_PRIVATE).edit().putBoolean("hide_amounts", newHidden).apply()
invalidateOptionsMenu() val avd = getDrawable(if (newHidden) R.drawable.avd_hide_amounts else R.drawable.avd_show_amounts)
as? android.graphics.drawable.AnimatedVectorDrawable
item.icon = avd
avd?.start()
return true return true
} }
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)

View File

@@ -330,36 +330,48 @@ class TransferReceiptFragment : Fragment() {
} }
private fun showFullScreenReceipt() { private fun showFullScreenReceipt() {
captureReceiptBitmap { bitmap -> val ctx = requireContext()
if (bitmap == null) return@captureReceiptBitmap val bank = arguments?.getString(ARG_BANK, "MIB") ?: "MIB"
val ctx = requireContext() val dialog = Dialog(ctx, android.R.style.Theme_Black_NoTitleBar_Fullscreen)
val dialog = Dialog(ctx, android.R.style.Theme_Black_NoTitleBar_Fullscreen)
val iv = android.widget.ImageView(ctx).apply { val scrollView = android.widget.ScrollView(ctx).apply {
setImageBitmap(bitmap) setBackgroundColor(Color.BLACK)
scaleType = android.widget.ImageView.ScaleType.FIT_CENTER }
setBackgroundColor(Color.BLACK)
} val cardView = if (bank == "MIB") {
iv.setOnClickListener { dialog.dismiss() } val binding = FragmentReceiptMibBinding.inflate(layoutInflater)
dialog.setContentView(iv) bindMib(binding)
val actWin = requireActivity().window binding.receiptCard
val prevColor = actWin.statusBarColor } else {
val insetsCtrl = androidx.core.view.WindowInsetsControllerCompat(actWin, actWin.decorView) val binding = FragmentReceiptBmlBinding.inflate(layoutInflater)
actWin.statusBarColor = Color.BLACK bindBml(binding)
insetsCtrl.isAppearanceLightStatusBars = false binding.receiptCard
dialog.setOnDismissListener { }
actWin.statusBarColor = prevColor (cardView.parent as? ViewGroup)?.removeView(cardView)
val isLight = (resources.configuration.uiMode and cardView.setOnClickListener { dialog.dismiss() }
android.content.res.Configuration.UI_MODE_NIGHT_MASK) == scrollView.addView(cardView)
android.content.res.Configuration.UI_MODE_NIGHT_NO scrollView.setOnTouchListener { _, _ -> dialog.dismiss(); true }
insetsCtrl.isAppearanceLightStatusBars = isLight
} dialog.setContentView(scrollView)
dialog.show()
dialog.window?.let { win -> val actWin = requireActivity().window
androidx.core.view.WindowCompat.setDecorFitsSystemWindows(win, false) val prevColor = actWin.statusBarColor
androidx.core.view.WindowInsetsControllerCompat(win, iv).apply { val insetsCtrl = androidx.core.view.WindowInsetsControllerCompat(actWin, actWin.decorView)
hide(androidx.core.view.WindowInsetsCompat.Type.systemBars()) actWin.statusBarColor = Color.BLACK
systemBarsBehavior = androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE insetsCtrl.isAppearanceLightStatusBars = false
} dialog.setOnDismissListener {
actWin.statusBarColor = prevColor
val isLight = (resources.configuration.uiMode and
android.content.res.Configuration.UI_MODE_NIGHT_MASK) ==
android.content.res.Configuration.UI_MODE_NIGHT_NO
insetsCtrl.isAppearanceLightStatusBars = isLight
}
dialog.show()
dialog.window?.let { win ->
androidx.core.view.WindowCompat.setDecorFitsSystemWindows(win, false)
androidx.core.view.WindowInsetsControllerCompat(win, scrollView).apply {
hide(androidx.core.view.WindowInsetsCompat.Type.systemBars())
systemBarsBehavior = androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
} }
} }
} }

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
android:tint="?attr/colorControlNormal">
<path
android:name="strike_through"
android:pathData="M3.27,4.27 L19.74,20.74"
android:strokeColor="@android:color/white"
android:strokeLineCap="square"
android:strokeWidth="1.8"
android:trimPathEnd="0"/>
<group>
<clip-path
android:name="eye_mask"
android:pathData="M2,4.27 L2,4.27 L4.54,1.73 L4.54,1.73 L4.54,1 L23,1 L23,23 L1,23 L1,4.27 Z"/>
<path
android:name="eye"
android:fillColor="@android:color/white"
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
</group>
</vector>
</aapt:attr>
<target android:name="eye_mask">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="320"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M2,4.27 L2,4.27 L4.54,1.73 L4.54,1.73 L4.54,1 L23,1 L23,23 L1,23 L1,4.27 Z"
android:valueTo="M2,4.27 L19.73,22 L22.27,19.46 L4.54,1.73 L4.54,1 L23,1 L23,23 L1,23 L1,4.27 Z"
android:valueType="pathType"/>
</aapt:attr>
</target>
<target android:name="strike_through">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="320"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="trimPathEnd"
android:valueFrom="0"
android:valueTo="1"/>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
android:tint="?attr/colorControlNormal">
<!--
Shackle drawn first (behind body) so it appears to slot into the body.
Starts translateY=-4 (open/raised), animates to 0 (locked).
-->
<group
android:name="shackle"
android:translateY="-4">
<path
android:fillColor="@android:color/transparent"
android:pathData="M8.9,10V6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1V10"
android:strokeColor="@android:color/white"
android:strokeLineCap="round"
android:strokeWidth="2.2"/>
</group>
<!--
Body on top — covers the shackle legs once they slide inside.
Even-odd fill cuts out the keyhole.
-->
<path
android:fillColor="@android:color/white"
android:fillType="evenOdd"
android:pathData="M6,8H18c1.1,0 2,0.9 2,2V20c0,1.1-0.9,2-2,2H6c-1.1,0-2,-0.9-2,-2V10c0,-1.1 0.9,-2 2,-2zM12,15c-1.1,0-2,0.9-2,2s0.9,2 2,2 2,-0.9 2,-2-0.9,-2-2,-2z"/>
</vector>
</aapt:attr>
<target android:name="shackle">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="320"
android:interpolator="@android:interpolator/overshoot"
android:propertyName="translateY"
android:valueFrom="-4"
android:valueTo="0"/>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
android:tint="?attr/colorControlNormal">
<path
android:name="strike_through"
android:pathData="M3.27,4.27 L19.74,20.74"
android:strokeColor="@android:color/white"
android:strokeLineCap="square"
android:strokeWidth="1.8"/>
<group>
<clip-path
android:name="eye_mask"
android:pathData="M2,4.27 L19.73,22 L22.27,19.46 L4.54,1.73 L4.54,1 L23,1 L23,23 L1,23 L1,4.27 Z"/>
<path
android:name="eye"
android:fillColor="@android:color/white"
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
</group>
</vector>
</aapt:attr>
<target android:name="eye_mask">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="200"
android:interpolator="@android:interpolator/fast_out_linear_in"
android:propertyName="pathData"
android:valueFrom="M2,4.27 L19.73,22 L22.27,19.46 L4.54,1.73 L4.54,1 L23,1 L23,23 L1,23 L1,4.27 Z"
android:valueTo="M2,4.27 L2,4.27 L4.54,1.73 L4.54,1.73 L4.54,1 L23,1 L23,23 L1,23 L1,4.27 Z"
android:valueType="pathType"/>
</aapt:attr>
</target>
<target android:name="strike_through">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="200"
android:interpolator="@android:interpolator/fast_out_linear_in"
android:propertyName="trimPathEnd"
android:valueFrom="1"
android:valueTo="0"/>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -5,7 +5,19 @@
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24" android:viewportHeight="24"
android:tint="?attr/colorControlNormal"> android:tint="?attr/colorControlNormal">
<!-- Shackle (behind body) -->
<path
android:fillColor="@android:color/transparent"
android:pathData="M8.9,10V6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1V10"
android:strokeColor="@android:color/white"
android:strokeLineCap="round"
android:strokeWidth="2.2"/>
<!-- Body + keyhole cutout -->
<path <path
android:fillColor="@android:color/white" android:fillColor="@android:color/white"
android:pathData="M18,8h-1V6c0-2.76-2.24-5-5-5S7,3.24 7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10c0,-1.1-0.9,-2-2,-2zm-6,9c-1.1,0-2,-0.9-2,-2s0.9,-2 2,-2 2,0.9 2,2-0.9,2-2,2zm3.1,-9H8.9V6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z" /> android:fillType="evenOdd"
android:pathData="M6,8H18c1.1,0 2,0.9 2,2V20c0,1.1-0.9,2-2,2H6c-1.1,0-2,-0.9-2,-2V10c0,-1.1 0.9,-2 2,-2zM12,15c-1.1,0-2,0.9-2,2s0.9,2 2,2 2,-0.9 2,-2-0.9,-2-2,-2z"/>
</vector> </vector>