@oxy.so/services 12.2.1 → 12.4.0

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 (161) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/index.js +17 -2
  3. package/lib/commonjs/index.js.map +1 -1
  4. package/lib/commonjs/ui/client.js +54 -0
  5. package/lib/commonjs/ui/client.js.map +1 -1
  6. package/lib/commonjs/ui/components/signIn/OxyAuthenticatorPanel.js +11 -10
  7. package/lib/commonjs/ui/components/signIn/OxyAuthenticatorPanel.js.map +1 -1
  8. package/lib/commonjs/ui/components/signIn/OxyDeleteAccountPanel.js +19 -18
  9. package/lib/commonjs/ui/components/signIn/OxyDeleteAccountPanel.js.map +1 -1
  10. package/lib/commonjs/ui/components/signIn/OxyEmailPanel.js +251 -0
  11. package/lib/commonjs/ui/components/signIn/OxyEmailPanel.js.map +1 -0
  12. package/lib/commonjs/ui/components/signIn/OxyLinkCommonsPanel.js +40 -33
  13. package/lib/commonjs/ui/components/signIn/OxyLinkCommonsPanel.js.map +1 -1
  14. package/lib/commonjs/ui/components/signIn/OxyPasswordPanel.js +51 -19
  15. package/lib/commonjs/ui/components/signIn/OxyPasswordPanel.js.map +1 -1
  16. package/lib/commonjs/ui/components/signIn/OxySignInSecurityPanel.js +154 -0
  17. package/lib/commonjs/ui/components/signIn/OxySignInSecurityPanel.js.map +1 -0
  18. package/lib/commonjs/ui/components/signIn/ReauthStep.js +6 -4
  19. package/lib/commonjs/ui/components/signIn/ReauthStep.js.map +1 -1
  20. package/lib/commonjs/ui/components/signIn/SessionsSection.js +200 -0
  21. package/lib/commonjs/ui/components/signIn/SessionsSection.js.map +1 -0
  22. package/lib/commonjs/ui/components/signIn/accountFlowParts.js +6 -0
  23. package/lib/commonjs/ui/components/signIn/accountFlowParts.js.map +1 -1
  24. package/lib/commonjs/ui/components/signIn/accountSecurityState.js +74 -0
  25. package/lib/commonjs/ui/components/signIn/accountSecurityState.js.map +1 -0
  26. package/lib/commonjs/ui/navigation/routes.js +1 -1
  27. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  28. package/lib/commonjs/ui/navigation/screenComponents.js +4 -0
  29. package/lib/commonjs/ui/navigation/screenComponents.js.map +1 -1
  30. package/lib/commonjs/ui/navigation/surfaceRegistry.js.map +1 -1
  31. package/lib/commonjs/ui/screens/AccountSecurityPanelScreen.js +1 -1
  32. package/lib/commonjs/ui/screens/ManageAccountScreen.js +8 -196
  33. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
  34. package/lib/commonjs/ui/screens/SignInEmailScreen.js +19 -0
  35. package/lib/commonjs/ui/screens/SignInEmailScreen.js.map +1 -0
  36. package/lib/commonjs/ui/screens/SignInSecurityScreen.js +30 -0
  37. package/lib/commonjs/ui/screens/SignInSecurityScreen.js.map +1 -0
  38. package/lib/module/index.js +5 -2
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/ui/client.js +11 -1
  41. package/lib/module/ui/client.js.map +1 -1
  42. package/lib/module/ui/components/signIn/OxyAuthenticatorPanel.js +12 -11
  43. package/lib/module/ui/components/signIn/OxyAuthenticatorPanel.js.map +1 -1
  44. package/lib/module/ui/components/signIn/OxyDeleteAccountPanel.js +20 -19
  45. package/lib/module/ui/components/signIn/OxyDeleteAccountPanel.js.map +1 -1
  46. package/lib/module/ui/components/signIn/OxyEmailPanel.js +246 -0
  47. package/lib/module/ui/components/signIn/OxyEmailPanel.js.map +1 -0
  48. package/lib/module/ui/components/signIn/OxyLinkCommonsPanel.js +40 -33
  49. package/lib/module/ui/components/signIn/OxyLinkCommonsPanel.js.map +1 -1
  50. package/lib/module/ui/components/signIn/OxyPasswordPanel.js +52 -20
  51. package/lib/module/ui/components/signIn/OxyPasswordPanel.js.map +1 -1
  52. package/lib/module/ui/components/signIn/OxySignInSecurityPanel.js +149 -0
  53. package/lib/module/ui/components/signIn/OxySignInSecurityPanel.js.map +1 -0
  54. package/lib/module/ui/components/signIn/ReauthStep.js +6 -4
  55. package/lib/module/ui/components/signIn/ReauthStep.js.map +1 -1
  56. package/lib/module/ui/components/signIn/SessionsSection.js +194 -0
  57. package/lib/module/ui/components/signIn/SessionsSection.js.map +1 -0
  58. package/lib/module/ui/components/signIn/accountFlowParts.js +6 -0
  59. package/lib/module/ui/components/signIn/accountFlowParts.js.map +1 -1
  60. package/lib/module/ui/components/signIn/accountSecurityState.js +69 -0
  61. package/lib/module/ui/components/signIn/accountSecurityState.js.map +1 -0
  62. package/lib/module/ui/navigation/routes.js +1 -1
  63. package/lib/module/ui/navigation/routes.js.map +1 -1
  64. package/lib/module/ui/navigation/screenComponents.js +4 -0
  65. package/lib/module/ui/navigation/screenComponents.js.map +1 -1
  66. package/lib/module/ui/navigation/surfaceRegistry.js.map +1 -1
  67. package/lib/module/ui/screens/AccountSecurityPanelScreen.js +1 -1
  68. package/lib/module/ui/screens/ManageAccountScreen.js +9 -197
  69. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
  70. package/lib/module/ui/screens/SignInEmailScreen.js +17 -0
  71. package/lib/module/ui/screens/SignInEmailScreen.js.map +1 -0
  72. package/lib/module/ui/screens/SignInSecurityScreen.js +26 -0
  73. package/lib/module/ui/screens/SignInSecurityScreen.js.map +1 -0
  74. package/lib/typescript/commonjs/index.d.ts +4 -0
  75. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  76. package/lib/typescript/commonjs/ui/client.d.ts +8 -1
  77. package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
  78. package/lib/typescript/commonjs/ui/components/signIn/OxyAuthenticatorPanel.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/ui/components/signIn/OxyDeleteAccountPanel.d.ts +3 -2
  80. package/lib/typescript/commonjs/ui/components/signIn/OxyDeleteAccountPanel.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/ui/components/signIn/OxyEmailPanel.d.ts +21 -0
  82. package/lib/typescript/commonjs/ui/components/signIn/OxyEmailPanel.d.ts.map +1 -0
  83. package/lib/typescript/commonjs/ui/components/signIn/OxyLinkCommonsPanel.d.ts +2 -1
  84. package/lib/typescript/commonjs/ui/components/signIn/OxyLinkCommonsPanel.d.ts.map +1 -1
  85. package/lib/typescript/commonjs/ui/components/signIn/OxyPasswordPanel.d.ts +5 -4
  86. package/lib/typescript/commonjs/ui/components/signIn/OxyPasswordPanel.d.ts.map +1 -1
  87. package/lib/typescript/commonjs/ui/components/signIn/OxySignInSecurityPanel.d.ts +25 -0
  88. package/lib/typescript/commonjs/ui/components/signIn/OxySignInSecurityPanel.d.ts.map +1 -0
  89. package/lib/typescript/commonjs/ui/components/signIn/ReauthStep.d.ts +8 -2
  90. package/lib/typescript/commonjs/ui/components/signIn/ReauthStep.d.ts.map +1 -1
  91. package/lib/typescript/commonjs/ui/components/signIn/SessionsSection.d.ts +9 -0
  92. package/lib/typescript/commonjs/ui/components/signIn/SessionsSection.d.ts.map +1 -0
  93. package/lib/typescript/commonjs/ui/components/signIn/accountFlowParts.d.ts.map +1 -1
  94. package/lib/typescript/commonjs/ui/components/signIn/accountSecurityState.d.ts +26 -0
  95. package/lib/typescript/commonjs/ui/components/signIn/accountSecurityState.d.ts.map +1 -0
  96. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
  97. package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/ui/navigation/screenComponents.d.ts.map +1 -1
  99. package/lib/typescript/commonjs/ui/navigation/surfaceRegistry.d.ts +2 -0
  100. package/lib/typescript/commonjs/ui/navigation/surfaceRegistry.d.ts.map +1 -1
  101. package/lib/typescript/commonjs/ui/screens/AccountSecurityPanelScreen.d.ts +1 -1
  102. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts +3 -2
  103. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  104. package/lib/typescript/commonjs/ui/screens/SignInEmailScreen.d.ts +6 -0
  105. package/lib/typescript/commonjs/ui/screens/SignInEmailScreen.d.ts.map +1 -0
  106. package/lib/typescript/commonjs/ui/screens/SignInSecurityScreen.d.ts +6 -0
  107. package/lib/typescript/commonjs/ui/screens/SignInSecurityScreen.d.ts.map +1 -0
  108. package/lib/typescript/module/index.d.ts +4 -0
  109. package/lib/typescript/module/index.d.ts.map +1 -1
  110. package/lib/typescript/module/ui/client.d.ts +8 -1
  111. package/lib/typescript/module/ui/client.d.ts.map +1 -1
  112. package/lib/typescript/module/ui/components/signIn/OxyAuthenticatorPanel.d.ts.map +1 -1
  113. package/lib/typescript/module/ui/components/signIn/OxyDeleteAccountPanel.d.ts +3 -2
  114. package/lib/typescript/module/ui/components/signIn/OxyDeleteAccountPanel.d.ts.map +1 -1
  115. package/lib/typescript/module/ui/components/signIn/OxyEmailPanel.d.ts +21 -0
  116. package/lib/typescript/module/ui/components/signIn/OxyEmailPanel.d.ts.map +1 -0
  117. package/lib/typescript/module/ui/components/signIn/OxyLinkCommonsPanel.d.ts +2 -1
  118. package/lib/typescript/module/ui/components/signIn/OxyLinkCommonsPanel.d.ts.map +1 -1
  119. package/lib/typescript/module/ui/components/signIn/OxyPasswordPanel.d.ts +5 -4
  120. package/lib/typescript/module/ui/components/signIn/OxyPasswordPanel.d.ts.map +1 -1
  121. package/lib/typescript/module/ui/components/signIn/OxySignInSecurityPanel.d.ts +25 -0
  122. package/lib/typescript/module/ui/components/signIn/OxySignInSecurityPanel.d.ts.map +1 -0
  123. package/lib/typescript/module/ui/components/signIn/ReauthStep.d.ts +8 -2
  124. package/lib/typescript/module/ui/components/signIn/ReauthStep.d.ts.map +1 -1
  125. package/lib/typescript/module/ui/components/signIn/SessionsSection.d.ts +9 -0
  126. package/lib/typescript/module/ui/components/signIn/SessionsSection.d.ts.map +1 -0
  127. package/lib/typescript/module/ui/components/signIn/accountFlowParts.d.ts.map +1 -1
  128. package/lib/typescript/module/ui/components/signIn/accountSecurityState.d.ts +26 -0
  129. package/lib/typescript/module/ui/components/signIn/accountSecurityState.d.ts.map +1 -0
  130. package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
  131. package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
  132. package/lib/typescript/module/ui/navigation/screenComponents.d.ts.map +1 -1
  133. package/lib/typescript/module/ui/navigation/surfaceRegistry.d.ts +2 -0
  134. package/lib/typescript/module/ui/navigation/surfaceRegistry.d.ts.map +1 -1
  135. package/lib/typescript/module/ui/screens/AccountSecurityPanelScreen.d.ts +1 -1
  136. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts +3 -2
  137. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  138. package/lib/typescript/module/ui/screens/SignInEmailScreen.d.ts +6 -0
  139. package/lib/typescript/module/ui/screens/SignInEmailScreen.d.ts.map +1 -0
  140. package/lib/typescript/module/ui/screens/SignInSecurityScreen.d.ts +6 -0
  141. package/lib/typescript/module/ui/screens/SignInSecurityScreen.d.ts.map +1 -0
  142. package/package.json +5 -5
  143. package/src/index.ts +7 -2
  144. package/src/ui/client.ts +16 -1
  145. package/src/ui/components/signIn/OxyAuthenticatorPanel.tsx +11 -8
  146. package/src/ui/components/signIn/OxyDeleteAccountPanel.tsx +15 -16
  147. package/src/ui/components/signIn/OxyEmailPanel.tsx +258 -0
  148. package/src/ui/components/signIn/OxyLinkCommonsPanel.tsx +27 -15
  149. package/src/ui/components/signIn/OxyPasswordPanel.tsx +49 -14
  150. package/src/ui/components/signIn/OxySignInSecurityPanel.tsx +147 -0
  151. package/src/ui/components/signIn/ReauthStep.tsx +13 -4
  152. package/src/ui/components/signIn/SessionsSection.tsx +218 -0
  153. package/src/ui/components/signIn/accountFlowParts.tsx +6 -0
  154. package/src/ui/components/signIn/accountSecurityState.tsx +75 -0
  155. package/src/ui/navigation/routes.ts +5 -1
  156. package/src/ui/navigation/screenComponents.ts +4 -0
  157. package/src/ui/navigation/surfaceRegistry.ts +2 -0
  158. package/src/ui/screens/AccountSecurityPanelScreen.tsx +1 -1
  159. package/src/ui/screens/ManageAccountScreen.tsx +8 -241
  160. package/src/ui/screens/SignInEmailScreen.tsx +13 -0
  161. package/src/ui/screens/SignInSecurityScreen.tsx +19 -0
@@ -1 +1 @@
1
- {"version":3,"file":"surfaceRegistry.d.ts","sourceRoot":"","sources":["../../../../../src/ui/navigation/surfaceRegistry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"surfaceRegistry.d.ts","sourceRoot":"","sources":["../../../../../src/ui/navigation/surfaceRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAA+B,CAAC;AAEzE;;;;;;;;;;GAUG;AAEH,sFAAsF;AACtF,KAAK,YAAY,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,IAAI;IAClE,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,YAAY,CAAC;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,aAAa,EAAE,YAAY,CAAC;IAC5B,mBAAmB,EAAE,YAAY,CAAC;IAClC,cAAc,EAAE,YAAY,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,gBAAgB,EAAE,YAAY,CAAC;IAC/B,eAAe,EAAE,YAAY,CAAC;IAC9B,cAAc,EAAE,YAAY,CAAC;IAC7B;;;;;OAKG;IACH,cAAc,EAAE,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,CAAC;IACpE,sEAAsE;IACtE,SAAS,EAAE,YAAY,CAAC;IACxB,WAAW,EAAE,YAAY,CAAC;IAC1B,SAAS,EAAE,YAAY,CAAC;IACxB,MAAM,EAAE,YAAY,CAAC;IACrB,cAAc,EAAE,YAAY,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,cAAc,EAAE,YAAY,CAAC;IAC7B,WAAW,EAAE,YAAY,CAAC;IAC1B,WAAW,EAAE,YAAY,CAAC;IAC1B,gBAAgB,EAAE,YAAY,CAAC;IAC/B,kBAAkB,EAAE,YAAY,CAAC;IACjC,WAAW,EAAE,YAAY,CAAC;IAC1B,gBAAgB,EAAE,YAAY,CAAC;IAC/B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,YAAY,CAAC;IACzB,UAAU,EAAE,YAAY,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,YAAY,CAAC;IACtB,aAAa,EAAE,YAAY,CAAC;IAC5B,aAAa,EAAE,YAAY,CAAC;IAC5B,aAAa,EAAE,YAAY,CAAC;IAC5B,cAAc,EAAE,YAAY,CAAC;IAC7B,eAAe,EAAE,YAAY,CAAC;IAC9B;;;;;OAKG;IACH,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,mBAAmB,CAAC,CAAC;IAC5F;;;OAGG;IACH,UAAU,EAAE,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACpE,aAAa,EAAE,YAAY,CAAC;IAC5B,aAAa,EAAE,YAAY,CAAC;IAC5B,WAAW,EAAE,YAAY,CAAC;IAC1B,aAAa,EAAE,YAAY,CAAC;IAC5B,WAAW,EAAE,YAAY,CAAC;IAC1B,cAAc,EAAE,YAAY,CAAC;IAC7B,WAAW,EAAE,YAAY,CAAC;IAC1B,cAAc,EAAE,YAAY,CAAC;IAC7B,mBAAmB,EAAE,YAAY,CAAC;IAClC,yFAAyF;IACzF,aAAa,EAAE,YAAY,CAAC;QAAE,WAAW,CAAC,EAAE,iBAAiB,CAAA;KAAE,CAAC,CAAC;CAClE;AAeD,6CAA6C;AAC7C,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,SAAS,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAC5E,8EAA8E;AAC9E,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,SAAS,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAE9E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAC;AAE/E;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,YAAY,EAAE,mBAAmB,CAAC;IAClC,2EAA2E;IAC3E,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,UAAU,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAClC;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;;;;;OASG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;;OAMG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB,iFAAiF;IACjF,gBAAgB,EAAE,OAAO,CAAC;IAC1B,mFAAmF;IACnF,eAAe,EAAE,OAAO,CAAC;IACzB,qFAAqF;IACrF,eAAe,CAAC,EAAE,MAAM,SAAS,CAAC;CACnC;AAsDD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,OAAO,SAAS,EAChB,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,kBAsBF,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,sBAAsB,GACjC,OAAO,SAAS,EAChB,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,mBAAkE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The frame the account's own security panels render in when presented as a
3
- * surface (`showBottomSheet('DeleteAccount' | 'LinkCommons' | 'SignInPassword'
3
+ * surface (`showBottomSheet('DeleteAccount' | 'LinkCommons' | 'SignInEmail' | 'SignInPassword'
4
4
  * | 'SignInAuthenticator')`): the panel draws its own large header, so the bar
5
5
  * holds only the way back, and the body keeps the dialog's screen gutter.
6
6
  */
@@ -4,8 +4,9 @@ import type { BaseScreenProps } from '../types/navigation.js';
4
4
  * Unified "Manage your Oxy Account" screen.
5
5
  *
6
6
  * Replaces AccountOverview + AccountSettings + the per-account half of
7
- * SessionManagement. Lists ONLY the active user's profile, sessions on this
8
- * device, and security/destructive actions for THIS account. Multi-account
7
+ * SessionManagement. Lists ONLY the active user's profile, its sign-in and
8
+ * security page (`SignInSecurity`: methods and sessions), and the destructive
9
+ * actions for THIS account. Multi-account
9
10
  * surface lives in the unified `OxyAccountDialogScreen` — keep these concerns separate.
10
11
  */
11
12
  interface ManageAccountScreenProps extends BaseScreenProps {
@@ -1 +1 @@
1
- {"version":3,"file":"ManageAccountScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/ManageAccountScreen.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAiB/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;AA6C3D;;;;;;;GAOG;AACH,UAAU,wBAAyB,SAAQ,eAAe;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAgqB3D,CAAC;AAYF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"ManageAccountScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/ManageAccountScreen.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;AAY3D;;;;;;;;GAQG;AACH,UAAU,wBAAyB,SAAQ,eAAe;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAyd3D,CAAC;AAYF,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type React from 'react';
2
+ import type { BaseScreenProps } from '../types/navigation.js';
3
+ /** `SignInEmail`: add, change or remove the account's email. */
4
+ declare const SignInEmailScreen: React.FC<BaseScreenProps>;
5
+ export default SignInEmailScreen;
6
+ //# sourceMappingURL=SignInEmailScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignInEmailScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/SignInEmailScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;AAG3D,gEAAgE;AAChE,QAAA,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAIhD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type React from 'react';
2
+ import type { BaseScreenProps } from '../types/navigation.js';
3
+ /** `SignInSecurity`: how the account signs in, and where it is signed in. */
4
+ declare const SignInSecurityScreen: React.FC<BaseScreenProps>;
5
+ export default SignInSecurityScreen;
6
+ //# sourceMappingURL=SignInSecurityScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignInSecurityScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/SignInSecurityScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;AAE3D,6EAA6E;AAC7E,QAAA,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAQnD,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxy.so/services",
3
- "version": "12.2.1",
3
+ "version": "12.4.0",
4
4
  "description": "OxyHQ Expo/React Native SDK — UI components, screens, and native features",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -151,7 +151,7 @@
151
151
  "prepublishOnly": "node ../../scripts/assert-bun-publish.mjs && bun run typescript && bun run test && bun run build"
152
152
  },
153
153
  "dependencies": {
154
- "@oxy.so/contracts": "^5.0.0",
154
+ "@oxy.so/contracts": "^5.1.0",
155
155
  "color": "^5.0.3",
156
156
  "@peable.to/sdk": "0.4.1"
157
157
  },
@@ -160,7 +160,7 @@
160
160
  "@commitlint/config-conventional": "^21.2.0",
161
161
  "@expo/app-integrity": "~58.0.2",
162
162
  "@expo/vector-icons": "^15.0.3",
163
- "@oxy.so/core": "6.0.0",
163
+ "@oxy.so/core": "6.1.0",
164
164
  "@react-native-async-storage/async-storage": "^2.0.0",
165
165
  "@react-native-community/netinfo": "^12.0.1",
166
166
  "@react-native/babel-preset": "^0.88.0",
@@ -210,12 +210,12 @@
210
210
  "expo-video": "~58.0.11"
211
211
  },
212
212
  "//@oxy.so/bloom": "Bloom 11.1.0 adds the shared grouped sections, usage card, subscription plans, frame appearance and overlay navigation APIs used by this SDK. First-party Bloom peers remain open above this tested minimum.",
213
- "//@oxy.so/core": "Core 5.5.0 supplies the shared account-screen translations and updated profile/follow contracts required by this release. Keep one Core instance per app; raise this floor with the root catalogue when new runtime APIs are required. Core 6.0.0 removes only `OxyInferenceClient.decide()` and `getGenerationRecordByIdempotencyKey()` (decisions moved to kaana.ai/v1), which this package never used, so the peer admits both majors (`^5.5.0 || ^6.0.0`) rather than moving the cap.",
213
+ "//@oxy.so/core": "Core 6.1.0 supplies `oxy.auth.email.{startChange,change,remove}` and `oxy.auth.password.remove`, which the sign-in & security panels call, and their translations. Keep one Core instance per app; raise this floor with the root catalogue when new runtime APIs are required.",
214
214
  "peerDependencies": {
215
215
  "@expo/app-integrity": ">=56.0.0 <59.0.0",
216
216
  "@expo/vector-icons": "^15.0.3",
217
217
  "@oxy.so/bloom": ">=11.1.0",
218
- "@oxy.so/core": "^5.5.0 || ^6.0.0",
218
+ "@oxy.so/core": "^6.1.0",
219
219
  "@react-native-async-storage/async-storage": "^2.0.0",
220
220
  "@react-native-community/netinfo": ">=11.4.1 <13.0.0",
221
221
  "@tanstack/query-async-storage-persister": "^5.101",
package/src/index.ts CHANGED
@@ -394,8 +394,13 @@ export type { OxySignUpPanelProps } from './ui/components/signIn/OxySignUpPanel'
394
394
  export { OxyAccountPicker } from './ui/components/signIn/OxyAccountPicker';
395
395
  export type { OxyAccountPickerProps } from './ui/components/signIn/OxyAccountPicker';
396
396
  // The account's own sign-in security, for its settings (the Accounts app, and
397
- // the account dialog's "Manage your account" through the `DeleteAccount`,
398
- // `LinkCommons`, `SignInPassword` and `SignInAuthenticator` routes).
397
+ // the account dialog's "Manage your account" through the `SignInSecurity`,
398
+ // `SignInEmail`, `SignInPassword`, `SignInAuthenticator`, `LinkCommons` and
399
+ // `DeleteAccount` routes).
400
+ export { OxySignInSecurityPanel } from './ui/components/signIn/OxySignInSecurityPanel';
401
+ export type { OxySignInSecurityPanelProps } from './ui/components/signIn/OxySignInSecurityPanel';
402
+ export { OxyEmailPanel } from './ui/components/signIn/OxyEmailPanel';
403
+ export type { OxyEmailPanelProps } from './ui/components/signIn/OxyEmailPanel';
399
404
  export { OxyDeleteAccountPanel } from './ui/components/signIn/OxyDeleteAccountPanel';
400
405
  export type { OxyDeleteAccountPanelProps } from './ui/components/signIn/OxyDeleteAccountPanel';
401
406
  export { OxyLinkCommonsPanel } from './ui/components/signIn/OxyLinkCommonsPanel';
package/src/ui/client.ts CHANGED
@@ -69,7 +69,22 @@ export { useStorage } from './hooks/useStorage';
69
69
  // Realtime events and the profile mutation, which startup code (a socket hook,
70
70
  // a locale provider) needs without the root barrel's account screens.
71
71
  export { useOxyEvent } from './hooks/useOxyEvent';
72
- export { useUpdateProfile } from './hooks/mutations/useAccountMutations';
72
+ // Data hooks a product screen needs (a review's photo upload, a price in the
73
+ // viewer's currency, a "Syncing..." badge) without the root barrel's screens:
74
+ // mercaria.co shipped ~225 KB gzip of account screens on first paint because
75
+ // its review upload could only get `useUploadFile` from the root.
76
+ export {
77
+ useUpdateProfile,
78
+ useUploadAvatar,
79
+ useUploadFile,
80
+ } from './hooks/mutations/useAccountMutations';
81
+ export { useFileDownloadUrl } from './hooks/useFileDownloadUrl';
82
+ export { useMutationStatus } from './hooks/useMutationStatus';
83
+ export type { MutationStatus } from './hooks/useMutationStatus';
84
+ export { useOnlineStatus } from './hooks/useOnlineStatus';
85
+ export { useDisplayCurrency } from './hooks/useDisplayCurrency';
86
+ export { useDisplayPrice } from './hooks/useDisplayPrice';
87
+ export { DisplayCurrencySelector } from './components/DisplayCurrencySelector';
73
88
  export type { UseStorageOptions, UseStorageResult } from './hooks/useStorage';
74
89
 
75
90
  // Route screens live at `@oxy.so/services/screens` so client imports preserve
@@ -23,12 +23,11 @@ import type { TotpEnrollResponse } from '@oxy.so/contracts';
23
23
  import { TOTP_DIGITS } from '@oxy.so/contracts/client';
24
24
  import { useQueryClient } from '@tanstack/react-query';
25
25
  import { useOxy } from '../../context/oxyRuntimeContext';
26
- import { useSignInMethods } from '../../hooks/queries/useAuthMethods';
27
26
  import { queryKeys } from '../../hooks/queries/queryKeys';
28
27
  import { useI18n } from '../../hooks/useI18n';
29
28
  import { copyText } from '../../utils/clipboard';
30
29
  import { SubtleLink } from '../authChooser/primitives';
31
- import { OxyAuthLoading, OxyAuthScreen, OxyAuthScreenHeader } from './OxyAuthScreen';
30
+ import { OxyAuthScreen, OxyAuthScreenHeader } from './OxyAuthScreen';
32
31
  import { ReauthStep } from './ReauthStep';
33
32
  import {
34
33
  AccountFlowAction,
@@ -38,6 +37,7 @@ import {
38
37
  AccountFlowProgress,
39
38
  describeSignInError,
40
39
  } from './accountFlowParts';
40
+ import { accountSecurityFallback, useAccountSecurityState } from './accountSecurityState';
41
41
 
42
42
  /** High-contrast, un-themed on purpose: scan reliability. */
43
43
  const QR_PLATE_BG = '#FFFFFF';
@@ -60,10 +60,9 @@ export interface OxyAuthenticatorPanelProps {
60
60
  export const OxyAuthenticatorPanel: React.FC<OxyAuthenticatorPanelProps> = ({ onDone }) => {
61
61
  const theme = useTheme();
62
62
  const { t } = useI18n();
63
- const { oxyServices, user } = useOxy();
63
+ const { oxyServices } = useOxy();
64
64
  const queryClient = useQueryClient();
65
- const keyed = Boolean(user?.publicKey);
66
- const methods = useSignInMethods({ enabled: !keyed });
65
+ const security = useAccountSecurityState();
67
66
  const [step, setStep] = useState<Step>({ name: 'status' });
68
67
  const [code, setCode] = useState('');
69
68
  const [pending, setPending] = useState(false);
@@ -72,7 +71,7 @@ export const OxyAuthenticatorPanel: React.FC<OxyAuthenticatorPanelProps> = ({ on
72
71
  const refresh = () =>
73
72
  void queryClient.invalidateQueries({ queryKey: queryKeys.signInMethods.all });
74
73
 
75
- if (keyed) {
74
+ if (security.keyed) {
76
75
  return (
77
76
  <OxyAuthScreen>
78
77
  <OxyAuthScreenHeader
@@ -82,8 +81,9 @@ export const OxyAuthenticatorPanel: React.FC<OxyAuthenticatorPanelProps> = ({ on
82
81
  </OxyAuthScreen>
83
82
  );
84
83
  }
85
- if (!methods.data) return <OxyAuthLoading />;
86
- const { hasPassword, totpEnabled, backupCodesRemaining } = methods.data;
84
+ const fallback = accountSecurityFallback(security, t('signInSecurity.totp.title'), t);
85
+ if (fallback || !security.methods.data) return fallback;
86
+ const { hasEmail, hasPassword, totpEnabled, backupCodesRemaining } = security.methods.data;
87
87
 
88
88
  const setUp = () => {
89
89
  if (pending) return;
@@ -157,6 +157,7 @@ export const OxyAuthenticatorPanel: React.FC<OxyAuthenticatorPanelProps> = ({ on
157
157
  description={t('signInSecurity.totp.scan')}
158
158
  action="totp"
159
159
  allowPassword={hasPassword}
160
+ allowEmail={hasEmail}
160
161
  totpEnabled={false}
161
162
  submitLabel={t('signInSecurity.totp.enable')}
162
163
  validate={() =>
@@ -213,6 +214,7 @@ export const OxyAuthenticatorPanel: React.FC<OxyAuthenticatorPanelProps> = ({ on
213
214
  description={t('signInSecurity.totp.regenerateDescription')}
214
215
  action="totp"
215
216
  allowPassword={hasPassword}
217
+ allowEmail={hasEmail}
216
218
  totpEnabled
217
219
  submitLabel={t('signInSecurity.totp.regenerate')}
218
220
  onSubmit={async (reauth) => {
@@ -230,6 +232,7 @@ export const OxyAuthenticatorPanel: React.FC<OxyAuthenticatorPanelProps> = ({ on
230
232
  description={t('signInSecurity.totp.description')}
231
233
  action="totp"
232
234
  allowPassword={hasPassword}
235
+ allowEmail={hasEmail}
233
236
  totpEnabled
234
237
  submitLabel={t('signInSecurity.totp.disable')}
235
238
  destructive
@@ -2,8 +2,9 @@
2
2
  * Deleting an account that has no key of its own, from the account's settings
3
3
  * (the account dialog's "Manage your account", or the Accounts app):
4
4
  *
5
- * type the username → a code sent to the account's email (+ the
6
- * authenticator's code when it has one) → deleted, and signed out
5
+ * type the username → a code sent to the account's email, or its password
6
+ * when it has no email (+ the authenticator's code when it has one) →
7
+ * deleted, and signed out
7
8
  *
8
9
  * An account with a Commons key is deleted with that key — in Commons, or in
9
10
  * an app that holds it (`ManageAccountScreen`); this panel says so instead.
@@ -14,11 +15,11 @@ import type React from 'react';
14
15
  import { useState } from 'react';
15
16
  import { surfaces } from '@oxy.so/bloom/surfaces';
16
17
  import { useOxy } from '../../context/oxyRuntimeContext';
17
- import { useSignInMethods } from '../../hooks/queries/useAuthMethods';
18
18
  import { useI18n } from '../../hooks/useI18n';
19
- import { OxyAuthLoading, OxyAuthScreen, OxyAuthScreenHeader } from './OxyAuthScreen';
19
+ import { OxyAuthScreen, OxyAuthScreenHeader } from './OxyAuthScreen';
20
20
  import { ReauthStep } from './ReauthStep';
21
21
  import { AccountFlowField, AccountFlowNotice } from './accountFlowParts';
22
+ import { accountSecurityFallback, useAccountSecurityState } from './accountSecurityState';
22
23
 
23
24
  export interface OxyDeleteAccountPanelProps {
24
25
  /** The account is gone and this origin signed out of it. */
@@ -33,8 +34,7 @@ export const OxyDeleteAccountPanel: React.FC<OxyDeleteAccountPanelProps> = ({
33
34
  }) => {
34
35
  const { t } = useI18n();
35
36
  const { user, oxyServices, logout } = useOxy();
36
- const keyed = Boolean(user?.publicKey);
37
- const methods = useSignInMethods({ enabled: !keyed });
37
+ const security = useAccountSecurityState();
38
38
  const [confirmText, setConfirmText] = useState('');
39
39
  const [deleted, setDeleted] = useState(false);
40
40
 
@@ -49,7 +49,7 @@ export const OxyDeleteAccountPanel: React.FC<OxyDeleteAccountPanelProps> = ({
49
49
  );
50
50
  }
51
51
 
52
- if (keyed) {
52
+ if (security.keyed) {
53
53
  return (
54
54
  <OxyAuthScreen>
55
55
  <OxyAuthScreenHeader title={t('deleteAccount.handoff.commonsTitle')} />
@@ -60,7 +60,9 @@ export const OxyDeleteAccountPanel: React.FC<OxyDeleteAccountPanelProps> = ({
60
60
  );
61
61
  }
62
62
 
63
- if (!methods.data) return <OxyAuthLoading />;
63
+ const fallback = accountSecurityFallback(security, t('deleteAccount.title'), t);
64
+ if (fallback || !security.methods.data) return fallback;
65
+ const { hasEmail, totpEnabled } = security.methods.data;
64
66
 
65
67
  const username = user?.username ?? '';
66
68
 
@@ -69,14 +71,16 @@ export const OxyDeleteAccountPanel: React.FC<OxyDeleteAccountPanelProps> = ({
69
71
  title={t('deleteAccount.title')}
70
72
  description={t('deleteAccount.keyless.subtitle', { username })}
71
73
  action="delete_account"
72
- totpEnabled={methods.data.totpEnabled}
74
+ // The mailbox proves it when there is one; the password only without.
75
+ allowPassword={!hasEmail}
76
+ allowEmail={hasEmail}
77
+ totpEnabled={totpEnabled}
73
78
  submitLabel={t('deleteAccount.keyless.action')}
74
79
  destructive
75
80
  validate={() =>
76
81
  confirmText.trim() === username ? null : t('deleteAccount.confirmLabel', { username })
77
82
  }
78
83
  onSubmit={async (proof) => {
79
- if (!proof.emailCode) throw new Error(t('reauth.errors.invalid'));
80
84
  // The last word before it is gone: the proof is ready, and nothing has
81
85
  // been sent yet. Cancelling keeps the screen as it is, code and all.
82
86
  const confirmed = await surfaces.confirm({
@@ -87,12 +91,7 @@ export const OxyDeleteAccountPanel: React.FC<OxyDeleteAccountPanelProps> = ({
87
91
  destructive: true,
88
92
  });
89
93
  if (!confirmed) return;
90
- await oxyServices.users.deleteMe(confirmText.trim(), {
91
- reauth: {
92
- emailCode: proof.emailCode,
93
- ...(proof.totpCode ? { totpCode: proof.totpCode } : {}),
94
- },
95
- });
94
+ await oxyServices.users.deleteMe(confirmText.trim(), { reauth: proof });
96
95
  await logout().catch(() => undefined);
97
96
  setDeleted(true);
98
97
  onDeleted?.();
@@ -0,0 +1,258 @@
1
+ /**
2
+ * The account's email, from its settings: add one, change it, or remove it.
3
+ *
4
+ * add / change: the new address → a code sent to IT, plus the person's
5
+ * proof (the password, or a code to the current email; + the
6
+ * authenticator's) → saved, and every other session signed out
7
+ *
8
+ * remove: only with a password set, confirmed with that password (+ the
9
+ * authenticator's) → the account signs in, and is recovered, with its
10
+ * password alone
11
+ *
12
+ * Sign-in codes, links and security notices go to this address. An account
13
+ * with a Commons key has no email; this panel says so instead.
14
+ */
15
+
16
+ import type React from 'react';
17
+ import { useState } from 'react';
18
+ import { toast } from '@oxy.so/bloom/toast';
19
+ import { EMAIL_CODE_LENGTH, checkContract, emailAddressCheck } from '@oxy.so/contracts/client';
20
+ import { useQueryClient } from '@tanstack/react-query';
21
+ import { useOxy } from '../../context/oxyRuntimeContext';
22
+ import { queryKeys } from '../../hooks/queries/queryKeys';
23
+ import { useI18n } from '../../hooks/useI18n';
24
+ import { SubtleLink } from '../authChooser/primitives';
25
+ import { OxyAuthScreen, OxyAuthScreenHeader } from './OxyAuthScreen';
26
+ import { ReauthStep } from './ReauthStep';
27
+ import {
28
+ AccountFlowAction,
29
+ AccountFlowCodeField,
30
+ AccountFlowField,
31
+ AccountFlowNote,
32
+ AccountFlowNotice,
33
+ describeSignInError,
34
+ } from './accountFlowParts';
35
+ import { accountSecurityFallback, useAccountSecurityState } from './accountSecurityState';
36
+
37
+ type Step =
38
+ | { name: 'status' }
39
+ | { name: 'address' }
40
+ | { name: 'confirm'; email: string; verificationId: string }
41
+ | { name: 'remove' };
42
+
43
+ export interface OxyEmailPanelProps {
44
+ /** The email was added, changed or removed. */
45
+ onDone?: () => void;
46
+ }
47
+
48
+ export const OxyEmailPanel: React.FC<OxyEmailPanelProps> = ({ onDone }) => {
49
+ const { t } = useI18n();
50
+ const { oxyServices, user } = useOxy();
51
+ const queryClient = useQueryClient();
52
+ const security = useAccountSecurityState();
53
+ const [step, setStep] = useState<Step>({ name: 'status' });
54
+ const [address, setAddress] = useState('');
55
+ const [code, setCode] = useState('');
56
+ const [pending, setPending] = useState(false);
57
+ const [error, setError] = useState<string | null>(null);
58
+
59
+ if (security.keyed) {
60
+ return (
61
+ <OxyAuthScreen>
62
+ <OxyAuthScreenHeader
63
+ title={t('signInSecurity.email.title')}
64
+ description={t('linkCommons.already')}
65
+ />
66
+ </OxyAuthScreen>
67
+ );
68
+ }
69
+ const fallback = accountSecurityFallback(security, t('signInSecurity.email.title'), t);
70
+ if (fallback || !security.methods.data) return fallback;
71
+ const { hasEmail, hasPassword, totpEnabled } = security.methods.data;
72
+ const current = hasEmail ? (user?.email ?? null) : null;
73
+
74
+ const finish = (message: string) => {
75
+ void queryClient.invalidateQueries({ queryKey: queryKeys.signInMethods.all });
76
+ void queryClient.invalidateQueries({ queryKey: queryKeys.accounts.all });
77
+ toast.success(message);
78
+ setStep({ name: 'status' });
79
+ setAddress('');
80
+ setCode('');
81
+ onDone?.();
82
+ };
83
+
84
+ const sendCode = (email: string) => {
85
+ if (pending) return;
86
+ setError(null);
87
+ setPending(true);
88
+ oxyServices.auth.email
89
+ .startChange(email)
90
+ .then((started) => {
91
+ setCode('');
92
+ setStep({ name: 'confirm', email, verificationId: started.verificationId });
93
+ })
94
+ .catch((reason: unknown) => setError(describeSignInError(reason, t)))
95
+ .finally(() => setPending(false));
96
+ };
97
+
98
+ const submitAddress = () => {
99
+ const email = checkContract(emailAddressCheck, address);
100
+ if (!email) {
101
+ setError(t('signInSecurity.email.invalid'));
102
+ return;
103
+ }
104
+ if (email === current) {
105
+ setError(t('signInSecurity.errors.emailUnchanged'));
106
+ return;
107
+ }
108
+ sendCode(email);
109
+ };
110
+
111
+ switch (step.name) {
112
+ case 'address':
113
+ return (
114
+ <OxyAuthScreen>
115
+ <OxyAuthScreenHeader
116
+ title={hasEmail ? t('signInSecurity.email.change') : t('signInSecurity.email.add')}
117
+ description={t('signInSecurity.email.newDescription')}
118
+ />
119
+ <AccountFlowField
120
+ label={t('signInSecurity.email.newLabel')}
121
+ value={address}
122
+ onChange={(value) => {
123
+ setAddress(value);
124
+ if (error) setError(null);
125
+ }}
126
+ onSubmit={submitAddress}
127
+ error={error}
128
+ disabled={pending}
129
+ autoComplete="email"
130
+ keyboardType="email-address"
131
+ testID="email-new"
132
+ />
133
+ <AccountFlowAction
134
+ label={t('signInSecurity.email.sendCode')}
135
+ onPress={submitAddress}
136
+ pending={pending}
137
+ testID="email-send-code"
138
+ />
139
+ <SubtleLink
140
+ label={t('common.cancel')}
141
+ onPress={() => {
142
+ setError(null);
143
+ setStep({ name: 'status' });
144
+ }}
145
+ disabled={pending}
146
+ testID="email-cancel"
147
+ />
148
+ </OxyAuthScreen>
149
+ );
150
+ case 'confirm':
151
+ return (
152
+ <ReauthStep
153
+ title={t('signInSecurity.email.confirmTitle')}
154
+ description={t('signInSecurity.email.confirmDescription', { email: step.email })}
155
+ action="change_email"
156
+ allowPassword={hasPassword}
157
+ allowEmail={hasEmail}
158
+ totpEnabled={totpEnabled}
159
+ submitLabel={t('signInSecurity.email.save')}
160
+ validate={() =>
161
+ code.replace(/\D/g, '').length === EMAIL_CODE_LENGTH
162
+ ? null
163
+ : t('emailCode.errors.codeInvalid')
164
+ }
165
+ onSubmit={async (reauth) => {
166
+ await oxyServices.auth.email.change({
167
+ email: step.email,
168
+ verificationId: step.verificationId,
169
+ code: code.replace(/\D/g, ''),
170
+ reauth,
171
+ });
172
+ finish(t('signInSecurity.email.saved'));
173
+ }}
174
+ secondary={{ label: t('common.cancel'), onPress: () => setStep({ name: 'status' }) }}
175
+ >
176
+ <AccountFlowCodeField
177
+ label={t('signInSecurity.email.codeLabel')}
178
+ value={code}
179
+ onChange={setCode}
180
+ error={null}
181
+ length={EMAIL_CODE_LENGTH}
182
+ testID="email-new-code"
183
+ />
184
+ <SubtleLink
185
+ label={t('emailCode.resend')}
186
+ onPress={() => sendCode(step.email)}
187
+ disabled={pending}
188
+ testID="email-new-code-resend"
189
+ />
190
+ {error ? (
191
+ <AccountFlowNotice type="error" testID="email-new-code-error">
192
+ {error}
193
+ </AccountFlowNotice>
194
+ ) : null}
195
+ </ReauthStep>
196
+ );
197
+ case 'remove':
198
+ return (
199
+ <ReauthStep
200
+ title={t('signInSecurity.email.removeTitle')}
201
+ description={t('signInSecurity.email.removeDescription')}
202
+ action="change_email"
203
+ // Confirmed with the password it will rely on, never the mailbox it loses.
204
+ allowPassword
205
+ allowEmail={false}
206
+ totpEnabled={totpEnabled}
207
+ submitLabel={t('signInSecurity.email.remove')}
208
+ destructive
209
+ onSubmit={async (reauth) => {
210
+ await oxyServices.auth.email.remove(reauth);
211
+ finish(t('signInSecurity.email.removed'));
212
+ }}
213
+ secondary={{ label: t('common.cancel'), onPress: () => setStep({ name: 'status' }) }}
214
+ />
215
+ );
216
+ default:
217
+ return (
218
+ <OxyAuthScreen>
219
+ <OxyAuthScreenHeader
220
+ title={t('signInSecurity.email.title')}
221
+ description={
222
+ hasEmail
223
+ ? t('signInSecurity.email.description')
224
+ : t('signInSecurity.email.noneDescription')
225
+ }
226
+ />
227
+ {current ? <AccountFlowNote testID="email-current">{current}</AccountFlowNote> : null}
228
+ {!hasEmail ? (
229
+ <AccountFlowNotice type="warning" testID="email-none-warning">
230
+ {t('signInSecurity.noEmailWarning')}
231
+ </AccountFlowNotice>
232
+ ) : null}
233
+ <AccountFlowAction
234
+ label={hasEmail ? t('signInSecurity.email.change') : t('signInSecurity.email.add')}
235
+ onPress={() => {
236
+ setError(null);
237
+ setAddress('');
238
+ setStep({ name: 'address' });
239
+ }}
240
+ pending={false}
241
+ testID="email-change"
242
+ />
243
+ {hasEmail && hasPassword ? (
244
+ <SubtleLink
245
+ label={t('signInSecurity.email.remove')}
246
+ onPress={() => setStep({ name: 'remove' })}
247
+ testID="remove-email-link"
248
+ />
249
+ ) : null}
250
+ {hasEmail && !hasPassword ? (
251
+ <AccountFlowNote testID="email-remove-needs-password">
252
+ {t('signInSecurity.email.removeNeedsPassword')}
253
+ </AccountFlowNote>
254
+ ) : null}
255
+ </OxyAuthScreen>
256
+ );
257
+ }
258
+ };