Skip to content

Commit 833e06e

Browse files
committed
feat: add showScrollIndicators prop to inline in app message
1 parent 42bb037 commit 833e06e

8 files changed

Lines changed: 64 additions & 2 deletions

File tree

android/src/main/java/io/customer/reactnative/sdk/messaginginapp/InlineInAppMessageViewManager.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ class InlineInAppMessageViewManager :
5050
view?.elementId = value
5151
}
5252

53+
@ReactProp(name = "showScrollIndicators", defaultBoolean = true)
54+
override fun setShowScrollIndicators(view: ReactInlineInAppMessageView?, value: Boolean) {
55+
view?.showScrollIndicators = value
56+
}
57+
5358
companion object {
5459
internal const val NAME = "InlineMessageNative"
5560
}

android/src/main/java/io/customer/reactnative/sdk/messaginginapp/ReactInlineInAppMessageView.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package io.customer.reactnative.sdk.messaginginapp
22

33
import android.content.Context
44
import android.util.AttributeSet
5+
import android.view.View
6+
import android.view.ViewGroup
57
import androidx.annotation.AttrRes
68
import androidx.annotation.StyleRes
79
import io.customer.messaginginapp.type.InAppMessage
@@ -29,6 +31,26 @@ class ReactInlineInAppMessageView @JvmOverloads constructor(
2931
setActionListener(this)
3032
}
3133

34+
var showScrollIndicators: Boolean = true
35+
set(value) {
36+
if (field == value) return
37+
field = value
38+
applyScrollIndicators(this)
39+
}
40+
41+
override fun onViewAdded(child: View) {
42+
super.onViewAdded(child)
43+
applyScrollIndicators(child)
44+
}
45+
46+
private fun applyScrollIndicators(view: View) {
47+
view.isVerticalScrollBarEnabled = showScrollIndicators
48+
view.isHorizontalScrollBarEnabled = showScrollIndicators
49+
if (view is ViewGroup) {
50+
for (i in 0 until view.childCount) applyScrollIndicators(view.getChildAt(i))
51+
}
52+
}
53+
3254
override fun onActionClick(message: InAppMessage, actionValue: String, actionName: String) {
3355
val payload = mapOf(
3456
"message" to mapOf(

api-extractor-output/customerio-reactnative.api.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { TurboModule } from 'react-native';
1414
import type { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes';
1515
import type { ViewProps } from 'react-native';
1616
import { ViewStyle } from 'react-native';
17+
import type { WithDefault } from 'react-native/Libraries/Types/CodegenTypes';
1718

1819
// @public
1920
export type CioConfig = {
@@ -204,13 +205,14 @@ export const InlineInAppMessageView: React_2.FC<InlineInAppMessageViewProps>;
204205
// Warning: (ae-forgotten-export) The symbol "NativeProps" needs to be exported by the entry point index.d.ts
205206
//
206207
// @public (undocumented)
207-
export interface InlineInAppMessageViewProps extends Omit<NativeProps, 'onSizeChange' | 'onStateChange' | 'onActionClick'> {
208+
export interface InlineInAppMessageViewProps extends Omit<NativeProps, 'onSizeChange' | 'onStateChange' | 'onActionClick' | 'showsScrollIndicators'> {
208209
loadingComponent?: React_2.ReactNode;
209210
loadingContainerStyle?: ViewStyle;
210211
loadingIndicatorProps?: ActivityIndicatorProps & {
211212
minimumHeight?: number;
212213
};
213214
onActionClick?: (message: InAppMessage, actionValue: string, actionName: string) => void;
215+
showsScrollIndicators?: boolean;
214216
}
215217

216218
// @public

ios/wrappers/inapp/inline/RCTInlineMessageNative.mm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
5151
// On updates, diff against the parameter rather than _props so we never rely on
5252
// the ivar's runtime type.
5353
BOOL elementIdChanged = YES;
54+
BOOL showsScrollIndicatorsChanged = YES;
5455
if (oldProps) {
5556
const auto &oldViewProps = *std::static_pointer_cast<InlineMessageNativeProps const>(oldProps);
5657
elementIdChanged = oldViewProps.elementId != newViewProps.elementId;
58+
showsScrollIndicatorsChanged = oldViewProps.showsScrollIndicators != newViewProps.showsScrollIndicators;
5759
}
5860

5961
if (elementIdChanged) {
@@ -62,6 +64,11 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
6264
[self.bridge setElementId:elementId];
6365
}
6466

67+
if (showsScrollIndicatorsChanged) {
68+
[self assertBridgeAvailable:@"updating showsScrollIndicators prop"];
69+
[self.bridge setShowsScrollIndicators:newViewProps.showsScrollIndicators];
70+
}
71+
6572
[super updateProps:props oldProps:oldProps];
6673
}
6774

ios/wrappers/inapp/inline/ReactInlineMessageView.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ NS_ASSUME_NONNULL_BEGIN
2828
/// Sets the element ID for the inline message
2929
- (void)setElementId:(NSString *)elementId;
3030

31+
/// Sets container scroll indicators visibility
32+
- (void)setShowsScrollIndicators:(BOOL)showsScrollIndicators;
33+
3134
/// Prepares the view for reuse in React Native lifecycle
3235
- (void)setupForReuse;
3336

ios/wrappers/inapp/inline/ReactInlineMessageView.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import CioMessagingInApp
22
import Foundation
33
import UIKit
4+
import WebKit
45

56
/// React Native wrapper for inline message display with content view lifecycle management.
67
///
@@ -29,6 +30,14 @@ class ReactInlineMessageView: NSObject {
2930
contentView.elementId = elementId
3031
}
3132

33+
private var showScrollIndicators: Bool = true
34+
35+
@objc
36+
func setShowScrollIndicators(_ showScrollIndicators: Bool) {
37+
self.showScrollIndicators = showScrollIndicators
38+
applyScrollIndicators(in: contentView)
39+
}
40+
3241
@objc
3342
func setupForReuse() {
3443
contentView.onViewAttached()
@@ -106,6 +115,7 @@ extension ReactInlineMessageView: InlineMessageBridgeViewDelegate {
106115
}
107116

108117
func onMessageSizeChanged(width: CGFloat, height: CGFloat) {
118+
applyScrollIndicators(in: contentView)
109119
sendOnSizeChangeEvent(width: width, height: height)
110120
}
111121

@@ -114,11 +124,20 @@ extension ReactInlineMessageView: InlineMessageBridgeViewDelegate {
114124
}
115125

116126
func onStartLoading(onComplete: @escaping () -> Void) {
127+
applyScrollIndicators(in: contentView)
117128
sendOnStateChangeEvent(state: .loadingStarted)
118129
onComplete()
119130
}
120131

121132
func onFinishLoading() {
122133
sendOnStateChangeEvent(state: .loadingFinished)
123134
}
135+
136+
private func applyScrollIndicators(in view: UIView) {
137+
if let webView = view as? WKWebView {
138+
webView.scrollView.showsVerticalScrollIndicator = showScrollIndicators
139+
webView.scrollView.showsHorizontalScrollIndicator = showScrollIndicators
140+
}
141+
view.subviews.forEach { applyScrollIndicators(in: $0) }
142+
}
124143
}

src/components/InlineInAppMessageView.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import type { InAppMessage } from '../types';
2222
/** @public */
2323
export interface InlineInAppMessageViewProps extends Omit<
2424
NativeProps,
25-
'onSizeChange' | 'onStateChange' | 'onActionClick'
25+
'onSizeChange' | 'onStateChange' | 'onActionClick' | 'showScrollIndicators'
2626
> {
2727
/** Custom loading component to display while message is loading */
2828
loadingComponent?: React.ReactNode;
@@ -33,6 +33,8 @@ export interface InlineInAppMessageViewProps extends Omit<
3333
};
3434
/** Custom styles for the loading container */
3535
loadingContainerStyle?: ViewStyle;
36+
/** Controls whether the inline message's scroll indicators are visible. (default: true) */
37+
showScrollIndicators?: boolean;
3638
/** Callback triggered when a user clicks an action button in the inline message */
3739
onActionClick?: (
3840
message: InAppMessage,

src/specs/components/InlineMessageNativeComponent.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { HostComponent, ViewProps } from 'react-native';
88
import type {
99
DirectEventHandler,
1010
Double,
11+
WithDefault,
1112
} from 'react-native/Libraries/Types/CodegenTypes';
1213
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
1314

@@ -46,6 +47,7 @@ export interface ActionClickEvent {
4647
export interface NativeProps extends ViewProps {
4748
/** Required element ID for retrieving inline message content. */
4849
elementId: string;
50+
showScrollIndicators?: WithDefault<boolean, true>;
4951
onSizeChange: DirectEventHandler<SizeChangeEvent>;
5052
onStateChange?: DirectEventHandler<StateChangeEvent>;
5153
onActionClick?: DirectEventHandler<ActionClickEvent>;

0 commit comments

Comments
 (0)