@rango-dev/widget-embedded 0.20.1-next.22 → 0.20.1-next.23

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.
Files changed (82) hide show
  1. package/dist/QueueManager.d.ts.map +1 -1
  2. package/dist/components/ConfirmWalletsModal/ConfirmWallets.styles.d.ts +3 -3
  3. package/dist/components/ConfirmWalletsModal/WalletList.d.ts.map +1 -1
  4. package/dist/components/Layout/Layout.d.ts.map +1 -1
  5. package/dist/components/Quote/Quote.styles.d.ts +2 -2
  6. package/dist/components/QuoteWarningsAndErrors/HighValueLossWarningModal.d.ts +1 -0
  7. package/dist/components/QuoteWarningsAndErrors/HighValueLossWarningModal.d.ts.map +1 -1
  8. package/dist/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.d.ts.map +1 -1
  9. package/dist/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.types.d.ts +1 -0
  10. package/dist/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.types.d.ts.map +1 -1
  11. package/dist/components/QuoteWarningsAndErrors/SlippageWariningModal.d.ts +1 -0
  12. package/dist/components/QuoteWarningsAndErrors/SlippageWariningModal.d.ts.map +1 -1
  13. package/dist/components/QuoteWarningsAndErrors/UnknownPriceWarningModal.d.ts +1 -0
  14. package/dist/components/QuoteWarningsAndErrors/UnknownPriceWarningModal.d.ts.map +1 -1
  15. package/dist/components/SwapDetails/SwapDetails.d.ts.map +1 -1
  16. package/dist/components/SwapDetailsModal/SwapDetailsModal.WalletState.d.ts.map +1 -1
  17. package/dist/components/SwapDetailsModal/SwapDetailsModal.d.ts.map +1 -1
  18. package/dist/components/SwapDetailsModal/SwapDetailsModal.types.d.ts +2 -0
  19. package/dist/components/SwapDetailsModal/SwapDetailsModal.types.d.ts.map +1 -1
  20. package/dist/components/common/ActivateTabAlert/ActivateTabAlert.d.ts +4 -0
  21. package/dist/components/common/ActivateTabAlert/ActivateTabAlert.d.ts.map +1 -0
  22. package/dist/components/common/ActivateTabAlert/ActivateTabAlert.types.d.ts +4 -0
  23. package/dist/components/common/ActivateTabAlert/ActivateTabAlert.types.d.ts.map +1 -0
  24. package/dist/components/common/ActivateTabAlert/index.d.ts +2 -0
  25. package/dist/components/common/ActivateTabAlert/index.d.ts.map +1 -0
  26. package/dist/components/common/ActivateTabModal/ActivateTabModal.d.ts +4 -0
  27. package/dist/components/common/ActivateTabModal/ActivateTabModal.d.ts.map +1 -0
  28. package/dist/components/common/ActivateTabModal/ActivateTabModal.types.d.ts +6 -0
  29. package/dist/components/common/ActivateTabModal/ActivateTabModal.types.d.ts.map +1 -0
  30. package/dist/components/common/ActivateTabModal/index.d.ts +2 -0
  31. package/dist/components/common/ActivateTabModal/index.d.ts.map +1 -0
  32. package/dist/containers/Wallets/Wallets.d.ts.map +1 -1
  33. package/dist/containers/Widget/Widget.d.ts.map +1 -1
  34. package/dist/containers/WidgetInfo/WidgetInfo.d.ts.map +1 -1
  35. package/dist/containers/WidgetInfo/WidgetInfo.types.d.ts +2 -0
  36. package/dist/containers/WidgetInfo/WidgetInfo.types.d.ts.map +1 -1
  37. package/dist/index.js +2 -2
  38. package/dist/index.js.map +4 -4
  39. package/dist/libs/tabManager/index.d.ts +3 -0
  40. package/dist/libs/tabManager/index.d.ts.map +1 -0
  41. package/dist/libs/tabManager/tabManager.constants.d.ts +4 -0
  42. package/dist/libs/tabManager/tabManager.constants.d.ts.map +1 -0
  43. package/dist/libs/tabManager/tabManager.d.ts +63 -0
  44. package/dist/libs/tabManager/tabManager.d.ts.map +1 -0
  45. package/dist/libs/tabManager/tabManager.types.d.ts +29 -0
  46. package/dist/libs/tabManager/tabManager.types.d.ts.map +1 -0
  47. package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
  48. package/dist/pages/Home.d.ts.map +1 -1
  49. package/dist/pages/WalletsPage.d.ts.map +1 -1
  50. package/dist/store/ui.d.ts +24 -0
  51. package/dist/store/ui.d.ts.map +1 -0
  52. package/package.json +5 -5
  53. package/src/QueueManager.tsx +4 -1
  54. package/src/components/ConfirmWalletsModal/WalletList.tsx +3 -0
  55. package/src/components/Layout/Layout.tsx +36 -2
  56. package/src/components/QuoteWarningsAndErrors/HighValueLossWarningModal.tsx +3 -1
  57. package/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.tsx +3 -1
  58. package/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.types.ts +1 -0
  59. package/src/components/QuoteWarningsAndErrors/SlippageWariningModal.tsx +3 -1
  60. package/src/components/QuoteWarningsAndErrors/UnknownPriceWarningModal.tsx +3 -1
  61. package/src/components/SwapDetails/SwapDetails.tsx +3 -0
  62. package/src/components/SwapDetailsModal/SwapDetailsModal.WalletState.tsx +9 -1
  63. package/src/components/SwapDetailsModal/SwapDetailsModal.tsx +10 -2
  64. package/src/components/SwapDetailsModal/SwapDetailsModal.types.ts +2 -0
  65. package/src/components/common/ActivateTabAlert/ActivateTabAlert.tsx +26 -0
  66. package/src/components/common/ActivateTabAlert/ActivateTabAlert.types.ts +3 -0
  67. package/src/components/common/ActivateTabAlert/index.ts +1 -0
  68. package/src/components/common/ActivateTabModal/ActivateTabModal.tsx +31 -0
  69. package/src/components/common/ActivateTabModal/ActivateTabModal.types.ts +5 -0
  70. package/src/components/common/ActivateTabModal/index.ts +1 -0
  71. package/src/containers/Wallets/Wallets.tsx +3 -1
  72. package/src/containers/Widget/Widget.tsx +6 -1
  73. package/src/containers/WidgetInfo/WidgetInfo.tsx +5 -1
  74. package/src/containers/WidgetInfo/WidgetInfo.types.ts +2 -0
  75. package/src/libs/tabManager/index.ts +2 -0
  76. package/src/libs/tabManager/tabManager.constants.ts +3 -0
  77. package/src/libs/tabManager/tabManager.ts +222 -0
  78. package/src/libs/tabManager/tabManager.types.ts +28 -0
  79. package/src/pages/ConfirmSwapPage.tsx +4 -1
  80. package/src/pages/Home.tsx +4 -1
  81. package/src/pages/WalletsPage.tsx +3 -0
  82. package/src/store/ui.ts +49 -0
@@ -0,0 +1,3 @@
1
+ export { TabManager } from './tabManager';
2
+ export type { TabManagerInterface } from './tabManager.types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/libs/tabManager/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const TIMEOUT = 300;
2
+ export declare const MAXIMUM_TAB_ID = 100000;
3
+ export declare const CHANNEL_NAME = "rango-widget";
4
+ //# sourceMappingURL=tabManager.constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabManager.constants.d.ts","sourceRoot":"","sources":["../../../src/libs/tabManager/tabManager.constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,MAAM,CAAC;AAC3B,eAAO,MAAM,cAAc,SAAU,CAAC;AACtC,eAAO,MAAM,YAAY,iBAAiB,CAAC"}
@@ -0,0 +1,63 @@
1
+ import type { Events, TabManagerInterface } from './tabManager.types';
2
+ export declare class TabManager implements TabManagerInterface {
3
+ private tabId;
4
+ private state;
5
+ private lastTryClaim;
6
+ private events;
7
+ private channel;
8
+ constructor(events: Events);
9
+ /**
10
+ * This is applicable when a user in an inactive tab seeks to activate that tab.
11
+ */
12
+ forceClaim: () => void;
13
+ isClaimed: () => boolean;
14
+ /**
15
+ * remove event listeners
16
+ */
17
+ destroy: () => void;
18
+ /**
19
+ * Reacting to messages and window events to claim.
20
+ */
21
+ private initEvents;
22
+ /**
23
+ * Runs after a `ping` message and checks if current tab is claimed the tabs,
24
+ * if yes, it responds with `pong`, If not, it doesn't do anything.
25
+ *
26
+ * Note 1: If we receive a `ping` message,
27
+ * it means a tab is trying to claim tabs directly, usually it's the active tab.
28
+ *
29
+ * Note 2: If multiple tabs are opening at once, all of them are broadcasting `ping`
30
+ * and eventually all of them will `claim` the queue after the TIMEOUT.
31
+ * For avoiding this, we will accepts the oldest broadcasted ping. (`isPingSentBefore`)
32
+ */
33
+ private claimedByCurrentTab;
34
+ private handleMessageEvent;
35
+ private handleVisibilityChange;
36
+ private handleResume;
37
+ /**
38
+ * Runs after receiving `pong` message, which means one of tabs already claimed the tabs.
39
+ */
40
+ private alreadyClaimedByAnotherTab;
41
+ /**
42
+ * Try to send a `ping` message to know if the tabs `claimed` or not.
43
+ * On constructing instance, or whenever page is active we will try.
44
+ */
45
+ private tryClaim;
46
+ /**
47
+ * If `lastCheck` is exist, it means there is no other tabs which `claimed` the tabs.
48
+ * And we mark the current tab as `claimed`
49
+ */
50
+ private check;
51
+ private claim;
52
+ /**
53
+ * Setting current time as `lastCheck` and broadcast a `ping` message event.
54
+ */
55
+ private setLastCheck;
56
+ private resetLastCheck;
57
+ /**
58
+ * Upon receipt of a "force-claim" message,
59
+ * the presently active tab is expected to deactivate itself and initiate any attached callback associated with this event.
60
+ */
61
+ private forceRelease;
62
+ }
63
+ //# sourceMappingURL=tabManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabManager.d.ts","sourceRoot":"","sources":["../../../src/libs/tabManager/tabManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EAGN,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAI5B,qBAAa,UAAW,YAAW,mBAAmB;IACpD,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,KAAK,CAAgE;IAC7E,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAmB;gBAEtB,MAAM,EAAE,MAAM;IAQ1B;;OAEG;IACH,UAAU,aAUR;IAEF,SAAS,gBAEP;IAEF;;OAEG;IACH,OAAO,aAOL;IAEF;;OAEG;IACH,OAAO,CAAC,UAAU;IAiBlB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,kBAAkB,CAyBxB;IAEF,OAAO,CAAC,sBAAsB,CAI5B;IAEF,OAAO,CAAC,YAAY,CAOlB;IACF;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAIlC;;;OAGG;YACW,QAAQ;IAatB;;;OAGG;IACH,OAAO,CAAC,KAAK;IAeb,OAAO,CAAC,KAAK;IAKb;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,cAAc;IAItB;;;OAGG;IACH,OAAO,CAAC,YAAY;CAcrB"}
@@ -0,0 +1,29 @@
1
+ export type ID = number;
2
+ type PingMessage = {
3
+ name: 'ping';
4
+ pingAt: number;
5
+ };
6
+ type PongMessage = {
7
+ name: 'pong';
8
+ };
9
+ type ForceClaimMessage = {
10
+ name: 'force-claim';
11
+ candidateId: ID;
12
+ };
13
+ type ForceReleaseMessage = {
14
+ name: 'force-release';
15
+ candidateId: ID;
16
+ };
17
+ export type Message = PingMessage | PongMessage | ForceClaimMessage | ForceReleaseMessage;
18
+ export type Events = {
19
+ onInit?: () => void;
20
+ onClaim?: () => void;
21
+ onRelease?: () => void;
22
+ };
23
+ export interface TabManagerInterface {
24
+ forceClaim: () => void;
25
+ isClaimed: () => boolean;
26
+ destroy: () => void;
27
+ }
28
+ export {};
29
+ //# sourceMappingURL=tabManager.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabManager.types.d.ts","sourceRoot":"","sources":["../../../src/libs/tabManager/tabManager.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,EAAE,GAAG,MAAM,CAAC;AAExB,KAAK,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACpD,KAAK,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AACpC,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,EAAE,CAAC;CACjB,CAAC;AACF,KAAK,mBAAmB,GAAG;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,WAAW,EAAE,EAAE,CAAA;CAAE,CAAC;AAEtE,MAAM,MAAM,OAAO,GACf,WAAW,GACX,WAAW,GACX,iBAAiB,GACjB,mBAAmB,CAAC;AAExB,MAAM,MAAM,MAAM,GAAG;IAEnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConfirmSwapPage.d.ts","sourceRoot":"","sources":["../../src/pages/ConfirmSwapPage.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAuD,MAAM,OAAO,CAAC;AAkD5E,wBAAgB,eAAe,sBA0T9B"}
1
+ {"version":3,"file":"ConfirmSwapPage.d.ts","sourceRoot":"","sources":["../../src/pages/ConfirmSwapPage.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAuD,MAAM,OAAO,CAAC;AAmD5E,wBAAgB,eAAe,sBA4T9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"Home.d.ts","sourceRoot":"","sources":["../../src/pages/Home.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAsCnD,wBAAgB,IAAI,sBAuPnB"}
1
+ {"version":3,"file":"Home.d.ts","sourceRoot":"","sources":["../../src/pages/Home.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAuCnD,wBAAgB,IAAI,sBAyPnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"WalletsPage.d.ts","sourceRoot":"","sources":["../../src/pages/WalletsPage.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAsBxC,eAAO,MAAM,mBAAmB,OAAQ,CAAC;AACzC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,wBAAgB,WAAW,sBAkE1B"}
1
+ {"version":3,"file":"WalletsPage.d.ts","sourceRoot":"","sources":["../../src/pages/WalletsPage.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAuBxC,eAAO,MAAM,mBAAmB,OAAQ,CAAC;AACzC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,wBAAgB,WAAW,sBAoE1B"}
@@ -0,0 +1,24 @@
1
+ interface UiState {
2
+ isActiveTab: boolean;
3
+ tabManagerInitiated: boolean;
4
+ showActivateTabModal: boolean;
5
+ activateCurrentTab: (setCurrentTabAsActive: () => void, hasRunningSwaps: boolean) => void;
6
+ setShowActivateTabModal: (flag: boolean) => void;
7
+ }
8
+ export declare const useUiStore: {
9
+ (): UiState;
10
+ <U>(selector: (state: UiState) => U): U;
11
+ <U_1>(selector: (state: UiState) => U_1, equalityFn: (a: U_1, b: U_1) => boolean): U_1;
12
+ } & import("zustand").StoreApi<UiState> & {
13
+ use: {
14
+ isActiveTab: () => boolean;
15
+ tabManagerInitiated: () => boolean;
16
+ showActivateTabModal: () => boolean;
17
+ activateCurrentTab: () => (setCurrentTabAsActive: () => void, hasRunningSwaps: boolean) => void;
18
+ setShowActivateTabModal: () => (flag: boolean) => void;
19
+ };
20
+ };
21
+ export declare const setCurrentTabAsActive: () => void;
22
+ export declare const destroyTabManager: () => void;
23
+ export {};
24
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/store/ui.ts"],"names":[],"mappings":"AAQA,UAAU,OAAO;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,EAAE,CAClB,qBAAqB,EAAE,MAAM,IAAI,EACjC,eAAe,EAAE,OAAO,KACrB,IAAI,CAAC;IACV,uBAAuB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AAED,eAAO,MAAM,UAAU;;;;;;;;;0DANI,MAAM,IAAI,mBAChB,OAAO,KACrB,IAAI;8CACuB,OAAO,KAAK,IAAI;;CAqBjD,CAAC;AASF,eAAO,MAAM,qBAAqB,YAAwB,CAAC;AAE3D,eAAO,MAAM,iBAAiB,YAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rango-dev/widget-embedded",
3
- "version": "0.20.1-next.22",
3
+ "version": "0.20.1-next.23",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "source": "./src/index.ts",
@@ -23,9 +23,9 @@
23
23
  "@lingui/react": "4.2.1",
24
24
  "@rango-dev/provider-all": "^0.25.1-next.3",
25
25
  "@rango-dev/queue-manager-core": "^0.25.0",
26
- "@rango-dev/queue-manager-rango-preset": "^0.25.1-next.2",
27
- "@rango-dev/queue-manager-react": "^0.24.0",
28
- "@rango-dev/ui": "^0.26.1-next.12",
26
+ "@rango-dev/queue-manager-rango-preset": "^0.25.1-next.3",
27
+ "@rango-dev/queue-manager-react": "^0.24.1-next.0",
28
+ "@rango-dev/ui": "^0.26.1-next.13",
29
29
  "@rango-dev/wallets-react": "^0.11.1-next.1",
30
30
  "@rango-dev/wallets-shared": "^0.25.1-next.1",
31
31
  "bignumber.js": "^9.1.1",
@@ -47,4 +47,4 @@
47
47
  "publishConfig": {
48
48
  "access": "public"
49
49
  }
50
- }
50
+ }
@@ -13,6 +13,7 @@ import { isEvmBlockchain } from 'rango-types';
13
13
  import React, { useMemo } from 'react';
14
14
 
15
15
  import { useAppStore } from './store/AppStore';
16
+ import { useUiStore } from './store/ui';
16
17
  import { useWalletsStore } from './store/wallets';
17
18
  import { getConfig } from './utils/configs';
18
19
  import { walletAndSupportedChainsNames } from './utils/wallets';
@@ -91,6 +92,8 @@ function QueueManager(props: PropsWithChildren<{ apiKey?: string }>) {
91
92
  isMobileWallet,
92
93
  };
93
94
 
95
+ const isActiveTab = useUiStore.use.isActiveTab();
96
+
94
97
  return (
95
98
  <ManagerProvider
96
99
  queuesDefs={[swapQueueDef]}
@@ -98,7 +101,7 @@ function QueueManager(props: PropsWithChildren<{ apiKey?: string }>) {
98
101
  onPersistedDataLoaded={(manager) => {
99
102
  checkWaitingForNetworkChange(manager);
100
103
  }}
101
- isPaused={false}>
104
+ isPaused={!isActiveTab}>
102
105
  {props.children}
103
106
  </ManagerProvider>
104
107
  );
@@ -25,6 +25,7 @@ import {
25
25
  TIME_TO_IGNORE_MODAL,
26
26
  } from '../../pages/WalletsPage';
27
27
  import { useAppStore } from '../../store/AppStore';
28
+ import { useUiStore } from '../../store/ui';
28
29
  import { useWalletsStore } from '../../store/wallets';
29
30
  import { getBlockchainDisplayNameFor } from '../../utils/meta';
30
31
  import {
@@ -44,6 +45,7 @@ import {
44
45
  export function WalletList(props: PropTypes) {
45
46
  const { chain, isSelected, selectWallet, limit, onShowMore } = props;
46
47
  const { config } = useAppStore();
48
+ const isActiveTab = useUiStore.use.isActiveTab();
47
49
 
48
50
  const connectedWallets = useWalletsStore.use.connectedWallets();
49
51
  const { blockchains } = useAppStore();
@@ -289,6 +291,7 @@ export function WalletList(props: PropTypes) {
289
291
  description={connectedWalletDescription}
290
292
  onClick={onClick}
291
293
  selected={isSelected(wallet.type, chain)}
294
+ disabled={!isActiveTab}
292
295
  {...wallet}
293
296
  />
294
297
  </>
@@ -1,6 +1,8 @@
1
1
  import type { PropTypes } from './Layout.types';
2
+ import type { PendingSwap } from 'rango-types';
2
3
  import type { PropsWithChildren } from 'react';
3
4
 
5
+ import { useManager } from '@rango-dev/queue-manager-react';
4
6
  import { BottomLogo, Divider, Header } from '@rango-dev/ui';
5
7
  import React, { useEffect, useRef } from 'react';
6
8
 
@@ -8,9 +10,13 @@ import { RANGO_SWAP_BOX_ID } from '../../constants';
8
10
  import { useNavigateBack } from '../../hooks/useNavigateBack';
9
11
  import { useTheme } from '../../hooks/useTheme';
10
12
  import { useAppStore } from '../../store/AppStore';
13
+ import { setCurrentTabAsActive, useUiStore } from '../../store/ui';
11
14
  import { useWalletsStore } from '../../store/wallets';
12
15
  import { getContainer } from '../../utils/common';
16
+ import { getPendingSwaps } from '../../utils/queue';
13
17
  import { isFeatureHidden } from '../../utils/settings';
18
+ import { ActivateTabAlert } from '../common/ActivateTabAlert';
19
+ import { ActivateTabModal } from '../common/ActivateTabModal';
14
20
  import { BackButton, CancelButton, WalletButton } from '../HeaderButtons';
15
21
 
16
22
  import { onScrollContentAttachStatusToContainer } from './Layout.helpers';
@@ -29,7 +35,22 @@ function Layout(props: PropsWithChildren<PropTypes>) {
29
35
  features
30
36
  );
31
37
 
38
+ const {
39
+ isActiveTab,
40
+ tabManagerInitiated,
41
+ showActivateTabModal,
42
+ setShowActivateTabModal,
43
+ activateCurrentTab,
44
+ } = useUiStore();
32
45
  const navigateBack = useNavigateBack();
46
+ const { manager } = useManager();
47
+ const pendingSwaps: PendingSwap[] = getPendingSwaps(manager).map(
48
+ ({ swap }) => swap
49
+ );
50
+ const hasRunningSwap = pendingSwaps.some((swap) => swap.status === 'running');
51
+
52
+ const onActivateTab = () =>
53
+ activateCurrentTab(setCurrentTabAsActive, hasRunningSwap);
33
54
 
34
55
  const onConnectWallet = () => {
35
56
  header.onWallet?.();
@@ -74,12 +95,25 @@ function Layout(props: PropsWithChildren<PropTypes>) {
74
95
  }
75
96
  />
76
97
  <Content ref={scrollViewRef}>{children}</Content>
98
+ <ActivateTabModal
99
+ open={showActivateTabModal}
100
+ onClose={() => setShowActivateTabModal(false)}
101
+ onConfirm={onActivateTab}
102
+ />
77
103
  {(hasLogo || footer) && (
78
104
  <Footer>
79
- <div className="footer__content">{footer}</div>
105
+ <div className="footer__content">
106
+ {footer}
107
+ {tabManagerInitiated && !isActiveTab && (
108
+ <>
109
+ <Divider size={12} />
110
+ <ActivateTabAlert onActivateTab={onActivateTab} />
111
+ </>
112
+ )}
113
+ </div>
114
+ <Divider size={12} />
80
115
  {hasLogo && (
81
116
  <div className="footer__logo">
82
- <Divider size={12} />
83
117
  <BottomLogo />
84
118
  </div>
85
119
  )}
@@ -28,13 +28,14 @@ import { Flex } from './QuoteWarningsAndErrors.styles';
28
28
 
29
29
  type Props = {
30
30
  open: boolean;
31
+ confirmationDisabled: boolean;
31
32
  onClose: () => void;
32
33
  onConfirm: () => void;
33
34
  warning: HighValueLossWarning;
34
35
  };
35
36
 
36
37
  export function HighValueLossWarningModal(props: Props) {
37
- const { open, onClose, onConfirm, warning } = props;
38
+ const { open, onClose, onConfirm, warning, confirmationDisabled } = props;
38
39
  const type = warning.warningLevel === 'high' ? 'error' : 'warning';
39
40
  const highValueLossData = [
40
41
  {
@@ -99,6 +100,7 @@ export function HighValueLossWarningModal(props: Props) {
99
100
  size="large"
100
101
  prefix={<WarningIcon />}
101
102
  fullWidth
103
+ disabled={confirmationDisabled}
102
104
  onClick={onConfirm}>
103
105
  {errorMessages().highValueLossError.confirmMessage}
104
106
  </Button>
@@ -17,8 +17,9 @@ export function QuoteWarningsAndErrors(props: PropTypes) {
17
17
  const {
18
18
  warning,
19
19
  error,
20
- refetchQuote,
21
20
  showWarningModal,
21
+ confirmationDisabled,
22
+ refetchQuote,
22
23
  onOpenWarningModal,
23
24
  onCloseWarningModal,
24
25
  onConfirmWarningModal,
@@ -26,6 +27,7 @@ export function QuoteWarningsAndErrors(props: PropTypes) {
26
27
  } = props;
27
28
 
28
29
  const warningModalHandlers = {
30
+ confirmationDisabled,
29
31
  open: showWarningModal,
30
32
  onClose: onCloseWarningModal,
31
33
  onConfirm: onConfirmWarningModal,
@@ -5,6 +5,7 @@ export interface PropTypes {
5
5
  error: QuoteError | null;
6
6
  warning: QuoteWarning | null;
7
7
  showWarningModal: boolean;
8
+ confirmationDisabled: boolean;
8
9
  refetchQuote: () => void;
9
10
  onOpenWarningModal: () => void;
10
11
  onCloseWarningModal: () => void;
@@ -15,6 +15,7 @@ import { getContainer } from '../../utils/common';
15
15
 
16
16
  type PropsTypes = {
17
17
  open: boolean;
18
+ confirmationDisabled: boolean;
18
19
  onClose: () => void;
19
20
  onConfirm: () => void;
20
21
  warning: InsufficientSlippageWarning | HighSlippageWarning;
@@ -22,7 +23,7 @@ type PropsTypes = {
22
23
 
23
24
  export function SlippageWarningModal(props: PropsTypes) {
24
25
  const { customSlippage, slippage } = useAppStore();
25
- const { open, onClose, onConfirm, warning } = props;
26
+ const { open, onClose, onConfirm, warning, confirmationDisabled } = props;
26
27
  const navigate = useNavigate();
27
28
  const userSlippage = customSlippage ?? slippage;
28
29
  return (
@@ -68,6 +69,7 @@ export function SlippageWarningModal(props: PropsTypes) {
68
69
  type="primary"
69
70
  variant="contained"
70
71
  fullWidth
72
+ disabled={confirmationDisabled}
71
73
  onClick={onConfirm}>
72
74
  {i18n.t('Confirm anyway')}
73
75
  </Button>
@@ -8,13 +8,14 @@ import { getContainer } from '../../utils/common';
8
8
 
9
9
  type Props = {
10
10
  open: boolean;
11
+ confirmationDisabled: boolean;
11
12
  onClose: () => void;
12
13
  onConfirm: () => void;
13
14
  warning: UnknownPriceWarning;
14
15
  };
15
16
 
16
17
  export function UnknownPriceWarningModal(props: Props) {
17
- const { open, onClose, onConfirm } = props;
18
+ const { open, onClose, onConfirm, confirmationDisabled } = props;
18
19
 
19
20
  return (
20
21
  <Modal open={open} onClose={onClose} container={getContainer()}>
@@ -30,6 +31,7 @@ export function UnknownPriceWarningModal(props: Props) {
30
31
  size="large"
31
32
  prefix={<WarningIcon />}
32
33
  fullWidth
34
+ disabled={confirmationDisabled}
33
35
  onClick={onConfirm}>
34
36
  {errorMessages().unknownPriceError.confirmMessage}
35
37
  </Button>
@@ -38,6 +38,7 @@ import {
38
38
  import { useAppStore } from '../../store/AppStore';
39
39
  import { useNotificationStore } from '../../store/notification';
40
40
  import { useQuoteStore } from '../../store/quote';
41
+ import { useUiStore } from '../../store/ui';
41
42
  import { getContainer } from '../../utils/common';
42
43
  import {
43
44
  formatTooltipNumbers,
@@ -79,6 +80,7 @@ export function SwapDetails(props: SwapDetailsProps) {
79
80
  const swappers = useAppStore().swappers();
80
81
  const tokens = useAppStore().tokens();
81
82
  const retry = useQuoteStore.use.retry();
83
+ const isActiveTab = useUiStore.use.isActiveTab();
82
84
  const navigate = useNavigate();
83
85
  const [_, handleCopy] = useCopyToClipboard(RESET_INTERVAL);
84
86
  const listRef = useRef<HTMLDivElement | null>(null);
@@ -407,6 +409,7 @@ export function SwapDetails(props: SwapDetailsProps) {
407
409
  onDelete={onDelete}
408
410
  message={stepMessage.detailedMessage.content}
409
411
  currentStepWallet={currentStepWallet}
412
+ walletButtonDisabled={!isActiveTab}
410
413
  />
411
414
  <SwapDetailsCompleteModal
412
415
  open={!!showCompletedModal}
@@ -10,7 +10,14 @@ import { mapStatusToWalletState } from '../../utils/wallets';
10
10
  import { WalletContainer } from './SwapDetailsModal.styles';
11
11
 
12
12
  export const WalletStateContent = (props: WalletStateContentProps) => {
13
- const { type, title, currentStepWallet, message, showWalletButton } = props;
13
+ const {
14
+ type,
15
+ title,
16
+ currentStepWallet,
17
+ message,
18
+ showWalletButton,
19
+ walletButtonDisabled,
20
+ } = props;
14
21
  const { connect, getWalletInfo, state } = useWallets();
15
22
  const walletType = currentStepWallet?.walletType;
16
23
  const walletState = walletType
@@ -31,6 +38,7 @@ export const WalletStateContent = (props: WalletStateContentProps) => {
31
38
  type={walletType}
32
39
  state={walletState}
33
40
  link={walletInfo.installLink}
41
+ disabled={walletButtonDisabled}
34
42
  onClick={async () => connect(walletType)}
35
43
  />
36
44
  </WalletContainer>
@@ -12,8 +12,15 @@ import { modalNetworkValues } from './SwapDetailsModal.helpers';
12
12
  import { WalletStateContent } from './SwapDetailsModal.WalletState';
13
13
 
14
14
  export function SwapDetailsModal(props: ModalPropTypes) {
15
- const { state, onClose, onDelete, onCancel, currentStepWallet, message } =
16
- props;
15
+ const {
16
+ state,
17
+ onClose,
18
+ onDelete,
19
+ onCancel,
20
+ currentStepWallet,
21
+ message,
22
+ walletButtonDisabled,
23
+ } = props;
17
24
 
18
25
  const showWalletStateContent =
19
26
  state === PendingSwapNetworkStatus.WaitingForNetworkChange ||
@@ -31,6 +38,7 @@ export function SwapDetailsModal(props: ModalPropTypes) {
31
38
  title={modalNetworkValues[state].title}
32
39
  currentStepWallet={currentStepWallet}
33
40
  message={message}
41
+ walletButtonDisabled={walletButtonDisabled}
34
42
  showWalletButton={
35
43
  state !== PendingSwapNetworkStatus.WaitingForNetworkChange
36
44
  }
@@ -17,6 +17,7 @@ export interface ModalPropTypes {
17
17
  state: ModalState;
18
18
  currentStepWallet: WalletTypeAndAddress | null;
19
19
  message: string;
20
+ walletButtonDisabled: boolean;
20
21
  }
21
22
 
22
23
  export interface CompleteModalPropTypes {
@@ -49,6 +50,7 @@ export interface WalletStateContentProps extends ModalNetworkValueTypes {
49
50
  currentStepWallet: WalletTypeAndAddress | null;
50
51
  message: string;
51
52
  showWalletButton: boolean;
53
+ walletButtonDisabled: boolean;
52
54
  }
53
55
 
54
56
  export type CancelContentProps = Pick<ModalPropTypes, 'onClose' | 'onCancel'>;
@@ -0,0 +1,26 @@
1
+ import type { PropTypes } from './ActivateTabAlert.types';
2
+
3
+ import { i18n } from '@lingui/core';
4
+ import { Alert, Button } from '@rango-dev/ui';
5
+ import React from 'react';
6
+
7
+ export function ActivateTabAlert(props: PropTypes) {
8
+ return (
9
+ <Alert
10
+ action={
11
+ <Button
12
+ onClick={props.onActivateTab}
13
+ variant="contained"
14
+ size="xxsmall"
15
+ type="warning">
16
+ {i18n.t('Activate')}
17
+ </Button>
18
+ }
19
+ type="warning"
20
+ variant="alarm"
21
+ title={i18n.t(
22
+ 'Another tab is open and handles transactions. You can activate this tab.'
23
+ )}
24
+ />
25
+ );
26
+ }
@@ -0,0 +1,3 @@
1
+ export type PropTypes = {
2
+ onActivateTab: () => void;
3
+ };
@@ -0,0 +1 @@
1
+ export { ActivateTabAlert } from './ActivateTabAlert';
@@ -0,0 +1,31 @@
1
+ import type { PropTypes } from './ActivateTabModal.types';
2
+
3
+ import { i18n } from '@lingui/core';
4
+ import { Button, Divider, MessageBox, Modal } from '@rango-dev/ui';
5
+ import React from 'react';
6
+
7
+ import { getContainer } from '../../../utils/common';
8
+
9
+ export function ActivateTabModal(props: PropTypes) {
10
+ const { open, onClose, onConfirm } = props;
11
+ return (
12
+ <Modal open={open} dismissible onClose={onClose} container={getContainer()}>
13
+ <MessageBox
14
+ title={i18n.t('Activate current tab')}
15
+ type="warning"
16
+ description={i18n.t(
17
+ 'Currently, some transactions are running and being handled by other browser tab. If you activate this tab, all transactions that are already in the transaction sign step will expire.'
18
+ )}>
19
+ <Divider size={20} />
20
+ <Button
21
+ variant="contained"
22
+ size="large"
23
+ type="primary"
24
+ fullWidth
25
+ onClick={onConfirm}>
26
+ {i18n.t('Confirm')}
27
+ </Button>
28
+ </MessageBox>
29
+ </Modal>
30
+ );
31
+ }
@@ -0,0 +1,5 @@
1
+ export type PropTypes = {
2
+ open: boolean;
3
+ onClose: () => void;
4
+ onConfirm: () => void;
5
+ };
@@ -0,0 +1 @@
1
+ export { ActivateTabModal } from './ActivateTabModal';
@@ -15,6 +15,7 @@ import React, { createContext, useEffect, useRef, useState } from 'react';
15
15
 
16
16
  import { useWalletProviders } from '../../hooks/useWalletProviders';
17
17
  import { AppStoreProvider, useAppStore } from '../../store/AppStore';
18
+ import { useUiStore } from '../../store/ui';
18
19
  import { useWalletsStore } from '../../store/wallets';
19
20
  import {
20
21
  prepareAccountsForWalletStore,
@@ -99,6 +100,7 @@ function Main(props: PropsWithChildren<PropTypes>) {
99
100
  props.onUpdateState(type, event, value, state, meta);
100
101
  }
101
102
  };
103
+ const isActiveTab = useUiStore.use.isActiveTab();
102
104
 
103
105
  useEffect(() => {
104
106
  if (accounts.length) {
@@ -118,7 +120,7 @@ function Main(props: PropsWithChildren<PropTypes>) {
118
120
  allBlockChains={blockchains}
119
121
  providers={providers}
120
122
  onUpdateState={onUpdateState}
121
- autoConnect>
123
+ autoConnect={!!isActiveTab}>
122
124
  {props.children}
123
125
  </Provider>
124
126
  </WidgetContext.Provider>
@@ -1,13 +1,18 @@
1
1
  import type { WidgetProps } from './Widget.types';
2
2
  import type { PropsWithChildren } from 'react';
3
3
 
4
- import React from 'react';
4
+ import React, { useEffect } from 'react';
5
5
 
6
6
  import { DEFAULT_CONFIG } from '../../store/slices/config';
7
+ import { destroyTabManager } from '../../store/ui';
7
8
  import { Main } from '../App';
8
9
  import { WidgetProvider } from '../WidgetProvider';
9
10
 
10
11
  export function Widget(props: PropsWithChildren<WidgetProps>) {
12
+ useEffect(() => {
13
+ return destroyTabManager;
14
+ }, []);
15
+
11
16
  if (!props.config?.externalWallets) {
12
17
  return (
13
18
  <WidgetProvider config={props.config ?? DEFAULT_CONFIG}>