react-native-web-serial-api 0.0.2 → 0.0.3

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.
@@ -657,11 +657,17 @@ public class NativeUsbSerialModule extends NativeUsbSerialSpec {
657
657
  Intent intent = new Intent(ACTION_USB_PERMISSION);
658
658
  intent.putExtra(EXTRA_REQUEST_CODE, requestCode);
659
659
 
660
+ intent.setPackage(getReactApplicationContext().getPackageName());
661
+
662
+ int flags = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S
663
+ ? PendingIntent.FLAG_MUTABLE
664
+ : 0;
665
+
660
666
  PendingIntent permissionIntent = PendingIntent.getBroadcast(
661
667
  getReactApplicationContext(),
662
668
  requestCode,
663
669
  intent,
664
- PendingIntent.FLAG_IMMUTABLE
670
+ flags
665
671
  );
666
672
  usbManager.requestPermission(driver.getDevice(), permissionIntent);
667
673
  } catch (Exception e) {
@@ -135,23 +135,24 @@ export function DevicesScreen({onSelect}: Props) {
135
135
  [onSelect],
136
136
  );
137
137
 
138
- // Tap on an unpermitted row: request Android USB permission. On grant, the
139
- // library emits "connect" -> refresh() runs -> the row becomes permitted.
140
- const grantPermission = React.useCallback(async (row: DeviceRow) => {
141
- setError(null);
142
- const usb = nativeUsb();
143
- if (!usb) {
144
- return;
145
- }
146
- try {
147
- await usb.requestPermission(row.deviceId);
148
- } catch (e: any) {
149
- setError(e?.message ?? String(e));
150
- } finally {
151
- // Always refresh after permission attempt (fixes stale state)
152
- refresh();
153
- }
154
- }, [refresh]);
138
+ // Tap on an unpermitted row: request Android USB permission. On grant,
139
+ // refresh immediately.
140
+ const grantPermission = React.useCallback(
141
+ async (row: DeviceRow) => {
142
+ setError(null);
143
+ const usb = nativeUsb();
144
+ if (!usb) {
145
+ return;
146
+ }
147
+ try {
148
+ await usb.requestPermission(row.deviceId);
149
+ } catch (e: any) {
150
+ setError(e?.message ?? String(e));
151
+ }
152
+ refresh();
153
+ },
154
+ [refresh],
155
+ );
155
156
 
156
157
  const requestNew = React.useCallback(async () => {
157
158
  setError(null);
@@ -171,7 +172,10 @@ export function DevicesScreen({onSelect}: Props) {
171
172
  refresh();
172
173
  }
173
174
  };
174
- const subscription = AppState.addEventListener('change', handleAppStateChange);
175
+ const subscription = AppState.addEventListener(
176
+ 'change',
177
+ handleAppStateChange,
178
+ );
175
179
  return () => {
176
180
  subscription.remove();
177
181
  };
@@ -249,6 +249,14 @@ export function TerminalScreen({port, settings, onBack}: Props) {
249
249
  }, [teardown]);
250
250
 
251
251
  const connect = React.useCallback(async () => {
252
+ // Idempotent: ignore overlapping triggers. On re-attach the device may emit
253
+ // several "connect" events (USB attach + permission-grant), and port.open()
254
+ // itself awaits the permission dialog — so guard against re-entrancy that
255
+ // would otherwise cause a double-open ("port already open") and leave us
256
+ // stuck in the failed/closed state.
257
+ if (connectedRef.current !== 'False') {
258
+ return;
259
+ }
252
260
  connectedRef.current = 'Pending';
253
261
  setConnected('Pending');
254
262
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-web-serial-api",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "W3C Web Serial API (navigator.serial) for React Native on Android, backed by a USB-serial TurboModule (built on mik3y/usb-serial-for-android).",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "react-native": "lib/commonjs/index.js",