@planningcenter/chat-react-native 4.0.0-rc.0 → 4.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,6 +23,7 @@ export * from './text_button';
23
23
  export * from './text_inline_button';
24
24
  export * from './text';
25
25
  export * from './toggle_button';
26
+ export * from './keyboard_scroll_view';
26
27
  export * from './keyboard_view';
27
28
  export * from './platform_modal_header_buttons';
28
29
  export * from './pressable_row';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/display/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,QAAQ,CAAA;AACtB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iCAAiC,CAAA;AAC/C,cAAc,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/display/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,QAAQ,CAAA;AACtB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iCAAiC,CAAA;AAC/C,cAAc,iBAAiB,CAAA"}
@@ -23,6 +23,7 @@ export * from './text_button';
23
23
  export * from './text_inline_button';
24
24
  export * from './text';
25
25
  export * from './toggle_button';
26
+ export * from './keyboard_scroll_view';
26
27
  export * from './keyboard_view';
27
28
  export * from './platform_modal_header_buttons';
28
29
  export * from './pressable_row';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/display/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,QAAQ,CAAA;AACtB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iCAAiC,CAAA;AAC/C,cAAc,iBAAiB,CAAA","sourcesContent":["export * from './avatar_group'\nexport * from './avatar'\nexport * from './badge'\nexport * from './conversation_avatar'\nexport * from './emoji_avatar'\nexport * from './icon_avatar'\nexport * from './banner_collapsible'\nexport * from './banner'\nexport * from './button'\nexport * from './adult_requirement_notice'\nexport * from './child_notice'\nexport * from './heading'\nexport * from './icon_button'\nexport * from './icon'\nexport * from './image'\nexport * from './file_attachment_preview'\nexport * from './image_attachment_preview'\nexport * from './video_attachment_preview'\nexport * from './person'\nexport * from './spinner'\nexport * from './switch'\nexport * from './text_button'\nexport * from './text_inline_button'\nexport * from './text'\nexport * from './toggle_button'\nexport * from './keyboard_view'\nexport * from './platform_modal_header_buttons'\nexport * from './pressable_row'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/display/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,QAAQ,CAAA;AACtB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iCAAiC,CAAA;AAC/C,cAAc,iBAAiB,CAAA","sourcesContent":["export * from './avatar_group'\nexport * from './avatar'\nexport * from './badge'\nexport * from './conversation_avatar'\nexport * from './emoji_avatar'\nexport * from './icon_avatar'\nexport * from './banner_collapsible'\nexport * from './banner'\nexport * from './button'\nexport * from './adult_requirement_notice'\nexport * from './child_notice'\nexport * from './heading'\nexport * from './icon_button'\nexport * from './icon'\nexport * from './image'\nexport * from './file_attachment_preview'\nexport * from './image_attachment_preview'\nexport * from './video_attachment_preview'\nexport * from './person'\nexport * from './spinner'\nexport * from './switch'\nexport * from './text_button'\nexport * from './text_inline_button'\nexport * from './text'\nexport * from './toggle_button'\nexport * from './keyboard_scroll_view'\nexport * from './keyboard_view'\nexport * from './platform_modal_header_buttons'\nexport * from './pressable_row'\n"]}
@@ -0,0 +1,5 @@
1
+ import { ScrollViewProps } from 'react-native';
2
+ type KeyboardScrollViewProps = Pick<ScrollViewProps, 'children' | 'contentContainerStyle'>;
3
+ export declare function KeyboardScrollView({ children, contentContainerStyle }: KeyboardScrollViewProps): import("react/jsx-runtime").JSX.Element;
4
+ export {};
5
+ //# sourceMappingURL=keyboard_scroll_view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard_scroll_view.d.ts","sourceRoot":"","sources":["../../../src/components/display/keyboard_scroll_view.tsx"],"names":[],"mappings":"AACA,OAAO,EAAwB,eAAe,EAAa,MAAM,cAAc,CAAA;AAK/E,KAAK,uBAAuB,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,uBAAuB,CAAC,CAAA;AAE1F,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,qBAAqB,EAAE,EAAE,uBAAuB,2CA6C9F"}
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useRef } from 'react';
3
+ import { Keyboard, ScrollView, TextInput } from 'react-native';
4
+ import { KeyboardView } from './keyboard_view';
5
+ const FOCUSED_INPUT_BOTTOM_MARGIN = 32;
6
+ export function KeyboardScrollView({ children, contentContainerStyle }) {
7
+ const scrollViewRef = useRef(null);
8
+ const scrollFocusedInputIntoView = useCallback(() => {
9
+ const scrollView = scrollViewRef.current;
10
+ const input = TextInput.State.currentlyFocusedInput();
11
+ if (!scrollView || !input)
12
+ return;
13
+ const nativeScrollView = scrollView.getNativeScrollRef();
14
+ const innerView = scrollView.getInnerViewRef();
15
+ if (!nativeScrollView || !innerView)
16
+ return;
17
+ nativeScrollView.measureInWindow((_scrollX, scrollTop, _scrollWidth, scrollHeight) => {
18
+ const keyboardTop = Keyboard.metrics()?.screenY;
19
+ const scrollBottom = scrollTop + scrollHeight;
20
+ const visibleBottom = keyboardTop === undefined ? scrollBottom : Math.min(scrollBottom, keyboardTop);
21
+ const visibleHeight = visibleBottom - scrollTop;
22
+ input.measureInWindow((_inputX, inputTop, _inputWidth, inputHeight) => {
23
+ const inputBottom = inputTop + inputHeight + FOCUSED_INPUT_BOTTOM_MARGIN;
24
+ if (inputBottom <= visibleBottom)
25
+ return;
26
+ input.measureLayout(innerView, (_left, contentTop, _contentWidth, contentHeight) => {
27
+ scrollView.scrollTo({
28
+ y: contentTop + contentHeight + FOCUSED_INPUT_BOTTOM_MARGIN - visibleHeight,
29
+ animated: true,
30
+ });
31
+ });
32
+ });
33
+ });
34
+ }, []);
35
+ return (_jsx(KeyboardView, { children: _jsx(ScrollView, { ref: scrollViewRef, contentContainerStyle: contentContainerStyle, onLayout: scrollFocusedInputIntoView, onContentSizeChange: scrollFocusedInputIntoView, children: children }) }));
36
+ }
37
+ //# sourceMappingURL=keyboard_scroll_view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard_scroll_view.js","sourceRoot":"","sources":["../../../src/components/display/keyboard_scroll_view.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAmB,SAAS,EAAE,MAAM,cAAc,CAAA;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C,MAAM,2BAA2B,GAAG,EAAE,CAAA;AAItC,MAAM,UAAU,kBAAkB,CAAC,EAAE,QAAQ,EAAE,qBAAqB,EAA2B;IAC7F,MAAM,aAAa,GAAG,MAAM,CAAa,IAAI,CAAC,CAAA;IAE9C,MAAM,0BAA0B,GAAG,WAAW,CAAC,GAAG,EAAE;QAClD,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAA;QACxC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,qBAAqB,EAAE,CAAA;QACrD,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK;YAAE,OAAM;QAEjC,MAAM,gBAAgB,GAAG,UAAU,CAAC,kBAAkB,EAAE,CAAA;QACxD,MAAM,SAAS,GAAG,UAAU,CAAC,eAAe,EAAE,CAAA;QAC9C,IAAI,CAAC,gBAAgB,IAAI,CAAC,SAAS;YAAE,OAAM;QAE3C,gBAAgB,CAAC,eAAe,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE;YACnF,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,OAAO,CAAA;YAC/C,MAAM,YAAY,GAAG,SAAS,GAAG,YAAY,CAAA;YAC7C,MAAM,aAAa,GACjB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;YAChF,MAAM,aAAa,GAAG,aAAa,GAAG,SAAS,CAAA;YAE/C,KAAK,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE;gBACpE,MAAM,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,2BAA2B,CAAA;gBACxE,IAAI,WAAW,IAAI,aAAa;oBAAE,OAAM;gBAExC,KAAK,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,EAAE;oBACjF,UAAU,CAAC,QAAQ,CAAC;wBAClB,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,2BAA2B,GAAG,aAAa;wBAC3E,QAAQ,EAAE,IAAI;qBACf,CAAC,CAAA;gBACJ,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CACL,KAAC,YAAY,cACX,KAAC,UAAU,IACT,GAAG,EAAE,aAAa,EAClB,qBAAqB,EAAE,qBAAqB,EAC5C,QAAQ,EAAE,0BAA0B,EACpC,mBAAmB,EAAE,0BAA0B,YAE9C,QAAQ,GACE,GACA,CAChB,CAAA;AACH,CAAC","sourcesContent":["import React, { useCallback, useRef } from 'react'\nimport { Keyboard, ScrollView, ScrollViewProps, TextInput } from 'react-native'\nimport { KeyboardView } from './keyboard_view'\n\nconst FOCUSED_INPUT_BOTTOM_MARGIN = 32\n\ntype KeyboardScrollViewProps = Pick<ScrollViewProps, 'children' | 'contentContainerStyle'>\n\nexport function KeyboardScrollView({ children, contentContainerStyle }: KeyboardScrollViewProps) {\n const scrollViewRef = useRef<ScrollView>(null)\n\n const scrollFocusedInputIntoView = useCallback(() => {\n const scrollView = scrollViewRef.current\n const input = TextInput.State.currentlyFocusedInput()\n if (!scrollView || !input) return\n\n const nativeScrollView = scrollView.getNativeScrollRef()\n const innerView = scrollView.getInnerViewRef()\n if (!nativeScrollView || !innerView) return\n\n nativeScrollView.measureInWindow((_scrollX, scrollTop, _scrollWidth, scrollHeight) => {\n const keyboardTop = Keyboard.metrics()?.screenY\n const scrollBottom = scrollTop + scrollHeight\n const visibleBottom =\n keyboardTop === undefined ? scrollBottom : Math.min(scrollBottom, keyboardTop)\n const visibleHeight = visibleBottom - scrollTop\n\n input.measureInWindow((_inputX, inputTop, _inputWidth, inputHeight) => {\n const inputBottom = inputTop + inputHeight + FOCUSED_INPUT_BOTTOM_MARGIN\n if (inputBottom <= visibleBottom) return\n\n input.measureLayout(innerView, (_left, contentTop, _contentWidth, contentHeight) => {\n scrollView.scrollTo({\n y: contentTop + contentHeight + FOCUSED_INPUT_BOTTOM_MARGIN - visibleHeight,\n animated: true,\n })\n })\n })\n })\n }, [])\n\n return (\n <KeyboardView>\n <ScrollView\n ref={scrollViewRef}\n contentContainerStyle={contentContainerStyle}\n onLayout={scrollFocusedInputIntoView}\n onContentSizeChange={scrollFocusedInputIntoView}\n >\n {children}\n </ScrollView>\n </KeyboardView>\n )\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"bug_report_screen.d.ts","sourceRoot":"","sources":["../../src/screens/bug_report_screen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,4BAA4B,EAC5B,sBAAsB,EACvB,MAAM,gCAAgC,CAAA;AAqDvC,eAAO,MAAM,sBAAsB,GAAI,iBAEpC,sBAAsB,CAAC,GAAG,CAAC,KAAG,4BAI9B,CAAA;AAoBH,wBAAgB,eAAe,4CAyS9B"}
1
+ {"version":3,"file":"bug_report_screen.d.ts","sourceRoot":"","sources":["../../src/screens/bug_report_screen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,4BAA4B,EAC5B,sBAAsB,EACvB,MAAM,gCAAgC,CAAA;AAqDvC,eAAO,MAAM,sBAAsB,GAAI,iBAEpC,sBAAsB,CAAC,GAAG,CAAC,KAAG,4BAI9B,CAAA;AAoBH,wBAAgB,eAAe,4CAmS9B"}
@@ -4,7 +4,7 @@ import { startsWith } from 'lodash';
4
4
  import { useCallback, useState } from 'react';
5
5
  import { View, StyleSheet, TextInput, Linking, ScrollView, TouchableOpacity, Platform, } from 'react-native';
6
6
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
7
- import { Button, Spinner, Text, TextInlineButton, ImageAttachmentPreview, Icon, KeyboardView, } from '../components';
7
+ import { Button, Spinner, Text, TextInlineButton, ImageAttachmentPreview, Icon, KeyboardScrollView, } from '../components';
8
8
  import { composeOptions, HeaderDismissButton, useHeaderRight, withLeftClose, } from '../components/display/platform_modal_header_buttons';
9
9
  import { VideoAttachmentPreview } from '../components/display/video_attachment_preview';
10
10
  import { DefaultLoading } from '../components/page/loading';
@@ -126,10 +126,10 @@ export function BugReportScreen() {
126
126
  if (status === 'error') {
127
127
  return (_jsxs(View, { style: styles.container, children: [_jsxs(Text, { children: ["This is embarrassing, we can't submit your bug report right now. If you still need help or would like to submit this bug report another way please", ' ', _jsx(TextInlineButton, { accessibilityRole: "link", onPress: () => Linking.openURL('https://support.planningcenteronline.com/hc/en-us/requests/new'), children: "contact our help center" }), "."] }), _jsx(Button, { title: "Return to chat", onPress: navigation.goBack, variant: "fill", size: "lg" })] }));
128
128
  }
129
- return (_jsx(KeyboardView, { children: _jsxs(ScrollView, { contentContainerStyle: styles.container, children: [_jsxs(Text, { style: styles.description, children: ["Thanks for helping us improve ", DisplayableAppName[name], ". We won't be able to respond to your submission, but your feedback helps us improve the experience helps us improve the experience."] }), _jsxs(View, { style: styles.textInputContainer, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["Where did you experience the issue? ", _jsx(Text, { style: styles.required, children: "*" })] }), _jsxs(TouchableOpacity, { style: styles.pickerButton, onPress: () => setShowBugTypePicker(true), children: [_jsx(Text, { style: [styles.pickerText, !bugType && styles.pickerPlaceholder], children: bugType }), _jsx(Icon, { name: "general.downChevron", style: styles.pickerArrow, accessibilityElementsHidden: true })] })] }), _jsx(SafeAreaModal, { visible: showBugTypePicker, animationType: "slide", presentationStyle: "pageSheet", onRequestClose: () => setShowBugTypePicker(false), children: _jsxs(View, { style: styles.modalContainer, children: [_jsxs(View, { style: styles.modalHeader, children: [_jsx(HeaderDismissButton, { title: "Cancel", onPress: () => setShowBugTypePicker(false) }), _jsx(Text, { style: styles.modalTitle, children: "Select Bug Type" }), _jsx(View, { style: styles.modalHeaderSpacer })] }), _jsx(ScrollView, { style: styles.modalContent, children: Object.values(BUG_TYPE_OPTIONS).map(option => (_jsxs(TouchableOpacity, { style: styles.modalOption, onPress: () => {
130
- setBugType(option);
131
- setShowBugTypePicker(false);
132
- }, children: [_jsx(Text, { style: styles.modalOptionText, children: option }), bugType === option && (_jsx(Icon, { name: "general.check", style: styles.modalCheckmark, accessibilityElementsHidden: true }))] }, option))) })] }) }), _jsxs(View, { style: styles.textInputContainer, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["What were you trying to do when you encountered the bug?", ' ', _jsx(Text, { style: styles.required, children: "*" })] }), _jsx(TextInput, { style: styles.textInput, multiline: true, placeholder: "Description", value: whatWereDoing, onChangeText: setWhatWereDoing, maxLength: MAX_DESCRIPTION_LENGTH }), whatWereDoing.length >= MAX_DESCRIPTION_LENGTH - 100 && (_jsxs(Text, { variant: "footnote", children: [whatWereDoing.length, "/", MAX_DESCRIPTION_LENGTH] }))] }), _jsxs(View, { style: styles.textInputContainer, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["What did you expect to happen? Please describe what actually happened.", ' ', _jsx(Text, { style: styles.required, children: "*" })] }), _jsx(TextInput, { style: styles.textInput, multiline: true, placeholder: "Description", value: whatExpected, onChangeText: setWhatExpected, maxLength: MAX_DESCRIPTION_LENGTH }), whatExpected.length >= MAX_DESCRIPTION_LENGTH - 100 && (_jsxs(Text, { variant: "footnote", children: [whatExpected.length, "/", MAX_DESCRIPTION_LENGTH] }))] }), _jsxs(View, { style: styles.attachmentSection, children: [_jsxs(View, { style: styles.attachmentHeader, children: [_jsxs(Text, { style: styles.attachmentLabel, children: ["Attachment ", _jsx(Text, { style: styles.subLabel, children: "(optional)" })] }), uploading && _jsx(Spinner, {})] }), uploadError && _jsx(Text, { style: styles.attachmentErrorText, children: uploadError }), attachment ? (_jsx(View, { style: styles.attachmentPreviewContainer, children: isImageAttachment ? (_jsx(ImageAttachmentPreview, { uri: imagePreviewURI, fileName: attachment.name, onRemovePress: handleRemoveAttachment })) : (_jsx(VideoAttachmentPreview, { name: attachment.name, onRemovePress: handleRemoveAttachment })) })) : (_jsx(Button, { title: "Attach a screenshot or recording", accessibilityHint: "Opens your device's image gallery", iconNameLeft: "general.paperclip", onPress: pickImage, size: "sm", variant: "outline", style: styles.attachButton, disabled: uploading || Boolean(attachment) })), _jsxs(Text, { variant: "footnote", children: ["Screenshots and screen recordings help us reproduce and fix issues faster.", ' ', _jsx(TextInlineButton, { accessibilityRole: "link", variant: "footnote", onPress: () => Linking.openURL(VIDEO_RECORDING_HELP_URL), children: "How to record your screen" })] })] }), _jsx(View, { style: styles.footer, children: _jsxs(Text, { variant: "footnote", children: ["For details on how we process your data and ensure its security, please refer to our", ' ', _jsx(TextInlineButton, { accessibilityRole: "link", variant: "footnote", onPress: () => Linking.openURL('https://www.planningcenter.com/privacy'), children: "Privacy Policy" }), "."] }) })] }) }));
129
+ return (_jsxs(KeyboardScrollView, { contentContainerStyle: styles.container, children: [_jsxs(Text, { style: styles.description, children: ["Thanks for helping us improve ", DisplayableAppName[name], ". We won't be able to respond to your submission, but your feedback helps us improve the experience helps us improve the experience."] }), _jsxs(View, { style: styles.textInputContainer, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["Where did you experience the issue? ", _jsx(Text, { style: styles.required, children: "*" })] }), _jsxs(TouchableOpacity, { style: styles.pickerButton, onPress: () => setShowBugTypePicker(true), children: [_jsx(Text, { style: [styles.pickerText, !bugType && styles.pickerPlaceholder], children: bugType }), _jsx(Icon, { name: "general.downChevron", style: styles.pickerArrow, accessibilityElementsHidden: true })] })] }), _jsx(SafeAreaModal, { visible: showBugTypePicker, animationType: "slide", presentationStyle: "pageSheet", onRequestClose: () => setShowBugTypePicker(false), children: _jsxs(View, { style: styles.modalContainer, children: [_jsxs(View, { style: styles.modalHeader, children: [_jsx(HeaderDismissButton, { title: "Cancel", onPress: () => setShowBugTypePicker(false) }), _jsx(Text, { style: styles.modalTitle, children: "Select Bug Type" }), _jsx(View, { style: styles.modalHeaderSpacer })] }), _jsx(ScrollView, { style: styles.modalContent, children: Object.values(BUG_TYPE_OPTIONS).map(option => (_jsxs(TouchableOpacity, { style: styles.modalOption, onPress: () => {
130
+ setBugType(option);
131
+ setShowBugTypePicker(false);
132
+ }, children: [_jsx(Text, { style: styles.modalOptionText, children: option }), bugType === option && (_jsx(Icon, { name: "general.check", style: styles.modalCheckmark, accessibilityElementsHidden: true }))] }, option))) })] }) }), _jsxs(View, { style: styles.textInputContainer, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["What were you trying to do when you encountered the bug?", ' ', _jsx(Text, { style: styles.required, children: "*" })] }), _jsx(TextInput, { style: styles.textInput, multiline: true, placeholder: "Description", value: whatWereDoing, onChangeText: setWhatWereDoing, maxLength: MAX_DESCRIPTION_LENGTH }), whatWereDoing.length >= MAX_DESCRIPTION_LENGTH - 100 && (_jsxs(Text, { variant: "footnote", children: [whatWereDoing.length, "/", MAX_DESCRIPTION_LENGTH] }))] }), _jsxs(View, { style: styles.textInputContainer, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["What did you expect to happen? Please describe what actually happened.", ' ', _jsx(Text, { style: styles.required, children: "*" })] }), _jsx(TextInput, { style: styles.textInput, multiline: true, placeholder: "Description", value: whatExpected, onChangeText: setWhatExpected, maxLength: MAX_DESCRIPTION_LENGTH }), whatExpected.length >= MAX_DESCRIPTION_LENGTH - 100 && (_jsxs(Text, { variant: "footnote", children: [whatExpected.length, "/", MAX_DESCRIPTION_LENGTH] }))] }), _jsxs(View, { style: styles.attachmentSection, children: [_jsxs(View, { style: styles.attachmentHeader, children: [_jsxs(Text, { style: styles.attachmentLabel, children: ["Attachment ", _jsx(Text, { style: styles.subLabel, children: "(optional)" })] }), uploading && _jsx(Spinner, {})] }), uploadError && _jsx(Text, { style: styles.attachmentErrorText, children: uploadError }), attachment ? (_jsx(View, { style: styles.attachmentPreviewContainer, children: isImageAttachment ? (_jsx(ImageAttachmentPreview, { uri: imagePreviewURI, fileName: attachment.name, onRemovePress: handleRemoveAttachment })) : (_jsx(VideoAttachmentPreview, { name: attachment.name, onRemovePress: handleRemoveAttachment })) })) : (_jsx(Button, { title: "Attach a screenshot or recording", accessibilityHint: "Opens your device's image gallery", iconNameLeft: "general.paperclip", onPress: pickImage, size: "sm", variant: "outline", style: styles.attachButton, disabled: uploading || Boolean(attachment) })), _jsxs(Text, { variant: "footnote", children: ["Screenshots and screen recordings help us reproduce and fix issues faster.", ' ', _jsx(TextInlineButton, { accessibilityRole: "link", variant: "footnote", onPress: () => Linking.openURL(VIDEO_RECORDING_HELP_URL), children: "How to record your screen" })] })] }), _jsx(View, { style: styles.footer, children: _jsxs(Text, { variant: "footnote", children: ["For details on how we process your data and ensure its security, please refer to our", ' ', _jsx(TextInlineButton, { accessibilityRole: "link", variant: "footnote", onPress: () => Linking.openURL('https://www.planningcenter.com/privacy'), children: "Privacy Policy" }), "."] }) })] }));
133
133
  }
134
134
  const VIDEO_RECORDING_HELP_URL = Platform.select({
135
135
  android: 'https://support.google.com/android/answer/9075928?hl=en',
@@ -1 +1 @@
1
- {"version":3,"file":"bug_report_screen.js","sourceRoot":"","sources":["../../src/screens/bug_report_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useNavigation } from '@react-navigation/native'\nimport type {\n NativeStackNavigationOptions,\n NativeStackScreenProps,\n} from '@react-navigation/native-stack'\nimport { startsWith } from 'lodash'\nimport React, { useCallback, useState } from 'react'\nimport {\n View,\n StyleSheet,\n TextInput,\n Linking,\n ScrollView,\n TouchableOpacity,\n Platform,\n} from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport {\n Button,\n Spinner,\n Text,\n TextInlineButton,\n ImageAttachmentPreview,\n Icon,\n KeyboardView,\n} from '../components'\nimport {\n composeOptions,\n HeaderDismissButton,\n useHeaderRight,\n withLeftClose,\n} from '../components/display/platform_modal_header_buttons'\nimport { VideoAttachmentPreview } from '../components/display/video_attachment_preview'\nimport { DefaultLoading } from '../components/page/loading'\nimport BlankState from '../components/primitive/blank_state_primitive'\nimport { SafeAreaModal } from '../components/safe_area_modal'\nimport { useTheme } from '../hooks'\nimport { useAppName } from '../hooks/use_app_name'\nimport { useReportBugAction } from '../hooks/use_report_bug_action'\nimport { useUploadClient } from '../hooks/use_upload_client'\nimport { ImagePicker, ImagePickerResult, platformFontWeightBold } from '../utils'\n\nconst MAX_DESCRIPTION_LENGTH = 2000\n\nenum BUG_TYPE_OPTIONS {\n Chat = 'Chat',\n FindMyChurch = 'Find my church',\n LoggingIn = 'Logging in',\n UsingGroups = 'Using groups (events, resources, members)',\n CheckingIn = 'Checking in',\n MakingADonation = 'Making a donation',\n RegisteringForAnEvent = 'Registering for an event',\n MyProfileAndSchedule = 'My profile and schedule',\n Directory = 'Directory',\n Other = 'Other',\n}\n\nexport const BugReportScreenOptions = ({\n navigation,\n}: NativeStackScreenProps<any>): NativeStackNavigationOptions =>\n composeOptions(\n { presentation: 'modal', title: 'Report a bug' },\n withLeftClose({ onPress: () => navigation.goBack() })\n )\n\ninterface Attachment {\n id: string\n name: string\n type: string\n}\n\nenum QualifiedMobileAppName {\n chat = 'Chat', // There is no app name for the mobile app\n churchcenter = 'Church Center App',\n services = 'Services Mobile',\n}\n\nenum DisplayableAppName {\n chat = 'Chat',\n churchcenter = 'Church Center',\n services = 'Services',\n}\n\nexport function BugReportScreen() {\n const styles = useStyles()\n const navigation = useNavigation()\n const name = useAppName()\n const appName = QualifiedMobileAppName[name]\n const [bugType, setBugType] = useState<BUG_TYPE_OPTIONS>(BUG_TYPE_OPTIONS.Chat)\n const [showBugTypePicker, setShowBugTypePicker] = useState(false)\n const [whatWereDoing, setWhatWereDoing] = useState('')\n const [whatExpected, setWhatExpected] = useState('')\n const uploadApi = useUploadClient()\n const [uploading, setUploading] = useState(false)\n const [attachment, setAttachment] = useState<Attachment | null>(null)\n const [uploadError, setUploadError] = useState<string | null>(null)\n const { mutate: createBugReport, status } = useReportBugAction()\n const formValid =\n bugType.trim().length > 0 &&\n whatWereDoing.trim().length > 0 &&\n whatExpected.trim().length > 0 &&\n status === 'idle' &&\n !uploading\n const [imagePreviewURI, setImagePreviewURI] = useState<string>('')\n const isImageAttachment = startsWith(attachment?.type, 'image/')\n\n const handleSubmit = useCallback(() => {\n const description = generateBugReportDescription(bugType, whatWereDoing, whatExpected)\n\n createBugReport({\n description,\n description_json: {\n bugType,\n whatWereDoing,\n whatExpected,\n appName: appName,\n },\n attachmentIds: attachment ? [attachment.id] : [],\n })\n }, [attachment, bugType, whatWereDoing, whatExpected, createBugReport, appName])\n\n const handleRemoveAttachment = useCallback(() => {\n setAttachment(null)\n setImagePreviewURI('')\n }, [])\n\n function uploadImagePickerResult(result: ImagePickerResult) {\n if (result.canceled || result.assets.length === 0) {\n setUploading(false)\n return\n }\n\n const asset = result.assets[0]\n\n uploadApi\n ?.uploadFile({\n uri: asset.uri,\n name: asset.fileName as string,\n type: asset.mimeType as string,\n })\n .then(uploadedResource => {\n setUploading(false)\n setImagePreviewURI(asset.uri)\n setAttachment({\n id: uploadedResource.id,\n name: asset.fileName || 'File',\n type: asset.mimeType as string,\n })\n })\n .catch(() => {\n setUploading(false)\n setUploadError(`Failed to upload attachment`)\n })\n }\n\n function pickImage() {\n setUploading(true)\n return ImagePicker.openImageLibraryAsync().then(result => uploadImagePickerResult(result))\n }\n\n useHeaderRight({\n icon: 'general.upArrow',\n accessibilityLabel: 'Submit',\n prominent: true,\n onPress: handleSubmit,\n disabled: !formValid,\n })\n\n if (status === 'pending') {\n return (\n <View style={[styles.container, styles.fullHeight]}>\n <DefaultLoading />\n </View>\n )\n }\n\n if (status === 'success') {\n return (\n <BlankState.Root>\n <BlankState.Imagery name=\"general.checkCircle\" style={styles.successIcon} />\n <BlankState.Content>\n <BlankState.Heading style={styles.successTitle}>Thank you!</BlankState.Heading>\n <BlankState.Text style={styles.successSubtitle}>\n We appreciate you taking the time to help improve {DisplayableAppName[name]}! We'll take\n a look at the issue you reported.\n </BlankState.Text>\n </BlankState.Content>\n <BlankState.Button\n title=\"Return to chat\"\n onPress={navigation.goBack}\n size=\"lg\"\n variant=\"fill\"\n />\n </BlankState.Root>\n )\n }\n\n if (status === 'error') {\n return (\n <View style={styles.container}>\n <Text>\n This is embarrassing, we can't submit your bug report right now. If you still need help or\n would like to submit this bug report another way please{' '}\n <TextInlineButton\n accessibilityRole=\"link\"\n onPress={() =>\n Linking.openURL('https://support.planningcenteronline.com/hc/en-us/requests/new')\n }\n >\n contact our help center\n </TextInlineButton>\n .\n </Text>\n <Button title=\"Return to chat\" onPress={navigation.goBack} variant=\"fill\" size=\"lg\" />\n </View>\n )\n }\n\n return (\n <KeyboardView>\n <ScrollView contentContainerStyle={styles.container}>\n <Text style={styles.description}>\n Thanks for helping us improve {DisplayableAppName[name]}. We won't be able to respond to\n your submission, but your feedback helps us improve the experience helps us improve the\n experience.\n </Text>\n\n <View style={styles.textInputContainer}>\n <Text style={styles.fieldLabel}>\n Where did you experience the issue? <Text style={styles.required}>*</Text>\n </Text>\n <TouchableOpacity style={styles.pickerButton} onPress={() => setShowBugTypePicker(true)}>\n <Text style={[styles.pickerText, !bugType && styles.pickerPlaceholder]}>{bugType}</Text>\n <Icon\n name=\"general.downChevron\"\n style={styles.pickerArrow}\n accessibilityElementsHidden\n />\n </TouchableOpacity>\n </View>\n\n <SafeAreaModal\n visible={showBugTypePicker}\n animationType=\"slide\"\n presentationStyle=\"pageSheet\"\n onRequestClose={() => setShowBugTypePicker(false)}\n >\n <View style={styles.modalContainer}>\n <View style={styles.modalHeader}>\n <HeaderDismissButton title=\"Cancel\" onPress={() => setShowBugTypePicker(false)} />\n <Text style={styles.modalTitle}>Select Bug Type</Text>\n <View style={styles.modalHeaderSpacer} />\n </View>\n <ScrollView style={styles.modalContent}>\n {Object.values(BUG_TYPE_OPTIONS).map(option => (\n <TouchableOpacity\n key={option}\n style={styles.modalOption}\n onPress={() => {\n setBugType(option)\n setShowBugTypePicker(false)\n }}\n >\n <Text style={styles.modalOptionText}>{option}</Text>\n {bugType === option && (\n <Icon\n name=\"general.check\"\n style={styles.modalCheckmark}\n accessibilityElementsHidden\n />\n )}\n </TouchableOpacity>\n ))}\n </ScrollView>\n </View>\n </SafeAreaModal>\n\n <View style={styles.textInputContainer}>\n <Text style={styles.fieldLabel}>\n What were you trying to do when you encountered the bug?{' '}\n <Text style={styles.required}>*</Text>\n </Text>\n <TextInput\n style={styles.textInput}\n multiline\n placeholder=\"Description\"\n value={whatWereDoing}\n onChangeText={setWhatWereDoing}\n maxLength={MAX_DESCRIPTION_LENGTH}\n />\n {whatWereDoing.length >= MAX_DESCRIPTION_LENGTH - 100 && (\n <Text variant=\"footnote\">\n {whatWereDoing.length}/{MAX_DESCRIPTION_LENGTH}\n </Text>\n )}\n </View>\n\n <View style={styles.textInputContainer}>\n <Text style={styles.fieldLabel}>\n What did you expect to happen? Please describe what actually happened.{' '}\n <Text style={styles.required}>*</Text>\n </Text>\n <TextInput\n style={styles.textInput}\n multiline\n placeholder=\"Description\"\n value={whatExpected}\n onChangeText={setWhatExpected}\n maxLength={MAX_DESCRIPTION_LENGTH}\n />\n {whatExpected.length >= MAX_DESCRIPTION_LENGTH - 100 && (\n <Text variant=\"footnote\">\n {whatExpected.length}/{MAX_DESCRIPTION_LENGTH}\n </Text>\n )}\n </View>\n\n <View style={styles.attachmentSection}>\n <View style={styles.attachmentHeader}>\n <Text style={styles.attachmentLabel}>\n Attachment <Text style={styles.subLabel}>(optional)</Text>\n </Text>\n {uploading && <Spinner />}\n </View>\n {uploadError && <Text style={styles.attachmentErrorText}>{uploadError}</Text>}\n {attachment ? (\n <View style={styles.attachmentPreviewContainer}>\n {isImageAttachment ? (\n <ImageAttachmentPreview\n uri={imagePreviewURI}\n fileName={attachment.name}\n onRemovePress={handleRemoveAttachment}\n />\n ) : (\n <VideoAttachmentPreview\n name={attachment.name}\n onRemovePress={handleRemoveAttachment}\n />\n )}\n </View>\n ) : (\n <Button\n title=\"Attach a screenshot or recording\"\n accessibilityHint=\"Opens your device's image gallery\"\n iconNameLeft=\"general.paperclip\"\n onPress={pickImage}\n size=\"sm\"\n variant=\"outline\"\n style={styles.attachButton}\n disabled={uploading || Boolean(attachment)}\n />\n )}\n <Text variant=\"footnote\">\n Screenshots and screen recordings help us reproduce and fix issues faster.{' '}\n <TextInlineButton\n accessibilityRole=\"link\"\n variant=\"footnote\"\n onPress={() => Linking.openURL(VIDEO_RECORDING_HELP_URL)}\n >\n How to record your screen\n </TextInlineButton>\n </Text>\n </View>\n\n <View style={styles.footer}>\n <Text variant=\"footnote\">\n For details on how we process your data and ensure its security, please refer to our{' '}\n <TextInlineButton\n accessibilityRole=\"link\"\n variant=\"footnote\"\n onPress={() => Linking.openURL('https://www.planningcenter.com/privacy')}\n >\n Privacy Policy\n </TextInlineButton>\n .\n </Text>\n </View>\n </ScrollView>\n </KeyboardView>\n )\n}\n\nconst VIDEO_RECORDING_HELP_URL = Platform.select({\n android: 'https://support.google.com/android/answer/9075928?hl=en',\n default: 'https://support.apple.com/en-us/102653',\n})\n\nconst generateBugReportDescription = (\n bugType: BUG_TYPE_OPTIONS,\n whatWereDoing: string,\n whatExpected: string\n) => {\n return `${whatWereDoing.substring(0, 100)}\n\n ## What kind of bug did you experience?\n${bugType}\n\n## What were you trying to do when you encountered the bug?\n${whatWereDoing}\n\n## What did you expect to happen? What actually happened?\n${whatExpected}\n`\n}\n\nconst useStyles = () => {\n const { bottom } = useSafeAreaInsets()\n const { colors } = useTheme()\n return StyleSheet.create({\n container: {\n padding: 16,\n paddingBottom: 16 + bottom,\n gap: 24,\n },\n fullHeight: {\n flex: 1,\n },\n description: {\n color: colors.textColorDefaultSecondary,\n },\n textInputContainer: {\n gap: 8,\n },\n fieldLabel: {\n fontSize: 16,\n fontWeight: platformFontWeightBold,\n color: colors.textColorDefaultPrimary,\n },\n required: {\n color: colors.statusErrorText,\n },\n pickerButton: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n borderWidth: 1,\n borderColor: colors.borderColorDefaultBase,\n borderRadius: 8,\n paddingHorizontal: 16,\n paddingVertical: 12,\n backgroundColor: colors.surfaceColor100,\n minHeight: 48,\n },\n pickerText: {\n fontSize: 16,\n color: colors.textColorDefaultPrimary,\n flex: 1,\n },\n pickerPlaceholder: {\n color: colors.textColorDefaultSecondary,\n },\n pickerArrow: {\n fontSize: 12,\n color: colors.iconColorDefaultSecondary,\n marginLeft: 8,\n },\n modalContainer: {\n flex: 1,\n backgroundColor: colors.surfaceColor100,\n },\n modalHeader: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: 16,\n borderBottomWidth: 1,\n borderBottomColor: colors.borderColorDefaultBase,\n },\n modalTitle: {\n fontSize: 18,\n fontWeight: platformFontWeightBold,\n color: colors.textColorDefaultPrimary,\n },\n modalHeaderSpacer: {\n width: 50, // Same width as cancel button to center title\n },\n modalContent: {\n flex: 1,\n },\n modalOption: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 16,\n paddingVertical: 16,\n borderBottomWidth: 1,\n borderBottomColor: colors.borderColorDefaultBase,\n },\n modalOptionText: {\n fontSize: 16,\n color: colors.textColorDefaultPrimary,\n flex: 1,\n },\n modalCheckmark: {\n fontSize: 16,\n color: colors.statusSuccessIcon,\n },\n textInput: {\n color: colors.textColorDefaultPrimary,\n fontSize: 16,\n textAlignVertical: 'top',\n minHeight: 120,\n maxHeight: 200,\n borderWidth: 1,\n borderColor: colors.borderColorDefaultBase,\n borderRadius: 8,\n paddingHorizontal: 16,\n paddingVertical: 12,\n backgroundColor: colors.surfaceColor100,\n },\n attachmentSection: {\n gap: 8,\n },\n attachmentHeader: {\n flexDirection: 'row',\n gap: 4,\n alignItems: 'center',\n },\n attachmentLabel: { fontWeight: platformFontWeightBold },\n subLabel: { fontWeight: 'normal', color: colors.textColorDefaultSecondary },\n attachmentPreviewContainer: {\n gap: 4,\n },\n attachmentErrorText: {\n color: colors.statusErrorText,\n },\n attachButton: {\n alignSelf: 'flex-start',\n },\n footer: { gap: 8 },\n successIcon: {\n color: colors.statusSuccessIcon,\n fontSize: 48,\n },\n successTitle: {\n fontSize: 24,\n marginBottom: 4,\n },\n successSubtitle: {\n fontSize: 16,\n marginBottom: 4,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"bug_report_screen.js","sourceRoot":"","sources":["../../src/screens/bug_report_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useNavigation } from '@react-navigation/native'\nimport type {\n NativeStackNavigationOptions,\n NativeStackScreenProps,\n} from '@react-navigation/native-stack'\nimport { startsWith } from 'lodash'\nimport React, { useCallback, useState } from 'react'\nimport {\n View,\n StyleSheet,\n TextInput,\n Linking,\n ScrollView,\n TouchableOpacity,\n Platform,\n} from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport {\n Button,\n Spinner,\n Text,\n TextInlineButton,\n ImageAttachmentPreview,\n Icon,\n KeyboardScrollView,\n} from '../components'\nimport {\n composeOptions,\n HeaderDismissButton,\n useHeaderRight,\n withLeftClose,\n} from '../components/display/platform_modal_header_buttons'\nimport { VideoAttachmentPreview } from '../components/display/video_attachment_preview'\nimport { DefaultLoading } from '../components/page/loading'\nimport BlankState from '../components/primitive/blank_state_primitive'\nimport { SafeAreaModal } from '../components/safe_area_modal'\nimport { useTheme } from '../hooks'\nimport { useAppName } from '../hooks/use_app_name'\nimport { useReportBugAction } from '../hooks/use_report_bug_action'\nimport { useUploadClient } from '../hooks/use_upload_client'\nimport { ImagePicker, ImagePickerResult, platformFontWeightBold } from '../utils'\n\nconst MAX_DESCRIPTION_LENGTH = 2000\n\nenum BUG_TYPE_OPTIONS {\n Chat = 'Chat',\n FindMyChurch = 'Find my church',\n LoggingIn = 'Logging in',\n UsingGroups = 'Using groups (events, resources, members)',\n CheckingIn = 'Checking in',\n MakingADonation = 'Making a donation',\n RegisteringForAnEvent = 'Registering for an event',\n MyProfileAndSchedule = 'My profile and schedule',\n Directory = 'Directory',\n Other = 'Other',\n}\n\nexport const BugReportScreenOptions = ({\n navigation,\n}: NativeStackScreenProps<any>): NativeStackNavigationOptions =>\n composeOptions(\n { presentation: 'modal', title: 'Report a bug' },\n withLeftClose({ onPress: () => navigation.goBack() })\n )\n\ninterface Attachment {\n id: string\n name: string\n type: string\n}\n\nenum QualifiedMobileAppName {\n chat = 'Chat', // There is no app name for the mobile app\n churchcenter = 'Church Center App',\n services = 'Services Mobile',\n}\n\nenum DisplayableAppName {\n chat = 'Chat',\n churchcenter = 'Church Center',\n services = 'Services',\n}\n\nexport function BugReportScreen() {\n const styles = useStyles()\n const navigation = useNavigation()\n const name = useAppName()\n const appName = QualifiedMobileAppName[name]\n const [bugType, setBugType] = useState<BUG_TYPE_OPTIONS>(BUG_TYPE_OPTIONS.Chat)\n const [showBugTypePicker, setShowBugTypePicker] = useState(false)\n const [whatWereDoing, setWhatWereDoing] = useState('')\n const [whatExpected, setWhatExpected] = useState('')\n const uploadApi = useUploadClient()\n const [uploading, setUploading] = useState(false)\n const [attachment, setAttachment] = useState<Attachment | null>(null)\n const [uploadError, setUploadError] = useState<string | null>(null)\n const { mutate: createBugReport, status } = useReportBugAction()\n const formValid =\n bugType.trim().length > 0 &&\n whatWereDoing.trim().length > 0 &&\n whatExpected.trim().length > 0 &&\n status === 'idle' &&\n !uploading\n const [imagePreviewURI, setImagePreviewURI] = useState<string>('')\n const isImageAttachment = startsWith(attachment?.type, 'image/')\n\n const handleSubmit = useCallback(() => {\n const description = generateBugReportDescription(bugType, whatWereDoing, whatExpected)\n\n createBugReport({\n description,\n description_json: {\n bugType,\n whatWereDoing,\n whatExpected,\n appName: appName,\n },\n attachmentIds: attachment ? [attachment.id] : [],\n })\n }, [attachment, bugType, whatWereDoing, whatExpected, createBugReport, appName])\n\n const handleRemoveAttachment = useCallback(() => {\n setAttachment(null)\n setImagePreviewURI('')\n }, [])\n\n function uploadImagePickerResult(result: ImagePickerResult) {\n if (result.canceled || result.assets.length === 0) {\n setUploading(false)\n return\n }\n\n const asset = result.assets[0]\n\n uploadApi\n ?.uploadFile({\n uri: asset.uri,\n name: asset.fileName as string,\n type: asset.mimeType as string,\n })\n .then(uploadedResource => {\n setUploading(false)\n setImagePreviewURI(asset.uri)\n setAttachment({\n id: uploadedResource.id,\n name: asset.fileName || 'File',\n type: asset.mimeType as string,\n })\n })\n .catch(() => {\n setUploading(false)\n setUploadError(`Failed to upload attachment`)\n })\n }\n\n function pickImage() {\n setUploading(true)\n return ImagePicker.openImageLibraryAsync().then(result => uploadImagePickerResult(result))\n }\n\n useHeaderRight({\n icon: 'general.upArrow',\n accessibilityLabel: 'Submit',\n prominent: true,\n onPress: handleSubmit,\n disabled: !formValid,\n })\n\n if (status === 'pending') {\n return (\n <View style={[styles.container, styles.fullHeight]}>\n <DefaultLoading />\n </View>\n )\n }\n\n if (status === 'success') {\n return (\n <BlankState.Root>\n <BlankState.Imagery name=\"general.checkCircle\" style={styles.successIcon} />\n <BlankState.Content>\n <BlankState.Heading style={styles.successTitle}>Thank you!</BlankState.Heading>\n <BlankState.Text style={styles.successSubtitle}>\n We appreciate you taking the time to help improve {DisplayableAppName[name]}! We'll take\n a look at the issue you reported.\n </BlankState.Text>\n </BlankState.Content>\n <BlankState.Button\n title=\"Return to chat\"\n onPress={navigation.goBack}\n size=\"lg\"\n variant=\"fill\"\n />\n </BlankState.Root>\n )\n }\n\n if (status === 'error') {\n return (\n <View style={styles.container}>\n <Text>\n This is embarrassing, we can't submit your bug report right now. If you still need help or\n would like to submit this bug report another way please{' '}\n <TextInlineButton\n accessibilityRole=\"link\"\n onPress={() =>\n Linking.openURL('https://support.planningcenteronline.com/hc/en-us/requests/new')\n }\n >\n contact our help center\n </TextInlineButton>\n .\n </Text>\n <Button title=\"Return to chat\" onPress={navigation.goBack} variant=\"fill\" size=\"lg\" />\n </View>\n )\n }\n\n return (\n <KeyboardScrollView contentContainerStyle={styles.container}>\n <Text style={styles.description}>\n Thanks for helping us improve {DisplayableAppName[name]}. We won't be able to respond to\n your submission, but your feedback helps us improve the experience helps us improve the\n experience.\n </Text>\n\n <View style={styles.textInputContainer}>\n <Text style={styles.fieldLabel}>\n Where did you experience the issue? <Text style={styles.required}>*</Text>\n </Text>\n <TouchableOpacity style={styles.pickerButton} onPress={() => setShowBugTypePicker(true)}>\n <Text style={[styles.pickerText, !bugType && styles.pickerPlaceholder]}>{bugType}</Text>\n <Icon name=\"general.downChevron\" style={styles.pickerArrow} accessibilityElementsHidden />\n </TouchableOpacity>\n </View>\n\n <SafeAreaModal\n visible={showBugTypePicker}\n animationType=\"slide\"\n presentationStyle=\"pageSheet\"\n onRequestClose={() => setShowBugTypePicker(false)}\n >\n <View style={styles.modalContainer}>\n <View style={styles.modalHeader}>\n <HeaderDismissButton title=\"Cancel\" onPress={() => setShowBugTypePicker(false)} />\n <Text style={styles.modalTitle}>Select Bug Type</Text>\n <View style={styles.modalHeaderSpacer} />\n </View>\n <ScrollView style={styles.modalContent}>\n {Object.values(BUG_TYPE_OPTIONS).map(option => (\n <TouchableOpacity\n key={option}\n style={styles.modalOption}\n onPress={() => {\n setBugType(option)\n setShowBugTypePicker(false)\n }}\n >\n <Text style={styles.modalOptionText}>{option}</Text>\n {bugType === option && (\n <Icon\n name=\"general.check\"\n style={styles.modalCheckmark}\n accessibilityElementsHidden\n />\n )}\n </TouchableOpacity>\n ))}\n </ScrollView>\n </View>\n </SafeAreaModal>\n\n <View style={styles.textInputContainer}>\n <Text style={styles.fieldLabel}>\n What were you trying to do when you encountered the bug?{' '}\n <Text style={styles.required}>*</Text>\n </Text>\n <TextInput\n style={styles.textInput}\n multiline\n placeholder=\"Description\"\n value={whatWereDoing}\n onChangeText={setWhatWereDoing}\n maxLength={MAX_DESCRIPTION_LENGTH}\n />\n {whatWereDoing.length >= MAX_DESCRIPTION_LENGTH - 100 && (\n <Text variant=\"footnote\">\n {whatWereDoing.length}/{MAX_DESCRIPTION_LENGTH}\n </Text>\n )}\n </View>\n\n <View style={styles.textInputContainer}>\n <Text style={styles.fieldLabel}>\n What did you expect to happen? Please describe what actually happened.{' '}\n <Text style={styles.required}>*</Text>\n </Text>\n <TextInput\n style={styles.textInput}\n multiline\n placeholder=\"Description\"\n value={whatExpected}\n onChangeText={setWhatExpected}\n maxLength={MAX_DESCRIPTION_LENGTH}\n />\n {whatExpected.length >= MAX_DESCRIPTION_LENGTH - 100 && (\n <Text variant=\"footnote\">\n {whatExpected.length}/{MAX_DESCRIPTION_LENGTH}\n </Text>\n )}\n </View>\n\n <View style={styles.attachmentSection}>\n <View style={styles.attachmentHeader}>\n <Text style={styles.attachmentLabel}>\n Attachment <Text style={styles.subLabel}>(optional)</Text>\n </Text>\n {uploading && <Spinner />}\n </View>\n {uploadError && <Text style={styles.attachmentErrorText}>{uploadError}</Text>}\n {attachment ? (\n <View style={styles.attachmentPreviewContainer}>\n {isImageAttachment ? (\n <ImageAttachmentPreview\n uri={imagePreviewURI}\n fileName={attachment.name}\n onRemovePress={handleRemoveAttachment}\n />\n ) : (\n <VideoAttachmentPreview\n name={attachment.name}\n onRemovePress={handleRemoveAttachment}\n />\n )}\n </View>\n ) : (\n <Button\n title=\"Attach a screenshot or recording\"\n accessibilityHint=\"Opens your device's image gallery\"\n iconNameLeft=\"general.paperclip\"\n onPress={pickImage}\n size=\"sm\"\n variant=\"outline\"\n style={styles.attachButton}\n disabled={uploading || Boolean(attachment)}\n />\n )}\n <Text variant=\"footnote\">\n Screenshots and screen recordings help us reproduce and fix issues faster.{' '}\n <TextInlineButton\n accessibilityRole=\"link\"\n variant=\"footnote\"\n onPress={() => Linking.openURL(VIDEO_RECORDING_HELP_URL)}\n >\n How to record your screen\n </TextInlineButton>\n </Text>\n </View>\n\n <View style={styles.footer}>\n <Text variant=\"footnote\">\n For details on how we process your data and ensure its security, please refer to our{' '}\n <TextInlineButton\n accessibilityRole=\"link\"\n variant=\"footnote\"\n onPress={() => Linking.openURL('https://www.planningcenter.com/privacy')}\n >\n Privacy Policy\n </TextInlineButton>\n .\n </Text>\n </View>\n </KeyboardScrollView>\n )\n}\n\nconst VIDEO_RECORDING_HELP_URL = Platform.select({\n android: 'https://support.google.com/android/answer/9075928?hl=en',\n default: 'https://support.apple.com/en-us/102653',\n})\n\nconst generateBugReportDescription = (\n bugType: BUG_TYPE_OPTIONS,\n whatWereDoing: string,\n whatExpected: string\n) => {\n return `${whatWereDoing.substring(0, 100)}\n\n ## What kind of bug did you experience?\n${bugType}\n\n## What were you trying to do when you encountered the bug?\n${whatWereDoing}\n\n## What did you expect to happen? What actually happened?\n${whatExpected}\n`\n}\n\nconst useStyles = () => {\n const { bottom } = useSafeAreaInsets()\n const { colors } = useTheme()\n return StyleSheet.create({\n container: {\n padding: 16,\n paddingBottom: 16 + bottom,\n gap: 24,\n },\n fullHeight: {\n flex: 1,\n },\n description: {\n color: colors.textColorDefaultSecondary,\n },\n textInputContainer: {\n gap: 8,\n },\n fieldLabel: {\n fontSize: 16,\n fontWeight: platformFontWeightBold,\n color: colors.textColorDefaultPrimary,\n },\n required: {\n color: colors.statusErrorText,\n },\n pickerButton: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n borderWidth: 1,\n borderColor: colors.borderColorDefaultBase,\n borderRadius: 8,\n paddingHorizontal: 16,\n paddingVertical: 12,\n backgroundColor: colors.surfaceColor100,\n minHeight: 48,\n },\n pickerText: {\n fontSize: 16,\n color: colors.textColorDefaultPrimary,\n flex: 1,\n },\n pickerPlaceholder: {\n color: colors.textColorDefaultSecondary,\n },\n pickerArrow: {\n fontSize: 12,\n color: colors.iconColorDefaultSecondary,\n marginLeft: 8,\n },\n modalContainer: {\n flex: 1,\n backgroundColor: colors.surfaceColor100,\n },\n modalHeader: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: 16,\n borderBottomWidth: 1,\n borderBottomColor: colors.borderColorDefaultBase,\n },\n modalTitle: {\n fontSize: 18,\n fontWeight: platformFontWeightBold,\n color: colors.textColorDefaultPrimary,\n },\n modalHeaderSpacer: {\n width: 50, // Same width as cancel button to center title\n },\n modalContent: {\n flex: 1,\n },\n modalOption: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 16,\n paddingVertical: 16,\n borderBottomWidth: 1,\n borderBottomColor: colors.borderColorDefaultBase,\n },\n modalOptionText: {\n fontSize: 16,\n color: colors.textColorDefaultPrimary,\n flex: 1,\n },\n modalCheckmark: {\n fontSize: 16,\n color: colors.statusSuccessIcon,\n },\n textInput: {\n color: colors.textColorDefaultPrimary,\n fontSize: 16,\n textAlignVertical: 'top',\n minHeight: 120,\n maxHeight: 200,\n borderWidth: 1,\n borderColor: colors.borderColorDefaultBase,\n borderRadius: 8,\n paddingHorizontal: 16,\n paddingVertical: 12,\n backgroundColor: colors.surfaceColor100,\n },\n attachmentSection: {\n gap: 8,\n },\n attachmentHeader: {\n flexDirection: 'row',\n gap: 4,\n alignItems: 'center',\n },\n attachmentLabel: { fontWeight: platformFontWeightBold },\n subLabel: { fontWeight: 'normal', color: colors.textColorDefaultSecondary },\n attachmentPreviewContainer: {\n gap: 4,\n },\n attachmentErrorText: {\n color: colors.statusErrorText,\n },\n attachButton: {\n alignSelf: 'flex-start',\n },\n footer: { gap: 8 },\n successIcon: {\n color: colors.statusSuccessIcon,\n fontSize: 48,\n },\n successTitle: {\n fontSize: 24,\n marginBottom: 4,\n },\n successSubtitle: {\n fontSize: 16,\n marginBottom: 4,\n },\n })\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useNavigation, StackActions } from '@react-navigation/native';
3
3
  import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
4
- import { View, StyleSheet, TextInput, ScrollView } from 'react-native';
4
+ import { View, StyleSheet, TextInput } from 'react-native';
5
5
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
6
- import { Spinner, Text, KeyboardView } from '../components';
6
+ import { Spinner, Text, KeyboardScrollView } from '../components';
7
7
  import { composeOptions, useHeaderRight, withLeftClose, } from '../components/display/platform_modal_header_buttons';
8
8
  import BlankState from '../components/primitive/blank_state_primitive';
9
9
  import { useTheme } from '../hooks';
@@ -81,7 +81,7 @@ function MessageReportScreenContent({ message, conversation_id, }) {
81
81
  if (status === 'error') {
82
82
  return (_jsxs(BlankState.Root, { children: [_jsx(BlankState.Imagery, { name: "general.exclamationTriangle" }), _jsxs(BlankState.Content, { children: [_jsx(BlankState.Heading, { children: "Unable to submit report" }), _jsx(BlankState.Text, { children: "We were unable to report this message. Please try again." })] }), _jsx(BlankState.Button, { title: "Close", onPress: handleClose, size: "lg", variant: "outline" })] }));
83
83
  }
84
- return (_jsx(KeyboardView, { children: _jsxs(ScrollView, { contentContainerStyle: styles.container, children: [_jsx(Text, { style: styles.warningText, maxFontSizeMultiplier: 1.5, children: "Reporting this message will notify a church leader. The person you are reporting will not receive a notification from Church Center. If someone is in immediate danger, call local emergency services. Don't wait." }), _jsx(MessagePreview, { message: message }), _jsxs(View, { style: styles.reasonSection, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["What best describes the problem? ", _jsx(Text, { style: styles.required, children: "*" })] }), _jsx(View, { style: styles.reasonListContainer, children: _jsx(ReportReasonList, { selectedReason: selectedReason, onReasonChange: handleReasonChange }) })] }), selectedReason === 'other' && (_jsxs(View, { style: styles.detailSection, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["Please provide more details ", _jsx(Text, { style: styles.required, children: "*" })] }), _jsx(TextInput, { style: styles.textInput, multiline: true, placeholder: "Describe the issue...", value: reasonDetail, onChangeText: setReasonDetail, maxLength: MAX_DETAIL_LENGTH, accessibilityLabel: "Additional details", accessibilityHint: "Provide more information about why you're reporting this message" }), reasonDetail.length >= MAX_DETAIL_LENGTH - 100 && (_jsxs(Text, { variant: "footnote", children: [reasonDetail.length, "/", MAX_DETAIL_LENGTH] }))] }))] }) }));
84
+ return (_jsxs(KeyboardScrollView, { contentContainerStyle: styles.container, children: [_jsx(Text, { style: styles.warningText, maxFontSizeMultiplier: 1.5, children: "Reporting this message will notify a church leader. The person you are reporting will not receive a notification from Church Center. If someone is in immediate danger, call local emergency services. Don't wait." }), _jsx(MessagePreview, { message: message }), _jsxs(View, { style: styles.reasonSection, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["What best describes the problem? ", _jsx(Text, { style: styles.required, children: "*" })] }), _jsx(View, { style: styles.reasonListContainer, children: _jsx(ReportReasonList, { selectedReason: selectedReason, onReasonChange: handleReasonChange }) })] }), selectedReason === 'other' && (_jsxs(View, { style: styles.detailSection, children: [_jsxs(Text, { style: styles.fieldLabel, children: ["Please provide more details ", _jsx(Text, { style: styles.required, children: "*" })] }), _jsx(TextInput, { style: styles.textInput, multiline: true, placeholder: "Describe the issue...", value: reasonDetail, onChangeText: setReasonDetail, maxLength: MAX_DETAIL_LENGTH, accessibilityLabel: "Additional details", accessibilityHint: "Provide more information about why you're reporting this message" }), reasonDetail.length >= MAX_DETAIL_LENGTH - 100 && (_jsxs(Text, { variant: "footnote", children: [reasonDetail.length, "/", MAX_DETAIL_LENGTH] }))] }))] }));
85
85
  }
86
86
  const useStyles = () => {
87
87
  const { bottom } = useSafeAreaInsets();
@@ -1 +1 @@
1
- {"version":3,"file":"message_report_screen.js","sourceRoot":"","sources":["../../src/screens/message_report_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StaticScreenProps, useNavigation, StackActions } from '@react-navigation/native'\nimport type {\n NativeStackNavigationOptions,\n NativeStackScreenProps,\n} from '@react-navigation/native-stack'\nimport React, { useCallback, useLayoutEffect, useMemo, useState } from 'react'\nimport { View, StyleSheet, TextInput, ScrollView } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Spinner, Text, KeyboardView } from '../components'\nimport {\n composeOptions,\n useHeaderRight,\n withLeftClose,\n} from '../components/display/platform_modal_header_buttons'\nimport BlankState from '../components/primitive/blank_state_primitive'\nimport { useTheme } from '../hooks'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useReportMessage } from '../hooks/use_report_message'\nimport { MessageResource } from '../types'\nimport { MessageReportReason } from '../types/resources/message_report'\nimport { platformFontWeightBold } from '../utils'\nimport { MessagePreview } from './message_report/components/message_preview'\nimport { ReportReasonList } from './message_report/components/report_reason_list'\n\nconst MAX_DETAIL_LENGTH = 500\n\nexport const MessageReportScreenOptions = ({\n navigation,\n route,\n}: NativeStackScreenProps<any>): NativeStackNavigationOptions => {\n const handleClose = () =>\n navigation.dispatch(\n StackActions.popTo(\n 'Conversation',\n { conversation_id: route.params?.conversation_id },\n { merge: true }\n )\n )\n\n return composeOptions(\n { presentation: 'modal', title: 'Report message' },\n withLeftClose({ onPress: handleClose })\n )\n}\n\nexport type MessageReportScreenProps = StaticScreenProps<{\n conversation_id: number\n message_id: string\n}>\n\nexport function MessageReportScreen({ route }: MessageReportScreenProps) {\n const { conversation_id, message_id } = route.params\n\n const { messages } = useConversationMessages({ conversation_id }, { refetchOnMount: false })\n const message = messages.find(m => m.id === message_id)\n\n if (!message) return null\n\n return <MessageReportScreenContent message={message} conversation_id={conversation_id} />\n}\n\nfunction MessageReportScreenContent({\n message,\n conversation_id,\n}: {\n message: MessageResource\n conversation_id: number\n}) {\n const styles = useStyles()\n const navigation = useNavigation()\n const [selectedReason, setSelectedReason] = useState<MessageReportReason | null>(null)\n const [reasonDetail, setReasonDetail] = useState('')\n const { mutate: submitReport, status } = useReportMessage(conversation_id, message.id)\n\n const handleReasonChange = useCallback((reason: MessageReportReason) => {\n setSelectedReason(reason)\n\n if (reason !== 'other') {\n setReasonDetail('')\n }\n }, [])\n\n const isFormValid = useMemo(() => {\n if (selectedReason === null) return false\n\n if (selectedReason === 'other' && reasonDetail.trim().length === 0) {\n return false\n }\n\n if (status === 'pending') return false\n\n return true\n }, [selectedReason, reasonDetail, status])\n\n const handleSubmit = useCallback(() => {\n if (!isFormValid || !selectedReason) return\n\n submitReport({\n reason: selectedReason,\n reasonDetail: selectedReason === 'other' ? reasonDetail : undefined,\n })\n }, [isFormValid, selectedReason, reasonDetail, submitReport])\n\n const handleClose = useCallback(() => {\n navigation.dispatch(StackActions.popTo('Conversation', { conversation_id }, { merge: true }))\n }, [navigation, conversation_id])\n\n const formVisible = status !== 'pending' && status !== 'success'\n\n useHeaderRight({\n icon: 'general.upArrow',\n accessibilityLabel: 'Submit',\n prominent: true,\n onPress: handleSubmit,\n disabled: !isFormValid,\n enabled: formVisible,\n })\n\n useLayoutEffect(() => {\n if (formVisible) {\n navigation.setOptions({ headerTitle: 'Report message' })\n }\n }, [formVisible, navigation])\n\n if (status === 'pending') {\n return (\n <View style={styles.fullScreenContainer}>\n <Spinner />\n <Text style={styles.loadingText}>Submitting report...</Text>\n </View>\n )\n }\n\n if (status === 'success') {\n return (\n <View style={styles.fullScreenContainer}>\n <BlankState.Root>\n <BlankState.Imagery name=\"general.checkCircle\" style={styles.successIcon} />\n <BlankState.Content>\n <BlankState.Heading style={styles.successTitle}>Message reported</BlankState.Heading>\n <BlankState.Text style={styles.successSubtitle}>\n The message has been reported and a church leader will be contacted.\n </BlankState.Text>\n </BlankState.Content>\n <BlankState.Button title=\"Close\" onPress={handleClose} size=\"lg\" variant=\"fill\" />\n </BlankState.Root>\n </View>\n )\n }\n\n if (status === 'error') {\n return (\n <BlankState.Root>\n <BlankState.Imagery name=\"general.exclamationTriangle\" />\n <BlankState.Content>\n <BlankState.Heading>Unable to submit report</BlankState.Heading>\n <BlankState.Text>\n We were unable to report this message. Please try again.\n </BlankState.Text>\n </BlankState.Content>\n <BlankState.Button title=\"Close\" onPress={handleClose} size=\"lg\" variant=\"outline\" />\n </BlankState.Root>\n )\n }\n\n return (\n <KeyboardView>\n <ScrollView contentContainerStyle={styles.container}>\n <Text style={styles.warningText} maxFontSizeMultiplier={1.5}>\n Reporting this message will notify a church leader. The person you are reporting will not\n receive a notification from Church Center. If someone is in immediate danger, call local\n emergency services. Don&apos;t wait.\n </Text>\n\n <MessagePreview message={message} />\n\n <View style={styles.reasonSection}>\n <Text style={styles.fieldLabel}>\n What best describes the problem? <Text style={styles.required}>*</Text>\n </Text>\n\n <View style={styles.reasonListContainer}>\n <ReportReasonList selectedReason={selectedReason} onReasonChange={handleReasonChange} />\n </View>\n </View>\n\n {selectedReason === 'other' && (\n <View style={styles.detailSection}>\n <Text style={styles.fieldLabel}>\n Please provide more details <Text style={styles.required}>*</Text>\n </Text>\n <TextInput\n style={styles.textInput}\n multiline\n placeholder=\"Describe the issue...\"\n value={reasonDetail}\n onChangeText={setReasonDetail}\n maxLength={MAX_DETAIL_LENGTH}\n accessibilityLabel=\"Additional details\"\n accessibilityHint=\"Provide more information about why you're reporting this message\"\n />\n {reasonDetail.length >= MAX_DETAIL_LENGTH - 100 && (\n <Text variant=\"footnote\">\n {reasonDetail.length}/{MAX_DETAIL_LENGTH}\n </Text>\n )}\n </View>\n )}\n </ScrollView>\n </KeyboardView>\n )\n}\n\nconst useStyles = () => {\n const { bottom } = useSafeAreaInsets()\n const { colors } = useTheme()\n\n return StyleSheet.create({\n container: {\n padding: 16,\n paddingBottom: 16 + bottom,\n gap: 24,\n },\n fullHeight: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n },\n fullScreenContainer: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n backgroundColor: colors.surfaceColor100,\n },\n loadingText: {\n marginTop: 16,\n fontSize: 16,\n fontWeight: '600',\n color: colors.textColorDefaultPrimary,\n },\n warningText: {\n fontSize: 14,\n lineHeight: 20,\n color: colors.textColorDefaultSecondary,\n },\n reasonSection: {\n gap: 8,\n },\n fieldLabel: {\n fontSize: 16,\n fontWeight: platformFontWeightBold,\n color: colors.textColorDefaultPrimary,\n },\n required: {\n color: colors.statusErrorText,\n },\n reasonListContainer: {\n backgroundColor: colors.surfaceColor100,\n },\n detailSection: {\n gap: 8,\n },\n textInput: {\n color: colors.textColorDefaultPrimary,\n fontSize: 16,\n textAlignVertical: 'top',\n minHeight: 120,\n maxHeight: 200,\n borderWidth: 1,\n borderColor: colors.borderColorDefaultBase,\n borderRadius: 8,\n paddingHorizontal: 16,\n paddingVertical: 12,\n backgroundColor: colors.surfaceColor100,\n },\n successIcon: {\n color: colors.statusSuccessIcon,\n fontSize: 48,\n },\n successTitle: {\n fontSize: 24,\n marginBottom: 4,\n },\n successSubtitle: {\n fontSize: 16,\n marginBottom: 4,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"message_report_screen.js","sourceRoot":"","sources":["../../src/screens/message_report_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StaticScreenProps, useNavigation, StackActions } from '@react-navigation/native'\nimport type {\n NativeStackNavigationOptions,\n NativeStackScreenProps,\n} from '@react-navigation/native-stack'\nimport React, { useCallback, useLayoutEffect, useMemo, useState } from 'react'\nimport { View, StyleSheet, TextInput } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Spinner, Text, KeyboardScrollView } from '../components'\nimport {\n composeOptions,\n useHeaderRight,\n withLeftClose,\n} from '../components/display/platform_modal_header_buttons'\nimport BlankState from '../components/primitive/blank_state_primitive'\nimport { useTheme } from '../hooks'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useReportMessage } from '../hooks/use_report_message'\nimport { MessageResource } from '../types'\nimport { MessageReportReason } from '../types/resources/message_report'\nimport { platformFontWeightBold } from '../utils'\nimport { MessagePreview } from './message_report/components/message_preview'\nimport { ReportReasonList } from './message_report/components/report_reason_list'\n\nconst MAX_DETAIL_LENGTH = 500\n\nexport const MessageReportScreenOptions = ({\n navigation,\n route,\n}: NativeStackScreenProps<any>): NativeStackNavigationOptions => {\n const handleClose = () =>\n navigation.dispatch(\n StackActions.popTo(\n 'Conversation',\n { conversation_id: route.params?.conversation_id },\n { merge: true }\n )\n )\n\n return composeOptions(\n { presentation: 'modal', title: 'Report message' },\n withLeftClose({ onPress: handleClose })\n )\n}\n\nexport type MessageReportScreenProps = StaticScreenProps<{\n conversation_id: number\n message_id: string\n}>\n\nexport function MessageReportScreen({ route }: MessageReportScreenProps) {\n const { conversation_id, message_id } = route.params\n\n const { messages } = useConversationMessages({ conversation_id }, { refetchOnMount: false })\n const message = messages.find(m => m.id === message_id)\n\n if (!message) return null\n\n return <MessageReportScreenContent message={message} conversation_id={conversation_id} />\n}\n\nfunction MessageReportScreenContent({\n message,\n conversation_id,\n}: {\n message: MessageResource\n conversation_id: number\n}) {\n const styles = useStyles()\n const navigation = useNavigation()\n const [selectedReason, setSelectedReason] = useState<MessageReportReason | null>(null)\n const [reasonDetail, setReasonDetail] = useState('')\n const { mutate: submitReport, status } = useReportMessage(conversation_id, message.id)\n\n const handleReasonChange = useCallback((reason: MessageReportReason) => {\n setSelectedReason(reason)\n\n if (reason !== 'other') {\n setReasonDetail('')\n }\n }, [])\n\n const isFormValid = useMemo(() => {\n if (selectedReason === null) return false\n\n if (selectedReason === 'other' && reasonDetail.trim().length === 0) {\n return false\n }\n\n if (status === 'pending') return false\n\n return true\n }, [selectedReason, reasonDetail, status])\n\n const handleSubmit = useCallback(() => {\n if (!isFormValid || !selectedReason) return\n\n submitReport({\n reason: selectedReason,\n reasonDetail: selectedReason === 'other' ? reasonDetail : undefined,\n })\n }, [isFormValid, selectedReason, reasonDetail, submitReport])\n\n const handleClose = useCallback(() => {\n navigation.dispatch(StackActions.popTo('Conversation', { conversation_id }, { merge: true }))\n }, [navigation, conversation_id])\n\n const formVisible = status !== 'pending' && status !== 'success'\n\n useHeaderRight({\n icon: 'general.upArrow',\n accessibilityLabel: 'Submit',\n prominent: true,\n onPress: handleSubmit,\n disabled: !isFormValid,\n enabled: formVisible,\n })\n\n useLayoutEffect(() => {\n if (formVisible) {\n navigation.setOptions({ headerTitle: 'Report message' })\n }\n }, [formVisible, navigation])\n\n if (status === 'pending') {\n return (\n <View style={styles.fullScreenContainer}>\n <Spinner />\n <Text style={styles.loadingText}>Submitting report...</Text>\n </View>\n )\n }\n\n if (status === 'success') {\n return (\n <View style={styles.fullScreenContainer}>\n <BlankState.Root>\n <BlankState.Imagery name=\"general.checkCircle\" style={styles.successIcon} />\n <BlankState.Content>\n <BlankState.Heading style={styles.successTitle}>Message reported</BlankState.Heading>\n <BlankState.Text style={styles.successSubtitle}>\n The message has been reported and a church leader will be contacted.\n </BlankState.Text>\n </BlankState.Content>\n <BlankState.Button title=\"Close\" onPress={handleClose} size=\"lg\" variant=\"fill\" />\n </BlankState.Root>\n </View>\n )\n }\n\n if (status === 'error') {\n return (\n <BlankState.Root>\n <BlankState.Imagery name=\"general.exclamationTriangle\" />\n <BlankState.Content>\n <BlankState.Heading>Unable to submit report</BlankState.Heading>\n <BlankState.Text>\n We were unable to report this message. Please try again.\n </BlankState.Text>\n </BlankState.Content>\n <BlankState.Button title=\"Close\" onPress={handleClose} size=\"lg\" variant=\"outline\" />\n </BlankState.Root>\n )\n }\n\n return (\n <KeyboardScrollView contentContainerStyle={styles.container}>\n <Text style={styles.warningText} maxFontSizeMultiplier={1.5}>\n Reporting this message will notify a church leader. The person you are reporting will not\n receive a notification from Church Center. If someone is in immediate danger, call local\n emergency services. Don&apos;t wait.\n </Text>\n\n <MessagePreview message={message} />\n\n <View style={styles.reasonSection}>\n <Text style={styles.fieldLabel}>\n What best describes the problem? <Text style={styles.required}>*</Text>\n </Text>\n\n <View style={styles.reasonListContainer}>\n <ReportReasonList selectedReason={selectedReason} onReasonChange={handleReasonChange} />\n </View>\n </View>\n\n {selectedReason === 'other' && (\n <View style={styles.detailSection}>\n <Text style={styles.fieldLabel}>\n Please provide more details <Text style={styles.required}>*</Text>\n </Text>\n <TextInput\n style={styles.textInput}\n multiline\n placeholder=\"Describe the issue...\"\n value={reasonDetail}\n onChangeText={setReasonDetail}\n maxLength={MAX_DETAIL_LENGTH}\n accessibilityLabel=\"Additional details\"\n accessibilityHint=\"Provide more information about why you're reporting this message\"\n />\n {reasonDetail.length >= MAX_DETAIL_LENGTH - 100 && (\n <Text variant=\"footnote\">\n {reasonDetail.length}/{MAX_DETAIL_LENGTH}\n </Text>\n )}\n </View>\n )}\n </KeyboardScrollView>\n )\n}\n\nconst useStyles = () => {\n const { bottom } = useSafeAreaInsets()\n const { colors } = useTheme()\n\n return StyleSheet.create({\n container: {\n padding: 16,\n paddingBottom: 16 + bottom,\n gap: 24,\n },\n fullHeight: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n },\n fullScreenContainer: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n backgroundColor: colors.surfaceColor100,\n },\n loadingText: {\n marginTop: 16,\n fontSize: 16,\n fontWeight: '600',\n color: colors.textColorDefaultPrimary,\n },\n warningText: {\n fontSize: 14,\n lineHeight: 20,\n color: colors.textColorDefaultSecondary,\n },\n reasonSection: {\n gap: 8,\n },\n fieldLabel: {\n fontSize: 16,\n fontWeight: platformFontWeightBold,\n color: colors.textColorDefaultPrimary,\n },\n required: {\n color: colors.statusErrorText,\n },\n reasonListContainer: {\n backgroundColor: colors.surfaceColor100,\n },\n detailSection: {\n gap: 8,\n },\n textInput: {\n color: colors.textColorDefaultPrimary,\n fontSize: 16,\n textAlignVertical: 'top',\n minHeight: 120,\n maxHeight: 200,\n borderWidth: 1,\n borderColor: colors.borderColorDefaultBase,\n borderRadius: 8,\n paddingHorizontal: 16,\n paddingVertical: 12,\n backgroundColor: colors.surfaceColor100,\n },\n successIcon: {\n color: colors.statusSuccessIcon,\n fontSize: 48,\n },\n successTitle: {\n fontSize: 24,\n marginBottom: 4,\n },\n successSubtitle: {\n fontSize: 16,\n marginBottom: 4,\n },\n })\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "4.0.0-rc.0",
3
+ "version": "4.0.0-rc.1",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -78,5 +78,5 @@
78
78
  "sf-symbols-typescript": "^2.2.0",
79
79
  "typescript": "~6.0.3"
80
80
  },
81
- "gitHead": "b528eaada6793bdc405230fcf0a249fb5a2389dc"
81
+ "gitHead": "0acb61429b82088f4d7ce9638f2e18cec4cdbfb1"
82
82
  }
@@ -23,6 +23,7 @@ export * from './text_button'
23
23
  export * from './text_inline_button'
24
24
  export * from './text'
25
25
  export * from './toggle_button'
26
+ export * from './keyboard_scroll_view'
26
27
  export * from './keyboard_view'
27
28
  export * from './platform_modal_header_buttons'
28
29
  export * from './pressable_row'
@@ -0,0 +1,54 @@
1
+ import React, { useCallback, useRef } from 'react'
2
+ import { Keyboard, ScrollView, ScrollViewProps, TextInput } from 'react-native'
3
+ import { KeyboardView } from './keyboard_view'
4
+
5
+ const FOCUSED_INPUT_BOTTOM_MARGIN = 32
6
+
7
+ type KeyboardScrollViewProps = Pick<ScrollViewProps, 'children' | 'contentContainerStyle'>
8
+
9
+ export function KeyboardScrollView({ children, contentContainerStyle }: KeyboardScrollViewProps) {
10
+ const scrollViewRef = useRef<ScrollView>(null)
11
+
12
+ const scrollFocusedInputIntoView = useCallback(() => {
13
+ const scrollView = scrollViewRef.current
14
+ const input = TextInput.State.currentlyFocusedInput()
15
+ if (!scrollView || !input) return
16
+
17
+ const nativeScrollView = scrollView.getNativeScrollRef()
18
+ const innerView = scrollView.getInnerViewRef()
19
+ if (!nativeScrollView || !innerView) return
20
+
21
+ nativeScrollView.measureInWindow((_scrollX, scrollTop, _scrollWidth, scrollHeight) => {
22
+ const keyboardTop = Keyboard.metrics()?.screenY
23
+ const scrollBottom = scrollTop + scrollHeight
24
+ const visibleBottom =
25
+ keyboardTop === undefined ? scrollBottom : Math.min(scrollBottom, keyboardTop)
26
+ const visibleHeight = visibleBottom - scrollTop
27
+
28
+ input.measureInWindow((_inputX, inputTop, _inputWidth, inputHeight) => {
29
+ const inputBottom = inputTop + inputHeight + FOCUSED_INPUT_BOTTOM_MARGIN
30
+ if (inputBottom <= visibleBottom) return
31
+
32
+ input.measureLayout(innerView, (_left, contentTop, _contentWidth, contentHeight) => {
33
+ scrollView.scrollTo({
34
+ y: contentTop + contentHeight + FOCUSED_INPUT_BOTTOM_MARGIN - visibleHeight,
35
+ animated: true,
36
+ })
37
+ })
38
+ })
39
+ })
40
+ }, [])
41
+
42
+ return (
43
+ <KeyboardView>
44
+ <ScrollView
45
+ ref={scrollViewRef}
46
+ contentContainerStyle={contentContainerStyle}
47
+ onLayout={scrollFocusedInputIntoView}
48
+ onContentSizeChange={scrollFocusedInputIntoView}
49
+ >
50
+ {children}
51
+ </ScrollView>
52
+ </KeyboardView>
53
+ )
54
+ }
@@ -22,7 +22,7 @@ import {
22
22
  TextInlineButton,
23
23
  ImageAttachmentPreview,
24
24
  Icon,
25
- KeyboardView,
25
+ KeyboardScrollView,
26
26
  } from '../components'
27
27
  import {
28
28
  composeOptions,
@@ -217,166 +217,160 @@ export function BugReportScreen() {
217
217
  }
218
218
 
219
219
  return (
220
- <KeyboardView>
221
- <ScrollView contentContainerStyle={styles.container}>
222
- <Text style={styles.description}>
223
- Thanks for helping us improve {DisplayableAppName[name]}. We won't be able to respond to
224
- your submission, but your feedback helps us improve the experience helps us improve the
225
- experience.
226
- </Text>
220
+ <KeyboardScrollView contentContainerStyle={styles.container}>
221
+ <Text style={styles.description}>
222
+ Thanks for helping us improve {DisplayableAppName[name]}. We won't be able to respond to
223
+ your submission, but your feedback helps us improve the experience helps us improve the
224
+ experience.
225
+ </Text>
227
226
 
228
- <View style={styles.textInputContainer}>
229
- <Text style={styles.fieldLabel}>
230
- Where did you experience the issue? <Text style={styles.required}>*</Text>
231
- </Text>
232
- <TouchableOpacity style={styles.pickerButton} onPress={() => setShowBugTypePicker(true)}>
233
- <Text style={[styles.pickerText, !bugType && styles.pickerPlaceholder]}>{bugType}</Text>
234
- <Icon
235
- name="general.downChevron"
236
- style={styles.pickerArrow}
237
- accessibilityElementsHidden
238
- />
239
- </TouchableOpacity>
240
- </View>
227
+ <View style={styles.textInputContainer}>
228
+ <Text style={styles.fieldLabel}>
229
+ Where did you experience the issue? <Text style={styles.required}>*</Text>
230
+ </Text>
231
+ <TouchableOpacity style={styles.pickerButton} onPress={() => setShowBugTypePicker(true)}>
232
+ <Text style={[styles.pickerText, !bugType && styles.pickerPlaceholder]}>{bugType}</Text>
233
+ <Icon name="general.downChevron" style={styles.pickerArrow} accessibilityElementsHidden />
234
+ </TouchableOpacity>
235
+ </View>
241
236
 
242
- <SafeAreaModal
243
- visible={showBugTypePicker}
244
- animationType="slide"
245
- presentationStyle="pageSheet"
246
- onRequestClose={() => setShowBugTypePicker(false)}
247
- >
248
- <View style={styles.modalContainer}>
249
- <View style={styles.modalHeader}>
250
- <HeaderDismissButton title="Cancel" onPress={() => setShowBugTypePicker(false)} />
251
- <Text style={styles.modalTitle}>Select Bug Type</Text>
252
- <View style={styles.modalHeaderSpacer} />
253
- </View>
254
- <ScrollView style={styles.modalContent}>
255
- {Object.values(BUG_TYPE_OPTIONS).map(option => (
256
- <TouchableOpacity
257
- key={option}
258
- style={styles.modalOption}
259
- onPress={() => {
260
- setBugType(option)
261
- setShowBugTypePicker(false)
262
- }}
263
- >
264
- <Text style={styles.modalOptionText}>{option}</Text>
265
- {bugType === option && (
266
- <Icon
267
- name="general.check"
268
- style={styles.modalCheckmark}
269
- accessibilityElementsHidden
270
- />
271
- )}
272
- </TouchableOpacity>
273
- ))}
274
- </ScrollView>
237
+ <SafeAreaModal
238
+ visible={showBugTypePicker}
239
+ animationType="slide"
240
+ presentationStyle="pageSheet"
241
+ onRequestClose={() => setShowBugTypePicker(false)}
242
+ >
243
+ <View style={styles.modalContainer}>
244
+ <View style={styles.modalHeader}>
245
+ <HeaderDismissButton title="Cancel" onPress={() => setShowBugTypePicker(false)} />
246
+ <Text style={styles.modalTitle}>Select Bug Type</Text>
247
+ <View style={styles.modalHeaderSpacer} />
275
248
  </View>
276
- </SafeAreaModal>
277
-
278
- <View style={styles.textInputContainer}>
279
- <Text style={styles.fieldLabel}>
280
- What were you trying to do when you encountered the bug?{' '}
281
- <Text style={styles.required}>*</Text>
282
- </Text>
283
- <TextInput
284
- style={styles.textInput}
285
- multiline
286
- placeholder="Description"
287
- value={whatWereDoing}
288
- onChangeText={setWhatWereDoing}
289
- maxLength={MAX_DESCRIPTION_LENGTH}
290
- />
291
- {whatWereDoing.length >= MAX_DESCRIPTION_LENGTH - 100 && (
292
- <Text variant="footnote">
293
- {whatWereDoing.length}/{MAX_DESCRIPTION_LENGTH}
294
- </Text>
295
- )}
249
+ <ScrollView style={styles.modalContent}>
250
+ {Object.values(BUG_TYPE_OPTIONS).map(option => (
251
+ <TouchableOpacity
252
+ key={option}
253
+ style={styles.modalOption}
254
+ onPress={() => {
255
+ setBugType(option)
256
+ setShowBugTypePicker(false)
257
+ }}
258
+ >
259
+ <Text style={styles.modalOptionText}>{option}</Text>
260
+ {bugType === option && (
261
+ <Icon
262
+ name="general.check"
263
+ style={styles.modalCheckmark}
264
+ accessibilityElementsHidden
265
+ />
266
+ )}
267
+ </TouchableOpacity>
268
+ ))}
269
+ </ScrollView>
296
270
  </View>
271
+ </SafeAreaModal>
297
272
 
298
- <View style={styles.textInputContainer}>
299
- <Text style={styles.fieldLabel}>
300
- What did you expect to happen? Please describe what actually happened.{' '}
301
- <Text style={styles.required}>*</Text>
273
+ <View style={styles.textInputContainer}>
274
+ <Text style={styles.fieldLabel}>
275
+ What were you trying to do when you encountered the bug?{' '}
276
+ <Text style={styles.required}>*</Text>
277
+ </Text>
278
+ <TextInput
279
+ style={styles.textInput}
280
+ multiline
281
+ placeholder="Description"
282
+ value={whatWereDoing}
283
+ onChangeText={setWhatWereDoing}
284
+ maxLength={MAX_DESCRIPTION_LENGTH}
285
+ />
286
+ {whatWereDoing.length >= MAX_DESCRIPTION_LENGTH - 100 && (
287
+ <Text variant="footnote">
288
+ {whatWereDoing.length}/{MAX_DESCRIPTION_LENGTH}
302
289
  </Text>
303
- <TextInput
304
- style={styles.textInput}
305
- multiline
306
- placeholder="Description"
307
- value={whatExpected}
308
- onChangeText={setWhatExpected}
309
- maxLength={MAX_DESCRIPTION_LENGTH}
310
- />
311
- {whatExpected.length >= MAX_DESCRIPTION_LENGTH - 100 && (
312
- <Text variant="footnote">
313
- {whatExpected.length}/{MAX_DESCRIPTION_LENGTH}
314
- </Text>
315
- )}
316
- </View>
290
+ )}
291
+ </View>
317
292
 
318
- <View style={styles.attachmentSection}>
319
- <View style={styles.attachmentHeader}>
320
- <Text style={styles.attachmentLabel}>
321
- Attachment <Text style={styles.subLabel}>(optional)</Text>
322
- </Text>
323
- {uploading && <Spinner />}
324
- </View>
325
- {uploadError && <Text style={styles.attachmentErrorText}>{uploadError}</Text>}
326
- {attachment ? (
327
- <View style={styles.attachmentPreviewContainer}>
328
- {isImageAttachment ? (
329
- <ImageAttachmentPreview
330
- uri={imagePreviewURI}
331
- fileName={attachment.name}
332
- onRemovePress={handleRemoveAttachment}
333
- />
334
- ) : (
335
- <VideoAttachmentPreview
336
- name={attachment.name}
337
- onRemovePress={handleRemoveAttachment}
338
- />
339
- )}
340
- </View>
341
- ) : (
342
- <Button
343
- title="Attach a screenshot or recording"
344
- accessibilityHint="Opens your device's image gallery"
345
- iconNameLeft="general.paperclip"
346
- onPress={pickImage}
347
- size="sm"
348
- variant="outline"
349
- style={styles.attachButton}
350
- disabled={uploading || Boolean(attachment)}
351
- />
352
- )}
293
+ <View style={styles.textInputContainer}>
294
+ <Text style={styles.fieldLabel}>
295
+ What did you expect to happen? Please describe what actually happened.{' '}
296
+ <Text style={styles.required}>*</Text>
297
+ </Text>
298
+ <TextInput
299
+ style={styles.textInput}
300
+ multiline
301
+ placeholder="Description"
302
+ value={whatExpected}
303
+ onChangeText={setWhatExpected}
304
+ maxLength={MAX_DESCRIPTION_LENGTH}
305
+ />
306
+ {whatExpected.length >= MAX_DESCRIPTION_LENGTH - 100 && (
353
307
  <Text variant="footnote">
354
- Screenshots and screen recordings help us reproduce and fix issues faster.{' '}
355
- <TextInlineButton
356
- accessibilityRole="link"
357
- variant="footnote"
358
- onPress={() => Linking.openURL(VIDEO_RECORDING_HELP_URL)}
359
- >
360
- How to record your screen
361
- </TextInlineButton>
308
+ {whatExpected.length}/{MAX_DESCRIPTION_LENGTH}
362
309
  </Text>
363
- </View>
310
+ )}
311
+ </View>
364
312
 
365
- <View style={styles.footer}>
366
- <Text variant="footnote">
367
- For details on how we process your data and ensure its security, please refer to our{' '}
368
- <TextInlineButton
369
- accessibilityRole="link"
370
- variant="footnote"
371
- onPress={() => Linking.openURL('https://www.planningcenter.com/privacy')}
372
- >
373
- Privacy Policy
374
- </TextInlineButton>
375
- .
313
+ <View style={styles.attachmentSection}>
314
+ <View style={styles.attachmentHeader}>
315
+ <Text style={styles.attachmentLabel}>
316
+ Attachment <Text style={styles.subLabel}>(optional)</Text>
376
317
  </Text>
318
+ {uploading && <Spinner />}
377
319
  </View>
378
- </ScrollView>
379
- </KeyboardView>
320
+ {uploadError && <Text style={styles.attachmentErrorText}>{uploadError}</Text>}
321
+ {attachment ? (
322
+ <View style={styles.attachmentPreviewContainer}>
323
+ {isImageAttachment ? (
324
+ <ImageAttachmentPreview
325
+ uri={imagePreviewURI}
326
+ fileName={attachment.name}
327
+ onRemovePress={handleRemoveAttachment}
328
+ />
329
+ ) : (
330
+ <VideoAttachmentPreview
331
+ name={attachment.name}
332
+ onRemovePress={handleRemoveAttachment}
333
+ />
334
+ )}
335
+ </View>
336
+ ) : (
337
+ <Button
338
+ title="Attach a screenshot or recording"
339
+ accessibilityHint="Opens your device's image gallery"
340
+ iconNameLeft="general.paperclip"
341
+ onPress={pickImage}
342
+ size="sm"
343
+ variant="outline"
344
+ style={styles.attachButton}
345
+ disabled={uploading || Boolean(attachment)}
346
+ />
347
+ )}
348
+ <Text variant="footnote">
349
+ Screenshots and screen recordings help us reproduce and fix issues faster.{' '}
350
+ <TextInlineButton
351
+ accessibilityRole="link"
352
+ variant="footnote"
353
+ onPress={() => Linking.openURL(VIDEO_RECORDING_HELP_URL)}
354
+ >
355
+ How to record your screen
356
+ </TextInlineButton>
357
+ </Text>
358
+ </View>
359
+
360
+ <View style={styles.footer}>
361
+ <Text variant="footnote">
362
+ For details on how we process your data and ensure its security, please refer to our{' '}
363
+ <TextInlineButton
364
+ accessibilityRole="link"
365
+ variant="footnote"
366
+ onPress={() => Linking.openURL('https://www.planningcenter.com/privacy')}
367
+ >
368
+ Privacy Policy
369
+ </TextInlineButton>
370
+ .
371
+ </Text>
372
+ </View>
373
+ </KeyboardScrollView>
380
374
  )
381
375
  }
382
376
 
@@ -4,9 +4,9 @@ import type {
4
4
  NativeStackScreenProps,
5
5
  } from '@react-navigation/native-stack'
6
6
  import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react'
7
- import { View, StyleSheet, TextInput, ScrollView } from 'react-native'
7
+ import { View, StyleSheet, TextInput } from 'react-native'
8
8
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
9
- import { Spinner, Text, KeyboardView } from '../components'
9
+ import { Spinner, Text, KeyboardScrollView } from '../components'
10
10
  import {
11
11
  composeOptions,
12
12
  useHeaderRight,
@@ -164,50 +164,48 @@ function MessageReportScreenContent({
164
164
  }
165
165
 
166
166
  return (
167
- <KeyboardView>
168
- <ScrollView contentContainerStyle={styles.container}>
169
- <Text style={styles.warningText} maxFontSizeMultiplier={1.5}>
170
- Reporting this message will notify a church leader. The person you are reporting will not
171
- receive a notification from Church Center. If someone is in immediate danger, call local
172
- emergency services. Don&apos;t wait.
173
- </Text>
167
+ <KeyboardScrollView contentContainerStyle={styles.container}>
168
+ <Text style={styles.warningText} maxFontSizeMultiplier={1.5}>
169
+ Reporting this message will notify a church leader. The person you are reporting will not
170
+ receive a notification from Church Center. If someone is in immediate danger, call local
171
+ emergency services. Don&apos;t wait.
172
+ </Text>
174
173
 
175
- <MessagePreview message={message} />
174
+ <MessagePreview message={message} />
176
175
 
177
- <View style={styles.reasonSection}>
178
- <Text style={styles.fieldLabel}>
179
- What best describes the problem? <Text style={styles.required}>*</Text>
180
- </Text>
176
+ <View style={styles.reasonSection}>
177
+ <Text style={styles.fieldLabel}>
178
+ What best describes the problem? <Text style={styles.required}>*</Text>
179
+ </Text>
181
180
 
182
- <View style={styles.reasonListContainer}>
183
- <ReportReasonList selectedReason={selectedReason} onReasonChange={handleReasonChange} />
184
- </View>
181
+ <View style={styles.reasonListContainer}>
182
+ <ReportReasonList selectedReason={selectedReason} onReasonChange={handleReasonChange} />
185
183
  </View>
184
+ </View>
186
185
 
187
- {selectedReason === 'other' && (
188
- <View style={styles.detailSection}>
189
- <Text style={styles.fieldLabel}>
190
- Please provide more details <Text style={styles.required}>*</Text>
186
+ {selectedReason === 'other' && (
187
+ <View style={styles.detailSection}>
188
+ <Text style={styles.fieldLabel}>
189
+ Please provide more details <Text style={styles.required}>*</Text>
190
+ </Text>
191
+ <TextInput
192
+ style={styles.textInput}
193
+ multiline
194
+ placeholder="Describe the issue..."
195
+ value={reasonDetail}
196
+ onChangeText={setReasonDetail}
197
+ maxLength={MAX_DETAIL_LENGTH}
198
+ accessibilityLabel="Additional details"
199
+ accessibilityHint="Provide more information about why you're reporting this message"
200
+ />
201
+ {reasonDetail.length >= MAX_DETAIL_LENGTH - 100 && (
202
+ <Text variant="footnote">
203
+ {reasonDetail.length}/{MAX_DETAIL_LENGTH}
191
204
  </Text>
192
- <TextInput
193
- style={styles.textInput}
194
- multiline
195
- placeholder="Describe the issue..."
196
- value={reasonDetail}
197
- onChangeText={setReasonDetail}
198
- maxLength={MAX_DETAIL_LENGTH}
199
- accessibilityLabel="Additional details"
200
- accessibilityHint="Provide more information about why you're reporting this message"
201
- />
202
- {reasonDetail.length >= MAX_DETAIL_LENGTH - 100 && (
203
- <Text variant="footnote">
204
- {reasonDetail.length}/{MAX_DETAIL_LENGTH}
205
- </Text>
206
- )}
207
- </View>
208
- )}
209
- </ScrollView>
210
- </KeyboardView>
205
+ )}
206
+ </View>
207
+ )}
208
+ </KeyboardScrollView>
211
209
  )
212
210
  }
213
211
 
@@ -0,0 +1,7 @@
1
+ import type { HostInstance } from 'react-native'
2
+
3
+ declare module 'react-native' {
4
+ interface ScrollView {
5
+ getInnerViewRef(): HostInstance | null
6
+ }
7
+ }