@robotical/webapp-types 3.17.52 → 3.18.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.
@@ -24,6 +24,8 @@ export default class ApplicationManager {
24
24
  [key: string]: RAFT;
25
25
  };
26
26
  private _connectPromise;
27
+ private _connectAttemptSequence;
28
+ private _activeConnectAttemptId;
27
29
  private _disconnectPromises;
28
30
  connectedRaftsContext: ConnectedRaftItem[];
29
31
  returnToMainApp: () => void;
@@ -93,6 +95,9 @@ export default class ApplicationManager {
93
95
  */
94
96
  connectGeneric(afterRaftConnectedCb: (raft: RAFT) => void, uuids?: string[], shouldShowQrModal?: boolean): Promise<void>;
95
97
  private _clearConnectPromise;
98
+ private _dismissConnectAttempt;
99
+ private _isConnectAttemptActive;
100
+ private _createConnectingModal;
96
101
  private _connectGeneric;
97
102
  /**
98
103
  * Disconnect from RAFT generic
@@ -91,6 +91,8 @@ var ApplicationManager = /** @class */ (function () {
91
91
  // Connected RICs
92
92
  this.connectedRafts = {};
93
93
  this._connectPromise = null;
94
+ this._connectAttemptSequence = 0;
95
+ this._activeConnectAttemptId = null;
94
96
  this._disconnectPromises = new Map();
95
97
  this.connectedRaftsContext = [];
96
98
  this.returnToMainApp = function () { };
@@ -519,18 +521,38 @@ var ApplicationManager = /** @class */ (function () {
519
521
  }));
520
522
  return Promise.resolve();
521
523
  }
522
- var connectPromise = this._connectGeneric(afterRaftConnectedCb, uuids, shouldShowQrModal);
524
+ var connectAttemptId = ++this._connectAttemptSequence;
525
+ this._activeConnectAttemptId = connectAttemptId;
526
+ var connectPromise = this._connectGeneric(afterRaftConnectedCb, uuids, shouldShowQrModal, connectAttemptId);
523
527
  this._connectPromise = connectPromise;
524
- void connectPromise.then(function () { return _this._clearConnectPromise(connectPromise); }, function () { return _this._clearConnectPromise(connectPromise); });
528
+ void connectPromise.then(function () { return _this._clearConnectPromise(connectPromise, connectAttemptId); }, function () { return _this._clearConnectPromise(connectPromise, connectAttemptId); });
525
529
  return connectPromise;
526
530
  };
527
- ApplicationManager.prototype._clearConnectPromise = function (connectPromise) {
531
+ ApplicationManager.prototype._clearConnectPromise = function (connectPromise, connectAttemptId) {
528
532
  if (this._connectPromise === connectPromise) {
529
533
  this._connectPromise = null;
530
534
  }
535
+ if (this._activeConnectAttemptId === connectAttemptId) {
536
+ this._activeConnectAttemptId = null;
537
+ }
531
538
  };
532
- ApplicationManager.prototype._connectGeneric = function (afterRaftConnectedCb, uuids, shouldShowQrModal) {
533
- if (shouldShowQrModal === void 0) { shouldShowQrModal = true; }
539
+ ApplicationManager.prototype._dismissConnectAttempt = function (connectAttemptId) {
540
+ if (this._activeConnectAttemptId !== connectAttemptId) {
541
+ return;
542
+ }
543
+ this._activeConnectAttemptId = null;
544
+ this._connectPromise = null;
545
+ };
546
+ ApplicationManager.prototype._isConnectAttemptActive = function (connectAttemptId) {
547
+ return this._activeConnectAttemptId === connectAttemptId;
548
+ };
549
+ ApplicationManager.prototype._createConnectingModal = function (connectAttemptId) {
550
+ var _this = this;
551
+ return createElement(ConnectingLoadingSpinnerModal, {
552
+ onDismiss: function () { return _this._dismissConnectAttempt(connectAttemptId); },
553
+ });
554
+ };
555
+ ApplicationManager.prototype._connectGeneric = function (afterRaftConnectedCb, uuids, shouldShowQrModal, connectAttemptId) {
534
556
  return __awaiter(this, void 0, void 0, function () {
535
557
  var verificationMethod, cancelVerificationResult, isQRVerification, e_1, newRaft, wasAdopted, e_2;
536
558
  var _this = this;
@@ -559,7 +581,7 @@ var ApplicationManager = /** @class */ (function () {
559
581
  return [2 /*return*/];
560
582
  }
561
583
  if (verificationMethod.action === "switch-to-marty") {
562
- return [2 /*return*/, this._connectGeneric(afterRaftConnectedCb, [ConnManager.RICUUID], false)];
584
+ return [2 /*return*/, this._connectGeneric(afterRaftConnectedCb, [ConnManager.RICUUID], false, connectAttemptId)];
563
585
  }
564
586
  isQRVerification = false;
565
587
  if (verificationMethod.action === "qr") {
@@ -577,7 +599,7 @@ var ApplicationManager = /** @class */ (function () {
577
599
  case 3:
578
600
  _a.trys.push([3, 8, , 9]);
579
601
  if (!isQRVerification) return [3 /*break*/, 5];
580
- secondaryModalState.setModal(createElement(ConnectingLoadingSpinnerModal, {}), i18n.t("connection.connecting_msg"), false);
602
+ secondaryModalState.setModal(this._createConnectingModal(connectAttemptId), i18n.t("connection.connecting_msg"), false);
581
603
  this.ricSelectedCb = null;
582
604
  return [4 /*yield*/, window.applicationManager.startDiscoveryWithoutVerification(uuids, afterRaftConnectedCb)];
583
605
  case 4:
@@ -607,13 +629,16 @@ var ApplicationManager = /** @class */ (function () {
607
629
  return [3 /*break*/, 9];
608
630
  case 9: return [3 /*break*/, 18];
609
631
  case 10:
610
- secondaryModalState.setModal(createElement(ConnectingLoadingSpinnerModal, {}), i18n.t("connection.connecting_msg"), false);
632
+ secondaryModalState.setModal(this._createConnectingModal(connectAttemptId), i18n.t("connection.connecting_msg"), false);
611
633
  _a.label = 11;
612
634
  case 11:
613
635
  _a.trys.push([11, 16, , 17]);
614
636
  return [4 /*yield*/, window.applicationManager.connectToRIC(RaftConnectionMethod.WEB_BLE, uuids, isQRVerification)];
615
637
  case 12:
616
638
  newRaft = _a.sent();
639
+ if (!this._isConnectAttemptActive(connectAttemptId)) {
640
+ return [2 /*return*/];
641
+ }
617
642
  if (!newRaft) return [3 /*break*/, 15];
618
643
  return [4 /*yield*/, this.addConnectedRaftToContext(newRaft)];
619
644
  case 13:
@@ -632,7 +657,9 @@ var ApplicationManager = /** @class */ (function () {
632
657
  Logger.error(SHOW_LOGS, TAG, "Failed to connect to new robot: ".concat(e_2));
633
658
  return [3 /*break*/, 17];
634
659
  case 17:
635
- secondaryModalState.closeModalWithoutAnimation();
660
+ if (this._isConnectAttemptActive(connectAttemptId)) {
661
+ secondaryModalState.closeModalWithoutAnimation();
662
+ }
636
663
  _a.label = 18;
637
664
  case 18: return [2 /*return*/];
638
665
  }
@@ -0,0 +1,4 @@
1
+ import { type IScannerProps } from "@yudiel/react-qr-scanner";
2
+ type Props = IScannerProps;
3
+ export default function SwitchableCameraScanner({ constraints, ...scannerProps }: Props): import("react/jsx-runtime").JSX.Element;
4
+ export {};
@@ -0,0 +1,47 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __rest = (this && this.__rest) || function (s, e) {
13
+ var t = {};
14
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
15
+ t[p] = s[p];
16
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
17
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
18
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
19
+ t[p[i]] = s[p[i]];
20
+ }
21
+ return t;
22
+ };
23
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
24
+ import { useMemo, useState } from "react";
25
+ import { useTranslation } from "react-i18next";
26
+ import { MdCameraswitch } from "react-icons/md";
27
+ import { Scanner } from "@yudiel/react-qr-scanner";
28
+ import isPhoneApp from "../../../utils/phone-app-communication/is-phone-app";
29
+ import styles from "./styles.module.css";
30
+ export default function SwitchableCameraScanner(_a) {
31
+ var constraints = _a.constraints, scannerProps = __rest(_a, ["constraints"]);
32
+ var t = useTranslation().t;
33
+ var _b = useState("environment"), facingMode = _b[0], setFacingMode = _b[1];
34
+ var cameraConstraints = useMemo(function () { return (__assign(__assign({}, constraints), {
35
+ // A plain facingMode is an ideal constraint. Older browsers and devices
36
+ // with one camera can therefore fall back instead of failing outright.
37
+ facingMode: facingMode })); }, [constraints, facingMode]);
38
+ var switchToFrontCamera = facingMode === "environment";
39
+ var cameraSwitchLabel = switchToFrontCamera
40
+ ? t("connection.switch_to_front_camera")
41
+ : t("connection.switch_to_rear_camera");
42
+ return (_jsxs("div", __assign({ className: styles.container }, { children: [_jsx(Scanner, __assign({}, scannerProps, { constraints: cameraConstraints })), isPhoneApp() && (_jsx("button", __assign({ type: "button", className: styles.cameraSwitchButton, "aria-label": cameraSwitchLabel, title: cameraSwitchLabel, onClick: function () {
43
+ return setFacingMode(function (currentFacingMode) {
44
+ return currentFacingMode === "environment" ? "user" : "environment";
45
+ });
46
+ } }, { children: _jsx(MdCameraswitch, { className: styles.cameraSwitchIcon, "aria-hidden": "true", focusable: "false" }) })))] })));
47
+ }
@@ -1,3 +1,5 @@
1
- type Props = {};
2
- export default function ConnectingLoadingSpinnerModal({}: Props): import("react/jsx-runtime").JSX.Element;
1
+ type Props = {
2
+ onDismiss?: () => void;
3
+ };
4
+ export default function ConnectingLoadingSpinnerModal({ onDismiss }: Props): import("react/jsx-runtime").JSX.Element;
3
5
  export {};
@@ -9,18 +9,25 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
- import { jsx as _jsx } from "react/jsx-runtime";
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import { useTranslation } from "react-i18next";
14
- import { useEffect } from "react";
14
+ import { useCallback, useEffect } from "react";
15
15
  import { secondaryModalState } from "../../../state-observables/modal/ModalState";
16
+ import SimpleButton from "../../disposables/buttons/SimpleButton";
16
17
  import styles from "./styles.module.css";
17
18
  export default function ConnectingLoadingSpinnerModal(_a) {
19
+ var onDismiss = _a.onDismiss;
18
20
  var t = useTranslation().t;
21
+ var dismissLabel = String(t("connection.dismiss", "Dismiss"));
22
+ var dismissAriaLabel = String(t("connection.dismiss_connecting_modal", "Dismiss connecting dialog"));
23
+ var dismiss = useCallback(function () {
24
+ onDismiss === null || onDismiss === void 0 ? void 0 : onDismiss();
25
+ secondaryModalState.closeModalWithoutAnimation();
26
+ }, [onDismiss]);
19
27
  useEffect(function () {
20
28
  // close modal after 3 minutes assuming no connection will take that long
21
- setTimeout(function () {
22
- secondaryModalState.closeModalWithoutAnimation();
23
- }, 180000);
24
- }, []);
25
- return (_jsx("div", __assign({ className: styles.container }, { children: t("connection.connecting_loading") })));
29
+ var timeout = setTimeout(dismiss, 180000);
30
+ return function () { return clearTimeout(timeout); };
31
+ }, [dismiss]);
32
+ return (_jsxs("div", __assign({ className: styles.container }, { children: [_jsx("span", { children: t("connection.connecting_loading") }), _jsx("div", __assign({ className: styles.dismissButton, "data-testid": "connecting-modal-dismiss" }, { children: _jsx(SimpleButton, { ariaLabel: dismissAriaLabel, onClick: dismiss, title: dismissLabel }) }))] })));
26
33
  }
@@ -54,9 +54,10 @@ import { MdQrCode } from "react-icons/md";
54
54
  import { ReactComponent as BluetoothSVG } from "../../../assets/configuration/bluetooth.svg";
55
55
  import { MAIN_BLUE } from "../../../styles/colors";
56
56
  //@ts-ignore
57
- import { Scanner, centerText } from '@yudiel/react-qr-scanner';
57
+ import { centerText } from '@yudiel/react-qr-scanner';
58
58
  import { ConnManager } from "@robotical/roboticaljs";
59
59
  import { useTranslation } from "react-i18next";
60
+ import SwitchableCameraScanner from "../../disposables/SwitchableCameraScanner";
60
61
  export default function LEDLightsOrQRVerificationModal(_a) {
61
62
  var _this = this;
62
63
  var targetRaftType = _a.targetRaftType, _b = _a.allowSwitchToMarty, allowSwitchToMarty = _b === void 0 ? false : _b;
@@ -134,7 +135,7 @@ function QRContent(_a) {
134
135
  });
135
136
  }); };
136
137
  var isWebapp = ((_b = window.applicationManager.deviceInfo) === null || _b === void 0 ? void 0 : _b.manufacturer) === "Webapp";
137
- return (_jsx("div", __assign({ className: styles.QRcontainer }, { children: _jsx("div", __assign({ className: styles.QRscannerContainer }, { children: _jsx(Scanner, { styles: { container: { transform: isWebapp ? 'scaleX(-1)' : 'none' } }, onError: function (err) { return console.error(err); }, formats: [
138
+ return (_jsx("div", __assign({ className: styles.QRcontainer }, { children: _jsx("div", __assign({ className: styles.QRscannerContainer }, { children: _jsx(SwitchableCameraScanner, { styles: { container: { transform: isWebapp ? 'scaleX(-1)' : 'none' } }, onError: function (err) { return console.error(err); }, formats: [
138
139
  "qr_code",
139
140
  "micro_qr_code",
140
141
  "rm_qr_code",
@@ -249,6 +249,8 @@ var resources = {
249
249
  "qr_subtitle": "Scan a QR code to verify.",
250
250
  "qr_title": "QR Code Verification",
251
251
  "scan_again": "SCAN AGAIN",
252
+ "switch_to_front_camera": "Switch to front camera",
253
+ "switch_to_rear_camera": "Switch to rear camera",
252
254
  "verification_method": "Verification Method",
253
255
  "yes": "Yes"
254
256
  },
@@ -54,22 +54,24 @@ var ConnectorFactory = /** @class */ (function () {
54
54
  */
55
55
  ConnectorFactory.connectToRaftHelper = function (method, uuids, onConnManagerCreated) {
56
56
  return __awaiter(this, void 0, void 0, function () {
57
- var connManager, connectorWasCreated, wasConnected, systemInfo, raftType, connector, error_1;
57
+ var connManager, connectorWasCreated, lowLevelConnectionSucceeded, connectionResult, systemInfo, raftType, connector, error_1;
58
58
  return __generator(this, function (_a) {
59
59
  switch (_a.label) {
60
60
  case 0:
61
61
  connManager = new ConnManager();
62
62
  connectorWasCreated = false;
63
+ lowLevelConnectionSucceeded = false;
63
64
  _a.label = 1;
64
65
  case 1:
65
66
  _a.trys.push([1, , 3, 8]);
66
67
  onConnManagerCreated === null || onConnManagerCreated === void 0 ? void 0 : onConnManagerCreated(connManager);
67
68
  Logger.info(SHOW_LOGS, TAG, "Connecting to RAFT with method: ".concat(method));
68
- return [4 /*yield*/, connManager.connect(method, "", uuids)];
69
+ return [4 /*yield*/, connManager.connectDetailed(method, "", uuids)];
69
70
  case 2:
70
- wasConnected = _a.sent();
71
- Logger.info(SHOW_LOGS, TAG, "Was connected to RAFT: ".concat(wasConnected));
72
- if (!wasConnected) {
71
+ connectionResult = _a.sent();
72
+ lowLevelConnectionSucceeded = connectionResult.status === "success";
73
+ Logger.info(SHOW_LOGS, TAG, "Connection result: ".concat(connectionResult.status));
74
+ if (!lowLevelConnectionSucceeded) {
73
75
  return [2 /*return*/, null];
74
76
  }
75
77
  systemInfo = connManager.getConnector().getRaftSystemUtils().getCachedSystemInfo();
@@ -79,7 +81,15 @@ var ConnectorFactory = /** @class */ (function () {
79
81
  return [2 /*return*/, connector];
80
82
  case 3:
81
83
  if (!!connectorWasCreated) return [3 /*break*/, 7];
82
- _a.label = 4;
84
+ if (!!lowLevelConnectionSucceeded) return [3 /*break*/, 4];
85
+ // Before connectDetailed reports success there is no established
86
+ // RAFT session to notify. Use immediate transport teardown for
87
+ // chooser cancellation, generic failure, and thrown cancellation.
88
+ // The graceful path sends `bledisconnect` retries and can otherwise
89
+ // keep the UI pending for several seconds for a connection that
90
+ // never existed.
91
+ connManager.disconnectForPageUnload();
92
+ return [3 /*break*/, 7];
83
93
  case 4:
84
94
  _a.trys.push([4, 6, , 7]);
85
95
  return [4 /*yield*/, connManager.disconnect()];
@@ -133,12 +133,16 @@ var MartyConnector = /** @class */ (function (_super) {
133
133
  */
134
134
  MartyConnector.prototype.disconnect = function () {
135
135
  return __awaiter(this, void 0, void 0, function () {
136
+ var raftChannel;
136
137
  return __generator(this, function (_a) {
137
138
  switch (_a.label) {
138
- case 0: return [4 /*yield*/, _super.prototype.disconnect.call(this)];
139
- case 1:
140
- // this.sendRestMessage('blerestart');
141
- return [2 /*return*/, _a.sent()];
139
+ case 0:
140
+ raftChannel = this.connManager.getConnector().getRaftChannel();
141
+ if (raftChannel) {
142
+ raftChannel.ricRestCmdBeforeDisconnect = function () { return null; };
143
+ }
144
+ return [4 /*yield*/, _super.prototype.disconnect.call(this)];
145
+ case 1: return [2 /*return*/, _a.sent()];
142
146
  }
143
147
  });
144
148
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robotical/webapp-types",
3
- "version": "3.17.52",
3
+ "version": "3.18.1",
4
4
  "description": "Type definitions for the Application Manager",
5
5
  "main": "dist/application-manager.d.ts",
6
6
  "types": "dist/application-manager.d.ts",