Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -501,9 +501,9 @@
}
lastEmittedPageSelected = position
clearFocusOutsidePage(position)
UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)?.dispatchEvent(
PageSelectedEvent(id, position)
PageSelectedEvent(UIManagerHelper.getSurfaceId(this), id, position)
)

Check notice on line 506 in android/src/main/java/com/reactnativepagerview/ComposePagerView.kt

View check run for this annotation

apex-sentinel-staging / Apex Sentinel

nit: Surface id resolved from the view instead of the ReactContext the dispatch already uses

All three dispatch sites now compute the surface id with `UIManagerHelper.getSurfaceId(this)` while the dispatcher is still obtained from `UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)`. `this` (the ComposePagerView) is constructed with a plain `ReactContext` (`createViewInstance` passes the `ThemedReactContext`, and the context is not necessarily a `ContextBase` carrying a surface id at view-construction time), and its `id` is generated locally in `init` (`id = View.generateViewId()`), i.e. it is not guaranteed to be a Fabric react tag registered in the tag registry that the View overload uses to find the surface. In those cases the overload returns the "unset" surface id (-1) and the event is dispatched with a surfaceId that does not match the dispatcher's surface, so `onPageScroll` / `onPageSelected` / `onPageScrollStateChanged` are dropped in multi-surface apps (e.g. a pager inside a `Modal` or a second surface created with `AppRegistry.runApplication`). The context used for the dispatcher is right there and is the authoritative source of the surface id for that dispatcher. ### Also raised here Also raised at this location by senior-developer: surfaceId taken from the view can be -1 while the pager is detached, dropping events — The three dispatch sites now read `UIManagerHelper.getSurfaceId(this)` from the `ComposePagerView` itself. This view is deliberately kept alive while detached from the window (see the `composeLifecycleOwner` comment at ComposePagerView\.kt:57-67: react-native-screens removes and re-adds the fragment view, and the Compose composition survives it), and scroll work is intentionally scheduled on the UI-thread handler rather than `View.post` precisely because "View\.post would wait while the pager is detached" (setCurrentItem, ComposePagerView\.kt:480-495). So `dispatchPageScroll` / `dispatchPageSelected` / `dispatchScrollState` can run at times when the view is not mounted, in which case a surface id derived from the vie…
}

private fun clearFocusOutsidePage(position: Int) {
Expand All @@ -529,7 +529,7 @@

private fun dispatchPageScroll(position: Int, offset: Float) {
UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)?.dispatchEvent(
PageScrollEvent(id, position, offset)
PageScrollEvent(UIManagerHelper.getSurfaceId(this), id, position, offset)
)
}

Expand All @@ -539,7 +539,7 @@
}
lastEmittedScrollState = state
UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)?.dispatchEvent(
PageScrollStateChangedEvent(id, state)
PageScrollStateChangedEvent(UIManagerHelper.getSurfaceId(this), id, state)
)
}

Expand Down Expand Up @@ -648,7 +648,6 @@
modifier = Modifier.fillMaxSize(),

@apex-sentinel-staging apex-sentinel-staging Bot Nov 2, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer raised on 58496ba.

🔵 Nit · reverseLayout = false removals are unrelated to this PR's scope

Dropping the explicit reverseLayout = false in both HorizontalPager calls is a no-op (the default is false), but it is a Compose API change bundled into a PR whose title is about deprecated event/package APIs; it also silently changes behavior on any Compose Foundation version where the parameter has no default. Split it into its own commit so a bisect over Android event regressions does not land on it.

Suggested change

Move the two reverseLayout = false removals into a separate commit (or keep them and mention them in the PR description).

Details

persona: maintainability, senior-developer

Reply @apex-sentinel-staging note ... to add context, or @apex-sentinel-staging pivot ... if this is wrong — I will re-check the cited code.

Useful? Reply @apex-sentinel-staging like, or @apex-sentinel-staging dislike <why> if it is not.

pageSpacing = pageSpacing,
userScrollEnabled = scrollEnabledState.value,
reverseLayout = false,
Comment thread
krozniata marked this conversation as resolved.
Resolved
beyondViewportPageCount = beyondViewportPageCount,
key = pageKey
) { page ->
Expand All @@ -660,7 +659,6 @@
modifier = Modifier.fillMaxSize(),
pageSpacing = pageSpacing,
userScrollEnabled = scrollEnabledState.value,
reverseLayout = false,
beyondViewportPageCount = beyondViewportPageCount,
key = pageKey
) { page ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.reactnativepagerview

import android.view.View
import android.view.ViewGroup
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.*
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.ViewManagerDelegate
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.viewmanagers.RNCViewPagerManagerDelegate
import com.facebook.react.viewmanagers.RNCViewPagerManagerInterface
Expand All @@ -16,21 +16,18 @@
@ReactModule(name = PagerViewViewManager.NAME)
class PagerViewViewManager : ViewGroupManager<ComposePagerView>(), RNCViewPagerManagerInterface<ComposePagerView> {
companion object {
const val NAME = "RNCViewPager"

Check failure on line 19 in android/src/main/java/com/reactnativepagerview/PagerViewViewManager.kt

View check run for this annotation

apex-sentinel-staging / Apex Sentinel

major: Removed receiveCommand override may stop JS commands from reaching the delegate

The PR deletes the explicit `override fun receiveCommand(root, commandId, args) { mDelegate.receiveCommand(root, commandId, args) }`, leaving command dispatch to whatever the base class does with `getDelegate()`. Every command this library exposes goes through that path — `Commands.setPage`, `setPageWithoutAnimation` and `setScrollEnabledImperatively` are called from `src/PagerView.tsx:93/98/106` — and the delegate (`RNCViewPagerManagerDelegate`) is the only thing that maps a command name string to `setPage`/`setPageWithoutAnimation`/`setScrollEnabledImperatively`. If the RN version's `ViewGroupManager`/`BaseViewManager.receiveCommand` does not forward to `getDelegate().receiveCommand(...)` (community view managers have historically had to write exactly that override, which is why it was there), all three imperative methods become silent no-ops: no crash, no error, `ref.setPage(3)` just does nothing. This is the more worrying case because commit ce0d489 (#​1212) just fixed `setPage` timing, i.e. this path is known-fragile. I could not verify the RN 0.88 base-class behaviour in this checkout (no node\_modules / RN sources available), so confidence is not full — but the merge should be gated on an actual run of the example app's `setPage`/`setPageWithoutAnimation`/`setScrollEnabledImperatively` (e2e covers these) rather than on the Kotlin compiling.

@apex-sentinel-staging apex-sentinel-staging Bot Nov 2, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Major · Removed receiveCommand override may stop JS commands from reaching the delegate

The PR deletes the explicit override fun receiveCommand(root, commandId, args) { mDelegate.receiveCommand(root, commandId, args) }, leaving command dispatch to whatever the base class does with getDelegate(). Every command this library exposes goes through that path — Commands.setPage, setPageWithoutAnimation and setScrollEnabledImperatively are called from src/PagerView.tsx:93/98/106 — and the delegate (RNCViewPagerManagerDelegate) is the only thing that maps a command name string to setPage/setPageWithoutAnimation/setScrollEnabledImperatively. If the RN version's ViewGroupManager/BaseViewManager.receiveCommand does not forward to getDelegate().receiveCommand(...) (community view managers have historically had to write exactly that override, which is why it was there), all three imperative methods become silent no-ops: no crash, no error, ref.setPage(3) just does nothing. This is the more worrying case because commit ce0d489 (#​1212) just fixed setPage timing, i.e. this path is known-fragile. I could not verify the RN 0.88 base-class behaviour in this checkout (no node_modules / RN sources available), so confidence is not full — but the merge should be gated on an actual run of the example app's setPage/setPageWithoutAnimation/setScrollEnabledImperatively (e2e covers these) rather than on the Kotlin compiling.

Suggested change

Either keep the explicit receiveCommand override delegating to delegate.receiveCommand(root, commandId, args), or confirm against the RN version in example (0.88.0) that the base manager forwards commands through getDelegate(), and run the example/e2e suite exercising setPage, setPageWithoutAnimation and setScrollEnabledImperatively.

Details

persona: senior-developer

Reply @apex-sentinel-staging note ... to add context, or @apex-sentinel-staging pivot ... if this is wrong — I will re-check the cited code.

Useful? Reply @apex-sentinel-staging like, or @apex-sentinel-staging dislike <why> if it is not.

}

private val mDelegate: ViewManagerDelegate<ComposePagerView> = RNCViewPagerManagerDelegate(this)
private val delegate: RNCViewPagerManagerDelegate<ComposePagerView, PagerViewViewManager> =
RNCViewPagerManagerDelegate(this)

override fun getDelegate() = mDelegate
override fun getDelegate(): ViewManagerDelegate<ComposePagerView> = delegate

override fun getName(): String {
return NAME
}

override fun receiveCommand(root: ComposePagerView, commandId: String, args: ReadableArray?) {
mDelegate.receiveCommand(root, commandId, args)
}

public override fun createViewInstance(reactContext: ThemedReactContext): ComposePagerView {
return ComposePagerView(reactContext)
}
Expand Down Expand Up @@ -67,83 +64,64 @@
}

@ReactProp(name = "scrollEnabled", defaultBoolean = true)
override fun setScrollEnabled(view: ComposePagerView?, value: Boolean) {
if (view != null) {
view.setScrollEnabled(value)
}
override fun setScrollEnabled(view: ComposePagerView, value: Boolean) {
view.setScrollEnabled(value)
}

@ReactProp(name = "layoutDirection")
override fun setLayoutDirection(view: ComposePagerView?, value: String?) {
if (view != null && value != null) {
override fun setLayoutDirection(view: ComposePagerView, value: String?) {
if (value != null) {
view.setLayoutDirection(value)
}
}

@ReactProp(name = "initialPage", defaultInt = 0)
override fun setInitialPage(view: ComposePagerView?, value: Int) {
if (view != null) {
view.setInitialPage(value)
}
override fun setInitialPage(view: ComposePagerView, value: Int) {
view.setInitialPage(value)
}

@ReactProp(name = "orientation")
override fun setOrientation(view: ComposePagerView?, value: String?) {
if (view != null && value != null) {
override fun setOrientation(view: ComposePagerView, value: String?) {
if (value != null) {
view.setOrientation(value)
}
}

@ReactProp(name = "offscreenPageLimit", defaultInt = -1)
override fun setOffscreenPageLimit(view: ComposePagerView?, value: Int) {
if (view != null) {
view.setOffscreenPageLimit(value)
}
override fun setOffscreenPageLimit(view: ComposePagerView, value: Int) {
view.setOffscreenPageLimit(value)
}

@ReactProp(name = "pageMargin", defaultInt = 0)
override fun setPageMargin(view: ComposePagerView?, value: Int) {
if (view != null) {
view.setPageMargin(value)
}
override fun setPageMargin(view: ComposePagerView, value: Int) {
view.setPageMargin(value)
}

@ReactProp(name = "overScrollMode")
override fun setOverScrollMode(view: ComposePagerView?, value: String?) {
if (view != null && value != null) {
override fun setOverScrollMode(view: ComposePagerView, value: String?) {
if (value != null) {
view.setOverScrollMode(value)
}
}

@apex-sentinel-staging apex-sentinel-staging Bot Nov 2, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer raised on 58496ba.

🔵 Nit · No-op prop stubs carry inconsistent one-line comments that point outside the module

setOverdrag and setKeyboardDismissMode keep their @ReactProp annotations and gained only an explanatory comment ("iOS only." / "Dismissed from JS on Android, see PagerView.tsx.") instead of the no-op bodies being removed. That is fine for JS compat, but the two comments use different conventions for the same kind of note and neither states what a caller should expect if they do pass the prop on Android; a reader grepping overdrag in the Android module now gets a one-line pointer to a TS file in another package. A short comment naming the JS-side file path (or a link) makes the stub self-explanatory.

Suggested change

Use one comment style for both Android no-op props and point at the file that already handles the behaviour (lib/src/PagerView.tsx) rather than a bare "see PagerView.tsx".

Details

persona: maintainability

Reply @apex-sentinel-staging note ... to add context, or @apex-sentinel-staging pivot ... if this is wrong — I will re-check the cited code.

Useful? Reply @apex-sentinel-staging like, or @apex-sentinel-staging dislike <why> if it is not.

// iOS only.
@ReactProp(name = "overdrag")
override fun setOverdrag(view: ComposePagerView?, value: Boolean) {
return
}
override fun setOverdrag(view: ComposePagerView, value: Boolean) = Unit

// Dismissed from JS on Android, see PagerView.tsx.
@ReactProp(name = "keyboardDismissMode")
override fun setKeyboardDismissMode(view: ComposePagerView?, value: String?) {
return
}

fun goTo(root: ComposePagerView?, selectedPage: Int, scrollWithAnimation: Boolean) {
if (root == null) {
return
}
root.setCurrentItem(selectedPage, scrollWithAnimation)
}
override fun setKeyboardDismissMode(view: ComposePagerView, value: String?) = Unit
Comment thread
krozniata marked this conversation as resolved.
Resolved

override fun setPage(view: ComposePagerView?, selectedPage: Int) {
goTo(view, selectedPage, true)
override fun setPage(view: ComposePagerView, selectedPage: Int) {
view.setCurrentItem(selectedPage, true)

Check notice on line 116 in android/src/main/java/com/reactnativepagerview/PagerViewViewManager.kt

View check run for this annotation

apex-sentinel-staging / Apex Sentinel

nit: Comment cites PagerView\.tsx for a native Android prop

`// Dismissed from JS on Android, see PagerView.tsx.` points an Android-native reader at a TypeScript file two layers up, and "dismissed" doesn't say what happens to the prop: keyboardDismissMode is still declared in the generated RNCViewPagerManagerInterface (this override exists to satisfy it), it is just a no-op on Android. "Ignored on Android (handled in JS / not implemented); prop kept for interface conformance" would tell the next maintainer whether deleting this override is even possible.
}

override fun setPageWithoutAnimation(view: ComposePagerView?, selectedPage: Int) {
goTo(view, selectedPage, false)
override fun setPageWithoutAnimation(view: ComposePagerView, selectedPage: Int) {
view.setCurrentItem(selectedPage, false)
}

override fun setScrollEnabledImperatively(view: ComposePagerView?, scrollEnabled: Boolean) {
if (view != null) {
view.setScrollEnabled(scrollEnabled)
}
override fun setScrollEnabledImperatively(view: ComposePagerView, scrollEnabled: Boolean) {
view.setScrollEnabled(scrollEnabled)
}

override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> = mutableMapOf(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package com.reactnativepagerview

import com.facebook.react.ReactPackage
import com.facebook.react.BaseReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.model.ReactModuleInfoProvider
import com.facebook.react.uimanager.ViewManager


class PagerViewPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return emptyList()
}

class PagerViewPackage : BaseReactPackage() {
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return listOf(PagerViewViewManager())
}

// The package only provides a view manager.
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? = null

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🆕 🔵 Nit · getReactModuleInfoProvider() returns an empty map, bypassing generated module info

PagerViewPackage now extends BaseReactPackage but overrides getReactModuleInfoProvider() to return ReactModuleInfoProvider { emptyMap() }. RN's BaseReactPackage implements this by returning the annotation-processor-generated ReactPackageSupport.getReactModuleInfo(...) map, so this override throws away generated metadata for any @​ReactModule-annotated class in this package (PagerViewViewManager carries @​ReactModule(NAME)) and will silently swallow the metadata of every module a future version adds here — the module lookup/info path has to be updated by hand, and the empty map is exactly the kind of thing that drifts. Returning the inherited implementation (i.e. deleting this override) keeps the package module-free today and stays correct later.

Suggested change

Drop the getReactModuleInfoProvider() override and rely on BaseReactPackage's generated ReactPackageSupport-backed implementation; only supply a custom provider if a native module is actually added to this package.

Details

persona: maintainability

Reply @apex-sentinel-staging note ... to add context, or @apex-sentinel-staging pivot ... if this is wrong — I will re-check the cited code.

Useful? Reply @apex-sentinel-staging like, or @apex-sentinel-staging dislike <why> if it is not.

override fun getReactModuleInfoProvider() = ReactModuleInfoProvider { emptyMap() }

Check notice on line 18 in android/src/main/java/com/reactnativepagerview/PagerViewViewPackage.kt

View check run for this annotation

apex-sentinel-staging / Apex Sentinel

nit: getReactModuleInfoProvider() returns an empty map, bypassing generated module info

PagerViewPackage now extends BaseReactPackage but overrides getReactModuleInfoProvider() to return `ReactModuleInfoProvider { emptyMap() }`. RN's BaseReactPackage implements this by returning the annotation-processor-generated `ReactPackageSupport.getReactModuleInfo(...)` map, so this override throws away generated metadata for any @​ReactModule-annotated class in this package (PagerViewViewManager carries @​ReactModule(NAME)) and will silently swallow the metadata of every module a future version adds here — the module lookup/info path has to be updated by hand, and the empty map is exactly the kind of thing that drifts. Returning the inherited implementation (i.e. deleting this override) keeps the package module-free today and stays correct later.
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,27 @@ package com.reactnativepagerview.event
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.events.RCTEventEmitter
import java.lang.Float.isInfinite
import java.lang.Float.isNaN


/**
* Event emitted by [ReactViewPager] when user scrolls between pages (or when animating
* between pages).
* Event emitted by [com.reactnativepagerview.ComposePagerView] when user scrolls between pages
* (or when animating between pages).
*
* Additional data provided by this event:
* - position - index of first page from the left that is currently visible
* - offset - value from range [0,1) describing stage between page transitions. Value x means that
* (1 - x) fraction of the page at "position" index is visible, and x fraction of the next page
* is visible.
*/
class PageScrollEvent(viewTag: Int, private val mPosition: Int, offset: Float) : Event<PageScrollEvent>(viewTag) {
private val mOffset: Float = if (isInfinite(offset) || isNaN(offset)) 0.0f else offset
class PageScrollEvent(surfaceId: Int, viewTag: Int, private val mPosition: Int, offset: Float) : Event<PageScrollEvent>(surfaceId, viewTag) {
// folly::toJson default options don't support serialize NaN or Infinite value
private val mOffset: Float = if (offset.isFinite()) offset else 0.0f

override fun getEventName(): String {
return EVENT_NAME
}

override fun dispatch(rctEventEmitter: RCTEventEmitter) {
rctEventEmitter.receiveEvent(viewTag, eventName, serializeEventData())
}

private fun serializeEventData(): WritableMap {
override fun getEventData(): WritableMap {
val eventData = Arguments.createMap()
eventData.putInt("position", mPosition)
eventData.putDouble("offset", mOffset.toDouble())
Expand All @@ -38,10 +33,4 @@ class PageScrollEvent(viewTag: Int, private val mPosition: Int, offset: Float) :
companion object {
const val EVENT_NAME = "topPageScroll"
}

init {

// folly::toJson default options don't support serialize NaN or Infinite value
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,24 @@
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.events.RCTEventEmitter


/**
* Event emitted by [ReactViewPager] when user scrolling state changed.
* Event emitted by [com.reactnativepagerview.ComposePagerView] when user scrolling state changed.
*
* Additional data provided by this event:
* - pageScrollState - {Idle,Dragging,Settling}
*/
class PageScrollStateChangedEvent(viewTag: Int, private val mPageScrollState: String) : Event<PageScrollStateChangedEvent>(viewTag) {
class PageScrollStateChangedEvent(surfaceId: Int, viewTag: Int, private val mPageScrollState: String) : Event<PageScrollStateChangedEvent>(surfaceId, viewTag) {
override fun getEventName(): String {
return EVENT_NAME
}
Comment thread
krozniata marked this conversation as resolved.
Resolved

override fun dispatch(rctEventEmitter: RCTEventEmitter) {
rctEventEmitter.receiveEvent(viewTag, eventName, serializeEventData())
override fun canCoalesce(): Boolean {

Check notice on line 19 in android/src/main/java/com/reactnativepagerview/event/PageScrollStateChangedEvent.kt

View check run for this annotation

apex-sentinel-staging / Apex Sentinel

nit: canCoalesce() = false added only to PageScrollStateChangedEvent is an undocumented event-delivery change

PageScrollStateChangedEvent previously used Event's default canCoalesce() (true); the rewrite to getEventData() also adds `canCoalesce() = false`, so rapid state sequences that used to collapse into the last event per frame are now all dispatched to JS — a visible change in how often onPageScrollStateChanged fires, and the PR (and its empty description) says nothing about it. The new rule is also inconsistent across the three events touched: PageScrollEvent leaves the default true while PageSelectedEvent and this one opt out. Either justify it in the PR (and README event docs) or make the coalescing policy uniform across the three classes this PR rewrites.
return false
}

private fun serializeEventData(): WritableMap {
override fun getEventData(): WritableMap {
val eventData = Arguments.createMap()
eventData.putString("pageScrollState", mPageScrollState)
return eventData
Expand All @@ -30,5 +29,4 @@
companion object {
const val EVENT_NAME = "topPageScrollStateChanged"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,24 @@ package com.reactnativepagerview.event
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.events.RCTEventEmitter


/**
* Event emitted by [ReactViewPager] when selected page changes.
* Event emitted by [com.reactnativepagerview.ComposePagerView] when selected page changes.
*
* Additional data provided by this event:
* - position - index of page that has been selected
*/
class PageSelectedEvent(viewTag: Int, private val mPosition: Int) : Event<PageSelectedEvent>(viewTag) {
class PageSelectedEvent(surfaceId: Int, viewTag: Int, private val mPosition: Int) : Event<PageSelectedEvent>(surfaceId, viewTag) {
override fun getEventName(): String {
return EVENT_NAME
}

override fun canCoalesce(): Boolean {
return false
return false
}

override fun dispatch(rctEventEmitter: RCTEventEmitter) {
rctEventEmitter.receiveEvent(viewTag, eventName, serializeEventData())
}

private fun serializeEventData(): WritableMap {
override fun getEventData(): WritableMap {
val eventData = Arguments.createMap()
eventData.putInt("position", mPosition)
return eventData
Expand All @@ -34,5 +29,4 @@ class PageSelectedEvent(viewTag: Int, private val mPosition: Int) : Event<PageSe
companion object {
const val EVENT_NAME = "topPageSelected"
}

}
Loading