Skip to content

Commit b3387ea

Browse files
tharindu20118claude
andcommitted
feat: let host apps opt out of the notification permission request
PermissionsAndroid.request(POST_NOTIFICATIONS) fired unconditionally whenever the bell button was tapped, with no way for a host app to prevent it. Adds enableNotificationBell (default true, backward compatible) to ChattyChatView — when false, the button is hidden and the SDK never calls PermissionsAndroid.request, so integrating apps fully control if/when/how it's requested. Camera/photo/mic already never request permissions themselves (host-supplied callbacks). Documents this in a new README Permissions section. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 482ff7e commit b3387ea

4 files changed

Lines changed: 50 additions & 6 deletions

File tree

‎README.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ this release; color, radius, and header/bubble treatment carry most of a design'
125125
onMessage={(message) => void}
126126
onVoiceCallPress={() => void}
127127
onNotificationBellPress={() => void}
128+
enableNotificationBell={boolean} // optional, defaults to true — see Permissions
128129
/>
129130
```
130131

@@ -148,6 +149,7 @@ The button color follows the active design's accent automatically — same as we
148149
onNotificationBellPress={() => void} // optional, header notification-bell button — see Notes
149150
onClose={() => void} // optional, renders a header close (✕) button.
150151
// ChattyLauncher passes this for you.
152+
enableNotificationBell={boolean} // optional, defaults to true — see Permissions
151153
/>
152154
```
153155

@@ -176,6 +178,32 @@ layout.
176178

177179
### Notes
178180

181+
<details open>
182+
<summary><strong id="permissions">Permissions — what this SDK requests, and how to opt out</strong></summary>
183+
184+
<br>
185+
186+
This SDK requests exactly one permission itself, and only in direct response to a button tap —
187+
never on load, never speculatively:
188+
189+
| Permission | Risk | Used for | Requested when |
190+
|---|---|---|---|
191+
| `POST_NOTIFICATIONS` (Android 13+) | Runtime-gated | Header bell button → local notification-permission ask | User taps the bell, only if `enableNotificationBell` (default `true`) |
192+
193+
Set `enableNotificationBell={false}` to hide the bell button entirely — the SDK then never calls
194+
`PermissionsAndroid.request` at all, so your app fully controls if/when/how notification
195+
permission is ever requested. Your app remains free to request it itself, on its own schedule,
196+
for its own purposes.
197+
198+
**Camera, photo library, and microphone are never requested by this SDK at all** — as noted
199+
above, `onCameraPress` / `onPhotoLibraryPress` / `onMicPress` are plain callbacks; your app
200+
supplies its own picker/recorder package (`expo-image-picker`, `react-native-image-picker`,
201+
`expo-av`, etc.) and that package's own permission flow runs entirely under your control. This
202+
SDK adds no `CAMERA`/`RECORD_AUDIO`/photo-library manifest entries or Info.plist keys of its own —
203+
whatever picker/recorder you choose documents what it needs.
204+
205+
</details>
206+
179207
<details open>
180208
<summary><strong>Security — <code>bot_id</code> and domain restriction</strong></summary>
181209

‎dist/ChattyChatView.d.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,12 @@ export interface ChattyChatViewProps extends UseChattyChatOptions {
3333
* your own close bar above ChattyChatView (e.g. in a modal wrapper), so there's one header,
3434
* not two stacked ones. ChattyLauncher already does this for you. */
3535
onClose?: () => void;
36+
/** Shows the header's notification-bell button and, on Android, requests
37+
* POST_NOTIFICATIONS (a runtime permission on API 33+) when tapped. Set `false` to hide the
38+
* button entirely — the SDK then never calls PermissionsAndroid.request at all, so your app
39+
* fully controls if/when/how notification permission is ever requested. Default `true`.
40+
* Camera/photo/mic aren't listed here because this SDK never requests those permissions
41+
* itself — see onCameraPress/onPhotoLibraryPress/onMicPress above. */
42+
enableNotificationBell?: boolean;
3643
}
3744
export declare function ChattyChatView(props: ChattyChatViewProps): React.JSX.Element;

‎dist/ChattyChatView.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,9 @@ export function ChattyChatView(props) {
122122
{theme?.voice_enabled ? (<TouchableOpacity style={styles.headerActionButton} onPress={() => props.onVoiceCallPress?.()}>
123123
<Text style={{ fontSize: 16 }}>📞</Text>
124124
</TouchableOpacity>) : null}
125-
<TouchableOpacity style={styles.headerActionButton} onPress={handleBellPress}>
126-
<Text style={{ fontSize: 16 }}>🔔</Text>
127-
</TouchableOpacity>
125+
{props.enableNotificationBell !== false ? (<TouchableOpacity style={styles.headerActionButton} onPress={handleBellPress}>
126+
<Text style={{ fontSize: 16 }}>🔔</Text>
127+
</TouchableOpacity>) : null}
128128
<TouchableOpacity style={styles.headerActionButton} onPress={() => void clearChat()}>
129129
<Text style={{ fontSize: 16 }}>↺</Text>
130130
</TouchableOpacity>

‎src/ChattyChatView.tsx‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ export interface ChattyChatViewProps extends UseChattyChatOptions {
6464
* your own close bar above ChattyChatView (e.g. in a modal wrapper), so there's one header,
6565
* not two stacked ones. ChattyLauncher already does this for you. */
6666
onClose?: () => void;
67+
/** Shows the header's notification-bell button and, on Android, requests
68+
* POST_NOTIFICATIONS (a runtime permission on API 33+) when tapped. Set `false` to hide the
69+
* button entirely — the SDK then never calls PermissionsAndroid.request at all, so your app
70+
* fully controls if/when/how notification permission is ever requested. Default `true`.
71+
* Camera/photo/mic aren't listed here because this SDK never requests those permissions
72+
* itself — see onCameraPress/onPhotoLibraryPress/onMicPress above. */
73+
enableNotificationBell?: boolean;
6774
}
6875

6976
/** bot/logo(no logoUrl)/custom(no avatarUrl) fall back to a generic chat
@@ -196,9 +203,11 @@ export function ChattyChatView(props: ChattyChatViewProps) {
196203
<Text style={{ fontSize: 16 }}>📞</Text>
197204
</TouchableOpacity>
198205
) : null}
199-
<TouchableOpacity style={styles.headerActionButton} onPress={handleBellPress}>
200-
<Text style={{ fontSize: 16 }}>🔔</Text>
201-
</TouchableOpacity>
206+
{props.enableNotificationBell !== false ? (
207+
<TouchableOpacity style={styles.headerActionButton} onPress={handleBellPress}>
208+
<Text style={{ fontSize: 16 }}>🔔</Text>
209+
</TouchableOpacity>
210+
) : null}
202211
<TouchableOpacity style={styles.headerActionButton} onPress={() => void clearChat()}>
203212
<Text style={{ fontSize: 16 }}>↺</Text>
204213
</TouchableOpacity>

0 commit comments

Comments
 (0)