Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions examples/demo/src/components/ActionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export default function ActionButton({
<TouchableOpacity
onPress={onPress}
disabled={disabled || loading}
accessibilityRole="button"
accessibilityLabel={label}
accessibilityState={{ disabled: !!(disabled || loading), busy: !!loading }}
testID={testID}
style={[
styles.button,
Expand Down
4 changes: 3 additions & 1 deletion examples/demo/src/components/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function AppHeader({ options, back }: NativeStackHeaderProps) {
typeof options.headerTitle === 'function' ? (
options.headerTitle({ children: options.title ?? '', tintColor: AppColors.white })
) : (
<Text style={styles.title}>{options.title ?? ''}</Text>
<Text style={styles.title}>{options.headerTitle ?? options.title ?? ''}</Text>
);

return (
Expand All @@ -25,6 +25,8 @@ export default function AppHeader({ options, back }: NativeStackHeaderProps) {
{back ? (
<Pressable
onPress={navigation.goBack}
accessibilityRole="button"
accessibilityLabel="Go back"
hitSlop={12}
style={({ pressed }) => [styles.backBtn, pressed && styles.pressed]}
>
Expand Down
10 changes: 9 additions & 1 deletion examples/demo/src/components/ListWidgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export function PairItem({
{onDelete && (
<TouchableOpacity
onPress={onDelete}
accessibilityRole="button"
accessibilityLabel={`Remove ${itemKey}`}
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
testID={sectionKey ? `${sectionKey}_remove_${itemKey}` : undefined}
>
Expand Down Expand Up @@ -91,6 +93,8 @@ export function SingleItem({ value, onDelete, sectionKey }: SingleItemProps) {
{onDelete && (
<TouchableOpacity
onPress={onDelete}
accessibilityRole="button"
accessibilityLabel={`Remove ${value}`}
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
testID={sectionKey ? `${sectionKey}_remove_${value}` : undefined}
>
Expand Down Expand Up @@ -221,7 +225,11 @@ export function CollapsibleSingleList({
</React.Fragment>
))}
{!showAll && hiddenCount > 0 && (
<TouchableOpacity onPress={() => setExpanded(true)} style={styles.moreButton}>
<TouchableOpacity
onPress={() => setExpanded(true)}
style={styles.moreButton}
accessibilityRole="button"
>
<Text style={styles.moreText}>{hiddenCount} more</Text>
</TouchableOpacity>
)}
Expand Down
6 changes: 5 additions & 1 deletion examples/demo/src/components/SectionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ export default function SectionCard({ title, children, onInfoTap, sectionKey, st
return (
<View style={[styles.wrapper, style]} testID={sectionKey ? `${sectionKey}_section` : undefined}>
<View style={styles.header}>
<Text style={styles.title}>{title}</Text>
<Text style={styles.title} accessibilityRole="header">
{title}
</Text>
{onInfoTap && (
<TouchableOpacity
onPress={onInfoTap}
accessibilityRole="button"
accessibilityLabel={`About ${title}`}
style={styles.infoButton}
testID={sectionKey ? `${sectionKey}_info_icon` : undefined}
>
Expand Down
2 changes: 2 additions & 0 deletions examples/demo/src/components/ToggleRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export default function ToggleRow({
{description && <Text style={styles.description}>{description}</Text>}
</View>
<Switch
accessibilityLabel={label}
accessibilityHint={description}
value={value}
onValueChange={onValueChange}
disabled={disabled}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export default function CustomNotificationModal({ visible, onConfirm, onClose }:
<TextInput

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

dont really need the accessibility changes for the sdk demos

style={[AppDialogStyles.input, styles.inputSpacing]}
placeholder="Title"
accessibilityLabel="Notification title"
placeholderTextColor={AppColors.osGrey600}
value={title}
onChangeText={setTitle}
Expand All @@ -59,6 +60,7 @@ export default function CustomNotificationModal({ visible, onConfirm, onClose }:
<TextInput
style={[AppDialogStyles.input, styles.inputSpacing]}
placeholder="Body"
accessibilityLabel="Notification body"
placeholderTextColor={AppColors.osGrey600}
value={body}
onChangeText={setBody}
Expand Down
15 changes: 9 additions & 6 deletions examples/demo/src/components/modals/MultiPairInputModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function MultiPairInputModal({
onConfirm,
onClose,
}: Props) {
const [rows, setRows] = useState<Row[]>([makeRow()]);
const [rows, setRows] = useState<Row[]>(() => [makeRow()]);

const allFilled = rows.every((r) => r.key.trim() && r.value.trim());

Expand All @@ -49,7 +49,8 @@ export default function MultiPairInputModal({
}, []);

const addRow = useCallback(() => {
setRows((prev) => [...prev, makeRow()]);
const row = makeRow();
setRows((prev) => [...prev, row]);
}, []);

const removeRow = useCallback((id: number) => {
Expand All @@ -60,10 +61,7 @@ export default function MultiPairInputModal({
if (!allFilled) {
return;
}
const pairs: Record<string, string> = {};
for (const row of rows) {
pairs[row.key.trim()] = row.value.trim();
}
const pairs = Object.fromEntries(rows.map((row) => [row.key.trim(), row.value.trim()]));
onConfirm(pairs);
reset();
onClose();
Expand Down Expand Up @@ -94,6 +92,7 @@ export default function MultiPairInputModal({
<TextInput
style={[AppDialogStyles.input, styles.halfInput]}
placeholder={keyPlaceholder}
accessibilityLabel={`${keyPlaceholder}, row ${idx + 1}`}
placeholderTextColor={AppColors.osGrey600}
value={row.key}
onChangeText={(t) => updateRow(row.id, 'key', t)}
Expand All @@ -104,6 +103,7 @@ export default function MultiPairInputModal({
<TextInput
style={[AppDialogStyles.input, styles.halfInput]}
placeholder={valuePlaceholder}
accessibilityLabel={`${valuePlaceholder}, row ${idx + 1}`}
placeholderTextColor={AppColors.osGrey600}
value={row.value}
onChangeText={(t) => updateRow(row.id, 'value', t)}
Expand All @@ -113,6 +113,8 @@ export default function MultiPairInputModal({
{rows.length > 1 && (
<TouchableOpacity
onPress={() => removeRow(row.id)}
accessibilityRole="button"
accessibilityLabel={`Remove row ${idx + 1}`}
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
>
<Icon name="close" size={20} color={AppColors.osGrey600} />
Expand All @@ -126,6 +128,7 @@ export default function MultiPairInputModal({
style={styles.addRowBtn}
testID="multipair_add_row_button"
accessibilityLabel="Add Row"
accessibilityRole="button"
>
<Icon name="add" size={18} color={AppColors.osPrimary} />
<Text style={styles.addRowText}>Add Row</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function MultiSelectRemoveModal({
onConfirm,
onClose,
}: Props) {
const [selected, setSelected] = useState<Set<string>>(new Set());
const [selected, setSelected] = useState<Set<string>>(() => new Set());

const toggle = (key: string) => {
setSelected((prev) => {
Expand Down Expand Up @@ -69,6 +69,9 @@ export default function MultiSelectRemoveModal({
key={key}
style={styles.row}
onPress={() => toggle(key)}
accessibilityRole="checkbox"
accessibilityLabel={key}
accessibilityState={{ checked: isChecked }}
testID={`remove_checkbox_${key}`}
>
<Icon
Expand Down
53 changes: 27 additions & 26 deletions examples/demo/src/components/modals/OutcomeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ import { AppColors, AppTextStyles, AppDialogStyles, AppInputProps } from '../../

type OutcomeType = 'normal' | 'unique' | 'withValue';

const OUTCOME_OPTIONS = [
{ type: 'normal', label: 'Normal Outcome', testID: 'outcome_type_normal_radio' },
{ type: 'unique', label: 'Unique Outcome', testID: 'outcome_type_unique_radio' },
{ type: 'withValue', label: 'Outcome with Value', testID: 'outcome_type_value_radio' },
] as const;

interface Props {
visible: boolean;
onSendNormal: (name: string) => void;
Expand All @@ -33,8 +39,9 @@ export default function OutcomeModal({
const [name, setName] = useState('');
const [value, setValue] = useState('');

const numericValue = Number(value);
const canSubmit =
name.trim() && (outcomeType !== 'withValue' || (value.trim() && !isNaN(parseFloat(value))));
name.trim() && (outcomeType !== 'withValue' || (value.trim() && Number.isFinite(numericValue)));

const handleSend = () => {
if (!canSubmit) {
Expand All @@ -48,7 +55,7 @@ export default function OutcomeModal({
onSendUnique(name.trim());
break;
case 'withValue':
onSendWithValue(name.trim(), parseFloat(value));
onSendWithValue(name.trim(), numericValue);
break;
}
handleClose();
Expand All @@ -61,23 +68,6 @@ export default function OutcomeModal({
onClose();
};

const RadioOption = ({
type,
label,
testID,
}: {
type: OutcomeType;
label: string;
testID: string;
}) => (
<TouchableOpacity style={styles.radioRow} onPress={() => setOutcomeType(type)} testID={testID}>
<View style={styles.radioOuter}>
{outcomeType === type && <View style={styles.radioInner} />}
</View>
<Text style={styles.radioLabel}>{label}</Text>
</TouchableOpacity>
);

return (
<Modal visible={visible} transparent animationType="fade" onRequestClose={handleClose}>
<KeyboardAvoidingView
Expand All @@ -86,13 +76,22 @@ export default function OutcomeModal({
>
<View style={AppDialogStyles.container}>
<Text style={AppDialogStyles.title}>Send Outcome</Text>
<RadioOption type="normal" label="Normal Outcome" testID="outcome_type_normal_radio" />
<RadioOption type="unique" label="Unique Outcome" testID="outcome_type_unique_radio" />
<RadioOption
type="withValue"
label="Outcome with Value"
testID="outcome_type_value_radio"
/>
{OUTCOME_OPTIONS.map(({ type, label, testID }) => (
<TouchableOpacity
key={type}
style={styles.radioRow}
onPress={() => setOutcomeType(type)}
accessibilityRole="radio"
accessibilityLabel={label}
accessibilityState={{ checked: outcomeType === type }}
testID={testID}
>
<View style={styles.radioOuter}>
{outcomeType === type && <View style={styles.radioInner} />}
</View>
<Text style={styles.radioLabel}>{label}</Text>
</TouchableOpacity>
))}
<TextInput
style={[AppDialogStyles.input, styles.inputSpacing]}
placeholder="Name"
Expand All @@ -102,6 +101,7 @@ export default function OutcomeModal({
autoFocus
{...AppInputProps}
testID="outcome_name_input"
accessibilityLabel="Outcome name"
/>
{outcomeType === 'withValue' && (
<TextInput
Expand All @@ -113,6 +113,7 @@ export default function OutcomeModal({
keyboardType="numeric"
{...AppInputProps}
testID="outcome_value_input"
accessibilityLabel="Outcome value"
/>
)}
<View style={AppDialogStyles.actions}>
Expand Down
2 changes: 2 additions & 0 deletions examples/demo/src/components/modals/PairInputModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default function PairInputModal({
<TextInput
style={[AppDialogStyles.input, styles.halfInput, styles.inputSpacing]}
placeholder={keyPlaceholder}
accessibilityLabel={keyPlaceholder}
placeholderTextColor={AppColors.osGrey600}
value={keyValue}
onChangeText={setKeyValue}
Expand All @@ -76,6 +77,7 @@ export default function PairInputModal({
<TextInput
style={[AppDialogStyles.input, styles.halfInput, styles.inputSpacing]}
placeholder={valuePlaceholder}
accessibilityLabel={valuePlaceholder}
placeholderTextColor={AppColors.osGrey600}
value={val}
onChangeText={setVal}
Expand Down
1 change: 1 addition & 0 deletions examples/demo/src/components/modals/SingleInputModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export default function SingleInputModal({
<TextInput
style={[AppDialogStyles.input, styles.inputSpacing]}
placeholder={placeholder}
accessibilityLabel={placeholder || title}
placeholderTextColor={AppColors.osGrey600}
value={value}
onChangeText={setValue}
Expand Down
17 changes: 9 additions & 8 deletions examples/demo/src/components/modals/TrackEventModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ export default function TrackEventModal({ visible, onConfirm, onClose }: Props)
return true;
}
try {
JSON.parse(text);
const properties = JSON.parse(text);
if (properties === null || typeof properties !== 'object' || Array.isArray(properties)) {
setJsonError('Properties must be a JSON object');
return false;
}
setJsonError('');
return true;
} catch {
Expand All @@ -40,15 +44,10 @@ export default function TrackEventModal({ visible, onConfirm, onClose }: Props)

const handlePropertiesChange = (text: string) => {
setPropertiesText(text);
if (text.trim()) {
validateJson(text);
} else {
setJsonError('');
}
validateJson(text);
};

const canSubmit =
name.trim() && !jsonError && (propertiesText.trim() === '' || !!propertiesText.trim());
const canSubmit = !!name.trim() && !jsonError;

const handleConfirm = () => {
if (!name.trim()) {
Expand Down Expand Up @@ -90,6 +89,7 @@ export default function TrackEventModal({ visible, onConfirm, onClose }: Props)
autoFocus
{...AppInputProps}
testID="event_name_input"
accessibilityLabel="Event name"
/>
<Text style={styles.label}>Properties (optional, JSON)</Text>
<TextInput
Expand All @@ -101,6 +101,7 @@ export default function TrackEventModal({ visible, onConfirm, onClose }: Props)
multiline
{...AppInputProps}
testID="event_properties_input"
accessibilityLabel="Properties (optional, JSON object)"
/>
{!!jsonError && <Text style={styles.errorText}>{jsonError}</Text>}
<View style={AppDialogStyles.actions}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ function InputRow({
value={value}
onChangeText={onChangeText}
placeholder={label}
accessibilityLabel={label}
placeholderTextColor={AppColors.osGrey500}
autoCapitalize="none"
autoCorrect={false}
Expand Down
2 changes: 1 addition & 1 deletion examples/demo/src/models/UserData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function userDataFromJson(json: Record<string, unknown>): UserData {
const properties = (json.properties as Record<string, unknown>) ?? {};
const subscriptions = (json.subscriptions as Array<Record<string, unknown>>) ?? [];

const aliases: Record<string, string> = {};
const aliases: Record<string, string> = Object.create(null);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

excessive, dont really need this change

for (const [key, value] of Object.entries(identity)) {
if (key !== 'external_id' && key !== 'onesignal_id') {
aliases[key] = String(value);
Expand Down
Loading