@craft-native/android 0.0.226 → 0.0.227

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@craft-native/android",
3
- "version": "0.0.226",
3
+ "version": "0.0.227",
4
4
  "homepage": "https://github.com/craft-native/craft/tree/main/packages/android#readme",
5
5
  "repository": {
6
6
  "type": "git",
@@ -643,6 +643,10 @@ internal class CraftNativeChrome(context: Context, private val tabs: List<CraftN
643
643
  private var accessorySpec: JSONObject? = null
644
644
  private val tabViews = mutableListOf<Pair<TextView, TextView>>()
645
645
  private val tabIconText = mutableMapOf<String, String>()
646
+ private val tabTitles = mutableMapOf<String, String>()
647
+ private val tabAccessibilityLabels = mutableMapOf<String, String>()
648
+ private val tabIconTints = mutableMapOf<String, Int>()
649
+ private val tabIconPulses = mutableSetOf<String>()
646
650
  private val tabImageURLs = mutableMapOf<String, String>()
647
651
  private val tabImages = mutableMapOf<String, android.graphics.drawable.Drawable>()
648
652
  private val navButtonSpecs = mutableMapOf<TextView, JSONObject>()
@@ -706,6 +710,7 @@ internal class CraftNativeChrome(context: Context, private val tabs: List<CraftN
706
710
  cell.gravity = Gravity.CENTER
707
711
  cell.background = rippleBackground()
708
712
  cell.contentDescription = tab.title
713
+ cell.tag = "craft-tab-${tab.id}"
709
714
  val icon = TextView(context)
710
715
  icon.text = CraftNativeSymbols.glyph(tab.symbol)
711
716
  icon.textSize = 22f
@@ -716,6 +721,7 @@ internal class CraftNativeChrome(context: Context, private val tabs: List<CraftN
716
721
  val label = TextView(context)
717
722
  label.text = tab.title
718
723
  label.textSize = 12f
724
+ label.fontFeatureSettings = "tnum"
719
725
  label.gravity = Gravity.CENTER
720
726
  label.isSingleLine = true
721
727
  cell.addView(icon, LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT))
@@ -844,12 +850,25 @@ internal class CraftNativeChrome(context: Context, private val tabs: List<CraftN
844
850
  val id = item.optString("id")
845
851
  val index = tabs.indexOfFirst { it.id == id }
846
852
  if (index < 0) return
847
- val cell = tabBar.getChildAt(index)
848
- if (item.has("accessibilityLabel")) cell.contentDescription = item.optString("accessibilityLabel").takeUnless { item.isNull("accessibilityLabel") || it.isBlank() } ?: tabs[index].title
853
+ if (item.has("accessibilityLabel")) {
854
+ tabAccessibilityLabels.remove(id)
855
+ item.optString("accessibilityLabel").takeUnless { item.isNull("accessibilityLabel") || it.isBlank() }?.let { tabAccessibilityLabels[id] = it.take(160) }
856
+ }
849
857
  if (item.has("iconText")) {
850
858
  tabIconText.remove(id)
851
859
  item.optString("iconText").takeUnless { item.isNull("iconText") || it.isBlank() }?.let { tabIconText[id] = it.take(8) }
852
860
  }
861
+ if (item.has("title")) {
862
+ tabTitles.remove(id)
863
+ item.optString("title").takeUnless { item.isNull("title") || it.isBlank() }?.let { tabTitles[id] = it.take(40) }
864
+ }
865
+ if (item.has("iconTint")) {
866
+ tabIconTints.remove(id)
867
+ if (!item.isNull("iconTint")) runCatching { Color.parseColor(item.optString("iconTint")) }.getOrNull()?.let { tabIconTints[id] = it }
868
+ }
869
+ if (item.has("iconPulse")) {
870
+ if (item.optBoolean("iconPulse", false)) tabIconPulses.add(id) else tabIconPulses.remove(id)
871
+ }
853
872
  if (item.has("image")) {
854
873
  val address = item.optString("image").takeIf { !item.isNull("image") && it.startsWith("https://") }
855
874
  if (address != tabImageURLs[id]) {
@@ -896,16 +915,41 @@ internal class CraftNativeChrome(context: Context, private val tabs: List<CraftN
896
915
  tabViews.forEachIndexed { index, (icon, label) ->
897
916
  tabBar.getChildAt(index).isSelected = index == selectedTab
898
917
  val color = if (index == selectedTab) accent else muted
899
- val number = tabIconText[tabs[index].id]
900
- icon.setTextColor(if (number != null) Color.parseColor("#FF2D55") else color)
918
+ val id = tabs[index].id
919
+ val number = tabIconText[id]
920
+ val iconColor = tabIconTints[id] ?: if (number != null) Color.parseColor("#FF2D55") else color
921
+ icon.setTextColor(iconColor)
922
+ label.text = tabTitles[id] ?: tabs[index].title
923
+ tabBar.getChildAt(index).contentDescription = tabAccessibilityLabels[id] ?: label.text
901
924
  label.setTextColor(color)
902
- val vector = tabImages[tabs[index].id] ?: if (number == null) CraftNativeIcons.drawable(context, null, tabs[index].symbol, color) else null
925
+ val vector = tabImages[id] ?: if (number == null) CraftNativeIcons.drawable(context, null, tabs[index].symbol, iconColor) else null
926
+ val pulse = tabIconPulses.contains(id) && number == null && tabImages[id] == null && hasWindowFocus() && android.animation.ValueAnimator.areAnimatorsEnabled()
927
+ if (pulse && icon.animation == null) {
928
+ icon.startAnimation(android.view.animation.AlphaAnimation(1f, 0.55f).apply {
929
+ duration = 700
930
+ repeatCount = android.view.animation.Animation.INFINITE
931
+ repeatMode = android.view.animation.Animation.REVERSE
932
+ })
933
+ } else if (!pulse) {
934
+ icon.clearAnimation()
935
+ icon.alpha = 1f
936
+ }
903
937
  icon.foreground = vector
904
938
  icon.text = if (vector != null) "" else number ?: CraftNativeSymbols.glyph(tabs[index].symbol)
905
939
  }
906
940
  navButtonSpecs.forEach { (view, spec) -> applyNavButtonTint(view, spec, dark) }
907
941
  }
908
942
 
943
+ override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
944
+ super.onWindowFocusChanged(hasWindowFocus)
945
+ if (hasWindowFocus) refreshColors() else tabViews.forEach { (icon, _) -> icon.clearAnimation() }
946
+ }
947
+
948
+ override fun onDetachedFromWindow() {
949
+ tabViews.forEach { (icon, _) -> icon.clearAnimation() }
950
+ super.onDetachedFromWindow()
951
+ }
952
+
909
953
  private fun navButton(button: JSONObject): View {
910
954
  val id = button.optString("id")
911
955
  val title = button.optString("title")