Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setLocalMobileUxConfiguration. #778

Merged
merged 7 commits into from
Aug 10, 2024
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
30 changes: 30 additions & 0 deletions android/src/main/java/com/stripeterminalreactnative/Mappers.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.stripeterminalreactnative

import android.graphics.Color
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableArray
Expand All @@ -21,6 +22,7 @@ import com.stripe.stripeterminal.external.models.ConnectionStatus
import com.stripe.stripeterminal.external.models.DeviceType
import com.stripe.stripeterminal.external.models.DisconnectReason
import com.stripe.stripeterminal.external.models.EmailResult
import com.stripe.stripeterminal.external.models.LocalMobileUxConfiguration
import com.stripe.stripeterminal.external.models.Location
import com.stripe.stripeterminal.external.models.LocationStatus
import com.stripe.stripeterminal.external.models.NetworkStatus
Expand Down Expand Up @@ -888,3 +890,31 @@ fun mapFromCollectDataType(type: String): CollectDataType? {
else -> null
}
}

fun mapToTapZoneIndicator(indicator: String?): LocalMobileUxConfiguration.TapZoneIndicator {
return when (indicator) {
"default" -> LocalMobileUxConfiguration.TapZoneIndicator.DEFAULT
"above" -> LocalMobileUxConfiguration.TapZoneIndicator.ABOVE
"below" -> LocalMobileUxConfiguration.TapZoneIndicator.BELOW
"front" -> LocalMobileUxConfiguration.TapZoneIndicator.FRONT
"behind" -> LocalMobileUxConfiguration.TapZoneIndicator.BEHIND
else -> LocalMobileUxConfiguration.TapZoneIndicator.DEFAULT
}
}

fun mapToDarkMode(mode: String?): LocalMobileUxConfiguration.DarkMode {
return when (mode) {
"dark" -> LocalMobileUxConfiguration.DarkMode.DARK
"light" -> LocalMobileUxConfiguration.DarkMode.LIGHT
"system" -> LocalMobileUxConfiguration.DarkMode.SYSTEM
else -> LocalMobileUxConfiguration.DarkMode.LIGHT
}
}

fun hexToArgb(color: String): Int {
return try {
Color.parseColor(color)
} catch (e: IllegalArgumentException) {
throw IllegalArgumentException("Invalid ARGB hex format", e)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ import com.stripe.stripeterminal.external.models.CollectConfiguration
import com.stripe.stripeterminal.external.models.CollectDataConfiguration
import com.stripe.stripeterminal.external.models.CollectInputsParameters
import com.stripe.stripeterminal.external.models.ConfirmConfiguration
import com.stripe.stripeterminal.external.models.ConnectionStatus
import com.stripe.stripeterminal.external.models.CreateConfiguration
import com.stripe.stripeterminal.external.models.DiscoveryConfiguration
import com.stripe.stripeterminal.external.models.EmailInput
import com.stripe.stripeterminal.external.models.Input
import com.stripe.stripeterminal.external.models.ListLocationsParameters
import com.stripe.stripeterminal.external.models.LocalMobileUxConfiguration
import com.stripe.stripeterminal.external.models.NumericInput
import com.stripe.stripeterminal.external.models.OfflineBehavior
import com.stripe.stripeterminal.external.models.PaymentIntent
Expand Down Expand Up @@ -778,7 +778,7 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) :
val refundApplicationFee = params.getBoolean("refundApplicationFee")
val reverseTransfer = params.getBoolean("reverseTransfer")

var intentParamsBuild = if (!paymentIntentId.isNullOrBlank()) {
val intentParamsBuild = if (!paymentIntentId.isNullOrBlank()) {
RefundParameters.Builder(
RefundParameters.Id.PaymentIntent(paymentIntentId),
amount,
Expand Down Expand Up @@ -860,7 +860,7 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) :
@ReactMethod
@Suppress("unused")
fun getConnectedReader(promise: Promise) {
promise.resolve((terminal.connectedReader ?: null)?.let { mapFromReader(it) })
promise.resolve(terminal.connectedReader?.let { mapFromReader(it) })
}

@ReactMethod
Expand All @@ -875,7 +875,7 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) :
val textToSpeechViaSpeakers = requireParam(getBoolean(params, "textToSpeechViaSpeakers")) {
"You must provide textToSpeechViaSpeakers parameters."
}
var readerSettingsParameters = ReaderSettingsParameters.AccessibilityParameters(
val readerSettingsParameters = ReaderSettingsParameters.AccessibilityParameters(
textToSpeechViaSpeakers
)
terminal.setReaderSettings(readerSettingsParameters, RNReadSettingsCallback(promise))
Expand Down Expand Up @@ -1082,6 +1082,51 @@ class StripeTerminalReactNativeModule(reactContext: ReactApplicationContext) :
promise.resolve(mapFromReaderSupportResult(readerSupportResult))
}

@ReactMethod
@Suppress("unused")
fun setLocalMobileUxConfiguration(params: ReadableMap, promise: Promise) = withExceptionResolver(promise) {
val localMobileUxConfigurationBuilder = LocalMobileUxConfiguration.Builder()

var tapZone: LocalMobileUxConfiguration.TapZone? = null
val tapZoneParam = params.getMap("tapZone")
tapZoneParam?.let {
val tapZoneIndicator = mapToTapZoneIndicator(tapZoneParam.getString("tapZoneIndicator"))

val tapZonePosition = tapZoneParam.getMap("tapZonePosition")?.let {
LocalMobileUxConfiguration.TapZonePosition.Manual(
it.getDouble("xBias").toFloat(),
it.getDouble("yBias").toFloat())
} ?: LocalMobileUxConfiguration.TapZonePosition.Default

tapZone = LocalMobileUxConfiguration.TapZone.Manual.Builder()
.indicator(tapZoneIndicator)
.position(tapZonePosition)
.build()
}
localMobileUxConfigurationBuilder.tapZone(tapZone?:LocalMobileUxConfiguration.TapZone.Default)

val colorsParam = params.getMap("colors")
colorsParam?.let {
val colorSchemeBuilder = LocalMobileUxConfiguration.ColorScheme.Builder()
colorSchemeBuilder.apply {
primary(it.getString("primary").toLocalMobileColor())
success(it.getString("success").toLocalMobileColor())
error(it.getString("error").toLocalMobileColor())
}
localMobileUxConfigurationBuilder.colors(colorSchemeBuilder.build())
}

localMobileUxConfigurationBuilder.darkMode(mapToDarkMode(params.getString("darkMode")))

terminal.setLocalMobileUxConfiguration(localMobileUxConfigurationBuilder.build())
}

private fun String?.toLocalMobileColor(): LocalMobileUxConfiguration.Color {
return this
?.let { LocalMobileUxConfiguration.Color.Value(hexToArgb(it)) }
?: LocalMobileUxConfiguration.Color.Default
}

@ReactMethod
fun addListener(eventName: String?) {
// Set up any upstream listeners or background tasks as necessary
Expand Down
4 changes: 4 additions & 0 deletions src/StripeTerminalSdk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import type {
CancelPaymentMethodParams,
CollectDataParams,
CollectDataResultType,
LocalMobileUxConfiguration,
} from './types';

const { StripeTerminalReactNative } = NativeModules;
Expand Down Expand Up @@ -171,6 +172,9 @@ export interface StripeTerminalSdkType {
supportsReadersOfType(
params: Reader.ReaderSupportParams
): Promise<Reader.ReaderSupportResult>;
setLocalMobileUxConfiguration(params: LocalMobileUxConfiguration): Promise<{
error?: StripeError;
}>;
}

export default StripeTerminalReactNative as StripeTerminalSdkType;
1 change: 1 addition & 0 deletions src/__tests__/__snapshots__/functions.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Object {
"retrievePaymentIntent": [Function],
"retrieveSetupIntent": [Function],
"setConnectionToken": [Function],
"setLocalMobileUxConfiguration": [Function],
"setReaderDisplay": [Function],
"setReaderSettings": [Function],
"setSimulatedCard": [Function],
Expand Down
12 changes: 12 additions & 0 deletions src/__tests__/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ Object {
"Failed": "Failed",
"Unknown": "Unknown",
},
"DarkMode": Object {
"DARK": "dark",
"LIGHT": "light",
"SYSTEM": "system",
},
"FETCH_TOKEN_PROVIDER": "FETCH_TOKEN_PROVIDER",
"FINISH_DISCOVERING_READERS": "FINISH_DISCOVERING_READERS",
"FINISH_INSTALLING_UPDATE": "FINISH_INSTALLING_UPDATE",
Expand Down Expand Up @@ -56,6 +61,13 @@ Object {
},
"StripeTerminalProvider": [Function],
"StripeTerminalProviderProps": undefined,
"TapZoneIndicator": Object {
"ABOVE": "above",
"BEHIND": "behind",
"BELOW": "below",
"DEFAULT": "default",
"FRONT": "front",
},
"ToggleResult": Object {
"DISABLED": "disabled",
"ENABLED": "enabled",
Expand Down
29 changes: 29 additions & 0 deletions src/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ import type {
CancelPaymentMethodParams,
CollectDataParams,
CollectDataResultType,
LocalMobileUxConfiguration,
} from './types';
import { CommonError } from './types';
import { Platform } from 'react-native';

export async function initialize(
params: InitParams
Expand Down Expand Up @@ -941,3 +944,29 @@ export async function supportsReadersOfType(
}
}, 'supportsReadersOfType')();
}

export async function setLocalMobileUxConfiguration(
params: LocalMobileUxConfiguration
): Promise<{
error?: StripeError;
}> {
if (Platform.OS === 'ios') {
return {
error: {
message: "'setLocalMobileUxConfiguration' is unsupported on iOS",
code: CommonError.Failed,
},
};
}

return Logger.traceSdkMethod(async () => {
try {
await StripeTerminalSdk.setLocalMobileUxConfiguration(params);
return {};
} catch (error) {
return {
error: error as any,
};
}
}, 'setLocalMobileUxConfiguration')();
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Object {
"rebootReader": [Function],
"retrievePaymentIntent": [Function],
"retrieveSetupIntent": [Function],
"setLocalMobileUxConfiguration": [Function],
"setReaderDisplay": [Function],
"setReaderSettings": [Function],
"setSimulatedCard": [Function],
Expand Down
20 changes: 20 additions & 0 deletions src/hooks/useStripeTerminal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
CancelSetupIntentMethodParams,
CancelPaymentMethodParams,
CollectDataParams,
LocalMobileUxConfiguration,
} from '../types';
import {
discoverReaders,
Expand Down Expand Up @@ -72,6 +73,7 @@ import {
getPaymentStatus,
getConnectionStatus,
getConnectedReader,
setLocalMobileUxConfiguration,
} from '../functions';
import { StripeTerminalContext } from '../components/StripeTerminalContext';
import { useListener } from './useListener';
Expand Down Expand Up @@ -1043,6 +1045,23 @@ export function useStripeTerminal(props?: Props) {
[_isInitialized, setLoading]
);

const _setLocalMobileUxConfiguration = useCallback(
async (params: LocalMobileUxConfiguration) => {
if (!_isInitialized()) {
console.error(NOT_INITIALIZED_ERROR_MESSAGE);
throw Error(NOT_INITIALIZED_ERROR_MESSAGE);
}
setLoading(true);

const response = await setLocalMobileUxConfiguration(params);

setLoading(false);

return response;
},
[_isInitialized, setLoading]
);

return {
initialize: _initialize,
discoverReaders: _discoverReaders,
Expand Down Expand Up @@ -1088,6 +1107,7 @@ export function useStripeTerminal(props?: Props) {
collectData: _collectData,
cancelReaderReconnection: _cancelReaderReconnection,
supportsReadersOfType: _supportsReadersOfType,
setLocalMobileUxConfiguration: _setLocalMobileUxConfiguration,
emitter: emitter,
discoveredReaders,
connectedReader,
Expand Down
36 changes: 36 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,3 +517,39 @@ export type CollectDataResultType =
collectedData?: undefined;
error: StripeError;
};

export type LocalMobileUxConfiguration = {
chr-stripe marked this conversation as resolved.
Show resolved Hide resolved
tapZone?: TapZone;
darkMode?: DarkMode;
colors?: Colors;
};

export type TapZone = {
tapZoneIndicator?: TapZoneIndicator;
tapZonePosition?: TapZonePosition;
};

export type TapZonePosition = {
xBias: number;
yBias: number;
};

export enum TapZoneIndicator {
DEFAULT = 'default',
ABOVE = 'above',
BELOW = 'below',
FRONT = 'front',
BEHIND = 'behind',
}

export type Colors = {
primary?: string;
success?: string;
error?: string;
};

export enum DarkMode {
DARK = 'dark',
LIGHT = 'light',
SYSTEM = 'system',
}