@oxy.so/services 12.10.1 → 12.11.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.
- package/lib/commonjs/ui/components/accountSettings/AccountCategoriesSection.js +142 -0
- package/lib/commonjs/ui/components/accountSettings/AccountCategoriesSection.js.map +1 -0
- package/lib/commonjs/ui/components/accountSettings/AccountSettings.js +361 -0
- package/lib/commonjs/ui/components/accountSettings/AccountSettings.js.map +1 -0
- package/lib/commonjs/ui/hooks/useAvatarPicker.js +54 -48
- package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +16 -237
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ChangeAvatarScreen.js +23 -4
- package/lib/commonjs/ui/screens/ChangeAvatarScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/index.js +7 -0
- package/lib/commonjs/ui/screens/index.js.map +1 -1
- package/lib/module/ui/components/accountSettings/AccountCategoriesSection.js +134 -0
- package/lib/module/ui/components/accountSettings/AccountCategoriesSection.js.map +1 -0
- package/lib/module/ui/components/accountSettings/AccountSettings.js +355 -0
- package/lib/module/ui/components/accountSettings/AccountSettings.js.map +1 -0
- package/lib/module/ui/hooks/useAvatarPicker.js +53 -48
- package/lib/module/ui/hooks/useAvatarPicker.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +16 -235
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/ChangeAvatarScreen.js +23 -4
- package/lib/module/ui/screens/ChangeAvatarScreen.js.map +1 -1
- package/lib/module/ui/screens/index.js +4 -0
- package/lib/module/ui/screens/index.js.map +1 -1
- package/lib/typescript/commonjs/ui/components/accountSettings/AccountCategoriesSection.d.ts +26 -0
- package/lib/typescript/commonjs/ui/components/accountSettings/AccountCategoriesSection.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/accountSettings/AccountSettings.d.ts +80 -0
- package/lib/typescript/commonjs/ui/components/accountSettings/AccountSettings.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/useAvatarPicker.d.ts +22 -1
- package/lib/typescript/commonjs/ui/hooks/useAvatarPicker.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AccountSettingsScreen.d.ts +4 -5
- package/lib/typescript/commonjs/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/ChangeAvatarScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/index.d.ts +1 -0
- package/lib/typescript/commonjs/ui/screens/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/accountSettings/AccountCategoriesSection.d.ts +26 -0
- package/lib/typescript/module/ui/components/accountSettings/AccountCategoriesSection.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/accountSettings/AccountSettings.d.ts +80 -0
- package/lib/typescript/module/ui/components/accountSettings/AccountSettings.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts +22 -1
- package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AccountSettingsScreen.d.ts +4 -5
- package/lib/typescript/module/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/ChangeAvatarScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/index.d.ts +1 -0
- package/lib/typescript/module/ui/screens/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/ui/components/accountSettings/AccountCategoriesSection.tsx +180 -0
- package/src/ui/components/accountSettings/AccountSettings.tsx +421 -0
- package/src/ui/components/accountSettings/__tests__/AccountSettings.test.tsx +101 -0
- package/src/ui/hooks/useAvatarPicker.ts +65 -69
- package/src/ui/screens/AccountSettingsScreen.tsx +13 -277
- package/src/ui/screens/ChangeAvatarScreen.tsx +25 -6
- package/src/ui/screens/index.ts +8 -0
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import type { BaseScreenProps } from '../types/navigation';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* graph.
|
|
4
|
+
* The `AccountSettings` surface: {@link AccountSettings} for the `accountId`
|
|
5
|
+
* route prop, under the surface's own header. Self-surface for the caller's own
|
|
6
|
+
* personal account lives in {@link ManageAccountScreen}; this screen manages a
|
|
7
|
+
* non-personal account in the graph.
|
|
9
8
|
*/
|
|
10
9
|
declare const AccountSettingsScreen: React.FC<BaseScreenProps>;
|
|
11
10
|
export default AccountSettingsScreen;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountSettingsScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/AccountSettingsScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"AccountSettingsScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/AccountSettingsScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAQ3D;;;;;GAKG;AACH,QAAA,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAmBpD,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChangeAvatarScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/ChangeAvatarScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsB/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"ChangeAvatarScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/ChangeAvatarScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsB/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAY3D;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,IAAI,CAAC;CACf;AAgFD,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAkPjD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -17,4 +17,5 @@ export { default as AccountMembersScreen } from './AccountMembersScreen';
|
|
|
17
17
|
export { default as AccountSettingsScreen } from './AccountSettingsScreen';
|
|
18
18
|
export { default as SupervisionScreen } from './SupervisionScreen';
|
|
19
19
|
export { default as OxyOneScreen } from './OxyOneScreen';
|
|
20
|
+
export { AccountSettings, type AccountSettingsProps, type AccountSettingsArchiveOptions, } from '../components/accountSettings/AccountSettings';
|
|
20
21
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAE3E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAE3E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAIzD,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,6BAA6B,GACnC,MAAM,+CAA+C,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { type AccountCategoryId } from '@oxy.so/core';
|
|
3
|
+
/**
|
|
4
|
+
* An account's categories are an ORDERED list whose element 0 is the primary —
|
|
5
|
+
* nothing else records which one is. So nothing here sorts: a choice joins at
|
|
6
|
+
* the end (choosing a second category must not demote the first), "Make
|
|
7
|
+
* primary" moves one to the front, and two lists are equal only in the same
|
|
8
|
+
* order (a promotion changes nothing BUT the order).
|
|
9
|
+
*/
|
|
10
|
+
export declare function toggleAccountCategory(current: readonly AccountCategoryId[], id: AccountCategoryId): AccountCategoryId[];
|
|
11
|
+
export declare function promoteAccountCategory(current: readonly AccountCategoryId[], id: AccountCategoryId): AccountCategoryId[];
|
|
12
|
+
export declare function accountCategoriesEqual(a: readonly AccountCategoryId[], b: readonly AccountCategoryId[]): boolean;
|
|
13
|
+
interface AccountCategoriesSectionProps {
|
|
14
|
+
value: readonly AccountCategoryId[];
|
|
15
|
+
onChange: (next: AccountCategoryId[]) => void;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The categories editor of `AccountSettings`: the chosen categories in their
|
|
20
|
+
* stored order (primary first), and a collapsible list of the vocabulary to add
|
|
21
|
+
* from. Only SELECTABLE ids are offered — a withdrawn one stays on an account
|
|
22
|
+
* that carries it, but Oxy refuses newly adding it.
|
|
23
|
+
*/
|
|
24
|
+
export declare const AccountCategoriesSection: React.FC<AccountCategoriesSectionProps>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=AccountCategoriesSection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccountCategoriesSection.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/accountSettings/AccountCategoriesSection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,EAKL,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AAKtB;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,iBAAiB,EAAE,EACrC,EAAE,EAAE,iBAAiB,GACpB,iBAAiB,EAAE,CAIrB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,SAAS,iBAAiB,EAAE,EACrC,EAAE,EAAE,iBAAiB,GACpB,iBAAiB,EAAE,CAGrB;AAED,wBAAgB,sBAAsB,CACpC,CAAC,EAAE,SAAS,iBAAiB,EAAE,EAC/B,CAAC,EAAE,SAAS,iBAAiB,EAAE,GAC9B,OAAO,CAET;AASD,UAAU,6BAA6B;IACrC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACpC,QAAQ,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,IAAI,CAAC;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC,6BAA6B,CAgH5E,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { type AccountNode, type User } from '@oxy.so/core';
|
|
4
|
+
import { type ClearableUserField } from '../../hooks/queries/userCache.js';
|
|
5
|
+
import type { BaseScreenProps } from '../../types/navigation.js';
|
|
6
|
+
/**
|
|
7
|
+
* How archiving the account behaves, for an app whose ending of an account
|
|
8
|
+
* means more than Oxy's archive.
|
|
9
|
+
*/
|
|
10
|
+
export interface AccountSettingsArchiveOptions {
|
|
11
|
+
/** The danger-zone row's title, replacing "Archive account". */
|
|
12
|
+
title?: string;
|
|
13
|
+
/**
|
|
14
|
+
* The row's subtitle. With a `title` of its own the row shows only this
|
|
15
|
+
* (nothing when omitted), never Oxy's subtitle under the app's title.
|
|
16
|
+
*/
|
|
17
|
+
description?: string;
|
|
18
|
+
/** The danger-zone section's footer. */
|
|
19
|
+
footer?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Replaces the default confirmation. Resolve `false` to back out; a rejection
|
|
22
|
+
* is reported as an archive failure and nothing is archived.
|
|
23
|
+
*/
|
|
24
|
+
confirm?: (node: AccountNode) => Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Runs after the confirmation and BEFORE Oxy archives the account — for an
|
|
27
|
+
* app's own data that has to go while the account still resolves. A
|
|
28
|
+
* rejection stops the archive and is reported as an archive failure.
|
|
29
|
+
*/
|
|
30
|
+
beforeArchive?: (node: AccountNode) => Promise<void>;
|
|
31
|
+
/** After the archive, in place of closing the surface. */
|
|
32
|
+
onArchived?: (node: AccountNode) => void;
|
|
33
|
+
/** The success toast, replacing "Account archived". */
|
|
34
|
+
successMessage?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface AccountSettingsProps {
|
|
37
|
+
accountId: string;
|
|
38
|
+
/**
|
|
39
|
+
* The app's own sections for this account, rendered after the account's
|
|
40
|
+
* profile, categories and members, and before the danger zone.
|
|
41
|
+
*/
|
|
42
|
+
extraSections?: ReactNode;
|
|
43
|
+
/**
|
|
44
|
+
* After each accepted profile write — name, bio, picture, categories — with
|
|
45
|
+
* the account Oxy returned and the fields the write cleared. The SDK's user
|
|
46
|
+
* cache already holds the change; this is for an app's own copies of the
|
|
47
|
+
* identity (posts that embed it, for example).
|
|
48
|
+
*/
|
|
49
|
+
onUpdated?: (account: User, change: {
|
|
50
|
+
cleared: ClearableUserField[];
|
|
51
|
+
}) => void;
|
|
52
|
+
archive?: AccountSettingsArchiveOptions;
|
|
53
|
+
/**
|
|
54
|
+
* The host surface's navigation, for the SDK routes this opens (Members).
|
|
55
|
+
* Omitted when the settings are embedded in an app's own page, and those
|
|
56
|
+
* routes open as a sheet.
|
|
57
|
+
*/
|
|
58
|
+
navigate?: BaseScreenProps['navigate'];
|
|
59
|
+
/** Called after an archive when `archive.onArchived` is not given. */
|
|
60
|
+
onClose?: () => void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The account-graph node {@link AccountSettings} edits — seeded from the
|
|
64
|
+
* session's account list, then read fresh. `node` is `null` until it resolves.
|
|
65
|
+
*/
|
|
66
|
+
export declare function useAccountSettingsNode(accountId: string): {
|
|
67
|
+
query: import("@tanstack/react-query").UseQueryResult<AccountNode, Error>;
|
|
68
|
+
node: AccountNode | null;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* A non-personal account's settings: its picture, name, bio and categories,
|
|
72
|
+
* its members, and archiving it. The one editor for every member-operated
|
|
73
|
+
* account — the `AccountSettings` surface renders it, and an app embeds it in
|
|
74
|
+
* its own page (`@oxy.so/services/screens`) with its own sections and archive
|
|
75
|
+
* steps around it. Oxy decides what the caller may do from the membership it
|
|
76
|
+
* resolved, so every section is shown only to a member who holds its right.
|
|
77
|
+
*/
|
|
78
|
+
export declare const AccountSettings: React.FC<AccountSettingsProps>;
|
|
79
|
+
export default AccountSettings;
|
|
80
|
+
//# sourceMappingURL=AccountSettings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccountSettings.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/accountSettings/AccountSettings.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAYvC,OAAO,EAQL,KAAK,WAAW,EAEhB,KAAK,IAAI,EACV,MAAM,cAAc,CAAC;AAItB,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,kCAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAAwB,CAAC;AAW9D;;;GAGG;AACH,MAAM,WAAW,6BAA6B;IAC5C,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,0DAA0D;IAC1D,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACzC,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE;QAAE,OAAO,EAAE,kBAAkB,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/E,OAAO,CAAC,EAAE,6BAA6B,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACvC,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM;;;EAYvD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAoS1D,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* Avatar Picker Hook
|
|
3
3
|
*
|
|
4
4
|
* The ONE write path for a user's profile picture. It owns no UI: the whole
|
|
5
|
-
* choose-and-crop experience is a single surface.
|
|
5
|
+
* choose-and-crop experience is a single surface. The choosing half —
|
|
6
|
+
* {@link pickAvatarFile} — is account-agnostic and also serves a managed
|
|
7
|
+
* account's picture (`AccountSettings`), so there is one picker, one cropper and
|
|
8
|
+
* one upload for every account an app can edit.
|
|
6
9
|
*
|
|
7
10
|
* Flow (typed promise over the shared surface stack — no callback props):
|
|
8
11
|
* 1. `openWithinOrPresent('ChangeAvatar')` opens the source list (device gallery,
|
|
@@ -27,6 +30,24 @@ interface UseAvatarPickerOptions {
|
|
|
27
30
|
activeSessionId: string | null;
|
|
28
31
|
queryClient: QueryClient;
|
|
29
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Whose picture the picker is changing, when it is not the signed-in user's —
|
|
35
|
+
* the source list previews it and offers "Remove" only when there is one.
|
|
36
|
+
*/
|
|
37
|
+
export interface AvatarPickerSubject {
|
|
38
|
+
avatar?: string | null;
|
|
39
|
+
displayName?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The shared choose-and-crop flow, then the crop uploaded as a NEW public file.
|
|
43
|
+
*
|
|
44
|
+
* Resolves the new file's id, `null` when the person chose to remove the
|
|
45
|
+
* picture, or `undefined` when they backed out. It writes no account: the
|
|
46
|
+
* caller decides whose picture the file becomes, which is what lets the
|
|
47
|
+
* signed-in user's profile and a managed account share every step before that.
|
|
48
|
+
* An upload failure rejects.
|
|
49
|
+
*/
|
|
50
|
+
export declare function pickAvatarFile(oxyServices: OxyServices, subject?: AvatarPickerSubject): Promise<string | null | undefined>;
|
|
30
51
|
export declare function useAvatarPicker({ oxyServices, currentLanguage, activeSessionId, queryClient, }: UseAvatarPickerOptions): {
|
|
31
52
|
openAvatarPicker: () => Promise<void>;
|
|
32
53
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAvatarPicker.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useAvatarPicker.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"useAvatarPicker.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useAvatarPicker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKzD,UAAU,sBAAsB;IAC9B,WAAW,EAAE,WAAW,CAAC;IACzB,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;CAC1B;AAkBD;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAmBpC;AAED,wBAAgB,eAAe,CAAC,EAC9B,WAAW,EACX,eAAe,EACf,eAAe,EACf,WAAW,GACZ,EAAE,sBAAsB;;EA2BxB"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import type { BaseScreenProps } from '../types/navigation.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* graph.
|
|
4
|
+
* The `AccountSettings` surface: {@link AccountSettings} for the `accountId`
|
|
5
|
+
* route prop, under the surface's own header. Self-surface for the caller's own
|
|
6
|
+
* personal account lives in {@link ManageAccountScreen}; this screen manages a
|
|
7
|
+
* non-personal account in the graph.
|
|
9
8
|
*/
|
|
10
9
|
declare const AccountSettingsScreen: React.FC<BaseScreenProps>;
|
|
11
10
|
export default AccountSettingsScreen;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountSettingsScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/AccountSettingsScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"AccountSettingsScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/AccountSettingsScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;AAQ3D;;;;;GAKG;AACH,QAAA,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAmBpD,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChangeAvatarScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/ChangeAvatarScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsB/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"ChangeAvatarScreen.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/ChangeAvatarScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsB/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;AAY3D;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,IAAI,CAAC;CACf;AAgFD,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAkPjD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -17,4 +17,5 @@ export { default as AccountMembersScreen } from './AccountMembersScreen.js';
|
|
|
17
17
|
export { default as AccountSettingsScreen } from './AccountSettingsScreen.js';
|
|
18
18
|
export { default as SupervisionScreen } from './SupervisionScreen.js';
|
|
19
19
|
export { default as OxyOneScreen } from './OxyOneScreen.js';
|
|
20
|
+
export { AccountSettings, type AccountSettingsProps, type AccountSettingsArchiveOptions, } from '../components/accountSettings/AccountSettings.js';
|
|
20
21
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,oBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,wBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,2BAAwB,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,4BAAyB,CAAC;AAE3E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,wBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ui/screens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,oBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,wBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,2BAAwB,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,4BAAyB,CAAC;AAE3E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,wBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAgB,CAAC;AAIzD,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,6BAA6B,GACnC,MAAM,kDAA+C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxy.so/services",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.11.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",
|
|
@@ -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.
|
|
163
|
+
"@oxy.so/core": "6.13.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 6.12.0 supplies `fileManagement.contentLost` and the `lost` file status a lost file is listed with; 6.11.0 supplies the `follow.errors.*` strings the follow error codes are worded with; 6.4.0 the `follow.*` strings the follow buttons read for every verb and language; 6.1.0 the `oxy.auth.email.{startChange,change,remove}` and `oxy.auth.password.remove` the sign-in & security panels call. Keep one Core instance per app; raise this floor with the root catalogue when new runtime APIs are required.",
|
|
213
|
+
"//@oxy.so/core": "Core 6.13.0 supplies the `accounts.settings.*` strings (picture, categories) the account settings speak in every language; 6.12.0 supplies `fileManagement.contentLost` and the `lost` file status a lost file is listed with; 6.11.0 supplies the `follow.errors.*` strings the follow error codes are worded with; 6.4.0 the `follow.*` strings the follow buttons read for every verb and language; 6.1.0 the `oxy.auth.email.{startChange,change,remove}` and `oxy.auth.password.remove` the sign-in & security panels call. 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": "^6.
|
|
218
|
+
"@oxy.so/core": "^6.13.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",
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { useCallback, useState } from 'react';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
import { Button, CloseButton } from '@oxy.so/bloom/button';
|
|
5
|
+
import { GroupedSection, GroupedSectionItem } from '@oxy.so/bloom/grouped-section';
|
|
6
|
+
import { useTheme } from '@oxy.so/bloom/theme';
|
|
7
|
+
import {
|
|
8
|
+
ACCOUNT_CATEGORY_IDS,
|
|
9
|
+
MAX_ACCOUNT_CATEGORIES,
|
|
10
|
+
SELECTABLE_ACCOUNT_CATEGORY_IDS,
|
|
11
|
+
accountCategoryLabel,
|
|
12
|
+
type AccountCategoryId,
|
|
13
|
+
} from '@oxy.so/core';
|
|
14
|
+
import MaterialCommunityIcons from '../../icons/MaterialCommunityIcons';
|
|
15
|
+
import { SettingsIcon } from '../SettingsIcon';
|
|
16
|
+
import { useI18n } from '../../hooks/useI18n';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* An account's categories are an ORDERED list whose element 0 is the primary —
|
|
20
|
+
* nothing else records which one is. So nothing here sorts: a choice joins at
|
|
21
|
+
* the end (choosing a second category must not demote the first), "Make
|
|
22
|
+
* primary" moves one to the front, and two lists are equal only in the same
|
|
23
|
+
* order (a promotion changes nothing BUT the order).
|
|
24
|
+
*/
|
|
25
|
+
export function toggleAccountCategory(
|
|
26
|
+
current: readonly AccountCategoryId[],
|
|
27
|
+
id: AccountCategoryId,
|
|
28
|
+
): AccountCategoryId[] {
|
|
29
|
+
if (current.includes(id)) return current.filter((entry) => entry !== id);
|
|
30
|
+
if (current.length >= MAX_ACCOUNT_CATEGORIES) return [...current];
|
|
31
|
+
return [...current, id];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function promoteAccountCategory(
|
|
35
|
+
current: readonly AccountCategoryId[],
|
|
36
|
+
id: AccountCategoryId,
|
|
37
|
+
): AccountCategoryId[] {
|
|
38
|
+
if (!current.includes(id)) return [...current];
|
|
39
|
+
return [id, ...current.filter((entry) => entry !== id)];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function accountCategoriesEqual(
|
|
43
|
+
a: readonly AccountCategoryId[],
|
|
44
|
+
b: readonly AccountCategoryId[],
|
|
45
|
+
): boolean {
|
|
46
|
+
return a.length === b.length && a.every((entry, index) => entry === b[index]);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A stored id can be one this build has never heard of — the vocabulary grows
|
|
51
|
+
* at Oxy, and an older client meets the newer id. It keeps its row (it counts
|
|
52
|
+
* against the cap and survives a save) but is never printed raw.
|
|
53
|
+
*/
|
|
54
|
+
const KNOWN_IDS: ReadonlySet<string> = new Set(ACCOUNT_CATEGORY_IDS);
|
|
55
|
+
|
|
56
|
+
interface AccountCategoriesSectionProps {
|
|
57
|
+
value: readonly AccountCategoryId[];
|
|
58
|
+
onChange: (next: AccountCategoryId[]) => void;
|
|
59
|
+
disabled?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The categories editor of `AccountSettings`: the chosen categories in their
|
|
64
|
+
* stored order (primary first), and a collapsible list of the vocabulary to add
|
|
65
|
+
* from. Only SELECTABLE ids are offered — a withdrawn one stays on an account
|
|
66
|
+
* that carries it, but Oxy refuses newly adding it.
|
|
67
|
+
*/
|
|
68
|
+
export const AccountCategoriesSection: React.FC<AccountCategoriesSectionProps> = ({
|
|
69
|
+
value,
|
|
70
|
+
onChange,
|
|
71
|
+
disabled = false,
|
|
72
|
+
}) => {
|
|
73
|
+
const { colors } = useTheme();
|
|
74
|
+
const { t, locale } = useI18n();
|
|
75
|
+
const [pickerOpen, setPickerOpen] = useState(false);
|
|
76
|
+
const atCap = value.length >= MAX_ACCOUNT_CATEGORIES;
|
|
77
|
+
|
|
78
|
+
const labelOf = useCallback(
|
|
79
|
+
(id: AccountCategoryId) =>
|
|
80
|
+
KNOWN_IDS.has(id)
|
|
81
|
+
? accountCategoryLabel(locale, id)
|
|
82
|
+
: t('accounts.settings.categories.unavailable'),
|
|
83
|
+
[locale, t],
|
|
84
|
+
);
|
|
85
|
+
const toggle = useCallback(
|
|
86
|
+
(id: AccountCategoryId) => onChange(toggleAccountCategory(value, id)),
|
|
87
|
+
[onChange, value],
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<View className="gap-space-8">
|
|
92
|
+
<GroupedSection
|
|
93
|
+
title={t('accounts.settings.categories.title')}
|
|
94
|
+
footer={t('accounts.settings.categories.footer', { max: MAX_ACCOUNT_CATEGORIES })}
|
|
95
|
+
>
|
|
96
|
+
{value.map((id, index) => {
|
|
97
|
+
const label = labelOf(id);
|
|
98
|
+
return (
|
|
99
|
+
<GroupedSectionItem
|
|
100
|
+
key={id}
|
|
101
|
+
icon={
|
|
102
|
+
<SettingsIcon
|
|
103
|
+
name={index === 0 ? 'star' : 'tag-outline'}
|
|
104
|
+
color={index === 0 ? colors.primary : colors.textSecondary}
|
|
105
|
+
/>
|
|
106
|
+
}
|
|
107
|
+
title={label}
|
|
108
|
+
description={index === 0 ? t('accounts.settings.categories.primary') : undefined}
|
|
109
|
+
showChevron={false}
|
|
110
|
+
disabled={disabled}
|
|
111
|
+
rightElement={
|
|
112
|
+
<View className="flex-row items-center gap-space-8">
|
|
113
|
+
{index > 0 ? (
|
|
114
|
+
<Button
|
|
115
|
+
appearance="subtle"
|
|
116
|
+
size="xs"
|
|
117
|
+
disabled={disabled}
|
|
118
|
+
onPress={() => onChange(promoteAccountCategory(value, id))}
|
|
119
|
+
>
|
|
120
|
+
{t('accounts.settings.categories.makePrimary')}
|
|
121
|
+
</Button>
|
|
122
|
+
) : null}
|
|
123
|
+
<CloseButton
|
|
124
|
+
size="xs"
|
|
125
|
+
disabled={disabled}
|
|
126
|
+
onPress={() => toggle(id)}
|
|
127
|
+
accessibilityLabel={t('accounts.settings.categories.remove', {
|
|
128
|
+
category: label,
|
|
129
|
+
})}
|
|
130
|
+
/>
|
|
131
|
+
</View>
|
|
132
|
+
}
|
|
133
|
+
/>
|
|
134
|
+
);
|
|
135
|
+
})}
|
|
136
|
+
<GroupedSectionItem
|
|
137
|
+
icon={<SettingsIcon name="plus" color={colors.textSecondary} />}
|
|
138
|
+
title={t('accounts.settings.categories.add')}
|
|
139
|
+
description={
|
|
140
|
+
atCap
|
|
141
|
+
? t('accounts.settings.categories.atCap', { max: MAX_ACCOUNT_CATEGORIES })
|
|
142
|
+
: undefined
|
|
143
|
+
}
|
|
144
|
+
disabled={disabled || atCap}
|
|
145
|
+
showChevron={false}
|
|
146
|
+
rightElement={
|
|
147
|
+
<MaterialCommunityIcons
|
|
148
|
+
name={pickerOpen ? 'chevron-up' : 'chevron-down'}
|
|
149
|
+
size={20}
|
|
150
|
+
color={colors.textSecondary}
|
|
151
|
+
/>
|
|
152
|
+
}
|
|
153
|
+
onPress={() => setPickerOpen((open) => !open)}
|
|
154
|
+
/>
|
|
155
|
+
</GroupedSection>
|
|
156
|
+
|
|
157
|
+
{pickerOpen && !atCap ? (
|
|
158
|
+
<GroupedSection>
|
|
159
|
+
{SELECTABLE_ACCOUNT_CATEGORY_IDS.map((id) => {
|
|
160
|
+
const selected = value.includes(id);
|
|
161
|
+
return (
|
|
162
|
+
<GroupedSectionItem
|
|
163
|
+
key={id}
|
|
164
|
+
title={accountCategoryLabel(locale, id)}
|
|
165
|
+
showChevron={false}
|
|
166
|
+
disabled={disabled}
|
|
167
|
+
rightElement={
|
|
168
|
+
selected ? (
|
|
169
|
+
<MaterialCommunityIcons name="check-circle" size={20} color={colors.primary} />
|
|
170
|
+
) : undefined
|
|
171
|
+
}
|
|
172
|
+
onPress={() => toggle(id)}
|
|
173
|
+
/>
|
|
174
|
+
);
|
|
175
|
+
})}
|
|
176
|
+
</GroupedSection>
|
|
177
|
+
) : null}
|
|
178
|
+
</View>
|
|
179
|
+
);
|
|
180
|
+
};
|