Skip to content

Commit 4711d20

Browse files
authored
feat: add React hooks for device state monitoring (#38)
* feat(hooks): add hooks directory structure and utilities - Create src/hooks/ directory for React hooks - Add barrel export file (index.ts) with all hook exports - Add utils.ts with platform-specific low battery threshold - iOS: 20% threshold (matches iOS low power mode) - Android: 15% threshold (matches Android low battery warning) * feat(hooks): implement battery monitoring hooks Add React hooks for battery state monitoring: - useBatteryLevel(): Returns battery level (0.0-1.0) - useBatteryLevelIsLow(): Returns level when below threshold - usePowerState(): Returns comprehensive power state object All hooks use polling-based updates (5s interval for battery, 2s for low battery detection) * feat(hooks): implement headphone detection hooks Add React hooks for audio device detection: - useIsHeadphonesConnected(): Any headphone connection - useIsWiredHeadphonesConnected(): Wired headphone connection - useIsBluetoothHeadphonesConnected(): Bluetooth audio connection All hooks poll every 1s for connection state changes. * feat(hooks): implement brightness monitoring hook Add useBrightness() hook for screen brightness monitoring: - iOS: Returns brightness level (0.0-1.0), polls every 500ms - Android: Returns -1 (not supported on Android) * feat(hooks): export all hooks from main entry point Re-export all 7 React hooks from src/index.ts: - useBatteryLevel, useBatteryLevelIsLow, usePowerState - useIsHeadphonesConnected, useIsWiredHeadphonesConnected, useIsBluetoothHeadphonesConnected - useBrightness * feat(example): add HooksDemo screen to showcase app Add interactive hooks demonstration screen: - Battery section: level, charging state, low battery warning - Audio Output section: headphone connection status - Display section: brightness level (iOS only) - Real-time timestamp tracking for value updates Update App.tsx with tab navigation: - Properties tab: existing DeviceInfoScreen - Hooks Demo tab: new HooksDemo screen * feat(example): add hooks performance benchmarks Add hooks benchmark file with performance tests: - Hook registration time - Hook cleanup validation (1000 cycles, no memory leaks) - Callback latency benchmark Update BenchmarkScreen with: - React Hooks Performance section - Pass/fail badges for each benchmark - Threshold vs actual value display * docs: add React hooks documentation Add comprehensive hooks documentation: - docs/api/hooks.md: Complete API reference for all 7 hooks with signatures, return types, and platform support tables - docs/guide/react-hooks.md: Usage guide with 5+ examples including battery monitoring, headphone detection, brightness - docs/api/migration.md: Updated with hooks comparison table and migration examples from react-native-device-info Update rspress.config.ts with navigation links: - Add React Hooks to Guide nav and sidebar - Add React Hooks to API Reference nav and sidebar * chore: clear comments/docs * chore: clear comments * fix(showcase): use SafeAreaView, StatusBar.currentHeight * fix: address PR review feedback - useBrightness: skip polling on Android where brightness is unsupported - HooksDemo: fix stale closure in useTimestampedValue with functional update - useBatteryLevel: improve code pattern consistency with other hooks - BenchmarkScreen: fix HTML entity rendering in threshold text * docs: remove unnecessary section from hooks guide * docs: more clearer * feat: refactor * docs: update docs * chore: setState with functional pattern & update docs
1 parent 28f4921 commit 4711d20

20 files changed

+2004
-7
lines changed

docs/docs/api/hooks.md

Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
# React Hooks
2+
3+
React hooks for monitoring runtime device properties. These hooks provide reactive access to device state, automatically re-rendering your components when values change.
4+
5+
## Import
6+
7+
```typescript
8+
import {
9+
useBatteryLevel,
10+
useBatteryLevelIsLow,
11+
usePowerState,
12+
useIsHeadphonesConnected,
13+
useIsWiredHeadphonesConnected,
14+
useIsBluetoothHeadphonesConnected,
15+
useBrightness,
16+
} from 'react-native-nitro-device-info';
17+
```
18+
19+
---
20+
21+
## Battery Hooks
22+
23+
### `useBatteryLevel()`
24+
25+
Monitor battery level changes in real-time.
26+
27+
```typescript
28+
function useBatteryLevel(): number | null
29+
```
30+
31+
**Returns**: Battery level (0.0 to 1.0), or `null` during initial load.
32+
33+
**Platform Support**:
34+
| Platform | Supported |
35+
|----------|-----------|
36+
| iOS ||
37+
| Android ||
38+
39+
**Example**:
40+
41+
```tsx
42+
import { useBatteryLevel } from 'react-native-nitro-device-info';
43+
44+
function BatteryIndicator() {
45+
const batteryLevel = useBatteryLevel();
46+
47+
if (batteryLevel === null) {
48+
return <Text>Loading...</Text>;
49+
}
50+
51+
return <Text>Battery: {Math.round(batteryLevel * 100)}%</Text>;
52+
}
53+
```
54+
55+
---
56+
57+
### `useBatteryLevelIsLow()`
58+
59+
Monitor for low battery conditions with platform-specific thresholds.
60+
61+
```typescript
62+
function useBatteryLevelIsLow(): number | null
63+
```
64+
65+
**Returns**: Battery level when below threshold, or `null` if battery is not low.
66+
67+
**Thresholds**:
68+
- **iOS**: 20% (matches iOS low power mode trigger)
69+
- **Android**: 15% (matches Android low battery warning)
70+
71+
**Platform Support**:
72+
| Platform | Supported |
73+
|----------|-----------|
74+
| iOS ||
75+
| Android ||
76+
77+
**Example**:
78+
79+
```tsx
80+
import { useBatteryLevelIsLow } from 'react-native-nitro-device-info';
81+
82+
function LowBatteryWarning() {
83+
const lowBattery = useBatteryLevelIsLow();
84+
85+
if (lowBattery !== null) {
86+
return (
87+
<View style={styles.warning}>
88+
<Text>Low Battery: {Math.round(lowBattery * 100)}%</Text>
89+
</View>
90+
);
91+
}
92+
93+
return null;
94+
}
95+
```
96+
97+
---
98+
99+
### `usePowerState()`
100+
101+
Monitor comprehensive power state including battery level, charging status, and low power mode.
102+
103+
```typescript
104+
function usePowerState(): Partial<PowerState>
105+
```
106+
107+
**Returns**: A `Partial<PowerState>` object. All properties are optional and may be `undefined` during initial load or if unavailable on the platform:
108+
- `batteryLevel?: number` - Battery charge level (0.0 to 1.0)
109+
- `batteryState?: BatteryState` - Charging status ('unknown', 'unplugged', 'charging', 'full')
110+
- `lowPowerMode?: boolean` - Whether low power mode is enabled (iOS only)
111+
112+
**Platform Support**:
113+
| Platform | Supported | Notes |
114+
|----------|-----------|-------|
115+
| iOS || Full support including lowPowerMode |
116+
| Android || lowPowerMode always false |
117+
118+
**Example**:
119+
120+
```tsx
121+
import { usePowerState } from 'react-native-nitro-device-info';
122+
123+
function PowerStatus() {
124+
const powerState = usePowerState();
125+
126+
return (
127+
<View>
128+
<Text>Level: {Math.round((powerState.batteryLevel ?? 0) * 100)}%</Text>
129+
<Text>Status: {powerState.batteryState ?? 'unknown'}</Text>
130+
<Text>Low Power: {powerState.lowPowerMode ? 'Yes' : 'No'}</Text>
131+
</View>
132+
);
133+
}
134+
```
135+
136+
---
137+
138+
## Headphone Hooks
139+
140+
### `useIsHeadphonesConnected()`
141+
142+
Monitor headphone connection state (wired or Bluetooth).
143+
144+
```typescript
145+
function useIsHeadphonesConnected(): boolean
146+
```
147+
148+
**Returns**: `true` if any headphones are connected, `false` otherwise.
149+
150+
**Platform Support**:
151+
| Platform | Supported |
152+
|----------|-----------|
153+
| iOS ||
154+
| Android ||
155+
156+
**Example**:
157+
158+
```tsx
159+
import { useIsHeadphonesConnected } from 'react-native-nitro-device-info';
160+
161+
function AudioOutput() {
162+
const headphonesConnected = useIsHeadphonesConnected();
163+
164+
return (
165+
<Text>
166+
Audio: {headphonesConnected ? 'Headphones' : 'Speaker'}
167+
</Text>
168+
);
169+
}
170+
```
171+
172+
---
173+
174+
### `useIsWiredHeadphonesConnected()`
175+
176+
Monitor wired headphone connection state.
177+
178+
```typescript
179+
function useIsWiredHeadphonesConnected(): boolean
180+
```
181+
182+
**Returns**: `true` if wired headphones are connected, `false` otherwise.
183+
184+
**Platform Support**:
185+
| Platform | Supported |
186+
|----------|-----------|
187+
| iOS ||
188+
| Android ||
189+
190+
**Example**:
191+
192+
```tsx
193+
import { useIsWiredHeadphonesConnected } from 'react-native-nitro-device-info';
194+
195+
function WiredAudioStatus() {
196+
const wiredConnected = useIsWiredHeadphonesConnected();
197+
198+
return (
199+
<Icon
200+
name={wiredConnected ? 'headphones' : 'headphones-off'}
201+
color={wiredConnected ? 'green' : 'gray'}
202+
/>
203+
);
204+
}
205+
```
206+
207+
---
208+
209+
### `useIsBluetoothHeadphonesConnected()`
210+
211+
Monitor Bluetooth headphone/audio device connection state.
212+
213+
```typescript
214+
function useIsBluetoothHeadphonesConnected(): boolean
215+
```
216+
217+
**Returns**: `true` if Bluetooth audio devices are connected, `false` otherwise.
218+
219+
**Platform Support**:
220+
| Platform | Supported |
221+
|----------|-----------|
222+
| iOS ||
223+
| Android ||
224+
225+
**Example**:
226+
227+
```tsx
228+
import { useIsBluetoothHeadphonesConnected } from 'react-native-nitro-device-info';
229+
230+
function BluetoothAudioStatus() {
231+
const bluetoothConnected = useIsBluetoothHeadphonesConnected();
232+
233+
return (
234+
<Icon
235+
name="bluetooth"
236+
color={bluetoothConnected ? 'blue' : 'gray'}
237+
/>
238+
);
239+
}
240+
```
241+
242+
---
243+
244+
## Display Hooks
245+
246+
### `useBrightness()`
247+
248+
Monitor screen brightness changes (iOS only).
249+
250+
```typescript
251+
function useBrightness(): number | null
252+
```
253+
254+
**Returns**:
255+
- **iOS**: Brightness level (0.0 to 1.0), or `null` during initial load
256+
- **Android**: `-1` (not supported)
257+
258+
**Platform Support**:
259+
| Platform | Supported | Notes |
260+
|----------|-----------|-------|
261+
| iOS || Real-time brightness monitoring |
262+
| Android || Returns -1 |
263+
264+
**Example**:
265+
266+
```tsx
267+
import { useBrightness } from 'react-native-nitro-device-info';
268+
import { Platform } from 'react-native';
269+
270+
function BrightnessIndicator() {
271+
const brightness = useBrightness();
272+
273+
if (Platform.OS === 'android') {
274+
return <Text>Brightness monitoring is iOS only</Text>;
275+
}
276+
277+
if (brightness === null) {
278+
return <Text>Loading...</Text>;
279+
}
280+
281+
return <Text>Brightness: {Math.round(brightness * 100)}%</Text>;
282+
}
283+
```
284+
285+
---
286+
287+
## Platform Support Summary
288+
289+
| Hook | iOS | Android |
290+
|------|-----|---------|
291+
| `useBatteryLevel` |||
292+
| `useBatteryLevelIsLow` |||
293+
| `usePowerState` |||
294+
| `useIsHeadphonesConnected` |||
295+
| `useIsWiredHeadphonesConnected` |||
296+
| `useIsBluetoothHeadphonesConnected` |||
297+
| `useBrightness` || ❌ (-1) |
298+
299+
---
300+
301+
## Best Practices
302+
303+
### Handle Loading States
304+
305+
```tsx
306+
const batteryLevel = useBatteryLevel();
307+
308+
if (batteryLevel === null) {
309+
return <LoadingSpinner />;
310+
}
311+
```
312+
313+
### Memoize Dependent Components
314+
315+
```tsx
316+
const BatteryIcon = React.memo(({ level }: { level: number }) => {
317+
return <Icon name={getBatteryIcon(level)} />;
318+
});
319+
320+
function Parent() {
321+
const level = useBatteryLevel();
322+
return level !== null && <BatteryIcon level={level} />;
323+
}
324+
```
325+
326+
### Platform-Specific Handling
327+
328+
```tsx
329+
import { Platform } from 'react-native';
330+
331+
function BrightnessControl() {
332+
const brightness = useBrightness();
333+
334+
if (Platform.OS === 'android') {
335+
return null; // Not supported on Android
336+
}
337+
338+
return <BrightnessSlider value={brightness} />;
339+
}
340+
```
341+
342+
---
343+
344+
## Migration from react-native-device-info
345+
346+
These hooks are designed to be drop-in replacements:
347+
348+
```tsx
349+
// Before (react-native-device-info)
350+
import { useBatteryLevel } from 'react-native-device-info';
351+
352+
// After (react-native-nitro-device-info)
353+
import { useBatteryLevel } from 'react-native-nitro-device-info';
354+
355+
// Usage remains identical
356+
const batteryLevel = useBatteryLevel();
357+
```
358+
359+
See the [Migration Guide](/api/migration) for more details.

0 commit comments

Comments
 (0)