@oxy.so/services 4.0.4 → 4.0.5
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/android/src/main/java/so/oxy/identity/OxyIdentityStore.kt +8 -7
- package/android/src/main/java/so/oxy/storage/OxyEncryptedPrefs.kt +41 -97
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js +5 -3
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAuthChooser.js +33 -23
- package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/SignInEntryView.js +9 -0
- package/lib/commonjs/ui/components/authChooser/SignInEntryView.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/primitives.js +16 -7
- package/lib/commonjs/ui/components/authChooser/primitives.js.map +1 -1
- package/lib/commonjs/ui/hooks/accountDialogSnapshot.js +1 -0
- package/lib/commonjs/ui/hooks/accountDialogSnapshot.js.map +1 -1
- package/lib/module/ui/components/OxyAccountDialogScreen.js +5 -3
- package/lib/module/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/module/ui/components/OxyAuthChooser.js +33 -23
- package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/module/ui/components/authChooser/SignInEntryView.js +9 -0
- package/lib/module/ui/components/authChooser/SignInEntryView.js.map +1 -1
- package/lib/module/ui/components/authChooser/primitives.js +16 -7
- package/lib/module/ui/components/authChooser/primitives.js.map +1 -1
- package/lib/module/ui/hooks/accountDialogSnapshot.js +1 -0
- package/lib/module/ui/hooks/accountDialogSnapshot.js.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts +6 -0
- package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts +8 -0
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/accountDialogSnapshot.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +1 -0
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts +6 -0
- package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts +8 -0
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/accountDialogSnapshot.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +1 -0
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/ui/components/OxyAccountDialogScreen.tsx +5 -3
- package/src/ui/components/OxyAuthChooser.tsx +33 -23
- package/src/ui/components/authChooser/SignInEntryView.tsx +13 -0
- package/src/ui/components/authChooser/primitives.tsx +20 -8
- package/src/ui/hooks/accountDialogSnapshot.ts +1 -0
|
@@ -169,30 +169,40 @@ const OxyAuthChooser: React.FC<OxyAuthChooserProps> = ({ onComplete }) => {
|
|
|
169
169
|
const handleActivate = useCallback(
|
|
170
170
|
async (contextId: string) => {
|
|
171
171
|
if (!controller) return;
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
172
|
+
// The controller decides what choosing a row MEANS. Signed in it is a
|
|
173
|
+
// switch; signed out it is "Continue as @handle" — the same sign-in
|
|
174
|
+
// "Continue with Oxy" runs. The signed-out case is why this is not a
|
|
175
|
+
// host-side "already active → close": the device can list an identity
|
|
176
|
+
// (Commons') as active while THIS app holds no session, and closing on it
|
|
177
|
+
// left the app signed out behind a sheet that looked done (#1375 item 20).
|
|
178
|
+
const outcome = await controller.chooseContext(contextId).catch(() => 'failed' as const);
|
|
179
|
+
switch (outcome) {
|
|
180
|
+
// Another switch or removal is already changing this device: the press
|
|
181
|
+
// is dropped, not queued — and it is not a failure to report.
|
|
182
|
+
case 'busy':
|
|
183
|
+
return;
|
|
184
|
+
// The sign-in flow owns the rest: its own view while it runs, and the
|
|
185
|
+
// dialog's close (through `onSignedIn`) when it completes.
|
|
186
|
+
case 'signing-in':
|
|
187
|
+
return;
|
|
188
|
+
// Already live: activating it again bumps nothing server-side, so treat
|
|
189
|
+
// the press as "yes, this one" and close.
|
|
190
|
+
case 'current':
|
|
191
|
+
onComplete?.();
|
|
192
|
+
return;
|
|
193
|
+
// The controller's own verdict on the SWITCH — never `snapshot.error`,
|
|
194
|
+
// which the directory re-read after a successful switch can also set.
|
|
195
|
+
case 'failed':
|
|
196
|
+
toast.error(t('accountSwitcher.toasts.activateFailed'));
|
|
197
|
+
return;
|
|
198
|
+
case 'switched':
|
|
199
|
+
// The subject changed, so every account-scoped query is now about
|
|
200
|
+
// somebody else. The runtime resets its own caches between the bearer
|
|
201
|
+
// commit and the notify; this drops the Query cache the same way.
|
|
202
|
+
queryClient.invalidateQueries();
|
|
203
|
+
onComplete?.();
|
|
204
|
+
return;
|
|
189
205
|
}
|
|
190
|
-
// The subject changed, so every account-scoped query is now about
|
|
191
|
-
// somebody else. The runtime resets its own caches between the bearer
|
|
192
|
-
// commit and the notify; this drops the Query cache the same way the
|
|
193
|
-
// account switch did.
|
|
194
|
-
queryClient.invalidateQueries();
|
|
195
|
-
onComplete?.();
|
|
196
206
|
},
|
|
197
207
|
[controller, onComplete, queryClient, t],
|
|
198
208
|
);
|
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Existing accounts still render ABOVE the CTA: "continue as one of these" is a
|
|
15
15
|
* choice of WHO, not of HOW.
|
|
16
|
+
*
|
|
17
|
+
* Signed in (the "Add another account" entry), a row is an account to switch
|
|
18
|
+
* to, and the current one carries its check. Signed out, nothing here is
|
|
19
|
+
* current: the device may still list an identity it holds (Commons' shared
|
|
20
|
+
* one), but THIS app has no session, so each row reads "Continue as @handle"
|
|
21
|
+
* and choosing it signs in (OxyHQ/oxy#1375 items 20 and 21).
|
|
16
22
|
*/
|
|
17
23
|
|
|
18
24
|
import type React from 'react';
|
|
@@ -90,6 +96,13 @@ const SignInEntryView: React.FC<SignInEntryViewProps> = ({
|
|
|
90
96
|
key={context.contextId}
|
|
91
97
|
context={context}
|
|
92
98
|
operatedBy={operatedBy}
|
|
99
|
+
continueAsLabel={
|
|
100
|
+
snapshot.hasSession
|
|
101
|
+
? null
|
|
102
|
+
: t('signin.chooser.continueAs', {
|
|
103
|
+
name: context.handle ? `@${context.handle}` : context.displayName,
|
|
104
|
+
})
|
|
105
|
+
}
|
|
93
106
|
theme={theme}
|
|
94
107
|
activating={snapshot.activatingContextId === context.contextId}
|
|
95
108
|
disabled={snapshot.activatingContextId !== null}
|
|
@@ -96,19 +96,31 @@ export const Dividerish: React.FC<{ theme: Theme; label: string }> = ({ theme, l
|
|
|
96
96
|
* directory), not from the theme and not from whoever is signed in. This surface
|
|
97
97
|
* is where a device holding two people is most visible, and it is reached while
|
|
98
98
|
* signed out — so there is no "current user" whose colour could stand in.
|
|
99
|
+
*
|
|
100
|
+
* `continueAsLabel` is the signed-out form. The device can list an identity
|
|
101
|
+
* (and even mark it active) while this app holds no session, so a check there
|
|
102
|
+
* would claim a sign-in that has not happened. Given a label, the row never
|
|
103
|
+
* reads as current: its first line is "Continue as @handle", the account's
|
|
104
|
+
* name moves to the second line, and it ends in a chevron like any other row.
|
|
99
105
|
*/
|
|
100
106
|
export const AccountRow: React.FC<{
|
|
101
107
|
context: SwitcherContextRow;
|
|
102
108
|
/** The person this account is reached through, when that is not obvious. */
|
|
103
109
|
operatedBy: string | null;
|
|
110
|
+
/** Signed out: the row's "Continue as @handle" line. `null` when signed in. */
|
|
111
|
+
continueAsLabel?: string | null;
|
|
104
112
|
theme: Theme;
|
|
105
113
|
activating: boolean;
|
|
106
114
|
disabled: boolean;
|
|
107
115
|
onPress: () => void;
|
|
108
|
-
}> = ({ context, operatedBy, theme, activating, disabled, onPress }) => {
|
|
116
|
+
}> = ({ context, operatedBy, continueAsLabel = null, theme, activating, disabled, onPress }) => {
|
|
109
117
|
const accent = resolveAccentHex(context.color, theme.colors.primary);
|
|
110
118
|
const rowDisabled = disabled || !context.canActivate;
|
|
111
|
-
const
|
|
119
|
+
const current = continueAsLabel === null && context.isActive;
|
|
120
|
+
const primary = continueAsLabel ?? context.displayName;
|
|
121
|
+
const secondary =
|
|
122
|
+
operatedBy ??
|
|
123
|
+
(continueAsLabel !== null ? context.displayName : context.handle ? `@${context.handle}` : null);
|
|
112
124
|
|
|
113
125
|
return (
|
|
114
126
|
<BloomColorScope colorPreset={toPreset(context.color)} asChild>
|
|
@@ -116,7 +128,7 @@ export const AccountRow: React.FC<{
|
|
|
116
128
|
style={[
|
|
117
129
|
styles.accountRow,
|
|
118
130
|
{
|
|
119
|
-
borderColor:
|
|
131
|
+
borderColor: current ? accent : theme.colors.border,
|
|
120
132
|
backgroundColor: theme.colors.card,
|
|
121
133
|
},
|
|
122
134
|
rowDisabled && !activating ? styles.rowDisabled : null,
|
|
@@ -124,10 +136,10 @@ export const AccountRow: React.FC<{
|
|
|
124
136
|
onPress={onPress}
|
|
125
137
|
disabled={rowDisabled}
|
|
126
138
|
accessibilityRole="button"
|
|
127
|
-
accessibilityState={{ selected:
|
|
128
|
-
accessibilityLabel={
|
|
139
|
+
accessibilityState={{ selected: current, disabled: rowDisabled }}
|
|
140
|
+
accessibilityLabel={primary}
|
|
129
141
|
>
|
|
130
|
-
<View style={[styles.avatarRing, { borderColor:
|
|
142
|
+
<View style={[styles.avatarRing, { borderColor: current ? accent : 'transparent' }]}>
|
|
131
143
|
<Avatar
|
|
132
144
|
source={context.avatarUrl ?? undefined}
|
|
133
145
|
variant="thumb"
|
|
@@ -137,7 +149,7 @@ export const AccountRow: React.FC<{
|
|
|
137
149
|
</View>
|
|
138
150
|
<View style={styles.rowMeta}>
|
|
139
151
|
<Text style={[styles.rowName, { color: theme.colors.text }]} numberOfLines={1}>
|
|
140
|
-
{
|
|
152
|
+
{primary}
|
|
141
153
|
</Text>
|
|
142
154
|
{secondary ? (
|
|
143
155
|
<Text style={[styles.rowHandle, { color: theme.colors.textSecondary }]} numberOfLines={1}>
|
|
@@ -147,7 +159,7 @@ export const AccountRow: React.FC<{
|
|
|
147
159
|
</View>
|
|
148
160
|
{activating ? (
|
|
149
161
|
<MaterialCommunityIcons name="loading" size={20} color={accent} />
|
|
150
|
-
) :
|
|
162
|
+
) : current ? (
|
|
151
163
|
<MaterialCommunityIcons name="check-circle" size={20} color={accent} />
|
|
152
164
|
) : (
|
|
153
165
|
<MaterialCommunityIcons name="chevron-right" size={20} color={theme.colors.textSecondary} />
|
|
@@ -15,6 +15,7 @@ import type { AccountDialogSnapshot } from '@oxy.so/core';
|
|
|
15
15
|
export const EMPTY_ACCOUNT_DIALOG_SNAPSHOT: AccountDialogSnapshot = {
|
|
16
16
|
view: 'accounts',
|
|
17
17
|
backView: null,
|
|
18
|
+
hasSession: false,
|
|
18
19
|
directory: null,
|
|
19
20
|
activeContext: null,
|
|
20
21
|
activatingContextId: null,
|