@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.
@@ -1,13 +1,19 @@
1
1
  package com.vkauth.vkid
2
2
 
3
+ import android.util.Log
3
4
  import com.facebook.react.bridge.ReactApplicationContext
4
5
  import com.vkauth.vkid.jsinput.App
5
6
  import com.vkauth.vkid.jsinput.VKID
6
7
 
7
8
  class InitDelegate(
8
- private val context: ReactApplicationContext
9
+ @Suppress("unused") private val context: ReactApplicationContext,
9
10
  ) {
10
11
  fun initialize(app: App, vkid: VKID) {
11
- SuperAppKitInitUtils.initSuperappKit(context, app, vkid)
12
+ // Конфигурация клиента — через manifest placeholders (VKIDClientID и т.д.) и VKID.init в Application.
13
+ Log.d(TAG, "initialize mode=${app.mode} appName=${vkid.appName}")
14
+ }
15
+
16
+ private companion object {
17
+ private const val TAG = "VkAuth"
12
18
  }
13
19
  }
@@ -0,0 +1,61 @@
1
+ package com.vkauth.vkid
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.vk.id.AccessToken
6
+ import com.vk.id.VKIDUser
7
+
8
+ /**
9
+ * Сериализация ответа VK ID SDK в WritableMap для JS (событие onAuth и отладка).
10
+ * Документация: https://vkcom.github.io/vkid-android-sdk/
11
+ */
12
+ internal object VkAuthPayload {
13
+
14
+ fun fromAccessToken(token: AccessToken): WritableMap {
15
+ val map = Arguments.createMap()
16
+ map.putString("type", "authorized")
17
+ map.putMap("vkid", buildVkidDebugMap(token))
18
+ return map
19
+ }
20
+
21
+ fun buildVkidDebugMap(token: AccessToken): WritableMap {
22
+ val vkid = Arguments.createMap()
23
+ vkid.putString("accessToken", token.token)
24
+ vkid.putDouble("userID", token.userID.toDouble())
25
+ vkid.putDouble("expireTime", token.expireTime.toDouble())
26
+ token.idToken?.let { vkid.putString("idToken", it) }
27
+ token.scopes?.let { scopes ->
28
+ val arr = Arguments.createArray()
29
+ scopes.forEach { arr.pushString(it) }
30
+ vkid.putArray("scopes", arr)
31
+ }
32
+ vkid.putMap("userData", fromVKIDUser(token.userData))
33
+ return vkid
34
+ }
35
+
36
+ fun fromVKIDUser(user: VKIDUser): WritableMap {
37
+ val m = Arguments.createMap()
38
+ m.putString("firstName", user.firstName)
39
+ m.putString("lastName", user.lastName)
40
+ user.phone?.let { m.putString("phone", it) }
41
+ user.email?.let { m.putString("email", it) }
42
+ user.photo50?.let { m.putString("photo50", it) }
43
+ user.photo100?.let { m.putString("photo100", it) }
44
+ user.photo200?.let { m.putString("photo200", it) }
45
+ return m
46
+ }
47
+
48
+ fun profileForJs(userId: Long, user: VKIDUser): WritableMap {
49
+ val m = Arguments.createMap()
50
+ val userIdMap = Arguments.createMap()
51
+ userIdMap.putString("value", userId.toString())
52
+ m.putMap("userID", userIdMap)
53
+ m.putString("firstName", user.firstName)
54
+ m.putString("lastName", user.lastName)
55
+ m.putString("phone", user.phone)
56
+ m.putString("photo200", user.photo200)
57
+ m.putString("email", user.email)
58
+ m.putNull("userHash")
59
+ return m
60
+ }
61
+ }
@@ -0,0 +1,8 @@
1
+ package com.vkauth.vkid
2
+
3
+ /**
4
+ * Общая ссылка на [AuthDelegate] для One Tap view и [com.vkauth.VkAuthModule].
5
+ */
6
+ internal object VkAuthServiceHolder {
7
+ var authDelegate: AuthDelegate? = null
8
+ }
@@ -1,166 +1,69 @@
1
1
  package com.vkauth.vkid.onetapbutton
2
2
 
3
- import android.content.Context
4
- import android.graphics.Color
3
+ import android.util.Log
5
4
  import com.facebook.react.bridge.ReactApplicationContext
6
5
  import com.facebook.react.bridge.ReadableMap
7
- import com.facebook.react.uimanager.LayoutShadowNode
8
6
  import com.facebook.react.uimanager.SimpleViewManager
9
7
  import com.facebook.react.uimanager.ThemedReactContext
10
8
  import com.facebook.react.uimanager.annotations.ReactProp
11
- import com.facebook.react.views.text.ReactTextShadowNode
12
- import com.vk.auth.ui.fastloginbutton.VkFastLoginButton
9
+ import com.vk.id.onetap.xml.OneTap
10
+ import com.vkauth.vkid.VkAuthServiceHolder
13
11
 
14
- class OneTabButtonManager : SimpleViewManager<VkFastLoginButton>() {
15
- override fun getName(): String = COMPONENT_NAME
12
+ /**
13
+ * VK ID One Tap (XML). См. [OneTap.setCallbacks](https://vkcom.github.io/vkid-android-sdk/onetap-xml/com.vk.id.onetap.xml/-one-tap/set-callbacks.html).
14
+ */
15
+ class OneTabButtonManager : SimpleViewManager<OneTap>() {
16
16
 
17
- override fun createShadowNodeInstance(context: ReactApplicationContext): LayoutShadowNode {
18
- return ReactTextShadowNode()
19
- }
17
+ override fun getName(): String = COMPONENT_NAME
20
18
 
21
- override fun createViewInstance(context: ThemedReactContext): VkFastLoginButton {
22
- return VkFastLoginButton(context)
19
+ override fun createViewInstance(context: ThemedReactContext): OneTap {
20
+ val view = OneTap(context)
21
+ view.setCallbacks(
22
+ onAuth = { _, accessToken ->
23
+ VkAuthServiceHolder.authDelegate?.emitAuthSuccess(accessToken)
24
+ },
25
+ onFail = { _, fail ->
26
+ Log.e(TAG, "OneTap onFail: $fail")
27
+ VkAuthServiceHolder.authDelegate?.emitAuthFail(fail.toString())
28
+ },
29
+ )
30
+ return view
23
31
  }
24
32
 
25
33
  @ReactProp(name = "backgroundStyle")
26
- fun setStyle(view: VkFastLoginButton, style: ReadableMap) {
27
- android.util.Log.d(TAG, "setStyle($style)")
28
-
29
- val vkStyle = when (style.getString("style")) {
30
- "BLUE" -> VkFastLoginButton.ButtonStyle.BLUE
31
- "WHITE" -> VkFastLoginButton.ButtonStyle.WHITE
32
- "CUSTOM" -> VkFastLoginButton.ButtonStyle.CUSTOM
33
- else -> null
34
- } ?: return
35
-
36
- if (vkStyle == VkFastLoginButton.ButtonStyle.CUSTOM) {
37
- val vkIconColor = when (style.getString("customVkIconColor")) {
38
- "BLUE" -> VkFastLoginButton.VkIconColor.BLUE
39
- "WHITE" -> VkFastLoginButton.VkIconColor.WHITE
40
- else -> null
41
- } ?: return
42
-
43
- view.setCustomStyle(
44
- bgColor = Color.parseColor(style.getString("customBackgroundColor")),
45
- textColor = Color.parseColor(style.getString("customTextColor")),
46
- vkIconColor = vkIconColor
47
- )
48
- } else {
49
- view.setButtonStyle(vkStyle)
50
- }
51
-
34
+ fun setBackgroundStyle(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") style: ReadableMap) {
35
+ // Стили One Tap задаются через [OneTap.style]; при необходимости сопоставьте с [com.vk.id.onetap.common.OneTapStyle].
52
36
  }
53
37
 
54
38
  @ReactProp(name = "iconGravity")
55
- fun setGravity(view: VkFastLoginButton, gravity: String) {
56
- android.util.Log.d(TAG, "setGravity($gravity)")
57
-
58
- val vkGravity = when (gravity) {
59
- "START" -> VkFastLoginButton.VkIconGravity.START
60
- "TEXT" -> VkFastLoginButton.VkIconGravity.TEXT
61
- else -> null
62
- } ?: return
63
-
64
- view.setVkIconGravity(vkGravity)
65
- }
39
+ fun setIconGravity(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") gravity: String) {}
66
40
 
67
41
  @ReactProp(name = "firstLineFieldType")
68
- fun setFirstLineField(view: VkFastLoginButton, type: String) {
69
- android.util.Log.d(TAG, "setFirstLineField($type)")
70
-
71
- val vkType = when (type) {
72
- "ACTION" -> VkFastLoginButton.LineFieldType.ACTION
73
- "PHONE" -> VkFastLoginButton.LineFieldType.PHONE
74
- "NONE" -> VkFastLoginButton.LineFieldType.NONE
75
- else -> null
76
- } ?: return
77
-
78
- view.setFirstLineField(vkType)
79
- }
42
+ fun setFirstLineField(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") type: String) {}
80
43
 
81
44
  @ReactProp(name = "secondLineFieldType")
82
- fun setSecondLineField(view: VkFastLoginButton, type: String) {
83
- android.util.Log.d(TAG, "setSecondLineField($type)")
84
- val vkType = when (type) {
85
- "ACTION" -> VkFastLoginButton.LineFieldType.ACTION
86
- "PHONE" -> VkFastLoginButton.LineFieldType.PHONE
87
- "NONE" -> VkFastLoginButton.LineFieldType.NONE
88
- else -> null
89
- } ?: return
90
-
91
- view.setSecondLineField(vkType)
92
- }
45
+ fun setSecondLineField(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") type: String) {}
93
46
 
94
47
  @ReactProp(name = "oneLineTextSize")
95
- fun setOneLineTextSize(view: VkFastLoginButton, size: Float) {
96
- android.util.Log.d(TAG, "setOneLineTextSize($size)")
97
- view.setOneLineTextSize(size)
98
- }
48
+ fun setOneLineTextSize(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") size: Float) {}
99
49
 
100
50
  @ReactProp(name = "firstLineTextSize")
101
- fun setFirstLineTextSize(view: VkFastLoginButton, size: Float) {
102
- android.util.Log.d(TAG, "setFirstLineTextSize($size)")
103
- view.setFirstLineTextSize(size)
104
- }
51
+ fun setFirstLineTextSize(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") size: Float) {}
105
52
 
106
53
  @ReactProp(name = "secondLineTextSize")
107
- fun setSecondLineTextSize(view: VkFastLoginButton, size: Float) {
108
- android.util.Log.d(TAG, "setSecondLineTextSize($size)")
109
- view.setSecondLineTextSize(size)
110
- }
54
+ fun setSecondLineTextSize(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") size: Float) {}
111
55
 
112
56
  @ReactProp(name = "avatarSize")
113
- fun setAvatarSize(view: VkFastLoginButton, size: Float) {
114
- android.util.Log.d(TAG, "setAvatarSize($size)")
115
-
116
- view.setAvatarSize(size.toInt())
117
- }
57
+ fun setAvatarSize(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") size: Float) {}
118
58
 
119
59
  @ReactProp(name = "iconSize")
120
- fun setVkIconSize(view: VkFastLoginButton, size: Float) {
121
- android.util.Log.d(TAG, "setVkIconSize($size)")
122
- view.setVkIconSize(size.toInt())
123
- }
60
+ fun setVkIconSize(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") size: Float) {}
124
61
 
125
62
  @ReactProp(name = "progressSize")
126
- fun setProgressSize(view: VkFastLoginButton, size: Float) {
127
- android.util.Log.d(TAG, "setProgressSize($size)")
128
- view.setProgressSize(size.toInt())
129
- }
63
+ fun setProgressSize(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") size: Float) {}
130
64
 
131
65
  @ReactProp(name = "texts")
132
- fun setTexts(view: VkFastLoginButton, texts: ReadableMap) {
133
- android.util.Log.d(TAG, "setTexts($texts)")
134
-
135
- view.setTextGetter(
136
- object : VkFastLoginButton.TextGetter() {
137
- override fun getNoUserText(
138
- context: Context,
139
- actionTextSize: VkFastLoginButton.ActionTextSize
140
- ): String {
141
- return texts.getString("noUserText") ?: super.getNoUserText(context, VkFastLoginButton.ActionTextSize.BIG)
142
- }
143
-
144
- override fun getActionText(
145
- context: Context,
146
- firstName: String,
147
- lastName: String,
148
- actionTextSize: VkFastLoginButton.ActionTextSize
149
- ): String {
150
- val text = texts.getString("actionText")
151
- ?.replace("{firstName}", firstName)
152
- ?.replace("{lastName}", lastName)
153
- return text ?: super.getActionText(context, firstName, lastName, VkFastLoginButton.ActionTextSize.BIG)
154
- }
155
-
156
- override fun getPhoneText(context: Context, phone: String): String {
157
- val text = texts.getString("phoneText")
158
- ?.replace("{phone}", phone)
159
- return text ?: super.getPhoneText(context, phone)
160
- }
161
- }
162
- )
163
- }
66
+ fun setTexts(@Suppress("UNUSED_PARAMETER") view: OneTap, @Suppress("UNUSED_PARAMETER") texts: ReadableMap) {}
164
67
 
165
68
  private companion object {
166
69
  private const val COMPONENT_NAME = "RTCVkOneTapButton"
package/ios/Event.swift CHANGED
@@ -1,7 +1,6 @@
1
1
  import Foundation
2
2
  import OSLog
3
-
4
- @_implementationOnly import VKSDK
3
+ import VKID
5
4
 
6
5
  extension VkAuth {
7
6
  func send(event: Event) {
@@ -25,17 +24,11 @@ struct Event {
25
24
  self.event = event
26
25
  }
27
26
 
28
- // MARK: - Accessors
29
-
30
27
  static let onLogout = Self(OnLogout())
31
28
 
32
- static func onAuth(userSession: VKID.UserSession) -> Self {
29
+ static func onAuth(userSession: UserSession) -> Self {
33
30
  .init(OnAuth(userSession: userSession))
34
31
  }
35
-
36
- static func onSilentDataReceive(silentToken: VKID.SilentToken) -> Self {
37
- .init(OnSilentDataReceive(silentToken: silentToken))
38
- }
39
32
  }
40
33
 
41
34
  extension Event: CustomStringConvertible {
@@ -54,17 +47,8 @@ extension Event {
54
47
  let name = "onAuth"
55
48
  let body: Any
56
49
 
57
- init(userSession: VKID.UserSession) {
50
+ init(userSession: UserSession) {
58
51
  self.body = userSession.dictionary
59
52
  }
60
53
  }
61
-
62
- private struct OnSilentDataReceive: RCTEvent {
63
- let name = "onSilentDataReceive"
64
- let body: Any
65
-
66
- init(silentToken: VKID.SilentToken) {
67
- self.body = ["token": ["value": silentToken.token.value], "uuid": silentToken.uuid]
68
- }
69
- }
70
54
  }
@@ -1,26 +1,30 @@
1
1
  import Foundation
2
-
3
- @_implementationOnly import VKSDK
2
+ import VKID
4
3
 
5
4
  protocol RCTDomain {
6
5
  var dictionary: [String: Any?] { get }
7
6
  }
8
7
 
9
- extension VKID.Profile: RCTDomain {
10
- #warning("Use value instead of description for userID")
11
- var dictionary: [String : Any?] {
8
+ extension User: RCTDomain {
9
+ var dictionary: [String: Any?] {
12
10
  [
13
- "userID": ["value": self.id.description],
14
- "firstName": self.name?.firstName,
15
- "lastName": self.name?.lastName,
16
- "phone": self.phoneMask,
17
- "photo200": self.image?.url?.absoluteString
11
+ "userID": ["value": String(self.id.value)],
12
+ "firstName": self.firstName,
13
+ "lastName": self.lastName,
14
+ "phone": self.phone,
15
+ "photo200": self.avatarURL?.absoluteString,
16
+ "email": self.email,
17
+ "userHash": nil,
18
18
  ]
19
19
  }
20
20
  }
21
21
 
22
- extension VKID.UserSession: RCTDomain {
23
- var dictionary: [String : Any?] {
24
- ["type": self.authorized == nil ? "authenticated" : "authorized"]
22
+ extension UserSession {
23
+ var dictionary: [String: Any?] {
24
+ [
25
+ "type": "authorized",
26
+ "userId": String(self.userId.value),
27
+ "accessToken": self.accessToken.value,
28
+ ]
25
29
  }
26
30
  }
package/ios/VkAuth.swift CHANGED
@@ -1,22 +1,40 @@
1
1
  import UIKit
2
2
  import OSLog
3
+ import React
4
+ import VKID
5
+ import VKIDCore
6
+
7
+ // MARK: - Общие хелперы (VK ID SDK 2.x, OAuth 2.1)
8
+
9
+ fileprivate func vkAuthTopViewController() -> UIViewController? {
10
+ let keyWindow: UIWindow?
11
+ if #available(iOS 13.0, *) {
12
+ keyWindow = UIApplication.shared.connectedScenes
13
+ .compactMap { $0 as? UIWindowScene }
14
+ .flatMap(\.windows)
15
+ .first { $0.isKeyWindow }
16
+ } else {
17
+ keyWindow = UIApplication.shared.keyWindow
18
+ }
19
+ guard var top = keyWindow?.rootViewController else { return nil }
20
+ while let presented = top.presentedViewController {
21
+ top = presented
22
+ }
23
+ return top
24
+ }
3
25
 
4
- @_implementationOnly import VKSDK
26
+ /// Публичный клиент + PKCE внутри SDK. Для обмена кода на бэкенде позже можно сменить на `confidentialClientFlow`.
27
+ fileprivate func vkAuthMakeConfiguration() -> AuthConfiguration {
28
+ AuthConfiguration(
29
+ flow: .publicClientFlow(),
30
+ scope: Scope([])
31
+ )
32
+ }
5
33
 
34
+ /// React Native мост для VK ID SDK. См. https://id.vk.com/about/business/go/docs/ru/vkid/latest/vk-id/connection/migration/ios/migration-ios
6
35
  @objc(VkAuth)
7
36
  final class VkAuth: RCTEventEmitter {
8
- private static var _sharedSDK: VKSDK.VK.Type2<App, VKID>? // DO NOT USE THIS DIRECTLY
9
- fileprivate static var _sharedSuperappKit: VkAuth?
10
-
11
- fileprivate static var sharedSDK: VKSDK.VK.Type2<App, VKID> {
12
- guard let _shared = Self._sharedSDK else {
13
- fatalError("VKSDK is not initialized. Call initialize(_:vkid:) method before using VkAuth.")
14
- }
15
-
16
- return _shared
17
- }
18
-
19
- private var activeAuthCompletion: ((Result<VKSDK.VKID.AccessToken, Error>) -> Void)?
37
+ fileprivate static weak var _sharedEmitter: VkAuth?
20
38
 
21
39
  @objc(initialize:vkid:)
22
40
  func initialize(_ app: NSDictionary, vkid: NSDictionary) {
@@ -30,50 +48,50 @@ final class VkAuth: RCTEventEmitter {
30
48
  }
31
49
 
32
50
  do {
33
- Self._sharedSDK = try VK {
34
- App(credentials: .init(clientId: clientId, clientSecret: clientSecret))
35
- VKID()
36
- }
37
- Self._sharedSuperappKit = self
51
+ try VKID.shared.set(
52
+ config: Configuration(
53
+ appCredentials: AppCredentials(
54
+ clientId: clientId,
55
+ clientSecret: clientSecret
56
+ )
57
+ )
58
+ )
59
+ VkAuth._sharedEmitter = self
60
+ VKID.shared.add(observer: self)
38
61
  } catch {
39
- os_log("VKSDK initialization failed", type: .error, error.localizedDescription)
62
+ os_log("VKID initialization failed: %{public}@", type: .error, error.localizedDescription)
40
63
  }
41
64
  }
42
65
 
43
66
  @objc(openURL:)
44
- func openURL(_ url: String) {
45
- guard let url = URL(string: url) else {
46
- return
47
- }
48
-
49
- try? Self.sharedSDK.open(url: url)
67
+ func openURL(_ urlString: String) {
68
+ guard let url = URL(string: urlString) else { return }
69
+ _ = VKID.shared.open(url: url)
50
70
  }
51
71
 
52
- // MARK: - Auth
53
-
54
72
  @objc func startAuth() {
55
- let flow = VKID.AuthFlow.exchanging(tokenExchanger: .custom(weak: self))
56
- let authController = VKID.AuthController(flow: flow, delegate: self)
57
-
58
- let viewController = try! Self.sharedSDK.vkid.ui(for: authController).uiViewController()
59
- UIApplication.shared.keyWindow?.rootViewController?.present(viewController, animated: true)
73
+ guard let presenter = vkAuthTopViewController() else {
74
+ os_log("No presenter for VKID authorize", type: .error)
75
+ return
76
+ }
77
+ VKID.shared.authorize(
78
+ with: vkAuthMakeConfiguration(),
79
+ using: .uiViewController(presenter)
80
+ ) { _ in }
60
81
  }
61
82
 
62
83
  @objc func closeAuth() {
63
- UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: true)
64
- os_log("Authorization closed", type: .info)
84
+ vkAuthTopViewController()?.dismiss(animated: true)
85
+ os_log("Authorization UI dismissed", type: .info)
65
86
  }
66
87
 
67
88
  @objc func logout() {
68
- guard let userSession = Self.sharedSDK.vkid.userSessions.first else {
69
- return
70
- }
71
-
72
- userSession.authorized?.logout { [weak self] _ in
73
- self?.send(event: .onLogout)
89
+ guard let session = VKID.shared.authorizedSessions.first else { return }
90
+ session.logout { [weak self] result in
91
+ if case .success = result {
92
+ self?.send(event: .onLogout)
93
+ }
74
94
  }
75
-
76
- os_log("Logout user session", type: .info, "\(userSession)")
77
95
  }
78
96
 
79
97
  @objc(getUserSessions:rejecter:)
@@ -81,7 +99,7 @@ final class VkAuth: RCTEventEmitter {
81
99
  resolver resolve: RCTPromiseResolveBlock,
82
100
  rejecter reject: RCTPromiseRejectBlock
83
101
  ) {
84
- resolve(Self.sharedSDK.vkid.userSessions.map(\.dictionary))
102
+ resolve(VKID.shared.authorizedSessions.map(\.dictionary))
85
103
  }
86
104
 
87
105
  @objc(getUserProfile:rejecter:)
@@ -89,92 +107,90 @@ final class VkAuth: RCTEventEmitter {
89
107
  resolver resolve: @escaping RCTPromiseResolveBlock,
90
108
  rejecter reject: @escaping RCTPromiseRejectBlock
91
109
  ) {
92
- guard let authorized = Self.sharedSDK.vkid.userSessions.first?.authorized else {
93
- reject(nil, nil, nil)
110
+ guard let session = VKID.shared.authorizedSessions.first else {
111
+ reject("no_session", "No authorized VK ID session", nil)
94
112
  return
95
113
  }
96
-
97
- authorized.requestProfile { result in
98
- do {
99
- let profile = try result.get()
100
- resolve(profile.dictionary)
101
- } catch {
102
- reject(nil, nil, nil)
114
+ session.fetchUser { result in
115
+ switch result {
116
+ case .success:
117
+ if let user = session.user {
118
+ resolve(user.dictionary)
119
+ } else {
120
+ resolve(["userID": ["value": String(session.userId.value)]])
121
+ }
122
+ case .failure(let error):
123
+ reject("profile_failed", error.localizedDescription, error)
103
124
  }
104
125
  }
105
126
  }
106
- }
107
-
108
- extension VkAuth: TokenExchanging {
109
- func exchange(silentToken: VKSDK.VKID.SilentToken, completion: @escaping (Result<VKSDK.VKID.AccessToken, Error>) -> Void) {
110
- self.activeAuthCompletion = completion
111
- self.send(event: .onSilentDataReceive(silentToken: silentToken))
112
- }
113
127
 
114
128
  @objc(accessTokenChangedSuccess:userId:)
115
129
  func accessTokenChangedSuccess(_ token: String, userId: NSNumber) {
116
- let accessToken = VKID.AccessToken(.init(token), userID: .init(userId.uint64Value))
117
- self.activeAuthCompletion?(.success(accessToken))
118
- self.activeAuthCompletion = nil
119
-
120
- os_log("Token exchange succeeded", type: .info)
130
+ os_log("accessTokenChangedSuccess ignored on VK ID iOS (no silent exchange)", type: .info)
121
131
  }
122
132
 
123
133
  @objc(accessTokenChangedFailed:)
124
134
  func accessTokenChangedFailed(_ error: NSDictionary) {
125
- let reactError = NSError(domain: "React Native", code: -9999, userInfo: error as! [String : Any])
126
- self.activeAuthCompletion?(.failure(reactError))
127
- self.activeAuthCompletion = nil
135
+ os_log("accessTokenChangedFailed ignored on VK ID iOS", type: .info)
136
+ }
128
137
 
129
- os_log("Token exchange failed", type: .error, reactError.localizedDescription)
138
+ @objc(supportedEvents)
139
+ override func supportedEvents() -> [String]! {
140
+ ["onLogout", "onAuth"]
130
141
  }
131
142
  }
132
143
 
133
- extension VkAuth: VKIDFlowDelegate {
134
- func vkid(_ vkid: VKSDK.VKID.Module, didCompleteAuthWith result: Result<VKSDK.VKID.UserSession, Error>) {
144
+ extension VkAuth: VKIDObserver {
145
+ func vkid(_ vkid: VKID, didCompleteAuthWith result: AuthResult, in oAuth: OAuthProvider) {
135
146
  do {
136
- self.send(event: .onAuth(userSession: try result.get()))
147
+ let session = try result.get()
148
+ send(event: .onAuth(userSession: session))
149
+ } catch AuthError.cancelled {
150
+ os_log("VKID auth cancelled", type: .info)
137
151
  } catch {
138
- os_log("Authorization failed", type: .error, error.localizedDescription)
152
+ os_log("VKID auth failed: %{public}@", type: .error, error.localizedDescription)
139
153
  }
140
154
  }
155
+
156
+ func vkid(_ vkid: VKID, didLogoutFrom session: UserSession, with result: LogoutResult) {
157
+ if case .success = result {
158
+ send(event: .onLogout)
159
+ }
160
+ }
161
+
162
+ func vkid(_ vkid: VKID, didStartAuthUsing oAuth: OAuthProvider) {}
163
+
164
+ func vkid(_ vkid: VKID, didUpdateUserIn session: UserSession, with result: UserFetchingResult) {}
165
+
166
+ func vkid(_ vkid: VKID, didRefreshAccessTokenIn session: UserSession, with result: TokenRefreshingResult) {}
141
167
  }
142
168
 
143
169
  @objc(RTCVkOneTapButton)
144
170
  final class OneTapButtonManager: RCTViewManager {
145
171
  override func view() -> UIView! {
146
- guard let sharedSuperappKit = VkAuth._sharedSuperappKit else {
147
- fatalError("VkAuth is not initialized. Call initialize(_:vkid:) method before using VkAuth.")
172
+ guard VkAuth._sharedEmitter != nil else {
173
+ os_log("VkAuth not initialized before OneTap", type: .fault)
148
174
  return UIView()
149
175
  }
150
- var authPresenter: VKSDK.UIKitPresenter = .newUIWindow
151
- if let root = UIApplication.shared.keyWindow?.rootViewController {
152
- authPresenter = .uiViewController(root)
176
+ guard let root = vkAuthTopViewController() else {
177
+ return UIView()
153
178
  }
154
179
 
155
- let flow = VKID.AuthFlow.exchanging(tokenExchanger: .custom(weak: sharedSuperappKit))
156
- let authController = VKID.AuthController(flow: flow, delegate: sharedSuperappKit)
157
-
158
- let button = VKID.OneTapButton(
159
- mode: .default,
160
- controllerConfiguration: .authController(
161
- authController,
162
- presenter: authPresenter
163
- )
180
+ let button = OneTapButton(
181
+ layout: .regular(
182
+ height: .medium(.h44),
183
+ cornerRadius: 8
184
+ ),
185
+ presenter: .uiViewController(root),
186
+ authConfiguration: vkAuthMakeConfiguration(),
187
+ onCompleteAuth: nil
164
188
  )
165
189
 
166
- guard let buttonView = try? VkAuth.sharedSDK.vkid.ui(for: button).uiView() else {
167
- fatalError("OneTapButton configuration problem")
190
+ guard let view = try? VKID.shared.ui(for: button).uiView() else {
191
+ os_log("OneTapButton uiView failed", type: .error)
168
192
  return UIView()
169
193
  }
170
-
171
- return buttonView
172
- }
173
- }
174
-
175
- extension VkAuth {
176
- @objc(supportedEvents)
177
- override func supportedEvents() -> [String] {
178
- ["onLogout", "onAuth", "onSilentDataReceive"]
194
+ return view
179
195
  }
180
196
  }