@oxyhq/services 26.0.0 → 26.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.
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/AvatarCameraBadge.js +2 -2
- package/lib/commonjs/ui/components/AvatarCameraBadge.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAuthChooser.js +20 -16
- package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/commonjs/ui/components/ProfileButton.js +19 -25
- package/lib/commonjs/ui/components/ProfileButton.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js +88 -73
- package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/primitives.js +9 -9
- package/lib/commonjs/ui/components/authChooser/primitives.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/types.js.map +1 -1
- package/lib/commonjs/ui/hooks/useAuth.js +4 -2
- package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
- package/lib/commonjs/ui/navigation/accountDialogManager.js +2 -0
- package/lib/commonjs/ui/navigation/accountDialogManager.js.map +1 -1
- package/lib/commonjs/ui/screens/CreateAccountScreen.js +11 -1
- package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/AvatarCameraBadge.js +1 -1
- package/lib/module/ui/components/AvatarCameraBadge.js.map +1 -1
- package/lib/module/ui/components/OxyAuthChooser.js +20 -16
- package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/module/ui/components/ProfileButton.js +10 -16
- package/lib/module/ui/components/ProfileButton.js.map +1 -1
- package/lib/module/ui/components/authChooser/AccountsMenuView.js +69 -54
- package/lib/module/ui/components/authChooser/AccountsMenuView.js.map +1 -1
- package/lib/module/ui/components/authChooser/primitives.js +1 -1
- package/lib/module/ui/components/authChooser/primitives.js.map +1 -1
- package/lib/module/ui/components/authChooser/types.js.map +1 -1
- package/lib/module/ui/hooks/useAuth.js +4 -2
- package/lib/module/ui/hooks/useAuth.js.map +1 -1
- package/lib/module/ui/navigation/accountDialogManager.js +2 -0
- package/lib/module/ui/navigation/accountDialogManager.js.map +1 -1
- package/lib/module/ui/screens/CreateAccountScreen.js +11 -1
- package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +1 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/AvatarCameraBadge.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts +3 -0
- package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts +6 -0
- package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts +6 -4
- package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts +8 -0
- package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +1 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/AvatarCameraBadge.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ProfileButton.d.ts +3 -0
- package/lib/typescript/module/ui/components/ProfileButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts +1 -1
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/types.d.ts +6 -0
- package/lib/typescript/module/ui/components/authChooser/types.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useAuth.d.ts +6 -4
- package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts +8 -0
- package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/package.json +16 -7
- package/src/index.ts +1 -0
- package/src/ui/components/AvatarCameraBadge.tsx +2 -1
- package/src/ui/components/OxyAuthChooser.tsx +17 -16
- package/src/ui/components/ProfileButton.tsx +10 -18
- package/src/ui/components/authChooser/AccountsMenuView.tsx +66 -52
- package/src/ui/components/authChooser/primitives.tsx +1 -1
- package/src/ui/components/authChooser/types.ts +6 -0
- package/src/ui/hooks/useAuth.ts +8 -4
- package/src/ui/navigation/accountDialogManager.ts +9 -0
- package/src/ui/screens/CreateAccountScreen.tsx +12 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/authChooser/primitives.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,SAAS,EAAQ,MAAM,
|
|
1
|
+
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/authChooser/primitives.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,SAAS,EAAQ,MAAM,6BAA6B,CAAC;AAK9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAA8B,KAAK,KAAK,EAAE,MAAM,YAAS,CAAC;AAKjE,KAAK,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,EAAE,WAAW,CAAC,GAAG;IACrF,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAcxD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAWA,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAMhE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;IAChC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAgDA,CAAC"}
|
|
@@ -56,6 +56,12 @@ export interface AccountsMenuActions {
|
|
|
56
56
|
onPrivacy: () => void;
|
|
57
57
|
onTerms: () => void;
|
|
58
58
|
onSignOut: () => void;
|
|
59
|
+
customItems: readonly {
|
|
60
|
+
key: string;
|
|
61
|
+
label: string;
|
|
62
|
+
icon?: string;
|
|
63
|
+
onPress: () => void;
|
|
64
|
+
}[];
|
|
59
65
|
}
|
|
60
66
|
/**
|
|
61
67
|
* Where a WebAuthn ceremony can run from the current origin.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/authChooser/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAsC,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC1G,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAqB,CAAC;AAEnD,MAAM,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAChD,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC;AAExD;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,iFAAiF;AACjF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,oFAAoF;AACpF,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,yFAAyF;AACzF,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/authChooser/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAsC,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC1G,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAqB,CAAC;AAEnD,MAAM,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAChD,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC;AAExD;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,iFAAiF;AACjF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,oFAAoF;AACpF,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,yFAAyF;AACzF,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,EAAE,SAAS;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,EAAE,CAAC;CACL;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,gBAAgB,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,uEAAuE;IACvE,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,uEAAuE;IACvE,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,uCAAuC;IACvC,eAAe,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG/E;AAED,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,SAAS,CAKvE"}
|
|
@@ -66,8 +66,8 @@ export interface AuthState {
|
|
|
66
66
|
export interface AuthActions {
|
|
67
67
|
/**
|
|
68
68
|
* Sign in
|
|
69
|
-
* - Web:
|
|
70
|
-
*
|
|
69
|
+
* - Web + native: opens the in-app Oxy account dialog (`openAccountDialog('signin')`).
|
|
70
|
+
* Never navigates to auth.oxy.so — that origin is third-party OAuth only.
|
|
71
71
|
*
|
|
72
72
|
* @param publicKey - Native: identity public key. Ignored on web.
|
|
73
73
|
*/
|
|
@@ -88,6 +88,8 @@ export interface AuthActions {
|
|
|
88
88
|
export interface UseAuthReturn extends AuthState, AuthActions {
|
|
89
89
|
/** Access to full OxyServices instance for advanced usage */
|
|
90
90
|
oxyServices: ReturnType<typeof useOxy>['oxyServices'];
|
|
91
|
+
/** Switch the device session to another account on this device */
|
|
92
|
+
switchToAccount: ReturnType<typeof useOxy>['switchToAccount'];
|
|
91
93
|
/** Open a bottom sheet screen (e.g. 'ManageAccount', 'FileManagement') */
|
|
92
94
|
showBottomSheet: ReturnType<typeof useOxy>['showBottomSheet'];
|
|
93
95
|
/** Open the avatar picker bottom sheet */
|
|
@@ -99,8 +101,8 @@ export interface UseAuthReturn extends AuthState, AuthActions {
|
|
|
99
101
|
* Features:
|
|
100
102
|
* - Zero config: Just wrap with OxyProvider and use
|
|
101
103
|
* - Cross-platform: Same API on native and web
|
|
102
|
-
* - Auto session restore:
|
|
103
|
-
*
|
|
104
|
+
* - Auto session restore: device-first cold boot (`deviceId` + `deviceSecret` mint);
|
|
105
|
+
* never auto-redirects to the IdP
|
|
104
106
|
* - Type-safe: Full TypeScript support
|
|
105
107
|
*/
|
|
106
108
|
export declare function useAuth(): UseAuthReturn;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useAuth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,0BAAuB,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,MAAM,WAAW,SAAS;IACxB,4DAA4D;IAC5D,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAElB,oCAAoC;IACpC,eAAe,EAAE,OAAO,CAAC;IAEzB,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAC;IAEnB,oDAAoD;IACpD,OAAO,EAAE,OAAO,CAAC;IAEjB,+EAA+E;IAC/E,cAAc,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,mBAAmB,EAAE,OAAO,CAAC;IAE7B;;;;;;;;;OASG;IACH,cAAc,EAAE,OAAO,CAAC;IAExB,oCAAoC;IACpC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;OAEG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B;;OAEG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhC;;OAEG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS,EAAE,WAAW;IAC3D,6DAA6D;IAC7D,WAAW,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC;IACtD,0EAA0E;IAC1E,eAAe,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC9D,0CAA0C;IAC1C,gBAAgB,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;CACjE;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,IAAI,aAAa,
|
|
1
|
+
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useAuth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,0BAAuB,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,MAAM,WAAW,SAAS;IACxB,4DAA4D;IAC5D,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAElB,oCAAoC;IACpC,eAAe,EAAE,OAAO,CAAC;IAEzB,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAC;IAEnB,oDAAoD;IACpD,OAAO,EAAE,OAAO,CAAC;IAEjB,+EAA+E;IAC/E,cAAc,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,mBAAmB,EAAE,OAAO,CAAC;IAE7B;;;;;;;;;OASG;IACH,cAAc,EAAE,OAAO,CAAC;IAExB,oCAAoC;IACpC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;OAEG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B;;OAEG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhC;;OAEG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS,EAAE,WAAW;IAC3D,6DAA6D;IAC7D,WAAW,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC;IACtD,kEAAkE;IAClE,eAAe,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC9D,0EAA0E;IAC1E,eAAe,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC9D,0CAA0C;IAC1C,gBAAgB,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;CACjE;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,IAAI,aAAa,CAqFvC"}
|
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
* view) from a non-React call site.
|
|
11
11
|
*/
|
|
12
12
|
import type { AccountDialogView } from '@oxyhq/core';
|
|
13
|
+
/** An app-owned action rendered inside the shared account menu. */
|
|
14
|
+
export interface AccountDialogMenuItem {
|
|
15
|
+
key: string;
|
|
16
|
+
label: string;
|
|
17
|
+
icon?: string;
|
|
18
|
+
onPress: () => void;
|
|
19
|
+
}
|
|
13
20
|
/**
|
|
14
21
|
* Live open/close handles registered by the mounted provider. `open` presents
|
|
15
22
|
* the `AccountDialog` surface (and points its view); `close` dismisses it. Both
|
|
@@ -28,6 +35,7 @@ export interface AccountDialogConsumerHooks {
|
|
|
28
35
|
onNavigateManage?: () => void;
|
|
29
36
|
onAddAccount?: () => void;
|
|
30
37
|
onNavigateProfile?: () => void;
|
|
38
|
+
menuItems?: readonly AccountDialogMenuItem[];
|
|
31
39
|
}
|
|
32
40
|
export declare function registerAccountDialogControls(next: AccountDialogControls): () => void;
|
|
33
41
|
/** Register app-local manage/add/profile handlers for the account dialog. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accountDialogManager.d.ts","sourceRoot":"","sources":["../../../../../src/ui/navigation/accountDialogManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACzC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"accountDialogManager.d.ts","sourceRoot":"","sources":["../../../../../src/ui/navigation/accountDialogManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,mEAAmE;AACnE,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACzC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;CAC9C;AAMD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,IAAI,CAOrF;AAED,6EAA6E;AAC7E,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,0BAA0B,GAAG,IAAI,GACtC,MAAM,IAAI,CAOZ;AAED,wBAAgB,6BAA6B,IAAI,0BAA0B,GAAG,IAAI,CAEjF;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAEhE;AAED,oDAAoD;AACpD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,sFAAsF;AACtF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAIpE;AAED,sDAAsD;AACtD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAKzF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateAccountScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/CreateAccountScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"CreateAccountScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/CreateAccountScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;AA2F3D;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA+SlD,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxyhq/services",
|
|
3
|
-
"version": "26.0.
|
|
3
|
+
"version": "26.0.3",
|
|
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",
|
|
@@ -138,8 +138,8 @@
|
|
|
138
138
|
}
|
|
139
139
|
},
|
|
140
140
|
"dependencies": {
|
|
141
|
-
"@oxyhq/contracts": "0.
|
|
142
|
-
"@oxyhq/core": "^17.0.
|
|
141
|
+
"@oxyhq/contracts": "0.21.0",
|
|
142
|
+
"@oxyhq/core": "^17.0.2",
|
|
143
143
|
"@simplewebauthn/browser": "^13.3.0",
|
|
144
144
|
"color": "^4.2.3"
|
|
145
145
|
},
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
"@commitlint/cli": "^21.2.1",
|
|
149
149
|
"@commitlint/config-conventional": "^21.2.0",
|
|
150
150
|
"@expo/vector-icons": "^15.0.3",
|
|
151
|
-
"@oxyhq/core": "17.0.
|
|
151
|
+
"@oxyhq/core": "17.0.2",
|
|
152
152
|
"@react-native-async-storage/async-storage": "^2.0.0",
|
|
153
153
|
"@react-native-community/netinfo": "^11.4.1",
|
|
154
154
|
"@react-native/babel-preset": "^0.86.0",
|
|
@@ -169,12 +169,13 @@
|
|
|
169
169
|
"expo-image": "~57.0.1",
|
|
170
170
|
"expo-linear-gradient": "~57.0.1",
|
|
171
171
|
"expo-notifications": "~57.0.5",
|
|
172
|
+
"expo-web-browser": "~57.0.1",
|
|
172
173
|
"husky": "^4.3.8",
|
|
173
174
|
"jest": "~29.7.0",
|
|
174
175
|
"lint-staged": "^15.2.4",
|
|
175
176
|
"nativewind": "5.0.0-preview.3",
|
|
176
177
|
"react-native-builder-bob": "^0.43.0",
|
|
177
|
-
"react-native-css": "^3.0.
|
|
178
|
+
"react-native-css": "^3.0.6",
|
|
178
179
|
"react-native-gesture-handler": "~2.32.0",
|
|
179
180
|
"react-native-keyboard-controller": "1.21.13",
|
|
180
181
|
"react-native-qrcode-svg": "^6.3.0",
|
|
@@ -190,7 +191,7 @@
|
|
|
190
191
|
"peerDependencies": {
|
|
191
192
|
"@expo/vector-icons": "^15.0.3",
|
|
192
193
|
"@oxyhq/bloom": ">=0.59.0",
|
|
193
|
-
"@oxyhq/core": "^17.0.
|
|
194
|
+
"@oxyhq/core": "^17.0.2",
|
|
194
195
|
"@react-native-async-storage/async-storage": "^2.0.0",
|
|
195
196
|
"@react-native-community/netinfo": ">=11.4.1",
|
|
196
197
|
"@tanstack/query-async-storage-persister": "^5.101",
|
|
@@ -208,9 +209,11 @@
|
|
|
208
209
|
"expo-image-manipulator": ">=56.0.0",
|
|
209
210
|
"expo-image-picker": ">=56.0.0",
|
|
210
211
|
"expo-linear-gradient": ">=56.0.0",
|
|
211
|
-
"expo-notifications": ">=56.0.0",
|
|
212
212
|
"expo-modules-core": "*",
|
|
213
|
+
"expo-notifications": ">=56.0.0",
|
|
214
|
+
"expo-web-browser": ">=56.0.0",
|
|
213
215
|
"nativewind": ">=5.0.0",
|
|
216
|
+
"react-native-css": "^3.0.6",
|
|
214
217
|
"react": ">=18.0.0",
|
|
215
218
|
"react-native": ">=0.85.0",
|
|
216
219
|
"react-native-gesture-handler": ">=2.31.1",
|
|
@@ -226,6 +229,9 @@
|
|
|
226
229
|
"nativewind": {
|
|
227
230
|
"optional": true
|
|
228
231
|
},
|
|
232
|
+
"react-native-css": {
|
|
233
|
+
"optional": true
|
|
234
|
+
},
|
|
229
235
|
"expo-modules-core": {
|
|
230
236
|
"optional": true
|
|
231
237
|
},
|
|
@@ -264,6 +270,9 @@
|
|
|
264
270
|
},
|
|
265
271
|
"expo-image-picker": {
|
|
266
272
|
"optional": true
|
|
273
|
+
},
|
|
274
|
+
"expo-web-browser": {
|
|
275
|
+
"optional": true
|
|
267
276
|
}
|
|
268
277
|
},
|
|
269
278
|
"react-native-builder-bob": {
|
package/src/index.ts
CHANGED
|
@@ -275,6 +275,7 @@ export { LogoText } from './ui/components/logo/LogoText';
|
|
|
275
275
|
// `useOxy().openAccountDialog`.
|
|
276
276
|
export { default as ProfileButton } from './ui/components/ProfileButton';
|
|
277
277
|
export type { ProfileButtonProps } from './ui/components/ProfileButton';
|
|
278
|
+
export type { AccountDialogMenuItem } from './ui/navigation/accountDialogManager';
|
|
278
279
|
|
|
279
280
|
// The account switcher/sign-in/sign-up chooser WITHOUT dialog chrome — the
|
|
280
281
|
// surface stack presents `OxyAccountDialogScreen` (which renders this) into
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import type { ViewStyle } from 'react-native';
|
|
3
|
+
import { View } from 'react-native-css/components';
|
|
3
4
|
import Ionicons from '@expo/vector-icons/Ionicons';
|
|
4
5
|
import { useTheme } from '@oxyhq/bloom/theme';
|
|
5
6
|
|
|
@@ -220,25 +220,19 @@ const OxyAuthChooser: React.FC<OxyAuthChooserProps> = ({
|
|
|
220
220
|
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
221
221
|
const { view } = snapshot;
|
|
222
222
|
|
|
223
|
-
const [switching, setSwitching] = useState(false);
|
|
224
|
-
|
|
225
223
|
const handleSwitch = useCallback(
|
|
226
224
|
async (accountId: string) => {
|
|
227
|
-
if (!controller
|
|
228
|
-
if (
|
|
225
|
+
if (!controller) return;
|
|
226
|
+
if (controller.getSnapshot().switchingAccountId) return;
|
|
227
|
+
if (accountId === controller.getSnapshot().activeAccountId) {
|
|
229
228
|
onComplete?.();
|
|
230
229
|
return;
|
|
231
230
|
}
|
|
232
|
-
setSwitching(true);
|
|
233
231
|
try {
|
|
234
232
|
await controller.switchTo(accountId);
|
|
235
|
-
// `switchTo`
|
|
236
|
-
//
|
|
237
|
-
//
|
|
238
|
-
// and NOT a snapshot-reaction). On success reload the app's account
|
|
239
|
-
// graph and drop cached account-scoped data so the new active identity
|
|
240
|
-
// re-fetches — the same side effects the context's own
|
|
241
|
-
// `switchToAccount` performs.
|
|
233
|
+
// `switchTo` records failures on the controller snapshot. Read that
|
|
234
|
+
// state after the operation so the same path works with both the real
|
|
235
|
+
// controller and framework test doubles that return void.
|
|
242
236
|
if (controller.getSnapshot().error) {
|
|
243
237
|
toast.error(t('accountSwitcher.toasts.switchFailed'));
|
|
244
238
|
return;
|
|
@@ -246,11 +240,11 @@ const OxyAuthChooser: React.FC<OxyAuthChooserProps> = ({
|
|
|
246
240
|
void refreshAccounts();
|
|
247
241
|
queryClient.invalidateQueries();
|
|
248
242
|
onComplete?.();
|
|
249
|
-
}
|
|
250
|
-
|
|
243
|
+
} catch {
|
|
244
|
+
// `switchTo` is documented as non-throwing; guard against regressions.
|
|
251
245
|
}
|
|
252
246
|
},
|
|
253
|
-
[controller,
|
|
247
|
+
[controller, onComplete, refreshAccounts, queryClient, t],
|
|
254
248
|
);
|
|
255
249
|
|
|
256
250
|
const handleManage = useCallback(() => {
|
|
@@ -317,7 +311,7 @@ const OxyAuthChooser: React.FC<OxyAuthChooserProps> = ({
|
|
|
317
311
|
// Real storage usage for the account menu's "Oxy storage" block. Disabled
|
|
318
312
|
// (no fetch) until a private-API session exists, so it is inert on the
|
|
319
313
|
// sign-in/request/sign-up views; when present the block shows live used/total.
|
|
320
|
-
const storageQuery = useAccountStorageUsage();
|
|
314
|
+
const storageQuery = useAccountStorageUsage({ enabled: view === 'accounts' });
|
|
321
315
|
const storage = useMemo<AccountStorageModel | null>(
|
|
322
316
|
() =>
|
|
323
317
|
storageQuery.data
|
|
@@ -354,6 +348,13 @@ const OxyAuthChooser: React.FC<OxyAuthChooserProps> = ({
|
|
|
354
348
|
void logout();
|
|
355
349
|
onComplete?.();
|
|
356
350
|
},
|
|
351
|
+
customItems: (getAccountDialogConsumerHooks()?.menuItems ?? []).map((item) => ({
|
|
352
|
+
...item,
|
|
353
|
+
onPress: () => {
|
|
354
|
+
onComplete?.();
|
|
355
|
+
item.onPress();
|
|
356
|
+
},
|
|
357
|
+
})),
|
|
357
358
|
};
|
|
358
359
|
}, [onComplete, showBottomSheet, logout]);
|
|
359
360
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import {
|
|
4
|
-
View,
|
|
5
|
-
Pressable,
|
|
6
4
|
StyleSheet,
|
|
7
5
|
Platform,
|
|
8
6
|
type StyleProp,
|
|
9
7
|
type ViewStyle,
|
|
10
8
|
} from 'react-native';
|
|
9
|
+
import { View, Pressable } from 'react-native-css/components';
|
|
11
10
|
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
|
|
12
11
|
import { Avatar } from '@oxyhq/bloom/avatar';
|
|
13
12
|
import * as Skeleton from '@oxyhq/bloom/skeleton';
|
|
@@ -18,6 +17,7 @@ import { useAuth } from '../hooks/useAuth';
|
|
|
18
17
|
import { useOxy } from '../context/OxyContext';
|
|
19
18
|
import { useI18n } from '../hooks/useI18n';
|
|
20
19
|
import { registerAccountDialogConsumerHooks } from '../navigation/accountDialogManager';
|
|
20
|
+
import type { AccountDialogMenuItem } from '../navigation/accountDialogManager';
|
|
21
21
|
|
|
22
22
|
const isWeb = Platform.OS === 'web';
|
|
23
23
|
|
|
@@ -30,7 +30,6 @@ const isWeb = Platform.OS === 'web';
|
|
|
30
30
|
*/
|
|
31
31
|
const BG_TRANSITION_MS = 150;
|
|
32
32
|
const AVATAR_TRANSITION_MS = 250;
|
|
33
|
-
const OPACITY_TRANSITION_MS = 150;
|
|
34
33
|
const LEAVE_DELAY_MS = 50;
|
|
35
34
|
|
|
36
35
|
/** Shrunk-avatar scale on hover, matching Bluesky's `scale: 2/3`. */
|
|
@@ -64,6 +63,8 @@ export interface ProfileButtonProps {
|
|
|
64
63
|
onAddAccount?: () => void;
|
|
65
64
|
/** Optional: navigate to the signed-in user's own profile. */
|
|
66
65
|
onNavigateProfile?: () => void;
|
|
66
|
+
/** App-owned actions rendered in the shared account menu. */
|
|
67
|
+
menuItems?: readonly AccountDialogMenuItem[];
|
|
67
68
|
/**
|
|
68
69
|
* Retained for source compatibility. The trigger now opens the unified
|
|
69
70
|
* `OxyAccountDialogScreen` (a centered / bottom-sheet modal) rather than an
|
|
@@ -106,6 +107,7 @@ const ProfileButton: React.FC<ProfileButtonProps> = ({
|
|
|
106
107
|
onNavigateManage,
|
|
107
108
|
onAddAccount,
|
|
108
109
|
onNavigateProfile,
|
|
110
|
+
menuItems,
|
|
109
111
|
className,
|
|
110
112
|
style,
|
|
111
113
|
}) => {
|
|
@@ -139,8 +141,9 @@ const ProfileButton: React.FC<ProfileButtonProps> = ({
|
|
|
139
141
|
onNavigateManage,
|
|
140
142
|
onAddAccount,
|
|
141
143
|
onNavigateProfile,
|
|
144
|
+
menuItems,
|
|
142
145
|
});
|
|
143
|
-
}, [onNavigateManage, onAddAccount, onNavigateProfile]);
|
|
146
|
+
}, [onNavigateManage, onAddAccount, onNavigateProfile, menuItems]);
|
|
144
147
|
|
|
145
148
|
const avatarUrl = useMemo(
|
|
146
149
|
() => (user?.avatar ? oxyServices.getFileDownloadUrl(user.avatar, 'thumb') : undefined),
|
|
@@ -301,22 +304,11 @@ const ProfileButton: React.FC<ProfileButtonProps> = ({
|
|
|
301
304
|
}
|
|
302
305
|
: undefined;
|
|
303
306
|
|
|
307
|
+
// Expanded mode always shows identity + chevron (console/inbox wide sidebar).
|
|
308
|
+
// Hover only animates the row background and avatar shrink — not text visibility.
|
|
304
309
|
const identityStyle: ViewStyle | undefined = isWeb
|
|
305
310
|
? {
|
|
306
311
|
marginLeft: -resolvedAvatarSize / 2,
|
|
307
|
-
opacity: active ? 1 : 0,
|
|
308
|
-
transitionProperty: 'opacity',
|
|
309
|
-
transitionDuration: `${OPACITY_TRANSITION_MS}ms`,
|
|
310
|
-
transitionDelay: active ? '0ms' : `${LEAVE_DELAY_MS}ms`,
|
|
311
|
-
}
|
|
312
|
-
: undefined;
|
|
313
|
-
|
|
314
|
-
const chevronStyle: ViewStyle | undefined = isWeb
|
|
315
|
-
? {
|
|
316
|
-
opacity: active ? 1 : 0,
|
|
317
|
-
transitionProperty: 'opacity',
|
|
318
|
-
transitionDuration: `${OPACITY_TRANSITION_MS}ms`,
|
|
319
|
-
transitionDelay: active ? '0ms' : `${LEAVE_DELAY_MS}ms`,
|
|
320
312
|
}
|
|
321
313
|
: undefined;
|
|
322
314
|
|
|
@@ -346,7 +338,7 @@ const ProfileButton: React.FC<ProfileButtonProps> = ({
|
|
|
346
338
|
</Text>
|
|
347
339
|
) : null}
|
|
348
340
|
</View>
|
|
349
|
-
<View
|
|
341
|
+
<View>
|
|
350
342
|
<MaterialCommunityIcons
|
|
351
343
|
name="dots-horizontal"
|
|
352
344
|
size={18}
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
import type React from 'react';
|
|
27
27
|
import { Fragment, useCallback, useState } from 'react';
|
|
28
|
-
import { Pressable, View } from 'react-native';
|
|
28
|
+
import { Pressable, View } from 'react-native-css/components';
|
|
29
29
|
import Animated, {
|
|
30
30
|
Extrapolation,
|
|
31
31
|
interpolate,
|
|
@@ -212,6 +212,7 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
212
212
|
// compact header it is not represented anywhere else once the hero moved out
|
|
213
213
|
// of the card, and the list is where you switch back to it.
|
|
214
214
|
const switchableAccounts = current ? [current, ...others] : others;
|
|
215
|
+
const switchableAccountKey = switchableAccounts.map((account) => account.accountId).join(':');
|
|
215
216
|
const facepile: AvatarGroupItem[] = switchableAccounts.map((account) => ({
|
|
216
217
|
id: account.accountId,
|
|
217
218
|
uri: account.avatarUrl ?? undefined,
|
|
@@ -381,61 +382,66 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
381
382
|
{/* SWITCH ACCOUNT — own NativeWind card, NOT a Bloom grouped section: it
|
|
382
383
|
is a disclosure header over an animated list, not a list of settings
|
|
383
384
|
rows, and the grouped section is not a bare card container. */}
|
|
384
|
-
<
|
|
385
|
-
<
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
385
|
+
<View className="mb-space-16">
|
|
386
|
+
<Animated.View style={[{ overflow: 'hidden' }, switchCardStyle]}>
|
|
387
|
+
<View className="bg-fill">
|
|
388
|
+
<HoverPressable
|
|
389
|
+
baseClassName={`flex-row items-center gap-space-12 px-space-12 py-[10px] min-h-[44px]${
|
|
390
|
+
switchingDisabled ? ' opacity-60' : ''
|
|
391
|
+
}`}
|
|
392
|
+
hoverClassName="bg-fill-secondary"
|
|
393
|
+
onPress={toggleExpanded}
|
|
394
|
+
disabled={switchingDisabled}
|
|
395
|
+
accessibilityRole="button"
|
|
396
|
+
// The ARIA prop, not `accessibilityState`: react-native-web 0.21
|
|
397
|
+
// forwards only this one, and RN maps it to
|
|
398
|
+
// `accessibilityState.expanded` natively — so the disclosure state
|
|
399
|
+
// reaches assistive tech on BOTH platforms.
|
|
400
|
+
aria-expanded={expanded}
|
|
401
|
+
accessibilityLabel={switchLabel}
|
|
402
|
+
>
|
|
403
|
+
<Text className="flex-1 text-body text-text" numberOfLines={1}>
|
|
404
|
+
{switchLabel}
|
|
405
|
+
</Text>
|
|
406
|
+
{/* The facepile previews who you can switch to; once the list is open
|
|
407
|
+
it would just restate the rows below it. */}
|
|
408
|
+
{expanded ? null : (
|
|
409
|
+
<AvatarGroup
|
|
410
|
+
items={facepile}
|
|
411
|
+
layout="stack"
|
|
412
|
+
size={FACEPILE_AVATAR_SIZE}
|
|
413
|
+
max={FACEPILE_MAX}
|
|
414
|
+
overlap={FACEPILE_OVERLAP}
|
|
415
|
+
variant="thumb"
|
|
416
|
+
showInitials
|
|
417
|
+
ringColor={theme.colors.card}
|
|
418
|
+
/>
|
|
419
|
+
)}
|
|
420
|
+
<View style={[styles.chevronCircle, { backgroundColor: theme.colors.contrast50 }]}>
|
|
421
|
+
<Animated.View style={chevronStyle}>
|
|
422
|
+
<MaterialCommunityIcons name="chevron-down" size={20} color={theme.colors.text} />
|
|
423
|
+
</Animated.View>
|
|
424
|
+
</View>
|
|
425
|
+
</HoverPressable>
|
|
423
426
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
>
|
|
431
|
-
<View
|
|
432
|
-
style={styles.collapseMeasure}
|
|
433
|
-
onLayout={(event) => setListContentHeight(event.nativeEvent.layout.height)}
|
|
427
|
+
{/* Animated reveal: an overflow-clipped container whose height + opacity
|
|
428
|
+
are driven by `listProgress`; the inner style-based wrapper measures
|
|
429
|
+
the natural content height via `onLayout`. */}
|
|
430
|
+
<Animated.View
|
|
431
|
+
style={[styles.collapse, listStyle]}
|
|
432
|
+
pointerEvents={expanded ? 'auto' : 'none'}
|
|
434
433
|
>
|
|
435
|
-
<View
|
|
434
|
+
<View
|
|
435
|
+
key={switchableAccountKey}
|
|
436
|
+
style={styles.collapseMeasure}
|
|
437
|
+
onLayout={(event) => setListContentHeight(event.nativeEvent.layout.height)}
|
|
438
|
+
>
|
|
439
|
+
<View>{listItems}</View>
|
|
440
|
+
</View>
|
|
441
|
+
</Animated.View>
|
|
436
442
|
</View>
|
|
437
443
|
</Animated.View>
|
|
438
|
-
</
|
|
444
|
+
</View>
|
|
439
445
|
|
|
440
446
|
{/* OXY STORAGE — own NativeWind card for the same reason: a title, a meter
|
|
441
447
|
and two chips are not settings rows. Its cloud sits in the same 20px
|
|
@@ -484,6 +490,14 @@ const AccountsMenuView: React.FC<AccountsMenuViewProps> = ({
|
|
|
484
490
|
title={t('accountMenu.help')}
|
|
485
491
|
onPress={menu.onHelp}
|
|
486
492
|
/>
|
|
493
|
+
{menu.customItems.map((item) => (
|
|
494
|
+
<SettingsListItem
|
|
495
|
+
key={item.key}
|
|
496
|
+
icon={<MenuIcon name={(item.icon ?? 'dots-horizontal') as keyof typeof MaterialCommunityIcons.glyphMap} theme={theme} />}
|
|
497
|
+
title={item.label}
|
|
498
|
+
onPress={item.onPress}
|
|
499
|
+
/>
|
|
500
|
+
))}
|
|
487
501
|
<SettingsListItem
|
|
488
502
|
icon={<MenuIcon name="logout" theme={theme} />}
|
|
489
503
|
title={t('accountMenu.signOut')}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import type React from 'react';
|
|
8
8
|
import { useState } from 'react';
|
|
9
|
-
import { Pressable, View } from 'react-native';
|
|
9
|
+
import { Pressable, View } from 'react-native-css/components';
|
|
10
10
|
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
|
|
11
11
|
import { Avatar } from '@oxyhq/bloom/avatar';
|
|
12
12
|
import { Text } from '@oxyhq/bloom/typography';
|
package/src/ui/hooks/useAuth.ts
CHANGED
|
@@ -79,8 +79,8 @@ export interface AuthState {
|
|
|
79
79
|
export interface AuthActions {
|
|
80
80
|
/**
|
|
81
81
|
* Sign in
|
|
82
|
-
* - Web:
|
|
83
|
-
*
|
|
82
|
+
* - Web + native: opens the in-app Oxy account dialog (`openAccountDialog('signin')`).
|
|
83
|
+
* Never navigates to auth.oxy.so — that origin is third-party OAuth only.
|
|
84
84
|
*
|
|
85
85
|
* @param publicKey - Native: identity public key. Ignored on web.
|
|
86
86
|
*/
|
|
@@ -105,6 +105,8 @@ export interface AuthActions {
|
|
|
105
105
|
export interface UseAuthReturn extends AuthState, AuthActions {
|
|
106
106
|
/** Access to full OxyServices instance for advanced usage */
|
|
107
107
|
oxyServices: ReturnType<typeof useOxy>['oxyServices'];
|
|
108
|
+
/** Switch the device session to another account on this device */
|
|
109
|
+
switchToAccount: ReturnType<typeof useOxy>['switchToAccount'];
|
|
108
110
|
/** Open a bottom sheet screen (e.g. 'ManageAccount', 'FileManagement') */
|
|
109
111
|
showBottomSheet: ReturnType<typeof useOxy>['showBottomSheet'];
|
|
110
112
|
/** Open the avatar picker bottom sheet */
|
|
@@ -117,8 +119,8 @@ export interface UseAuthReturn extends AuthState, AuthActions {
|
|
|
117
119
|
* Features:
|
|
118
120
|
* - Zero config: Just wrap with OxyProvider and use
|
|
119
121
|
* - Cross-platform: Same API on native and web
|
|
120
|
-
* - Auto session restore:
|
|
121
|
-
*
|
|
122
|
+
* - Auto session restore: device-first cold boot (`deviceId` + `deviceSecret` mint);
|
|
123
|
+
* never auto-redirects to the IdP
|
|
122
124
|
* - Type-safe: Full TypeScript support
|
|
123
125
|
*/
|
|
124
126
|
export function useAuth(): UseAuthReturn {
|
|
@@ -137,6 +139,7 @@ export function useAuth(): UseAuthReturn {
|
|
|
137
139
|
logoutAll,
|
|
138
140
|
refreshSessions,
|
|
139
141
|
oxyServices,
|
|
142
|
+
switchToAccount,
|
|
140
143
|
hasIdentity,
|
|
141
144
|
getPublicKey,
|
|
142
145
|
showBottomSheet,
|
|
@@ -201,6 +204,7 @@ export function useAuth(): UseAuthReturn {
|
|
|
201
204
|
|
|
202
205
|
// Advanced
|
|
203
206
|
oxyServices,
|
|
207
|
+
switchToAccount,
|
|
204
208
|
showBottomSheet,
|
|
205
209
|
openAvatarPicker,
|
|
206
210
|
};
|
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
|
|
13
13
|
import type { AccountDialogView } from '@oxyhq/core';
|
|
14
14
|
|
|
15
|
+
/** An app-owned action rendered inside the shared account menu. */
|
|
16
|
+
export interface AccountDialogMenuItem {
|
|
17
|
+
key: string;
|
|
18
|
+
label: string;
|
|
19
|
+
icon?: string;
|
|
20
|
+
onPress: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
/**
|
|
16
24
|
* Live open/close handles registered by the mounted provider. `open` presents
|
|
17
25
|
* the `AccountDialog` surface (and points its view); `close` dismisses it. Both
|
|
@@ -31,6 +39,7 @@ export interface AccountDialogConsumerHooks {
|
|
|
31
39
|
onNavigateManage?: () => void;
|
|
32
40
|
onAddAccount?: () => void;
|
|
33
41
|
onNavigateProfile?: () => void;
|
|
42
|
+
menuItems?: readonly AccountDialogMenuItem[];
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
let controls: AccountDialogControls | null = null;
|
|
@@ -17,8 +17,18 @@ import { toast } from '@oxyhq/bloom/toast';
|
|
|
17
17
|
|
|
18
18
|
type UsernameStatus = 'idle' | 'checking' | 'available' | 'taken' | 'invalid';
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Kind of account this screen can create.
|
|
22
|
+
*
|
|
23
|
+
* A strict subset of what `POST /accounts` accepts, not `Exclude<AccountKind,
|
|
24
|
+
* 'personal'>`: this screen SWITCHES INTO the account it just created, so it can
|
|
25
|
+
* only offer kinds an operator may act as. `personal` is a signup-minted root,
|
|
26
|
+
* and a `channel` is a content identity nobody occupies — creating one is
|
|
27
|
+
* Mention's job, through the API. Spelling the subset out here is what keeps a
|
|
28
|
+
* newly-added kind from silently inheriting the `project` label in
|
|
29
|
+
* {@link kindLabel}'s fallback.
|
|
30
|
+
*/
|
|
31
|
+
type CreatableAccountKind = Extract<AccountKind, 'organization' | 'project' | 'bot'>;
|
|
22
32
|
|
|
23
33
|
const USERNAME_REGEX = /^[a-zA-Z0-9_-]{3,30}$/;
|
|
24
34
|
const DEBOUNCE_MS = 400;
|