chore(android): add ktlint

This commit is contained in:
lodev09 2024-04-01 02:20:31 +08:00
parent 3393f76165
commit 6f286f5f67
No known key found for this signature in database
GPG Key ID: F098AE8F7143F3E0
13 changed files with 151 additions and 108 deletions

15
android/.editorconfig Normal file
View File

@ -0,0 +1,15 @@
[*.{kt,kts}]
indent_style=space
indent_size=2
continuation_indent_size=4
insert_final_newline=true
max_line_length=140
ktlint_code_style=android_studio
ktlint_standard=enabled
ktlint_experimental=enabled
ktlint_standard_filename=disabled # dont require PascalCase filenames
ktlint_standard_no-wildcard-imports=disabled # allow .* imports
ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than=5
ktlint_function_signature_body_expression_wrapping=multiline
ij_kotlin_allow_trailing_comma_on_call_site=false
ij_kotlin_allow_trailing_comma=false

View File

@ -6,11 +6,7 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
class TrueSheetPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(TrueSheetViewModule(reactContext))
}
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> = listOf(TrueSheetViewModule(reactContext))
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return listOf(TrueSheetViewManager())
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = listOf(TrueSheetViewManager())
}

View File

@ -21,7 +21,9 @@ import com.lodev09.truesheet.core.SheetBehavior
import com.lodev09.truesheet.core.SizeChangeEvent
import com.lodev09.truesheet.utils.maxSize
class TrueSheetView(context: Context) : ViewGroup(context), LifecycleEventListener {
class TrueSheetView(context: Context) :
ViewGroup(context),
LifecycleEventListener {
private var eventDispatcher: EventDispatcher? = null
private val reactContext: ThemedReactContext
@ -62,33 +64,31 @@ class TrueSheetView(context: Context) : ViewGroup(context), LifecycleEventListen
// Configure Sheet events
sheetBehavior.apply {
maxSize = maxSize(context)
addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(sheetView: View, slideOffset: Float) {
footerView?.let {
it.y = (sheetView.height - sheetView.top - it.height).toFloat()
}
}
override fun onStateChanged(view: View, newState: Int) {
val sizeInfo = getSizeInfoForState(sizes.size, newState)
if (sizeInfo != null && sizeInfo.index != sizeIndex) {
sizeIndex = sizeInfo.index
// dispatch onSizeChange event
eventDispatcher?.dispatchEvent(SizeChangeEvent(surfaceId, id, sizeInfo))
}
when (newState) {
BottomSheetBehavior.STATE_HIDDEN -> {
sheetDialog.dismiss()
addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(sheetView: View, slideOffset: Float) {
footerView?.let {
it.y = (sheetView.height - sheetView.top - it.height).toFloat()
}
}
override fun onStateChanged(view: View, newState: Int) {
val sizeInfo = getSizeInfoForState(sizes.size, newState)
if (sizeInfo != null && sizeInfo.index != sizeIndex) {
sizeIndex = sizeInfo.index
// dispatch onSizeChange event
eventDispatcher?.dispatchEvent(SizeChangeEvent(surfaceId, id, sizeInfo))
}
when (newState) {
BottomSheetBehavior.STATE_HIDDEN -> sheetDialog.dismiss()
else -> {}
}
BottomSheetBehavior.STATE_COLLAPSED -> {}
BottomSheetBehavior.STATE_DRAGGING -> {}
BottomSheetBehavior.STATE_EXPANDED -> {}
BottomSheetBehavior.STATE_HALF_EXPANDED -> {}
BottomSheetBehavior.STATE_SETTLING -> {}
}
}
})
)
}
// Configure the sheet layout
@ -131,7 +131,13 @@ class TrueSheetView(context: Context) : ViewGroup(context), LifecycleEventListen
sheetRootView.dispatchProvideStructure(structure)
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
override fun onLayout(
changed: Boolean,
l: Int,
t: Int,
r: Int,
b: Int
) {
// Do nothing as we are laid out by UIManager
}
@ -163,9 +169,7 @@ class TrueSheetView(context: Context) : ViewGroup(context), LifecycleEventListen
return sheetRootView.childCount
}
override fun getChildAt(index: Int): View {
return sheetRootView.getChildAt(index)
}
override fun getChildAt(index: Int): View = sheetRootView.getChildAt(index)
override fun removeView(child: View) {
sheetRootView.removeView(child)
@ -227,4 +231,3 @@ class TrueSheetView(context: Context) : ViewGroup(context), LifecycleEventListen
const val TAG = "TrueSheetView"
}
}

View File

@ -14,9 +14,7 @@ import com.lodev09.truesheet.core.SizeChangeEvent
class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {
override fun getName() = TAG
override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetView {
return TrueSheetView(reactContext)
}
override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetView = TrueSheetView(reactContext)
override fun onDropViewInstance(view: TrueSheetView) {
super.onDropViewInstance(view)

View File

@ -5,8 +5,9 @@ import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.events.Event
// onPresent
class PresentEvent(surfaceId: Int, viewId: Int): Event<PresentEvent>(surfaceId, viewId) {
class PresentEvent(surfaceId: Int, viewId: Int) : Event<PresentEvent>(surfaceId, viewId) {
override fun getEventName() = EVENT_NAME
override fun getEventData(): WritableMap = Arguments.createMap()
companion object {
@ -15,8 +16,9 @@ class PresentEvent(surfaceId: Int, viewId: Int): Event<PresentEvent>(surfaceId,
}
// onDismiss
class DismissEvent(surfaceId: Int, viewId: Int): Event<PresentEvent>(surfaceId, viewId) {
class DismissEvent(surfaceId: Int, viewId: Int) : Event<PresentEvent>(surfaceId, viewId) {
override fun getEventName() = EVENT_NAME
override fun getEventData(): WritableMap = Arguments.createMap()
companion object {
@ -24,8 +26,9 @@ class DismissEvent(surfaceId: Int, viewId: Int): Event<PresentEvent>(surfaceId,
}
}
class SizeChangeEvent(surfaceId: Int, viewId: Int, private val sizeInfo: SizeInfo): Event<SizeChangeEvent>(surfaceId, viewId) {
class SizeChangeEvent(surfaceId: Int, viewId: Int, private val sizeInfo: SizeInfo) : Event<SizeChangeEvent>(surfaceId, viewId) {
override fun getEventName() = EVENT_NAME
override fun getEventData(): WritableMap {
val data = Arguments.createMap()
data.putInt("index", sizeInfo.index)

View File

@ -26,7 +26,8 @@ import com.facebook.react.views.view.ReactViewGroup
* styleHeight on the LayoutShadowNode to be the window size. This is done through the
* UIManagerModule, and will then cause the children to layout as if they can fill the window.
*/
internal class RootViewGroup(context: Context?) : ReactViewGroup(context),
internal class RootViewGroup(context: Context?) :
ReactViewGroup(context),
RootView {
private var hasAdjustedSize = false
private var viewWidth = 0
@ -59,13 +60,15 @@ internal class RootViewGroup(context: Context?) : ReactViewGroup(context),
reactContext.runOnNativeModulesQueueThread(
object : GuardedRunnable(reactContext) {
override fun runGuarded() {
val uiManager: UIManagerModule = reactContext
.reactApplicationContext
.getNativeModule(UIManagerModule::class.java) ?: return
val uiManager: UIManagerModule =
reactContext
.reactApplicationContext
.getNativeModule(UIManagerModule::class.java) ?: return
uiManager.updateNodeSize(viewTag, viewWidth, viewHeight)
}
})
}
)
} else {
hasAdjustedSize = true
}

View File

@ -11,7 +11,7 @@ import com.lodev09.truesheet.utils.toDIP
data class SizeInfo(val index: Int, val value: Float)
class SheetBehavior<T: ViewGroup> : BottomSheetBehavior<T>() {
class SheetBehavior<T : ViewGroup> : BottomSheetBehavior<T>() {
var maxSize: Point = Point()
var contentView: ViewGroup? = null
@ -23,7 +23,7 @@ class SheetBehavior<T: ViewGroup> : BottomSheetBehavior<T>() {
val expanded = state == STATE_EXPANDED
if (isDownEvent && expanded) {
for(i in 0 until it.childCount) {
for (i in 0 until it.childCount) {
val contentChild = it.getChildAt(i)
val scrolled = (contentChild is ScrollView && contentChild.scrollY > 0)
@ -58,30 +58,44 @@ class SheetBehavior<T: ViewGroup> : BottomSheetBehavior<T>() {
private fun getSizeHeight(size: Any, contentHeight: Int): Int {
val maxHeight = maxSize.y
val height = when (size) {
is Double -> PixelUtil.toPixelFromDIP(size).toInt()
is Int -> PixelUtil.toPixelFromDIP(size.toDouble()).toInt()
is String -> {
return when (size) {
"auto" -> contentHeight
"large" -> maxHeight
"medium" -> (maxHeight * 0.50).toInt()
"small" -> (maxHeight * 0.25).toInt()
else -> {
if (size.endsWith('%')) {
val percent = size.trim('%').toDoubleOrNull()
return if (percent == null) 0
else ((percent / 100) * maxHeight).toInt()
} else {
val fixedHeight = size.toDoubleOrNull()
return if (fixedHeight == null) 0
else PixelUtil.toPixelFromDIP(fixedHeight).toInt()
val height =
when (size) {
is Double -> PixelUtil.toPixelFromDIP(size).toInt()
is Int -> PixelUtil.toPixelFromDIP(size.toDouble()).toInt()
is String -> {
return when (size) {
"auto" -> contentHeight
"large" -> maxHeight
"medium" -> (maxHeight * 0.50).toInt()
"small" -> (maxHeight * 0.25).toInt()
else -> {
if (size.endsWith('%')) {
val percent = size.trim('%').toDoubleOrNull()
return if (percent == null) {
0
} else {
((percent / 100) * maxHeight).toInt()
}
} else {
val fixedHeight = size.toDoubleOrNull()
return if (fixedHeight == null) {
0
} else {
PixelUtil.toPixelFromDIP(fixedHeight).toInt()
}
}
}
}
}
else -> (maxHeight * 0.5).toInt()
}
else -> (maxHeight * 0.5).toInt()
}
return minOf(height, maxHeight)
}
@ -103,10 +117,12 @@ class SheetBehavior<T: ViewGroup> : BottomSheetBehavior<T>() {
maxHeight = getSizeHeight(sizes[0], contentHeight)
skipCollapsed = true
}
2 -> {
peekHeight = getSizeHeight(sizes[0], contentHeight)
maxHeight = getSizeHeight(sizes[1], contentHeight)
}
3 -> {
// Enables half expanded
isFitToContents = false
@ -119,14 +135,15 @@ class SheetBehavior<T: ViewGroup> : BottomSheetBehavior<T>() {
}
}
fun getSizeInfoForState(sizeCount: Int, state: Int): SizeInfo? {
return when (sizeCount) {
fun getSizeInfoForState(sizeCount: Int, state: Int): SizeInfo? =
when (sizeCount) {
1 -> {
when (state) {
STATE_EXPANDED -> SizeInfo(0, PixelUtil.toDIPFromPixel(maxHeight.toFloat()))
else -> null
}
}
2 -> {
when (state) {
STATE_COLLAPSED -> SizeInfo(0, toDIP(peekHeight))
@ -134,40 +151,48 @@ class SheetBehavior<T: ViewGroup> : BottomSheetBehavior<T>() {
else -> null
}
}
3 -> {
when (state) {
STATE_COLLAPSED -> SizeInfo(0, toDIP(peekHeight))
STATE_HALF_EXPANDED -> {
val height = halfExpandedRatio * maxSize.y
SizeInfo(1, toDIP(height.toInt()))
}
STATE_EXPANDED -> SizeInfo(2, toDIP(maxHeight))
else -> null
}
}
else -> null
}
}
fun setStateForSizeIndex(sizeCount: Int, index: Int) {
state = when (sizeCount) {
1 -> STATE_EXPANDED
2 -> {
when (index) {
0 -> STATE_COLLAPSED
1 -> STATE_EXPANDED
else -> STATE_HIDDEN
state =
when (sizeCount) {
1 -> STATE_EXPANDED
2 -> {
when (index) {
0 -> STATE_COLLAPSED
1 -> STATE_EXPANDED
else -> STATE_HIDDEN
}
}
}
3 -> {
when(index) {
0 -> STATE_COLLAPSED
1 -> STATE_HALF_EXPANDED
2 -> STATE_EXPANDED
else -> STATE_HIDDEN
3 -> {
when (index) {
0 -> STATE_COLLAPSED
1 -> STATE_HALF_EXPANDED
2 -> STATE_EXPANDED
else -> STATE_HIDDEN
}
}
else -> STATE_HIDDEN
}
else -> STATE_HIDDEN
}
}
}

View File

@ -1,18 +1,20 @@
package com.lodev09.truesheet.utils
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Point
import android.view.WindowManager
import com.facebook.infer.annotation.Assertions
/**
* To get the size of the screen, we use information from the WindowManager and default Display.
* We don't use DisplayMetricsHolder, or Display#getSize() because they return values that include
* the status bar. We only want the values of what will actually be shown on screen. We use
* Display#getSize() to determine if the screen is in portrait or landscape. We don't use
* getRotation because the 'natural' rotation will be portrait on phones and landscape on tablets.
* This should only be called on the native modules/shadow nodes thread.
*/
* To get the size of the screen, we use information from the WindowManager and default Display.
* We don't use DisplayMetricsHolder, or Display#getSize() because they return values that include
* the status bar. We only want the values of what will actually be shown on screen. We use
* Display#getSize() to determine if the screen is in portrait or landscape. We don't use
* getRotation because the 'natural' rotation will be portrait on phones and landscape on tablets.
* This should only be called on the native modules/shadow nodes thread.
*/
@SuppressLint("DiscouragedApi", "InternalInsetResource")
fun maxSize(context: Context): Point {
val minPoint = Point()
val maxPoint = Point()

View File

@ -2,6 +2,4 @@ package com.lodev09.truesheet.utils
import com.facebook.react.uimanager.PixelUtil
fun toDIP(value: Int): Float {
return PixelUtil.toDIPFromPixel(value.toFloat())
}
fun toDIP(value: Int): Float = PixelUtil.toDIPFromPixel(value.toFloat())

View File

@ -31,7 +31,7 @@
"typecheck": "tsc --noEmit",
"lint": "eslint --fix \"**/*.{js,ts,tsx}\"",
"format": "prettier --write \"**/*.{js,ts,tsx}\"",
"tidy": "yarn typecheck && yarn lint && yarn format && scripts/swiftlint.sh && scripts/swiftformat.sh",
"tidy": "yarn typecheck && yarn lint && yarn format && scripts/swiftlint.sh && scripts/ktlint.sh",
"clean": "del-cli android/build lib && yarn workspace true-sheet-example clean",
"prepare": "bob build",
"release": "release-it"

8
scripts/ktlint.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
if which ktlint >/dev/null; then
cd android && ktlint --color --relative --editorconfig=./.editorconfig -F ./**/*.kt*
else
echo "error: KTLint not installed, install with 'brew install ktlint' (or manually from https://github.com/pinterest/ktlint)"
exit 1
fi

View File

@ -1,8 +0,0 @@
#!/bin/bash
if which swiftformat >/dev/null; then
cd ios && swiftformat --quiet .
else
echo "error: SwiftFormat not installed, install with 'brew install swiftformat' (or manually from https://github.com/nicklockwood/SwiftFormat)"
exit 1
fi

View File

@ -1,8 +1,8 @@
#!/bin/bash
if which swiftlint >/dev/null; then
cd ios && swiftlint --quiet --fix && swiftlint --quiet
cd ios && swiftlint --quiet --fix && swiftlint --quiet && swiftformat --quiet .
else
echo "error: SwiftLint not installed, install with 'brew install swiftlint' (or manually from https://github.com/realm/SwiftLint)"
echo "error: SwiftLint or SwiftFormat not installed, install with 'brew install swiftlint' (or manually from https://github.com/realm/SwiftLint)"
exit 1
fi