react-native-nitro-auth 0.5.1 → 0.5.4
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/README.md +362 -190
- package/android/build.gradle +2 -5
- package/android/src/main/cpp/PlatformAuth+Android.cpp +84 -18
- package/android/src/main/java/com/auth/AuthAdapter.kt +82 -182
- package/android/src/main/java/com/auth/NitroAuthPackage.kt +1 -1
- package/app.plugin.js +2 -9
- package/cpp/AuthCache.cpp +0 -134
- package/cpp/AuthCache.hpp +0 -7
- package/cpp/HybridAuth.cpp +57 -63
- package/cpp/HybridAuth.hpp +3 -4
- package/ios/AuthAdapter.swift +23 -25
- package/lib/commonjs/Auth.web.js +523 -201
- package/lib/commonjs/Auth.web.js.map +1 -1
- package/lib/commonjs/index.js +0 -12
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +0 -12
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/js-storage-adapter.js +2 -0
- package/lib/commonjs/js-storage-adapter.js.map +1 -0
- package/lib/commonjs/service.js +9 -86
- package/lib/commonjs/service.js.map +1 -1
- package/lib/commonjs/service.web.js +1 -5
- package/lib/commonjs/service.web.js.map +1 -1
- package/lib/commonjs/ui/social-button.js +44 -29
- package/lib/commonjs/ui/social-button.js.map +1 -1
- package/lib/commonjs/ui/social-button.web.js +44 -29
- package/lib/commonjs/ui/social-button.web.js.map +1 -1
- package/lib/commonjs/use-auth.js +56 -42
- package/lib/commonjs/use-auth.js.map +1 -1
- package/lib/commonjs/utils/logger.js +12 -4
- package/lib/commonjs/utils/logger.js.map +1 -1
- package/lib/module/Auth.web.js +523 -201
- package/lib/module/Auth.web.js.map +1 -1
- package/lib/module/index.js +0 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +0 -1
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/js-storage-adapter.js +2 -0
- package/lib/module/js-storage-adapter.js.map +1 -0
- package/lib/module/service.js +9 -86
- package/lib/module/service.js.map +1 -1
- package/lib/module/service.web.js +1 -5
- package/lib/module/service.web.js.map +1 -1
- package/lib/module/ui/social-button.js +44 -29
- package/lib/module/ui/social-button.js.map +1 -1
- package/lib/module/ui/social-button.web.js +44 -29
- package/lib/module/ui/social-button.web.js.map +1 -1
- package/lib/module/use-auth.js +56 -42
- package/lib/module/use-auth.js.map +1 -1
- package/lib/module/utils/logger.js +12 -4
- package/lib/module/utils/logger.js.map +1 -1
- package/lib/typescript/commonjs/Auth.nitro.d.ts +3 -3
- package/lib/typescript/commonjs/Auth.nitro.d.ts.map +1 -1
- package/lib/typescript/commonjs/Auth.web.d.ts +25 -6
- package/lib/typescript/commonjs/Auth.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +1 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +0 -1
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/js-storage-adapter.d.ts +6 -0
- package/lib/typescript/commonjs/js-storage-adapter.d.ts.map +1 -0
- package/lib/typescript/commonjs/service.d.ts +1 -8
- package/lib/typescript/commonjs/service.d.ts.map +1 -1
- package/lib/typescript/commonjs/service.web.d.ts +1 -8
- package/lib/typescript/commonjs/service.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/social-button.d.ts +6 -6
- package/lib/typescript/commonjs/ui/social-button.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/social-button.web.d.ts +6 -6
- package/lib/typescript/commonjs/ui/social-button.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/use-auth.d.ts +4 -4
- package/lib/typescript/commonjs/use-auth.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/logger.d.ts +4 -4
- package/lib/typescript/commonjs/utils/logger.d.ts.map +1 -1
- package/lib/typescript/module/Auth.nitro.d.ts +3 -3
- package/lib/typescript/module/Auth.nitro.d.ts.map +1 -1
- package/lib/typescript/module/Auth.web.d.ts +25 -6
- package/lib/typescript/module/Auth.web.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +1 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +0 -1
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/js-storage-adapter.d.ts +6 -0
- package/lib/typescript/module/js-storage-adapter.d.ts.map +1 -0
- package/lib/typescript/module/service.d.ts +1 -8
- package/lib/typescript/module/service.d.ts.map +1 -1
- package/lib/typescript/module/service.web.d.ts +1 -8
- package/lib/typescript/module/service.web.d.ts.map +1 -1
- package/lib/typescript/module/ui/social-button.d.ts +6 -6
- package/lib/typescript/module/ui/social-button.d.ts.map +1 -1
- package/lib/typescript/module/ui/social-button.web.d.ts +6 -6
- package/lib/typescript/module/ui/social-button.web.d.ts.map +1 -1
- package/lib/typescript/module/use-auth.d.ts +4 -4
- package/lib/typescript/module/use-auth.d.ts.map +1 -1
- package/lib/typescript/module/utils/logger.d.ts +4 -4
- package/lib/typescript/module/utils/logger.d.ts.map +1 -1
- package/nitrogen/generated/android/NitroAuth+autolinking.cmake +0 -1
- package/nitrogen/generated/shared/c++/AuthTokens.hpp +5 -1
- package/nitrogen/generated/shared/c++/AuthUser.hpp +5 -1
- package/nitrogen/generated/shared/c++/HybridAuthSpec.cpp +0 -1
- package/nitrogen/generated/shared/c++/HybridAuthSpec.hpp +0 -5
- package/package.json +11 -8
- package/react-native-nitro-auth.podspec +1 -1
- package/src/Auth.nitro.ts +4 -3
- package/src/Auth.web.ts +700 -246
- package/src/global.d.ts +0 -1
- package/src/index.ts +1 -2
- package/src/index.web.ts +0 -1
- package/src/js-storage-adapter.ts +5 -0
- package/src/service.ts +13 -106
- package/src/service.web.ts +0 -7
- package/src/ui/social-button.tsx +66 -43
- package/src/ui/social-button.web.tsx +67 -44
- package/src/use-auth.ts +116 -72
- package/src/utils/logger.ts +12 -4
- package/ios/KeychainStore.swift +0 -43
- package/lib/commonjs/AuthStorage.nitro.js +0 -6
- package/lib/commonjs/AuthStorage.nitro.js.map +0 -1
- package/lib/module/AuthStorage.nitro.js +0 -4
- package/lib/module/AuthStorage.nitro.js.map +0 -1
- package/lib/typescript/commonjs/AuthStorage.nitro.d.ts +0 -26
- package/lib/typescript/commonjs/AuthStorage.nitro.d.ts.map +0 -1
- package/lib/typescript/module/AuthStorage.nitro.d.ts +0 -26
- package/lib/typescript/module/AuthStorage.nitro.d.ts.map +0 -1
- package/nitrogen/generated/shared/c++/HybridAuthStorageAdapterSpec.cpp +0 -23
- package/nitrogen/generated/shared/c++/HybridAuthStorageAdapterSpec.hpp +0 -65
- package/src/AuthStorage.nitro.ts +0 -26
package/src/global.d.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export * from "./Auth.nitro";
|
|
2
|
-
export * from "./AuthStorage.nitro";
|
|
3
2
|
export * from "./ui/social-button";
|
|
4
3
|
export { useAuth, type UseAuthReturn } from "./use-auth";
|
|
5
|
-
export { AuthService
|
|
4
|
+
export { AuthService } from "./service";
|
package/src/index.web.ts
CHANGED
package/src/service.ts
CHANGED
|
@@ -3,66 +3,22 @@ import type {
|
|
|
3
3
|
Auth,
|
|
4
4
|
AuthProvider,
|
|
5
5
|
AuthTokens,
|
|
6
|
-
AuthUser,
|
|
7
6
|
LoginOptions,
|
|
7
|
+
AuthUser,
|
|
8
8
|
} from "./Auth.nitro";
|
|
9
|
-
import type { AuthStorageAdapter } from "./AuthStorage.nitro";
|
|
10
|
-
|
|
11
|
-
const STORAGE_KEY = "nitro_auth_user";
|
|
12
|
-
const SCOPES_KEY = "nitro_auth_scopes";
|
|
13
|
-
|
|
14
|
-
export interface JSStorageAdapter {
|
|
15
|
-
save(key: string, value: string): void | Promise<void>;
|
|
16
|
-
load(key: string): string | undefined | Promise<string | undefined>;
|
|
17
|
-
remove(key: string): void | Promise<void>;
|
|
18
|
-
}
|
|
19
9
|
|
|
20
10
|
const nitroAuth = NitroModules.createHybridObject<Auth>("Auth");
|
|
21
|
-
|
|
22
|
-
let jsStorageAdapter: JSStorageAdapter | undefined;
|
|
23
|
-
let cachedUser: AuthUser | undefined;
|
|
24
|
-
let cachedScopes: string[] = [];
|
|
25
|
-
|
|
26
|
-
async function loadFromJSStorage() {
|
|
27
|
-
if (!jsStorageAdapter) return;
|
|
28
|
-
const json = await jsStorageAdapter.load(STORAGE_KEY);
|
|
29
|
-
if (json) {
|
|
30
|
-
try {
|
|
31
|
-
cachedUser = JSON.parse(json);
|
|
32
|
-
} catch {}
|
|
33
|
-
}
|
|
34
|
-
const scopesJson = await jsStorageAdapter.load(SCOPES_KEY);
|
|
35
|
-
if (scopesJson) {
|
|
36
|
-
try {
|
|
37
|
-
cachedScopes = JSON.parse(scopesJson);
|
|
38
|
-
} catch {}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function saveToJSStorage(user: AuthUser | undefined) {
|
|
43
|
-
if (!jsStorageAdapter) return;
|
|
44
|
-
if (user) {
|
|
45
|
-
await jsStorageAdapter.save(STORAGE_KEY, JSON.stringify(user));
|
|
46
|
-
await jsStorageAdapter.save(SCOPES_KEY, JSON.stringify(cachedScopes));
|
|
47
|
-
} else {
|
|
48
|
-
await jsStorageAdapter.remove(STORAGE_KEY);
|
|
49
|
-
await jsStorageAdapter.remove(SCOPES_KEY);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export const AuthService: Auth & {
|
|
54
|
-
setJSStorageAdapter(adapter: JSStorageAdapter | undefined): void;
|
|
55
|
-
} = {
|
|
11
|
+
export const AuthService: Auth = {
|
|
56
12
|
get name() {
|
|
57
13
|
return nitroAuth.name;
|
|
58
14
|
},
|
|
59
15
|
|
|
60
16
|
get currentUser() {
|
|
61
|
-
return
|
|
17
|
+
return nitroAuth.currentUser;
|
|
62
18
|
},
|
|
63
19
|
|
|
64
20
|
get grantedScopes() {
|
|
65
|
-
return
|
|
21
|
+
return nitroAuth.grantedScopes;
|
|
66
22
|
},
|
|
67
23
|
|
|
68
24
|
get hasPlayServices() {
|
|
@@ -70,34 +26,15 @@ export const AuthService: Auth & {
|
|
|
70
26
|
},
|
|
71
27
|
|
|
72
28
|
async login(provider: AuthProvider, options?: LoginOptions) {
|
|
73
|
-
|
|
74
|
-
if (jsStorageAdapter) {
|
|
75
|
-
cachedUser = nitroAuth.currentUser;
|
|
76
|
-
cachedScopes = options?.scopes ?? nitroAuth.grantedScopes;
|
|
77
|
-
if (cachedUser) cachedUser.scopes = cachedScopes;
|
|
78
|
-
await saveToJSStorage(cachedUser);
|
|
79
|
-
}
|
|
29
|
+
return nitroAuth.login(provider, options);
|
|
80
30
|
},
|
|
81
31
|
|
|
82
32
|
async requestScopes(scopes: string[]) {
|
|
83
|
-
|
|
84
|
-
if (jsStorageAdapter) {
|
|
85
|
-
cachedUser = nitroAuth.currentUser;
|
|
86
|
-
for (const s of scopes) {
|
|
87
|
-
if (!cachedScopes.includes(s)) cachedScopes.push(s);
|
|
88
|
-
}
|
|
89
|
-
if (cachedUser) cachedUser.scopes = cachedScopes;
|
|
90
|
-
await saveToJSStorage(cachedUser);
|
|
91
|
-
}
|
|
33
|
+
return nitroAuth.requestScopes(scopes);
|
|
92
34
|
},
|
|
93
35
|
|
|
94
36
|
async revokeScopes(scopes: string[]) {
|
|
95
|
-
|
|
96
|
-
if (jsStorageAdapter) {
|
|
97
|
-
cachedScopes = cachedScopes.filter((s) => !scopes.includes(s));
|
|
98
|
-
if (cachedUser) cachedUser.scopes = cachedScopes;
|
|
99
|
-
await saveToJSStorage(cachedUser);
|
|
100
|
-
}
|
|
37
|
+
return nitroAuth.revokeScopes(scopes);
|
|
101
38
|
},
|
|
102
39
|
|
|
103
40
|
async getAccessToken() {
|
|
@@ -105,36 +42,20 @@ export const AuthService: Auth & {
|
|
|
105
42
|
},
|
|
106
43
|
|
|
107
44
|
async refreshToken() {
|
|
108
|
-
|
|
109
|
-
if (jsStorageAdapter && cachedUser) {
|
|
110
|
-
cachedUser.accessToken = tokens.accessToken;
|
|
111
|
-
cachedUser.idToken = tokens.idToken;
|
|
112
|
-
await saveToJSStorage(cachedUser);
|
|
113
|
-
}
|
|
114
|
-
return tokens;
|
|
45
|
+
return nitroAuth.refreshToken();
|
|
115
46
|
},
|
|
116
47
|
|
|
117
48
|
logout() {
|
|
118
49
|
nitroAuth.logout();
|
|
119
|
-
if (jsStorageAdapter) {
|
|
120
|
-
cachedUser = undefined;
|
|
121
|
-
cachedScopes = [];
|
|
122
|
-
saveToJSStorage(undefined);
|
|
123
|
-
}
|
|
124
50
|
},
|
|
125
51
|
|
|
126
52
|
async silentRestore() {
|
|
127
|
-
|
|
128
|
-
if (jsStorageAdapter) {
|
|
129
|
-
cachedUser = nitroAuth.currentUser;
|
|
130
|
-
cachedScopes = nitroAuth.grantedScopes;
|
|
131
|
-
await saveToJSStorage(cachedUser);
|
|
132
|
-
}
|
|
53
|
+
return nitroAuth.silentRestore();
|
|
133
54
|
},
|
|
134
55
|
|
|
135
56
|
onAuthStateChanged(callback: (user: AuthUser | undefined) => void) {
|
|
136
|
-
return nitroAuth.onAuthStateChanged(() => {
|
|
137
|
-
callback(
|
|
57
|
+
return nitroAuth.onAuthStateChanged((user) => {
|
|
58
|
+
callback(user);
|
|
138
59
|
});
|
|
139
60
|
},
|
|
140
61
|
|
|
@@ -146,25 +67,11 @@ export const AuthService: Auth & {
|
|
|
146
67
|
nitroAuth.setLoggingEnabled(enabled);
|
|
147
68
|
},
|
|
148
69
|
|
|
149
|
-
setStorageAdapter(adapter: AuthStorageAdapter | undefined): void {
|
|
150
|
-
nitroAuth.setStorageAdapter(adapter);
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
async setJSStorageAdapter(adapter: JSStorageAdapter | undefined) {
|
|
154
|
-
jsStorageAdapter = adapter;
|
|
155
|
-
if (adapter) {
|
|
156
|
-
await loadFromJSStorage();
|
|
157
|
-
} else {
|
|
158
|
-
cachedUser = undefined;
|
|
159
|
-
cachedScopes = [];
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
|
|
163
70
|
dispose() {
|
|
164
71
|
nitroAuth.dispose();
|
|
165
72
|
},
|
|
166
73
|
|
|
167
|
-
equals(other:
|
|
168
|
-
return
|
|
74
|
+
equals(other: Parameters<Auth["equals"]>[0]): boolean {
|
|
75
|
+
return nitroAuth.equals(other);
|
|
169
76
|
},
|
|
170
77
|
};
|
package/src/service.web.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { AuthModule } from "./Auth.web";
|
|
2
|
-
import type { AuthStorageAdapter } from "./AuthStorage.nitro";
|
|
3
|
-
import type { JSStorageAdapter } from "./service";
|
|
4
2
|
|
|
5
3
|
export const AuthService = {
|
|
6
4
|
...AuthModule,
|
|
@@ -31,11 +29,6 @@ export const AuthService = {
|
|
|
31
29
|
onAuthStateChanged: AuthModule.onAuthStateChanged.bind(AuthModule),
|
|
32
30
|
onTokensRefreshed: AuthModule.onTokensRefreshed.bind(AuthModule),
|
|
33
31
|
setLoggingEnabled: AuthModule.setLoggingEnabled.bind(AuthModule),
|
|
34
|
-
setStorageAdapter: AuthModule.setStorageAdapter.bind(AuthModule),
|
|
35
32
|
dispose: AuthModule.dispose.bind(AuthModule),
|
|
36
33
|
equals: AuthModule.equals.bind(AuthModule),
|
|
37
|
-
|
|
38
|
-
setJSStorageAdapter(adapter: JSStorageAdapter | undefined): void {
|
|
39
|
-
AuthModule.setStorageAdapter(adapter as AuthStorageAdapter | undefined);
|
|
40
|
-
},
|
|
41
34
|
};
|
package/src/ui/social-button.tsx
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
|
+
import type { ViewStyle, TextStyle } from "react-native";
|
|
2
3
|
import {
|
|
3
4
|
Pressable,
|
|
4
5
|
Text,
|
|
5
6
|
StyleSheet,
|
|
6
7
|
View,
|
|
7
|
-
ViewStyle,
|
|
8
|
-
TextStyle,
|
|
9
8
|
ActivityIndicator,
|
|
10
9
|
} from "react-native";
|
|
11
10
|
import { NitroModules } from "react-native-nitro-modules";
|
|
12
11
|
import type { Auth, AuthProvider, AuthUser } from "../Auth.nitro";
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
export type SocialButtonVariant = "primary" | "outline" | "white" | "black";
|
|
14
|
+
|
|
15
|
+
export type SocialButtonProps = {
|
|
15
16
|
provider: AuthProvider;
|
|
16
|
-
variant?:
|
|
17
|
+
variant?: SocialButtonVariant;
|
|
17
18
|
borderRadius?: number;
|
|
18
19
|
style?: ViewStyle;
|
|
19
20
|
textStyle?: TextStyle;
|
|
@@ -21,14 +22,45 @@ interface SocialButtonProps {
|
|
|
21
22
|
onSuccess?: (user: AuthUser) => void;
|
|
22
23
|
onError?: (error: unknown) => void;
|
|
23
24
|
onPress?: () => void;
|
|
24
|
-
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const PROVIDER_LABELS: Record<AuthProvider, string> = {
|
|
28
|
+
google: "Google",
|
|
29
|
+
apple: "Apple",
|
|
30
|
+
microsoft: "Microsoft",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const PROVIDER_PRIMARY_BACKGROUND: Record<AuthProvider, string> = {
|
|
34
|
+
google: "#4285F4",
|
|
35
|
+
apple: "#000000",
|
|
36
|
+
microsoft: "#2F2F2F",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const getBackgroundColor = ({
|
|
40
|
+
disabled,
|
|
41
|
+
variant,
|
|
42
|
+
provider,
|
|
43
|
+
}: {
|
|
44
|
+
disabled: boolean;
|
|
45
|
+
variant: SocialButtonVariant;
|
|
46
|
+
provider: AuthProvider;
|
|
47
|
+
}): string => {
|
|
48
|
+
if (disabled) return "#CCCCCC";
|
|
49
|
+
if (variant === "black") return "#000000";
|
|
50
|
+
if (variant === "white") return "#FFFFFF";
|
|
51
|
+
if (variant === "outline") return "transparent";
|
|
52
|
+
return PROVIDER_PRIMARY_BACKGROUND[provider];
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const getTextColor = (variant: SocialButtonVariant): string =>
|
|
56
|
+
variant === "white" || variant === "outline" ? "#000000" : "#FFFFFF";
|
|
25
57
|
|
|
26
58
|
async function performLogin(provider: AuthProvider): Promise<void> {
|
|
27
59
|
const auth = NitroModules.createHybridObject<Auth>("Auth");
|
|
28
60
|
await auth.login(provider);
|
|
29
61
|
}
|
|
30
62
|
|
|
31
|
-
export const SocialButton
|
|
63
|
+
export const SocialButton = ({
|
|
32
64
|
provider,
|
|
33
65
|
variant = "primary",
|
|
34
66
|
borderRadius = 8,
|
|
@@ -38,46 +70,30 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
38
70
|
onSuccess,
|
|
39
71
|
onError,
|
|
40
72
|
onPress,
|
|
41
|
-
}) => {
|
|
73
|
+
}: SocialButtonProps) => {
|
|
42
74
|
const [loading, setLoading] = useState(false);
|
|
43
75
|
|
|
44
|
-
const handleLogin = () => {
|
|
76
|
+
const handleLogin = async () => {
|
|
45
77
|
if (loading || disabled) return;
|
|
46
78
|
if (onPress) {
|
|
47
79
|
onPress();
|
|
48
80
|
return;
|
|
49
81
|
}
|
|
50
|
-
setLoading(true);
|
|
51
|
-
performLogin(provider)
|
|
52
|
-
.then(() => {
|
|
53
|
-
setLoading(false);
|
|
54
|
-
const user = NitroModules.createHybridObject<Auth>("Auth").currentUser;
|
|
55
|
-
if (user) onSuccess?.(user);
|
|
56
|
-
})
|
|
57
|
-
.catch((e) => {
|
|
58
|
-
setLoading(false);
|
|
59
|
-
onError?.(e);
|
|
60
|
-
});
|
|
61
|
-
};
|
|
62
82
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const getTextColor = () => {
|
|
78
|
-
if (variant === "white" || variant === "outline") return "#000000";
|
|
79
|
-
return "#FFFFFF";
|
|
83
|
+
setLoading(true);
|
|
84
|
+
try {
|
|
85
|
+
await performLogin(provider);
|
|
86
|
+
const user = NitroModules.createHybridObject<Auth>("Auth").currentUser;
|
|
87
|
+
if (user) {
|
|
88
|
+
onSuccess?.(user);
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
onError?.(error);
|
|
92
|
+
} finally {
|
|
93
|
+
setLoading(false);
|
|
94
|
+
}
|
|
80
95
|
};
|
|
96
|
+
const isDisabled = loading || disabled === true;
|
|
81
97
|
|
|
82
98
|
const getBorderColor = () => {
|
|
83
99
|
if (variant === "outline") return "#DDDDDD";
|
|
@@ -89,7 +105,11 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
89
105
|
style={[
|
|
90
106
|
styles.button,
|
|
91
107
|
{
|
|
92
|
-
backgroundColor: getBackgroundColor(
|
|
108
|
+
backgroundColor: getBackgroundColor({
|
|
109
|
+
disabled: isDisabled,
|
|
110
|
+
variant,
|
|
111
|
+
provider,
|
|
112
|
+
}),
|
|
93
113
|
borderRadius,
|
|
94
114
|
borderColor: getBorderColor(),
|
|
95
115
|
borderWidth: variant === "outline" ? 1 : 0,
|
|
@@ -101,7 +121,7 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
101
121
|
>
|
|
102
122
|
<View style={styles.content}>
|
|
103
123
|
{loading ? (
|
|
104
|
-
<ActivityIndicator size="small" color={getTextColor()} />
|
|
124
|
+
<ActivityIndicator size="small" color={getTextColor(variant)} />
|
|
105
125
|
) : (
|
|
106
126
|
<>
|
|
107
127
|
{provider === "google" && variant !== "primary" && (
|
|
@@ -111,7 +131,9 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
111
131
|
)}
|
|
112
132
|
{provider === "apple" && variant !== "primary" && (
|
|
113
133
|
<View style={styles.iconPlaceholder}>
|
|
114
|
-
<Text style={{ fontSize: 18, color: getTextColor() }}
|
|
134
|
+
<Text style={{ fontSize: 18, color: getTextColor(variant) }}>
|
|
135
|
+
|
|
136
|
+
</Text>
|
|
115
137
|
</View>
|
|
116
138
|
)}
|
|
117
139
|
{provider === "microsoft" && variant !== "primary" && (
|
|
@@ -119,9 +141,10 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
119
141
|
<Text style={{ fontSize: 16 }}>⊞</Text>
|
|
120
142
|
</View>
|
|
121
143
|
)}
|
|
122
|
-
<Text
|
|
123
|
-
|
|
124
|
-
|
|
144
|
+
<Text
|
|
145
|
+
style={[styles.text, { color: getTextColor(variant) }, textStyle]}
|
|
146
|
+
>
|
|
147
|
+
Sign in with {PROVIDER_LABELS[provider]}
|
|
125
148
|
</Text>
|
|
126
149
|
</>
|
|
127
150
|
)}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
|
+
import type { ViewStyle, TextStyle } from "react-native";
|
|
2
3
|
import {
|
|
3
4
|
Pressable,
|
|
4
5
|
Text,
|
|
5
6
|
StyleSheet,
|
|
6
7
|
View,
|
|
7
|
-
ViewStyle,
|
|
8
|
-
TextStyle,
|
|
9
8
|
ActivityIndicator,
|
|
10
9
|
} from "react-native";
|
|
11
|
-
import type { AuthProvider, AuthUser } from "../Auth.nitro";
|
|
12
10
|
import { AuthModule } from "../Auth.web";
|
|
11
|
+
import type { AuthProvider, AuthUser } from "../Auth.nitro";
|
|
12
|
+
|
|
13
|
+
export type SocialButtonVariant = "primary" | "outline" | "white" | "black";
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
export type SocialButtonProps = {
|
|
15
16
|
provider: AuthProvider;
|
|
16
|
-
variant?:
|
|
17
|
+
variant?: SocialButtonVariant;
|
|
17
18
|
borderRadius?: number;
|
|
18
19
|
style?: ViewStyle;
|
|
19
20
|
textStyle?: TextStyle;
|
|
@@ -21,13 +22,44 @@ interface SocialButtonProps {
|
|
|
21
22
|
onSuccess?: (user: AuthUser) => void;
|
|
22
23
|
onError?: (error: unknown) => void;
|
|
23
24
|
onPress?: () => void;
|
|
24
|
-
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const PROVIDER_LABELS: Record<AuthProvider, string> = {
|
|
28
|
+
google: "Google",
|
|
29
|
+
apple: "Apple",
|
|
30
|
+
microsoft: "Microsoft",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const PROVIDER_PRIMARY_BACKGROUND: Record<AuthProvider, string> = {
|
|
34
|
+
google: "#4285F4",
|
|
35
|
+
apple: "#000000",
|
|
36
|
+
microsoft: "#2F2F2F",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const getBackgroundColor = ({
|
|
40
|
+
disabled,
|
|
41
|
+
variant,
|
|
42
|
+
provider,
|
|
43
|
+
}: {
|
|
44
|
+
disabled: boolean;
|
|
45
|
+
variant: SocialButtonVariant;
|
|
46
|
+
provider: AuthProvider;
|
|
47
|
+
}): string => {
|
|
48
|
+
if (disabled) return "#CCCCCC";
|
|
49
|
+
if (variant === "black") return "#000000";
|
|
50
|
+
if (variant === "white") return "#FFFFFF";
|
|
51
|
+
if (variant === "outline") return "transparent";
|
|
52
|
+
return PROVIDER_PRIMARY_BACKGROUND[provider];
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const getTextColor = (variant: SocialButtonVariant): string =>
|
|
56
|
+
variant === "white" || variant === "outline" ? "#000000" : "#FFFFFF";
|
|
25
57
|
|
|
26
58
|
async function performLogin(provider: AuthProvider): Promise<void> {
|
|
27
59
|
await AuthModule.login(provider);
|
|
28
60
|
}
|
|
29
61
|
|
|
30
|
-
export const SocialButton
|
|
62
|
+
export const SocialButton = ({
|
|
31
63
|
provider,
|
|
32
64
|
variant = "primary",
|
|
33
65
|
borderRadius = 8,
|
|
@@ -37,46 +69,30 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
37
69
|
onSuccess,
|
|
38
70
|
onError,
|
|
39
71
|
onPress,
|
|
40
|
-
}) => {
|
|
72
|
+
}: SocialButtonProps) => {
|
|
41
73
|
const [loading, setLoading] = useState(false);
|
|
42
74
|
|
|
43
|
-
const handleLogin = () => {
|
|
75
|
+
const handleLogin = async () => {
|
|
44
76
|
if (loading || disabled) return;
|
|
45
77
|
if (onPress) {
|
|
46
78
|
onPress();
|
|
47
79
|
return;
|
|
48
80
|
}
|
|
49
|
-
setLoading(true);
|
|
50
|
-
performLogin(provider)
|
|
51
|
-
.then(() => {
|
|
52
|
-
setLoading(false);
|
|
53
|
-
const user = AuthModule.currentUser;
|
|
54
|
-
if (user) onSuccess?.(user);
|
|
55
|
-
})
|
|
56
|
-
.catch((e) => {
|
|
57
|
-
setLoading(false);
|
|
58
|
-
onError?.(e);
|
|
59
|
-
});
|
|
60
|
-
};
|
|
61
81
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const getTextColor = () => {
|
|
77
|
-
if (variant === "white" || variant === "outline") return "#000000";
|
|
78
|
-
return "#FFFFFF";
|
|
82
|
+
setLoading(true);
|
|
83
|
+
try {
|
|
84
|
+
await performLogin(provider);
|
|
85
|
+
const user = AuthModule.currentUser;
|
|
86
|
+
if (user) {
|
|
87
|
+
onSuccess?.(user);
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
onError?.(error);
|
|
91
|
+
} finally {
|
|
92
|
+
setLoading(false);
|
|
93
|
+
}
|
|
79
94
|
};
|
|
95
|
+
const isDisabled = loading || disabled === true;
|
|
80
96
|
|
|
81
97
|
const getBorderColor = () => {
|
|
82
98
|
if (variant === "outline") return "#DDDDDD";
|
|
@@ -88,7 +104,11 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
88
104
|
style={[
|
|
89
105
|
styles.button,
|
|
90
106
|
{
|
|
91
|
-
backgroundColor: getBackgroundColor(
|
|
107
|
+
backgroundColor: getBackgroundColor({
|
|
108
|
+
disabled: isDisabled,
|
|
109
|
+
variant,
|
|
110
|
+
provider,
|
|
111
|
+
}),
|
|
92
112
|
borderRadius,
|
|
93
113
|
borderColor: getBorderColor(),
|
|
94
114
|
borderWidth: variant === "outline" ? 1 : 0,
|
|
@@ -100,7 +120,7 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
100
120
|
>
|
|
101
121
|
<View style={styles.content}>
|
|
102
122
|
{loading ? (
|
|
103
|
-
<ActivityIndicator size="small" color={getTextColor()} />
|
|
123
|
+
<ActivityIndicator size="small" color={getTextColor(variant)} />
|
|
104
124
|
) : (
|
|
105
125
|
<>
|
|
106
126
|
{provider === "google" && variant !== "primary" && (
|
|
@@ -110,7 +130,9 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
110
130
|
)}
|
|
111
131
|
{provider === "apple" && variant !== "primary" && (
|
|
112
132
|
<View style={styles.iconPlaceholder}>
|
|
113
|
-
<Text style={{ fontSize: 18, color: getTextColor() }}
|
|
133
|
+
<Text style={{ fontSize: 18, color: getTextColor(variant) }}>
|
|
134
|
+
|
|
135
|
+
</Text>
|
|
114
136
|
</View>
|
|
115
137
|
)}
|
|
116
138
|
{provider === "microsoft" && variant !== "primary" && (
|
|
@@ -118,9 +140,10 @@ export const SocialButton: React.FC<SocialButtonProps> = ({
|
|
|
118
140
|
<Text style={{ fontSize: 16 }}>⊞</Text>
|
|
119
141
|
</View>
|
|
120
142
|
)}
|
|
121
|
-
<Text
|
|
122
|
-
|
|
123
|
-
|
|
143
|
+
<Text
|
|
144
|
+
style={[styles.text, { color: getTextColor(variant) }, textStyle]}
|
|
145
|
+
>
|
|
146
|
+
Sign in with {PROVIDER_LABELS[provider]}
|
|
124
147
|
</Text>
|
|
125
148
|
</>
|
|
126
149
|
)}
|