@onekeyfe/react-native-native-list 3.0.108 → 3.0.109
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/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +2 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +29 -2
- package/ios/NativeListModels.swift +2 -0
- package/ios/RNCNativeListView.swift +20 -4
- package/lib/module/validation.js +3 -0
- package/lib/typescript/src/models.d.ts +1 -0
- package/package.json +2 -2
- package/src/models.ts +1 -0
- package/src/validation.ts +9 -0
|
@@ -79,6 +79,7 @@ internal data class NativeListConfig(
|
|
|
79
79
|
val endReachedThreshold: Double,
|
|
80
80
|
val sectionIndexEnabled: Boolean,
|
|
81
81
|
val sectionIndexHapticsEnabled: Boolean,
|
|
82
|
+
val sectionIndexCenteredInWindow: Boolean,
|
|
82
83
|
val theme: JSONObject?,
|
|
83
84
|
val fixedFooter: NativeListItem?,
|
|
84
85
|
val items: List<NativeListItem>,
|
|
@@ -127,6 +128,7 @@ internal data class NativeListConfig(
|
|
|
127
128
|
endReachedThreshold = capabilities?.optDouble("endReachedThreshold", 0.2) ?: 0.2,
|
|
128
129
|
sectionIndexEnabled = sectionIndex?.optBoolean("enabled", false) ?: false,
|
|
129
130
|
sectionIndexHapticsEnabled = sectionIndex?.optBoolean("hapticsEnabled", true) ?: true,
|
|
131
|
+
sectionIndexCenteredInWindow = sectionIndex?.optBoolean("centeredInWindow", false) ?: false,
|
|
130
132
|
theme = root.optJSONObject("theme"),
|
|
131
133
|
fixedFooter = fixedFooter,
|
|
132
134
|
items = items,
|
|
@@ -21,6 +21,8 @@ import android.widget.FrameLayout
|
|
|
21
21
|
import android.widget.LinearLayout
|
|
22
22
|
import android.widget.SeekBar
|
|
23
23
|
import android.widget.TextView
|
|
24
|
+
import androidx.core.view.ViewCompat
|
|
25
|
+
import androidx.core.view.WindowInsetsCompat
|
|
24
26
|
import androidx.recyclerview.widget.GridLayoutManager
|
|
25
27
|
import androidx.recyclerview.widget.ItemTouchHelper
|
|
26
28
|
import androidx.recyclerview.widget.LinearLayoutManager
|
|
@@ -371,6 +373,7 @@ class NativeListView(
|
|
|
371
373
|
previous.endReachedThreshold != next.endReachedThreshold ||
|
|
372
374
|
previous.sectionIndexEnabled != next.sectionIndexEnabled ||
|
|
373
375
|
previous.sectionIndexHapticsEnabled != next.sectionIndexHapticsEnabled ||
|
|
376
|
+
previous.sectionIndexCenteredInWindow != next.sectionIndexCenteredInWindow ||
|
|
374
377
|
previous.theme?.toString() != next.theme?.toString() ||
|
|
375
378
|
previous.fixedFooter?.content != next.fixedFooter?.content ||
|
|
376
379
|
previous.items.size != next.items.size
|
|
@@ -907,6 +910,7 @@ class NativeListView(
|
|
|
907
910
|
themeColor(next.theme, "secondaryText", "#646464"),
|
|
908
911
|
themeColor(next.theme, "accent", "#108303"),
|
|
909
912
|
themeColor(next.theme, "inverseText", "#FCFCFC"),
|
|
913
|
+
next.sectionIndexCenteredInWindow,
|
|
910
914
|
)
|
|
911
915
|
sectionIndexView.visibility = if (sectionIndexEntries.isEmpty()) GONE else VISIBLE
|
|
912
916
|
sectionIndexPreview.setTextColor(themeColor(next.theme, "inverseText", "#FCFCFC"))
|
|
@@ -1704,7 +1708,10 @@ private class NativeListSectionIndexView(
|
|
|
1704
1708
|
private var normalColor = Color.GRAY
|
|
1705
1709
|
private var activeColor = Color.BLACK
|
|
1706
1710
|
private var activeTextColor = Color.WHITE
|
|
1711
|
+
private var centeredInWindow = false
|
|
1707
1712
|
private var lastTouchIndex: Int? = null
|
|
1713
|
+
private val rootLocationOnScreen = IntArray(2)
|
|
1714
|
+
private val locationOnScreen = IntArray(2)
|
|
1708
1715
|
private val activeBackgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
1709
1716
|
private val normalPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
1710
1717
|
textAlign = Paint.Align.CENTER
|
|
@@ -1727,11 +1734,13 @@ private class NativeListSectionIndexView(
|
|
|
1727
1734
|
normalColor: Int,
|
|
1728
1735
|
activeColor: Int,
|
|
1729
1736
|
activeTextColor: Int,
|
|
1737
|
+
centeredInWindow: Boolean,
|
|
1730
1738
|
) {
|
|
1731
1739
|
this.titles = titles
|
|
1732
1740
|
this.normalColor = normalColor
|
|
1733
1741
|
this.activeColor = activeColor
|
|
1734
1742
|
this.activeTextColor = activeTextColor
|
|
1743
|
+
this.centeredInWindow = centeredInWindow
|
|
1735
1744
|
activeIndex = null
|
|
1736
1745
|
updateContentDescription()
|
|
1737
1746
|
invalidate()
|
|
@@ -1748,7 +1757,7 @@ private class NativeListSectionIndexView(
|
|
|
1748
1757
|
super.onDraw(canvas)
|
|
1749
1758
|
if (titles.isEmpty()) return
|
|
1750
1759
|
val cellHeight = cellHeight()
|
|
1751
|
-
val originY = (
|
|
1760
|
+
val originY = indexOriginY(cellHeight, titles.size)
|
|
1752
1761
|
val textSize = NativeListScale.font(resources, 10f) * resources.displayMetrics.scaledDensity
|
|
1753
1762
|
normalPaint.color = normalColor
|
|
1754
1763
|
normalPaint.textSize = textSize
|
|
@@ -1856,7 +1865,7 @@ private class NativeListSectionIndexView(
|
|
|
1856
1865
|
|
|
1857
1866
|
private fun selectAt(y: Float, interacting: Boolean) {
|
|
1858
1867
|
val cellHeight = cellHeight()
|
|
1859
|
-
val originY = (
|
|
1868
|
+
val originY = indexOriginY(cellHeight, titles.size)
|
|
1860
1869
|
val index = ((y - originY) / cellHeight).toInt().coerceIn(0, titles.lastIndex)
|
|
1861
1870
|
if (interacting && lastTouchIndex == index) return
|
|
1862
1871
|
lastTouchIndex = index.takeIf { interacting }
|
|
@@ -1873,6 +1882,24 @@ private class NativeListSectionIndexView(
|
|
|
1873
1882
|
.coerceAtMost(NativeListScale.dp(resources, 16f))
|
|
1874
1883
|
.coerceAtLeast(1f)
|
|
1875
1884
|
|
|
1885
|
+
private fun indexOriginY(cellHeight: Float, count: Int): Float {
|
|
1886
|
+
val totalHeight = cellHeight * count
|
|
1887
|
+
val centeredOriginY = (height - totalHeight) / 2f
|
|
1888
|
+
if (!centeredInWindow || !isAttachedToWindow) return centeredOriginY
|
|
1889
|
+
val systemBarInsets = ViewCompat.getRootWindowInsets(rootView)
|
|
1890
|
+
?.getInsetsIgnoringVisibility(
|
|
1891
|
+
WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout(),
|
|
1892
|
+
) ?: return centeredOriginY
|
|
1893
|
+
rootView.getLocationOnScreen(rootLocationOnScreen)
|
|
1894
|
+
getLocationOnScreen(locationOnScreen)
|
|
1895
|
+
val safeTop = rootLocationOnScreen[1] + systemBarInsets.top
|
|
1896
|
+
val safeBottom = rootLocationOnScreen[1] + rootView.height - systemBarInsets.bottom
|
|
1897
|
+
if (safeBottom <= safeTop) return centeredOriginY
|
|
1898
|
+
val localCenterY = (safeTop + safeBottom) / 2f - locationOnScreen[1]
|
|
1899
|
+
return (localCenterY - totalHeight / 2f)
|
|
1900
|
+
.coerceIn(0f, (height - totalHeight).coerceAtLeast(0f))
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1876
1903
|
private fun updateContentDescription() {
|
|
1877
1904
|
contentDescription = activeIndex?.let { titles.getOrNull(it) }
|
|
1878
1905
|
?.let { "$ACCESSIBILITY_LABEL, $it" }
|
|
@@ -62,6 +62,7 @@ struct NativeListConfig {
|
|
|
62
62
|
let endReachedThreshold: Double
|
|
63
63
|
let sectionIndexEnabled: Bool
|
|
64
64
|
let sectionIndexHapticsEnabled: Bool
|
|
65
|
+
let sectionIndexCenteredInWindow: Bool
|
|
65
66
|
let theme: [String: Any]?
|
|
66
67
|
let fixedFooter: NativeListItem?
|
|
67
68
|
var items: [NativeListItem]
|
|
@@ -123,6 +124,7 @@ struct NativeListConfig {
|
|
|
123
124
|
endReachedThreshold: capabilities?["endReachedThreshold"] as? Double ?? 0.2,
|
|
124
125
|
sectionIndexEnabled: sectionIndex?["enabled"] as? Bool ?? false,
|
|
125
126
|
sectionIndexHapticsEnabled: sectionIndex?["hapticsEnabled"] as? Bool ?? true,
|
|
127
|
+
sectionIndexCenteredInWindow: sectionIndex?["centeredInWindow"] as? Bool ?? false,
|
|
126
128
|
theme: root["theme"] as? [String: Any],
|
|
127
129
|
fixedFooter: footer,
|
|
128
130
|
items: items
|
|
@@ -873,7 +873,8 @@ final class NativeListView: UIView {
|
|
|
873
873
|
titles: sectionIndexEntries.map(\.title),
|
|
874
874
|
textColor: nativeListColor(config.theme, "secondaryText", "#646464"),
|
|
875
875
|
activeColor: nativeListColor(config.theme, "accent", "#108303"),
|
|
876
|
-
activeTextColor: nativeListColor(config.theme, "inverseText", "#FCFCFC")
|
|
876
|
+
activeTextColor: nativeListColor(config.theme, "inverseText", "#FCFCFC"),
|
|
877
|
+
centeredInWindow: config.sectionIndexCenteredInWindow
|
|
877
878
|
)
|
|
878
879
|
sectionIndexView.isHidden = sectionIndexEntries.isEmpty
|
|
879
880
|
sectionIndexPreview.backgroundColor = nativeListColor(
|
|
@@ -1113,6 +1114,7 @@ final class NativeListView: UIView {
|
|
|
1113
1114
|
current.endReachedThreshold == next.endReachedThreshold,
|
|
1114
1115
|
current.sectionIndexEnabled == next.sectionIndexEnabled,
|
|
1115
1116
|
current.sectionIndexHapticsEnabled == next.sectionIndexHapticsEnabled,
|
|
1117
|
+
current.sectionIndexCenteredInWindow == next.sectionIndexCenteredInWindow,
|
|
1116
1118
|
dictionariesEqual(current.theme, next.theme),
|
|
1117
1119
|
current.fixedFooter?.content == next.fixedFooter?.content,
|
|
1118
1120
|
current.items.count == next.items.count else { return false }
|
|
@@ -1756,6 +1758,7 @@ private final class NativeListSectionIndexView: UIControl, UIGestureRecognizerDe
|
|
|
1756
1758
|
private var textColor: UIColor = .secondaryLabel
|
|
1757
1759
|
private var activeColor: UIColor = .tintColor
|
|
1758
1760
|
private var activeTextColor: UIColor = .white
|
|
1761
|
+
private var centeredInWindow = false
|
|
1759
1762
|
private var lastTouchIndex: Int?
|
|
1760
1763
|
private(set) var activeIndex: Int?
|
|
1761
1764
|
|
|
@@ -1796,12 +1799,14 @@ private final class NativeListSectionIndexView: UIControl, UIGestureRecognizerDe
|
|
|
1796
1799
|
titles: [String],
|
|
1797
1800
|
textColor: UIColor,
|
|
1798
1801
|
activeColor: UIColor,
|
|
1799
|
-
activeTextColor: UIColor
|
|
1802
|
+
activeTextColor: UIColor,
|
|
1803
|
+
centeredInWindow: Bool
|
|
1800
1804
|
) {
|
|
1801
1805
|
self.titles = titles
|
|
1802
1806
|
self.textColor = textColor
|
|
1803
1807
|
self.activeColor = activeColor
|
|
1804
1808
|
self.activeTextColor = activeTextColor
|
|
1809
|
+
self.centeredInWindow = centeredInWindow
|
|
1805
1810
|
labels.forEach { $0.removeFromSuperview() }
|
|
1806
1811
|
labels = titles.map { title in
|
|
1807
1812
|
let label = UILabel()
|
|
@@ -1829,7 +1834,7 @@ private final class NativeListSectionIndexView: UIControl, UIGestureRecognizerDe
|
|
|
1829
1834
|
super.layoutSubviews()
|
|
1830
1835
|
guard !labels.isEmpty else { return }
|
|
1831
1836
|
let height = min(16, max(8, bounds.height / CGFloat(labels.count)))
|
|
1832
|
-
let originY = (
|
|
1837
|
+
let originY = indexOriginY(cellHeight: height, count: labels.count)
|
|
1833
1838
|
for (index, label) in labels.enumerated() {
|
|
1834
1839
|
label.frame = CGRect(
|
|
1835
1840
|
x: 6,
|
|
@@ -1875,13 +1880,24 @@ private final class NativeListSectionIndexView: UIControl, UIGestureRecognizerDe
|
|
|
1875
1880
|
|
|
1876
1881
|
private func select(at y: CGFloat, interacting: Bool) {
|
|
1877
1882
|
let height = min(16, max(8, bounds.height / CGFloat(titles.count)))
|
|
1878
|
-
let originY = (
|
|
1883
|
+
let originY = indexOriginY(cellHeight: height, count: titles.count)
|
|
1879
1884
|
let index = Int(floor((y - originY) / height)).clamped(to: 0...(titles.count - 1))
|
|
1880
1885
|
if interacting && lastTouchIndex == index { return }
|
|
1881
1886
|
lastTouchIndex = interacting ? index : nil
|
|
1882
1887
|
select(index: index, interacting: interacting)
|
|
1883
1888
|
}
|
|
1884
1889
|
|
|
1890
|
+
private func indexOriginY(cellHeight: CGFloat, count: Int) -> CGFloat {
|
|
1891
|
+
let totalHeight = cellHeight * CGFloat(count)
|
|
1892
|
+
let centeredOriginY = (bounds.height - totalHeight) / 2
|
|
1893
|
+
guard centeredInWindow, let window else { return centeredOriginY }
|
|
1894
|
+
let windowCenterY = window.safeAreaLayoutGuide.layoutFrame.midY
|
|
1895
|
+
let localCenterY = convert(CGPoint(x: 0, y: windowCenterY), from: window).y
|
|
1896
|
+
return (localCenterY - totalHeight / 2).clamped(
|
|
1897
|
+
to: 0...max(0, bounds.height - totalHeight)
|
|
1898
|
+
)
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1885
1901
|
private func select(index: Int, interacting: Bool) {
|
|
1886
1902
|
onSelect?(index, interacting)
|
|
1887
1903
|
setActiveIndex(index)
|
package/lib/module/validation.js
CHANGED
|
@@ -392,6 +392,9 @@ export function validateSnapshot(snapshot) {
|
|
|
392
392
|
if (sectionIndex.hapticsEnabled !== undefined && typeof sectionIndex.hapticsEnabled !== 'boolean') {
|
|
393
393
|
fail('snapshot.capabilities.sectionIndex.hapticsEnabled', 'must be a boolean');
|
|
394
394
|
}
|
|
395
|
+
if (sectionIndex.centeredInWindow !== undefined && typeof sectionIndex.centeredInWindow !== 'boolean') {
|
|
396
|
+
fail('snapshot.capabilities.sectionIndex.centeredInWindow', 'must be a boolean');
|
|
397
|
+
}
|
|
395
398
|
if (sectionIndex.enabled && (snapshot.layout.kind !== 'sectioned' || snapshot.layout.orientation === 'horizontal')) {
|
|
396
399
|
fail('snapshot.capabilities.sectionIndex', 'requires a vertical sectioned layout');
|
|
397
400
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-native-list",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.109",
|
|
4
4
|
"description": "Template-driven native RecyclerView and UICollectionView for React Native",
|
|
5
5
|
"source": "./src/index.ts",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"typescript": "^5.9.2"
|
|
83
83
|
},
|
|
84
84
|
"peerDependencies": {
|
|
85
|
-
"@onekeyfe/react-native-image": "3.0.
|
|
85
|
+
"@onekeyfe/react-native-image": "3.0.109",
|
|
86
86
|
"react": "*",
|
|
87
87
|
"react-native": "*",
|
|
88
88
|
"react-native-nitro-modules": "0.37.0"
|
package/src/models.ts
CHANGED
package/src/validation.ts
CHANGED
|
@@ -698,6 +698,15 @@ export function validateSnapshot(
|
|
|
698
698
|
'must be a boolean'
|
|
699
699
|
);
|
|
700
700
|
}
|
|
701
|
+
if (
|
|
702
|
+
sectionIndex.centeredInWindow !== undefined &&
|
|
703
|
+
typeof sectionIndex.centeredInWindow !== 'boolean'
|
|
704
|
+
) {
|
|
705
|
+
fail(
|
|
706
|
+
'snapshot.capabilities.sectionIndex.centeredInWindow',
|
|
707
|
+
'must be a boolean'
|
|
708
|
+
);
|
|
709
|
+
}
|
|
701
710
|
if (
|
|
702
711
|
sectionIndex.enabled &&
|
|
703
712
|
(snapshot.layout.kind !== 'sectioned' ||
|