@pyrocancode/react-native-vk-auth 0.4.1 → 1.0.1

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 CHANGED
@@ -1,18 +1,14 @@
1
1
  # @pyrocancode/react-native-vk-auth
2
2
 
3
- React Native VK ID Auth.
4
-
5
- Форк библиотеки [@devsomersets/react-native-vk-auth](https://www.npmjs.com/package/@devsomersets/react-native-vk-auth) ([исходный репозиторий](https://github.com/somersets/react-native-vk-auth), автор Nikita Likhachev). Разработка ведётся в [pyrocancode/react-native-vk-auth](https://github.com/pyrocancode/react-native-vk-auth).
3
+ Тонкая обёртка над **VK ID SDK** для React Native: **OAuth 2.1**, нативные модули iOS и Android. Репозиторий: [pyrocancode/react-native-vk-auth](https://github.com/pyrocancode/react-native-vk-auth).
6
4
 
7
5
  ## Installation
8
6
 
9
- Из npm (после публикации пакета):
10
-
11
7
  ```sh
12
8
  npm install @pyrocancode/react-native-vk-auth
13
9
  ```
14
10
 
15
- Установка напрямую из GitHub:
11
+ Альтернатива установка из GitHub (конкретная ветка или коммит):
16
12
 
17
13
  ```sh
18
14
  npm install github:pyrocancode/react-native-vk-auth
@@ -88,21 +84,25 @@ cd ios && pod install
88
84
  }
89
85
  ```
90
86
 
91
- Затем в Typescript необходимо импортировать класс Linking при помощи которого вы сможете подписаться на события открытия ссылок и в месте обработки ссылок вызвать метод openURL у класса VK.
92
- ```javascript
87
+ Подключите `Linking` из React Native и `VK` из этого пакета в обработчике вызывайте `VK.openURL`, чтобы завершить OAuth-поток после возврата из клиента VK.
88
+
89
+ ```tsx
90
+ import { Linking } from 'react-native';
91
+ import { VK } from '@pyrocancode/react-native-vk-auth';
92
+
93
93
  React.useEffect(() => {
94
- Linking.getInitialURL().then((url) => {
95
- if (url) {
96
- handleOpenURL({'url': url});
97
- }
98
- }).catch(err => {
99
- console.warn('An error occurred', err);
100
- });
101
- Linking.addEventListener('url', handleOpenURL);
102
- });
94
+ Linking.getInitialURL()
95
+ .then((url) => {
96
+ if (url) handleOpenURL({ url });
97
+ })
98
+ .catch((err) => console.warn('getInitialURL', err));
99
+
100
+ const sub = Linking.addEventListener('url', handleOpenURL);
101
+ return () => sub.remove();
102
+ }, []);
103
103
 
104
104
  function handleOpenURL(event: { url: string }) {
105
- VK.openURL(event.url);
105
+ VK.openURL(event.url);
106
106
  }
107
107
  ```
108
108
 
@@ -146,148 +146,118 @@ dependencies { }
146
146
  <string name="vk_account_manager_id" translatable="false">your.package.account</string>
147
147
  ```
148
148
 
149
- ## Minimal common setup guide:
150
- 1. Initialization
151
-
152
- ```javascript
153
- import { VK, VKID } from 'react-native-superappkit-pub';
154
-
155
- // must be initialized only once
156
- let logo = Image.resolveAssetSource(require('./sample_logo.png'));
157
- let vkid = new VKID(
158
- 'Superappkit pub',
159
- '1.0',
160
- logo,
161
- {
162
- serviceUserAgreement: 'https://help.mail.ru/legal/terms/common/ua',
163
- servicePrivacyPolicy: 'https://help.mail.ru/legal/terms/common/privacy',
164
- serviceSupport: null,
165
- },
166
- new SilentTokenExchanger()
149
+ ## Минимальный общий сценарий (JS)
150
+
151
+ Инициализация выполняется **один раз** при старте приложения. Используйте `VK`, `VKID` и при необходимости `VKOneTapButton` из `@pyrocancode/react-native-vk-auth`.
152
+
153
+ ### 1. Инициализация
154
+
155
+ ```tsx
156
+ import { Image } from 'react-native';
157
+ import { VK, VKID } from '@pyrocancode/react-native-vk-auth';
158
+
159
+ const logo = Image.resolveAssetSource(require('./assets/logo.png'));
160
+
161
+ const vkid = new VKID(
162
+ 'Моё приложение',
163
+ '1.0.0',
164
+ logo,
165
+ {
166
+ serviceUserAgreement: 'https://example.com/terms',
167
+ servicePrivacyPolicy: 'https://example.com/privacy',
168
+ serviceSupport: null,
169
+ }
167
170
  );
168
171
 
169
172
  VK.initialize(
170
- {
171
- credentials: {
172
- clientId: 'your-client-id',
173
- clientSecret: 'your-client-secret',
174
- },
175
- mode: VK.Mode.DEBUG,
173
+ {
174
+ credentials: {
175
+ clientId: 'YOUR_CLIENT_ID',
176
+ clientSecret: 'YOUR_CLIENT_SECRET',
176
177
  },
177
- vkid
178
+ mode: VK.Mode.DEBUG,
179
+ },
180
+ vkid
178
181
  );
179
182
  ```
180
183
 
181
- 2. Auth
182
- ```javascript
183
- // App.tsx
184
-
185
- // 1. Silent Token Exchanger
186
- class SilentTokenExchanger implements VKID.SilentTokenExchanger {
187
- exchange(silentData: VKID.SilentToken): Promise<VKID.TokenExchangeResult<VKID.AccessToken, Error>> {
188
- return fetch('your_endpoint_for_exchange_token', {
189
- method: 'POST',
190
- headers: {'Content-Type': 'application/json; charset=UTF-8'},
191
- })
192
- .then((response) => response.json())
193
- .then((body) => {
194
- let accessToken = 'received access_token';
195
- let userId = 'received user_id';
196
- let result: VKID.TokenExchangeResult = {
197
- ok: true,
198
- accessToken: {
199
- token: new VKID.Token(accessToken),
200
- userID: new VKID.UserID(userId),
201
- }
202
- };
203
- return result;
204
- });
205
- }
206
- }
184
+ ### 2. Подписка на авторизацию и выход
185
+
186
+ ```tsx
187
+ vkid.setOnAuthChanged({
188
+ onAuthorized(payload) {
189
+ // OAuth 2.1: access token и идентификатор пользователя VK
190
+ console.log(payload.accessToken, payload.userId, payload.profile);
191
+ },
192
+ onLogout() {
193
+ console.log('Пользователь вышел');
194
+ },
195
+ onAuthFailed(message) {
196
+ console.warn(message);
197
+ },
198
+ });
199
+ ```
207
200
 
208
- //2. Set observer for auth state changing
209
- vkid.setOnAuthChanged(new class implements VKID.AuthChangedCallback {
210
- onAuth(userSession: VKID.Session.UserSession): void {
211
- if (userSession instanceof VKID.Session.Authorized) {
212
- // user was successfuly authorized, so show authorized flow or get user profile info
213
- userSession.userProfile.then((profileInfo) => {
214
- setProfileInfo("Profile info: " + profileInfo.userID.value + " " + profileInfo.firstName);
215
- })
216
- }
217
- }
201
+ ### 3. Кнопка One Tap или ручной старт
218
202
 
219
- onLogout(): void {
220
- // logout
221
- }
222
- })
203
+ ```tsx
204
+ import { Button } from 'react-native';
205
+ import { VKOneTapButton, VKID } from '@pyrocancode/react-native-vk-auth';
223
206
 
224
- // 2.1 Use One Tap Loggin button
225
- import { VKOneTapButton } from 'react-native-superappkit-pub';
207
+ // В разметке
226
208
  <VKOneTapButton />
227
209
 
228
- // 2.2 OR use start auth manually
229
- <Button title={'Auth by VK'} onPress={() => auth()} />
230
- function auth() {
231
- vkid.startAuth();
232
- }
210
+ // Или кнопка «Войти через VK»
211
+ <Button title="Войти через VK" onPress={() => vkid.startAuth()} />
233
212
 
234
- // You may use force close
213
+ // Принудительно закрыть экран авторизации
235
214
  function forceCloseAuth() {
236
- vkid.closeAuth();
215
+ vkid.closeAuth();
237
216
  }
238
217
 
239
- // Logout
240
218
  function logout() {
241
- vkid.logout();
219
+ vkid.logout();
242
220
  }
243
221
 
244
- // Check is logged in
245
- async function isLoggedIn() {
246
- let sessions = await vkid.getUserSessions();
247
- let isLoggedIn = sessions.some((session) => session instanceof VKID.UserSession.Authorized)
222
+ async function checkLoggedIn() {
223
+ const sessions = await vkid.userSessions();
224
+ return sessions.some((s) => s instanceof VKID.Session.Authorized);
248
225
  }
249
226
  ```
250
227
 
251
- ### One Tap Button customization
252
- ```javascript
253
- import { VKOneTapButton, VKOneTapButtonSpace } from 'react-native-superappkit-pub';
228
+ ### Кастомизация One Tap
229
+
230
+ ```tsx
231
+ import { VKOneTapButton, VKOneTapButtonSpace } from '@pyrocancode/react-native-vk-auth';
232
+
254
233
  <VKOneTapButton
255
- style={styles.vkView}
256
- backgroundStyle={{
257
- style: VKOneTapButtonSpace.BgColor.CUSTOM, /* or 'BLUE' (default) or 'WHITE' */
258
- customVkIconColor: '#your-color-if-using-custom-style',
259
- customBackgroundColor: '#your-color-if-using-custom-style',
260
- customTextColor: '#your-color-if-using-custom-style'
261
- }}
262
- iconGravity={
263
- // 'START' (by default) or 'TEXT'
264
- VKOneTapButtonSpace.IconGravity.START
265
- }
266
- firstLineFieldType={
267
- // 'NONE' (by default) or 'ACTION' or 'PHONE'
268
- VKOneTapButtonSpace.LineFieldType.ACTION
269
- }
270
- secondLineFieldType={
271
- // 'NONE' (by default) or 'ACTION' or 'PHONE'
272
- VKOneTapButtonSpace.LineFieldType.PHONE
273
- }
274
- texts={{
275
- noUserText: 'Login as VK',
276
- actionText: 'Login as {firstName} {lastName}', /* {firstName} and {lastName} are templates that will be replaced by real user names */
277
- phoneText: 'With phone {phone}', /* {phone} is a template that will be replaced by user phone */
278
- }}
279
- oneLineTextSize={ 16 }
280
- firstLineTextSize={ 16 }
281
- secondLineTextSize={ 14 }
282
- avatarSize={ 64 }
283
- iconSize={ 64 }
284
- progressSize={ 56 }
234
+ style={styles.vkView}
235
+ backgroundStyle={{
236
+ style: VKOneTapButtonSpace.BgColor.CUSTOM,
237
+ customVkIconColor: '#fff',
238
+ customBackgroundColor: '#0077FF',
239
+ customTextColor: '#fff',
240
+ }}
241
+ iconGravity={VKOneTapButtonSpace.IconGravity.START}
242
+ firstLineFieldType={VKOneTapButtonSpace.LineFieldType.ACTION}
243
+ secondLineFieldType={VKOneTapButtonSpace.LineFieldType.PHONE}
244
+ texts={{
245
+ noUserText: 'Войти через VK',
246
+ actionText: 'Продолжить как {firstName} {lastName}',
247
+ phoneText: 'Телефон {phone}',
248
+ }}
249
+ oneLineTextSize={16}
250
+ firstLineTextSize={16}
251
+ secondLineTextSize={14}
252
+ avatarSize={64}
253
+ iconSize={64}
254
+ progressSize={56}
285
255
  />
286
256
  ```
287
257
 
288
258
  ## Usage
289
259
 
290
- Раздел в разработке.
260
+ После настройки iOS/Android (см. выше) используйте API из раздела «Минимальный общий сценарий»: `VK.initialize`, `vkid.setOnAuthChanged`, `vkid.startAuth` / `VKOneTapButton`, `VK.openURL` для deep link.
291
261
 
292
262
  ## Contributing
293
263
 
@@ -295,8 +265,4 @@ See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the
295
265
 
296
266
  ## License
297
267
 
298
- [MIT](LICENSE). Исходный код Nikita Likhachev (2022); изменения и сопровождение форка — pyrocancode (2026). См. полный текст в файле `LICENSE`.
299
-
300
- ---
301
-
302
- Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
268
+ [MIT](LICENSE). См. полный текст в файле `LICENSE`.
@@ -1,5 +1,4 @@
1
1
  buildscript {
2
- // Buildscript is evaluated before everything else so we can't use getExtOrDefault
3
2
  def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['VkAuth_kotlinVersion']
4
3
 
5
4
  repositories {
@@ -9,7 +8,6 @@ buildscript {
9
8
 
10
9
  dependencies {
11
10
  classpath 'com.android.tools.build:gradle:3.5.3'
12
- // noinspection DifferentKotlinGradleVersion
13
11
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14
12
  }
15
13
  }
@@ -33,6 +31,7 @@ def getExtOrIntegerDefault(name) {
33
31
  return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['VkAuth_' + name]).toInteger()
34
32
  }
35
33
 
34
+ def vkidVersion = "2.6.2"
36
35
 
37
36
  android {
38
37
  compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
@@ -62,9 +61,9 @@ android {
62
61
  repositories {
63
62
  mavenCentral()
64
63
  google()
65
- maven {
66
- url = "https://artifactory-external.vkpartner.ru/artifactory/superappkit-maven-public/"
67
- }
64
+ maven { url = "https://artifactory-external.vkpartner.ru/artifactory/vkid-sdk-android/" }
65
+ maven { url = "https://artifactory-external.vkpartner.ru/artifactory/maven/" }
66
+ maven { url = "https://artifactory-external.vkpartner.ru/artifactory/vk-id-captcha/android/" }
68
67
 
69
68
  def found = false
70
69
  def defaultDir = null
@@ -133,17 +132,14 @@ repositories {
133
132
  }
134
133
 
135
134
  def kotlin_version = getExtOrDefault('kotlinVersion')
136
- def vkSdkVersion = "0.104-24412"
137
135
 
138
136
  dependencies {
139
- //noinspection GradleDynamicVersion
140
137
  implementation "com.facebook.react:react-native:+"
141
- implementation "com.vk:oauth-vk:${vkSdkVersion}"
142
- implementation "com.vk:vksdk-pub:${vkSdkVersion}"
138
+ implementation "com.vk.id:vkid:${vkidVersion}"
139
+ implementation "com.vk.id:onetap-xml:${vkidVersion}"
143
140
  implementation "androidx.appcompat:appcompat:1.6.1"
144
-
141
+ implementation "androidx.fragment:fragment-ktx:1.6.2"
145
142
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
146
- // From node_modules
147
143
  }
148
144
 
149
145
  if (isNewArchitectureEnabled()) {
@@ -1,25 +1,26 @@
1
1
  package com.vkauth
2
2
 
3
- import com.facebook.react.bridge.*
3
+ import com.facebook.react.bridge.Promise
4
+ import com.facebook.react.bridge.ReactApplicationContext
5
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
6
+ import com.facebook.react.bridge.ReactMethod
7
+ import com.facebook.react.bridge.ReadableMap
4
8
  import com.vkauth.vkid.AuthDelegate
5
9
  import com.vkauth.vkid.InitDelegate
6
10
  import com.vkauth.vkid.jsinput.App
7
- import com.vkauth.vkid.jsinput.VKID
11
+ import com.vkauth.vkid.jsinput.VKID as VkIdInput
8
12
 
9
13
  class VkAuthModule(
10
14
  reactContext: ReactApplicationContext,
11
15
  private val initDelegate: InitDelegate,
12
- private val authDelegate: AuthDelegate
13
- ) :
14
- ReactContextBaseJavaModule(reactContext) {
16
+ private val authDelegate: AuthDelegate,
17
+ ) : ReactContextBaseJavaModule(reactContext) {
15
18
 
16
- override fun getName(): String {
17
- return "VkAuth"
18
- }
19
+ override fun getName(): String = "VkAuth"
19
20
 
20
21
  @ReactMethod
21
22
  fun initialize(app: ReadableMap, vkid: ReadableMap) {
22
- initDelegate.initialize(App.fromMap(app), VKID.fromMap(vkid))
23
+ initDelegate.initialize(App.fromMap(app), VkIdInput.fromMap(vkid))
23
24
  }
24
25
 
25
26
  @ReactMethod
@@ -32,17 +33,18 @@ class VkAuthModule(
32
33
  authDelegate.closeAuth()
33
34
  }
34
35
 
35
- // to ignore react warning
36
36
  @ReactMethod
37
- fun addListener(eventName: String) {
38
- }
37
+ fun addListener(@Suppress("UNUSED_PARAMETER") eventName: String) {}
39
38
 
40
39
  @ReactMethod
41
- fun removeAllListeners() {
42
- }
40
+ fun removeAllListeners() {}
41
+
42
+ @ReactMethod
43
+ fun removeListeners(@Suppress("UNUSED_PARAMETER") type: Int?) {}
43
44
 
44
45
  @ReactMethod
45
- fun removeListeners(type: Int?) {
46
+ fun openURL(@Suppress("UNUSED_PARAMETER") url: String) {
47
+ // Редирект обрабатывает VK ID SDK / система; при необходимости дополните.
46
48
  }
47
49
 
48
50
  @ReactMethod
@@ -51,7 +53,7 @@ class VkAuthModule(
51
53
  }
52
54
 
53
55
  @ReactMethod
54
- fun accessTokenChangedFailed(error: ReadableMap) {
56
+ fun accessTokenChangedFailed(@Suppress("UNUSED_PARAMETER") error: ReadableMap) {
55
57
  authDelegate.accessTokenChangedFailed()
56
58
  }
57
59
 
@@ -6,15 +6,20 @@ import com.facebook.react.bridge.ReactApplicationContext
6
6
  import com.facebook.react.uimanager.ViewManager
7
7
  import com.vkauth.vkid.AuthDelegate
8
8
  import com.vkauth.vkid.InitDelegate
9
+ import com.vkauth.vkid.VkAuthServiceHolder
9
10
  import com.vkauth.vkid.onetapbutton.OneTabButtonManager
10
11
 
11
-
12
12
  class VkAuthPackage : ReactPackage {
13
13
  override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
14
- return listOf(VkAuthModule(reactContext,
15
- InitDelegate(reactContext),
16
- AuthDelegate(reactContext)
17
- ))
14
+ val authDelegate = AuthDelegate(reactContext)
15
+ VkAuthServiceHolder.authDelegate = authDelegate
16
+ return listOf(
17
+ VkAuthModule(
18
+ reactContext,
19
+ InitDelegate(reactContext),
20
+ authDelegate,
21
+ ),
22
+ )
18
23
  }
19
24
 
20
25
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
@@ -5,119 +5,127 @@ import androidx.fragment.app.FragmentActivity
5
5
  import com.facebook.react.bridge.Arguments
6
6
  import com.facebook.react.bridge.Promise
7
7
  import com.facebook.react.bridge.ReactApplicationContext
8
- import com.google.android.material.bottomsheet.BottomSheetDialogFragment
9
- import com.vk.api.sdk.VKApiCallback
10
- import com.vk.auth.api.models.AuthResult
11
- import com.vk.auth.main.VkClientAuthCallback
12
- import com.vk.auth.main.VkClientAuthLib
13
- import com.vk.auth.main.VkSilentTokenExchanger
14
- import com.vk.auth.ui.fastlogin.VkFastLoginBottomSheetFragment
15
- import com.vk.dto.common.id.UserId
16
- import com.vk.superapp.api.dto.account.ProfileShortInfo
17
- import com.vk.superapp.bridges.LogoutReason
18
- import com.vkauth.vkid.dto.UserSession
19
- import com.vkauth.vkid.dto.toMap
20
- import com.vkauth.vkid.jstutils.JsCbSender
21
-
22
- class AuthDelegate(
23
- private val context: ReactApplicationContext
24
- ) {
25
- private val jsCallbackSender = JsCbSender()
8
+ import com.facebook.react.bridge.WritableMap
9
+ import com.facebook.react.modules.core.DeviceEventManagerModule
10
+ import com.vk.id.VKID
11
+ import com.vk.id.VKIDAuthFail
12
+ import com.vk.id.auth.AuthCodeData
13
+ import com.vk.id.auth.VKIDAuthCallback
14
+ import com.vk.id.auth.VKIDAuthParams
15
+ import com.vk.id.logout.VKIDLogoutCallback
16
+ import com.vk.id.logout.VKIDLogoutFail
17
+
18
+ class AuthDelegate(private val reactContext: ReactApplicationContext) {
19
+
20
+ companion object {
21
+ private const val TAG = "VkAuth"
22
+ }
26
23
 
27
24
  init {
28
- VkClientAuthLib.addAuthCallback(object : VkClientAuthCallback {
29
- override fun onLogout(logoutReason: LogoutReason) {
30
- super.onLogout(logoutReason)
31
- jsCallbackSender.sendCallback(context, ON_LOGOUT_EVENT, null)
32
- }
33
- })
25
+ VKID.logsEnabled = true
34
26
  }
35
27
 
36
28
  fun startAuth() {
37
- val activity = context.currentActivity as? FragmentActivity ?: return
38
-
39
- if (isShown()) {
29
+ val activity = reactContext.currentActivity as? FragmentActivity
30
+ if (activity == null) {
31
+ Log.e(TAG, "startAuth: no FragmentActivity")
32
+ emitAuthFail("No activity")
40
33
  return
41
34
  }
35
+ VKID.instance.authorize(
36
+ activity,
37
+ object : VKIDAuthCallback {
38
+ override fun onAuth(accessToken: com.vk.id.AccessToken) {
39
+ Log.d(
40
+ TAG,
41
+ "VKID onAuth: userID=${accessToken.userID} expire=${accessToken.expireTime}",
42
+ )
43
+ emitAuthSuccess(accessToken)
44
+ }
42
45
 
43
- VkFastLoginBottomSheetFragment.Builder()
44
- .setDismissOnComplete(false)
45
- .show(activity.supportFragmentManager, FAST_LOGIN_TAG)
46
+ override fun onAuthCode(data: AuthCodeData, isCompletion: Boolean) {
47
+ Log.d(TAG, "VKID onAuthCode: isCompletion=$isCompletion code=${data.code} deviceId=${data.deviceId}")
48
+ }
49
+
50
+ override fun onFail(fail: VKIDAuthFail) {
51
+ Log.e(TAG, "VKID onFail: $fail")
52
+ emitAuthFail(fail.toString())
53
+ }
54
+ },
55
+ VKIDAuthParams.Builder().build(),
56
+ )
46
57
  }
47
58
 
48
59
  fun closeAuth() {
49
- val activity = context.currentActivity as? FragmentActivity ?: return
50
- (activity.supportFragmentManager.findFragmentByTag(FAST_LOGIN_TAG) as? BottomSheetDialogFragment)
51
- ?.dismissAllowingStateLoss()
52
- ?: run {
53
- (activity.supportFragmentManager
54
- .fragments
55
- .find { it is VkFastLoginBottomSheetFragment } as? BottomSheetDialogFragment)
56
- ?.dismissAllowingStateLoss()
57
- }
60
+ // VK ID SDK не требует явного закрытия веб-view из нативного модуля.
58
61
  }
59
62
 
60
- fun accessTokenChangedSuccess(token: String, userId: Int) {
61
- val userSessionJson = UserSession.Authorized.toMap()
62
- jsCallbackSender.sendCallback(context, ON_AUTH_EVENT, userSessionJson)
63
+ fun logout() {
64
+ val activity = reactContext.currentActivity as? FragmentActivity
65
+ if (activity == null) {
66
+ Log.e(TAG, "logout: no FragmentActivity")
67
+ return
68
+ }
69
+ VKID.instance.logout(
70
+ object : VKIDLogoutCallback {
71
+ override fun onSuccess() {
72
+ Log.d(TAG, "VKID logout success")
73
+ sendEvent("onLogout", null)
74
+ }
63
75
 
64
- closeAuth()
76
+ override fun onFail(fail: VKIDLogoutFail) {
77
+ Log.e(TAG, "VKID logout fail: $fail")
78
+ }
79
+ },
80
+ activity,
81
+ )
65
82
  }
66
83
 
67
- fun accessTokenChangedFailed() {
68
- closeAuth()
84
+ fun accessTokenChangedSuccess(token: String, userId: Int) {
85
+ // Старый поток silent token; оставлено для совместимости с JS до миграции приложения.
86
+ Log.d(TAG, "accessTokenChangedSuccess (legacy): userId=$userId")
69
87
  }
70
88
 
71
- fun logout() {
72
- VkClientAuthLib.logout()
89
+ fun accessTokenChangedFailed() {
90
+ Log.d(TAG, "accessTokenChangedFailed (legacy)")
73
91
  }
74
92
 
75
93
  fun getUserSessions(promise: Promise) {
76
- val creds = VkClientAuthLib.getAccessToken() ?: run {
77
- promise.resolve(Arguments.createArray())
78
- return
94
+ val token = VKID.instance.accessToken
95
+ val arr = com.facebook.react.bridge.Arguments.createArray()
96
+ if (token != null) {
97
+ val m = com.facebook.react.bridge.Arguments.createMap()
98
+ m.putString("type", "authorized")
99
+ arr.pushMap(m)
79
100
  }
80
-
81
- val array = Arguments.createArray().apply {
82
- pushMap(UserSession.Authorized.toMap())
83
- }
84
- promise.resolve(array)
101
+ promise.resolve(arr)
85
102
  }
86
103
 
87
- private fun isShown(): Boolean {
88
- val activity = context.currentActivity as? FragmentActivity ?: return false
89
-
90
- val byTag = (activity.supportFragmentManager.findFragmentByTag(FAST_LOGIN_TAG) as? BottomSheetDialogFragment) != null
91
-
92
- if (byTag) {
93
- return true
104
+ fun getUserProfile(promise: Promise) {
105
+ val token = VKID.instance.accessToken
106
+ if (token == null) {
107
+ promise.reject("E_VK_NOT_AUTHORIZED", "No VK ID access token")
108
+ return
94
109
  }
110
+ promise.resolve(VkAuthPayload.profileForJs(token.userID, token.userData))
111
+ }
95
112
 
96
- return activity.supportFragmentManager
97
- .fragments
98
- .any { it is VkFastLoginBottomSheetFragment }
113
+ fun emitAuthSuccess(accessToken: com.vk.id.AccessToken) {
114
+ val map = VkAuthPayload.fromAccessToken(accessToken)
115
+ map.putMap("profile", VkAuthPayload.profileForJs(accessToken.userID, accessToken.userData))
116
+ sendEvent("onAuth", map)
99
117
  }
100
118
 
101
- fun getUserProfile(promise: Promise) {
102
- val profile = VkClientAuthLib.getProfileInfo()?.toMap() ?: run {
103
- VkClientAuthLib.updateUserInfo(
104
- object : VKApiCallback<ProfileShortInfo> {
105
- override fun fail(error: Exception) {
106
- promise.reject(error)
107
- }
108
- override fun success(result: ProfileShortInfo) {
109
- promise.resolve(result.toMap())
110
- }
111
- }
112
- )
113
- return
114
- }
115
- promise.resolve(profile)
119
+ fun emitAuthFail(message: String) {
120
+ val map = Arguments.createMap()
121
+ map.putString("type", "error")
122
+ map.putString("error", message)
123
+ sendEvent("onAuth", map)
116
124
  }
117
125
 
118
- private companion object {
119
- private const val FAST_LOGIN_TAG = "vk_fast_login"
120
- private const val ON_AUTH_EVENT = "onAuth"
121
- private const val ON_LOGOUT_EVENT = "onLogout"
126
+ private fun sendEvent(eventName: String, params: WritableMap?) {
127
+ reactContext
128
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
129
+ .emit(eventName, params)
122
130
  }
123
131
  }