@capgo/capacitor-social-login 7.19.0 → 7.20.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.
@@ -148,8 +148,13 @@ public class AppleProvider implements SocialProvider {
148
148
  public void login(PluginCall call, JSONObject config) {
149
149
  if (this.lastcall != null) {
150
150
  call.reject("Last call is not null");
151
+ return;
151
152
  }
152
153
 
154
+ // Save the call reference immediately so it's always available
155
+ this.lastcall = call;
156
+ call.setKeepAlive(true);
157
+
153
158
  // Check if Broadcast Channel is enabled
154
159
  boolean useBroadcastChannel = config.optBoolean("useBroadcastChannel", this.useBroadcastChannel);
155
160
 
@@ -206,12 +211,11 @@ public class AppleProvider implements SocialProvider {
206
211
  }
207
212
 
208
213
  if (context == null || activity == null) {
209
- call.reject("Context or Activity is null");
214
+ this.lastcall.reject("Context or Activity is null");
215
+ this.lastcall = null;
210
216
  return;
211
217
  }
212
218
 
213
- this.lastcall = call;
214
- call.setKeepAlive(true);
215
219
  activity.runOnUiThread(() -> setupBroadcastChannelWebview(context, activity, call, appleAuthURLFull));
216
220
  }
217
221
 
@@ -256,12 +260,11 @@ public class AppleProvider implements SocialProvider {
256
260
  }
257
261
 
258
262
  if (context == null || activity == null) {
259
- call.reject("Context or Activity is null");
263
+ this.lastcall.reject("Context or Activity is null");
264
+ this.lastcall = null;
260
265
  return;
261
266
  }
262
267
 
263
- this.lastcall = call;
264
- call.setKeepAlive(true);
265
268
  activity.runOnUiThread(() -> setupWebview(context, activity, call, appleAuthURLFull));
266
269
  }
267
270
 
@@ -310,6 +313,11 @@ public class AppleProvider implements SocialProvider {
310
313
  }
311
314
 
312
315
  public void handleUrl(String url) {
316
+ if (this.lastcall == null) {
317
+ Log.e(SocialLoginPlugin.LOG_TAG, "handleUrl called but lastcall is null");
318
+ return;
319
+ }
320
+
313
321
  Uri uri = Uri.parse(url);
314
322
  String success = uri.getQueryParameter("success");
315
323
  if ("true".equals(success)) {
@@ -351,6 +359,7 @@ public class AppleProvider implements SocialProvider {
351
359
  } else {
352
360
  // Legacy mode: exchange the authorization code for tokens
353
361
  requestForAccessToken(appleAuthCode, appleClientSecret);
362
+ return; // Don't clear lastcall here, it will be cleared in the callback
354
363
  }
355
364
  }
356
365
  } else {
@@ -377,8 +386,12 @@ public class AppleProvider implements SocialProvider {
377
386
  new Callback() {
378
387
  @Override
379
388
  public void onFailure(@NonNull Call call, @NonNull IOException e) {
380
- AppleProvider.this.lastcall.reject("Cannot get access_token", e);
381
- AppleProvider.this.lastcall = null;
389
+ if (AppleProvider.this.lastcall != null) {
390
+ AppleProvider.this.lastcall.reject("Cannot get access_token", e);
391
+ AppleProvider.this.lastcall = null;
392
+ } else {
393
+ Log.e(SocialLoginPlugin.LOG_TAG, "Cannot get access_token: lastcall is null. Error: " + e.getMessage(), e);
394
+ }
382
395
  }
383
396
 
384
397
  @Override
@@ -407,11 +420,22 @@ public class AppleProvider implements SocialProvider {
407
420
  appleResponse.put("provider", "apple");
408
421
  appleResponse.put("result", result);
409
422
 
410
- AppleProvider.this.lastcall.resolve(appleResponse);
411
- AppleProvider.this.lastcall = null;
423
+ if (AppleProvider.this.lastcall != null) {
424
+ AppleProvider.this.lastcall.resolve(appleResponse);
425
+ AppleProvider.this.lastcall = null;
426
+ } else {
427
+ Log.e(
428
+ SocialLoginPlugin.LOG_TAG,
429
+ "Cannot resolve access_token response: lastcall is null. Response: " + appleResponse.toString()
430
+ );
431
+ }
412
432
  } catch (Exception e) {
413
- AppleProvider.this.lastcall.reject("Cannot get access_token", e);
414
- AppleProvider.this.lastcall = null;
433
+ if (AppleProvider.this.lastcall != null) {
434
+ AppleProvider.this.lastcall.reject("Cannot get access_token", e);
435
+ AppleProvider.this.lastcall = null;
436
+ } else {
437
+ Log.e(SocialLoginPlugin.LOG_TAG, "Cannot get access_token: lastcall is null. Error: " + e.getMessage(), e);
438
+ }
415
439
  } finally {
416
440
  response.close();
417
441
  }
@@ -488,6 +512,12 @@ public class AppleProvider implements SocialProvider {
488
512
  Uri uri = Uri.parse(url);
489
513
  String success = uri.getQueryParameter("success");
490
514
 
515
+ if (lastcall == null) {
516
+ Log.e(SocialLoginPlugin.LOG_TAG, "setupBroadcastChannelWebview: lastcall is null");
517
+ dialog.dismiss();
518
+ return true;
519
+ }
520
+
491
521
  if ("true".equals(success)) {
492
522
  String accessToken = uri.getQueryParameter("access_token");
493
523
  if (accessToken != null) {
@@ -635,6 +665,11 @@ public class AppleProvider implements SocialProvider {
635
665
 
636
666
  // Handle authentication messages
637
667
  if ("auth".equals(channel)) {
668
+ if (lastcall == null) {
669
+ Log.e(SocialLoginPlugin.LOG_TAG, "BroadcastChannelInterface.postMessage: lastcall is null");
670
+ return;
671
+ }
672
+
638
673
  String type = messageData.getString("type");
639
674
  if ("success".equals(type)) {
640
675
  // Handle successful authentication
@@ -653,18 +688,24 @@ public class AppleProvider implements SocialProvider {
653
688
  response.put("result", result);
654
689
 
655
690
  lastcall.resolve(response);
691
+ lastcall = null;
656
692
  } catch (JSONException e) {
657
693
  Log.e(SocialLoginPlugin.LOG_TAG, "Cannot create response", e);
658
694
  lastcall.reject("Cannot create response", e);
695
+ lastcall = null;
659
696
  }
660
697
  } else if ("error".equals(type)) {
661
698
  String error = messageData.optString("error", "Authentication failed");
662
699
  lastcall.reject(error);
700
+ lastcall = null;
663
701
  }
664
702
  }
665
703
  } catch (JSONException e) {
666
704
  Log.e("BroadcastChannel", "Error parsing message", e);
667
- lastcall.reject("Error parsing authentication message", e);
705
+ if (lastcall != null) {
706
+ lastcall.reject("Error parsing authentication message", e);
707
+ lastcall = null;
708
+ }
668
709
  }
669
710
  }
670
711
  }
@@ -9,6 +9,7 @@ import com.getcapacitor.Plugin;
9
9
  import com.getcapacitor.PluginCall;
10
10
  import com.getcapacitor.PluginMethod;
11
11
  import com.getcapacitor.annotation.CapacitorPlugin;
12
+ import ee.forgr.capacitor.social.login.helpers.DependencyAvailabilityChecker;
12
13
  import ee.forgr.capacitor.social.login.helpers.SocialProvider;
13
14
  import java.util.HashMap;
14
15
  import org.json.JSONArray;
@@ -18,7 +19,7 @@ import org.json.JSONObject;
18
19
  @CapacitorPlugin(name = "SocialLogin")
19
20
  public class SocialLoginPlugin extends Plugin {
20
21
 
21
- private final String pluginVersion = "7.19.0";
22
+ private final String pluginVersion = "7.20.0";
22
23
 
23
24
  public static String LOG_TAG = "CapgoSocialLogin";
24
25
 
@@ -26,6 +27,9 @@ public class SocialLoginPlugin extends Plugin {
26
27
 
27
28
  @PluginMethod
28
29
  public void initialize(PluginCall call) {
30
+ // Set plugin instance for config access
31
+ DependencyAvailabilityChecker.setPluginInstance(this);
32
+
29
33
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
30
34
  call.reject("Your android device is too old");
31
35
  return;
@@ -33,6 +37,15 @@ public class SocialLoginPlugin extends Plugin {
33
37
 
34
38
  JSObject apple = call.getObject("apple");
35
39
  if (apple != null) {
40
+ // Check if Apple dependencies are available
41
+ if (!DependencyAvailabilityChecker.isProviderAvailable("apple")) {
42
+ call.reject(
43
+ "Apple Sign-In provider is disabled. " +
44
+ "Dependencies are not available. Ensure JWT decode and CustomTabs dependencies are included in your app's build.gradle"
45
+ );
46
+ return;
47
+ }
48
+
36
49
  String androidAppleRedirect = apple.getString("redirectUrl");
37
50
  if (androidAppleRedirect == null || androidAppleRedirect.isEmpty()) {
38
51
  call.reject("apple.android.redirectUrl is null or empty");
@@ -89,6 +102,15 @@ public class SocialLoginPlugin extends Plugin {
89
102
 
90
103
  JSObject facebook = call.getObject("facebook");
91
104
  if (facebook != null) {
105
+ // Check if Facebook dependencies are available
106
+ if (!DependencyAvailabilityChecker.isProviderAvailable("facebook")) {
107
+ call.reject(
108
+ "Facebook provider is disabled. " +
109
+ "Dependencies are not available. Ensure Facebook Login dependencies are included in your app's build.gradle"
110
+ );
111
+ return;
112
+ }
113
+
92
114
  String facebookAppId = facebook.getString("appId");
93
115
  String facebookClientToken = facebook.getString("clientToken");
94
116
  if (facebookAppId == null || facebookAppId.isEmpty()) {
@@ -111,6 +133,15 @@ public class SocialLoginPlugin extends Plugin {
111
133
 
112
134
  JSObject twitter = call.getObject("twitter");
113
135
  if (twitter != null) {
136
+ // Check if Twitter dependencies are available
137
+ if (!DependencyAvailabilityChecker.isProviderAvailable("twitter")) {
138
+ call.reject(
139
+ "Twitter provider is disabled. " +
140
+ "Dependencies are not available. Ensure OkHttp dependencies are included in your app's build.gradle"
141
+ );
142
+ return;
143
+ }
144
+
114
145
  String twitterClientId = twitter.getString("clientId");
115
146
  String twitterRedirect = twitter.getString("redirectUrl");
116
147
  if (twitterClientId == null || twitterClientId.isEmpty()) {
@@ -145,7 +176,18 @@ public class SocialLoginPlugin extends Plugin {
145
176
 
146
177
  SocialProvider provider = this.socialProviderHashMap.get(providerStr);
147
178
  if (provider == null) {
148
- call.reject(String.format("Cannot find provider '%s'", providerStr));
179
+ // Check if provider is disabled (dependencies not available)
180
+ if (!DependencyAvailabilityChecker.isProviderAvailable(providerStr)) {
181
+ call.reject(
182
+ String.format(
183
+ "Provider '%s' is disabled. Dependencies are not available. " +
184
+ "Ensure required dependencies are included in your app's build.gradle",
185
+ providerStr
186
+ )
187
+ );
188
+ } else {
189
+ call.reject(String.format("Cannot find provider '%s'. Provider was not initialized.", providerStr));
190
+ }
149
191
  return;
150
192
  }
151
193
 
@@ -161,7 +203,18 @@ public class SocialLoginPlugin extends Plugin {
161
203
 
162
204
  SocialProvider provider = this.socialProviderHashMap.get(providerStr);
163
205
  if (provider == null) {
164
- call.reject(String.format("Cannot find provider '%s'", providerStr));
206
+ // Check if provider is disabled (dependencies not available)
207
+ if (!DependencyAvailabilityChecker.isProviderAvailable(providerStr)) {
208
+ call.reject(
209
+ String.format(
210
+ "Provider '%s' is disabled. Dependencies are not available. " +
211
+ "Ensure required dependencies are included in your app's build.gradle",
212
+ providerStr
213
+ )
214
+ );
215
+ } else {
216
+ call.reject(String.format("Cannot find provider '%s'. Provider was not initialized.", providerStr));
217
+ }
165
218
  return;
166
219
  }
167
220
 
@@ -177,7 +230,18 @@ public class SocialLoginPlugin extends Plugin {
177
230
 
178
231
  SocialProvider provider = this.socialProviderHashMap.get(providerStr);
179
232
  if (provider == null) {
180
- call.reject(String.format("Cannot find provider '%s'", providerStr));
233
+ // Check if provider is disabled (dependencies not available)
234
+ if (!DependencyAvailabilityChecker.isProviderAvailable(providerStr)) {
235
+ call.reject(
236
+ String.format(
237
+ "Provider '%s' is disabled. Dependencies are not available. " +
238
+ "Ensure required dependencies are included in your app's build.gradle",
239
+ providerStr
240
+ )
241
+ );
242
+ } else {
243
+ call.reject(String.format("Cannot find provider '%s'. Provider was not initialized.", providerStr));
244
+ }
181
245
  return;
182
246
  }
183
247
 
@@ -193,7 +257,18 @@ public class SocialLoginPlugin extends Plugin {
193
257
 
194
258
  SocialProvider provider = this.socialProviderHashMap.get(providerStr);
195
259
  if (provider == null) {
196
- call.reject(String.format("Cannot find provider '%s'", providerStr));
260
+ // Check if provider is disabled (dependencies not available)
261
+ if (!DependencyAvailabilityChecker.isProviderAvailable(providerStr)) {
262
+ call.reject(
263
+ String.format(
264
+ "Provider '%s' is disabled. Dependencies are not available. " +
265
+ "Ensure required dependencies are included in your app's build.gradle",
266
+ providerStr
267
+ )
268
+ );
269
+ } else {
270
+ call.reject(String.format("Cannot find provider '%s'. Provider was not initialized.", providerStr));
271
+ }
197
272
  return;
198
273
  }
199
274
 
@@ -209,7 +284,18 @@ public class SocialLoginPlugin extends Plugin {
209
284
 
210
285
  SocialProvider provider = this.socialProviderHashMap.get(providerStr);
211
286
  if (provider == null) {
212
- call.reject(String.format("Cannot find provider '%s'", providerStr));
287
+ // Check if provider is disabled (dependencies not available)
288
+ if (!DependencyAvailabilityChecker.isProviderAvailable(providerStr)) {
289
+ call.reject(
290
+ String.format(
291
+ "Provider '%s' is disabled. Dependencies are not available. " +
292
+ "Ensure required dependencies are included in your app's build.gradle",
293
+ providerStr
294
+ )
295
+ );
296
+ } else {
297
+ call.reject(String.format("Cannot find provider '%s'. Provider was not initialized.", providerStr));
298
+ }
213
299
  return;
214
300
  }
215
301
 
@@ -0,0 +1,287 @@
1
+ package ee.forgr.capacitor.social.login.helpers;
2
+
3
+ import android.util.Log;
4
+ import com.getcapacitor.JSObject;
5
+ import com.getcapacitor.Plugin;
6
+
7
+ /**
8
+ * Helper class to check if required dependencies are available at runtime using reflection.
9
+ * Results are cached to avoid repeated checks.
10
+ */
11
+ public class DependencyAvailabilityChecker {
12
+
13
+ private static final String LOG_TAG = "DependencyAvailabilityChecker";
14
+
15
+ // Static reference to plugin for config access
16
+ private static Plugin pluginInstance = null;
17
+
18
+ // Cached availability flags
19
+ private static Boolean googleDependenciesAvailable = null;
20
+ private static Boolean facebookDependenciesAvailable = null;
21
+ private static Boolean appleDependenciesAvailable = null;
22
+ private static Boolean twitterDependenciesAvailable = null;
23
+
24
+ /**
25
+ * Set the plugin instance for config access
26
+ */
27
+ public static void setPluginInstance(Plugin plugin) {
28
+ pluginInstance = plugin;
29
+ }
30
+
31
+ /**
32
+ * Check if a provider is enabled in Capacitor config.
33
+ * Returns true if not set (default enabled).
34
+ */
35
+ private static boolean isProviderEnabledInConfig(String providerName) {
36
+ if (pluginInstance == null) {
37
+ return true; // Default to enabled if plugin not available
38
+ }
39
+
40
+ try {
41
+ JSObject config = JSObject.fromJSONObject(pluginInstance.getConfig().getConfigJSON());
42
+
43
+ JSObject providers = config.getJSObject("providers");
44
+ if (providers == null) {
45
+ return true;
46
+ }
47
+
48
+ // Check if provider is explicitly set to false
49
+ if (providers.has(providerName)) {
50
+ Object value = providers.get(providerName);
51
+ if (value instanceof Boolean) {
52
+ return (Boolean) value;
53
+ }
54
+ // If it's a string "false", treat as disabled
55
+ if (value instanceof String && "false".equalsIgnoreCase((String) value)) {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ return true; // Default to enabled
61
+ } catch (Exception e) {
62
+ Log.w(LOG_TAG, "Failed to read config for provider " + providerName + ": " + e.getMessage());
63
+ return true; // Default to enabled on error
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Check if a provider's dependencies are available.
69
+ * @param providerName Provider name: "google", "facebook", "apple", or "twitter"
70
+ * @return true if dependencies are available, false otherwise
71
+ */
72
+ public static boolean isProviderAvailable(String providerName) {
73
+ if (providerName == null) {
74
+ return false;
75
+ }
76
+
77
+ switch (providerName.toLowerCase()) {
78
+ case "google":
79
+ return isGoogleAvailable();
80
+ case "facebook":
81
+ return isFacebookAvailable();
82
+ case "apple":
83
+ return isAppleAvailable();
84
+ case "twitter":
85
+ return isTwitterAvailable();
86
+ default:
87
+ Log.w(LOG_TAG, "Unknown provider: " + providerName);
88
+ return false;
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Check if Google Sign-In dependencies are available.
94
+ * Checks multiple classes to be resilient.
95
+ * Result is cached after first check.
96
+ */
97
+ private static boolean isGoogleAvailable() {
98
+ if (googleDependenciesAvailable != null) {
99
+ return googleDependenciesAvailable;
100
+ }
101
+
102
+ // Check multiple critical classes to be resilient
103
+ String[] googleClasses = {
104
+ "com.google.android.gms.auth.api.identity.AuthorizationRequest",
105
+ "com.google.android.gms.auth.api.identity.AuthorizationResult",
106
+ "com.google.android.gms.auth.api.identity.Identity",
107
+ "com.google.android.gms.common.api.ApiException",
108
+ "com.google.android.libraries.identity.googleid.GetGoogleIdOption",
109
+ "com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption",
110
+ "com.google.android.libraries.identity.googleid.GoogleIdTokenCredential"
111
+ };
112
+
113
+ boolean allAvailable = true;
114
+ for (String className : googleClasses) {
115
+ if (!isClassAvailable(className)) {
116
+ allAvailable = false;
117
+ Log.w(LOG_TAG, "Google dependency class not available: " + className);
118
+ }
119
+ }
120
+
121
+ googleDependenciesAvailable = allAvailable;
122
+
123
+ if (!allAvailable) {
124
+ Log.w(
125
+ LOG_TAG,
126
+ "Google Sign-In dependencies are not available. " +
127
+ "Ensure Google Play Services Auth dependencies are included in your app's build.gradle"
128
+ );
129
+ }
130
+
131
+ return allAvailable;
132
+ }
133
+
134
+ /**
135
+ * Check if Facebook SDK dependencies are available.
136
+ * Checks multiple classes to be resilient.
137
+ * Result is cached after first check.
138
+ */
139
+ private static boolean isFacebookAvailable() {
140
+ if (facebookDependenciesAvailable != null) {
141
+ return facebookDependenciesAvailable;
142
+ }
143
+
144
+ // Check multiple critical classes to be resilient
145
+ String[] facebookClasses = {
146
+ "com.facebook.FacebookSdk",
147
+ "com.facebook.login.LoginManager",
148
+ "com.facebook.AccessToken",
149
+ "com.facebook.CallbackManager",
150
+ "com.facebook.GraphRequest",
151
+ "com.facebook.login.LoginResult"
152
+ };
153
+
154
+ boolean allAvailable = true;
155
+ for (String className : facebookClasses) {
156
+ if (!isClassAvailable(className)) {
157
+ allAvailable = false;
158
+ Log.w(LOG_TAG, "Facebook dependency class not available: " + className);
159
+ }
160
+ }
161
+
162
+ facebookDependenciesAvailable = allAvailable;
163
+
164
+ if (!allAvailable) {
165
+ Log.w(
166
+ LOG_TAG,
167
+ "Facebook SDK dependencies are not available. " +
168
+ "Ensure Facebook Login dependencies are included in your app's build.gradle"
169
+ );
170
+ }
171
+
172
+ return allAvailable;
173
+ }
174
+
175
+ /**
176
+ * Check if Apple Sign-In dependencies are available.
177
+ * Checks config first (for "fake disable"), then checks classes.
178
+ * Result is cached after first check.
179
+ */
180
+ private static boolean isAppleAvailable() {
181
+ if (appleDependenciesAvailable != null) {
182
+ return appleDependenciesAvailable;
183
+ }
184
+
185
+ // First check config - if disabled via config, return false immediately
186
+ if (!isProviderEnabledInConfig("apple")) {
187
+ appleDependenciesAvailable = false;
188
+ Log.d(LOG_TAG, "Apple provider is disabled via config");
189
+ return false;
190
+ }
191
+
192
+ // Check multiple critical classes to be resilient
193
+ String[] appleClasses = {
194
+ "com.auth0.android.jwt.JWT",
195
+ "androidx.browser.customtabs.CustomTabsSession",
196
+ "androidx.browser.customtabs.CustomTabsServiceConnection",
197
+ "androidx.browser.customtabs.CustomTabsClient",
198
+ "androidx.browser.customtabs.CustomTabsIntent"
199
+ };
200
+
201
+ boolean allAvailable = true;
202
+ for (String className : appleClasses) {
203
+ if (!isClassAvailable(className)) {
204
+ allAvailable = false;
205
+ Log.w(LOG_TAG, "Apple dependency class not available: " + className);
206
+ }
207
+ }
208
+
209
+ appleDependenciesAvailable = allAvailable;
210
+
211
+ if (!allAvailable) {
212
+ Log.w(
213
+ LOG_TAG,
214
+ "Apple Sign-In dependencies are not available. " +
215
+ "Ensure JWT decode and CustomTabs dependencies are included in your app's build.gradle"
216
+ );
217
+ }
218
+
219
+ return allAvailable;
220
+ }
221
+
222
+ /**
223
+ * Check if Twitter OAuth dependencies are available.
224
+ * Checks config first (for "fake disable"), then checks classes.
225
+ * Result is cached after first check.
226
+ */
227
+ private static boolean isTwitterAvailable() {
228
+ if (twitterDependenciesAvailable != null) {
229
+ return twitterDependenciesAvailable;
230
+ }
231
+
232
+ // First check config - if disabled via config, return false immediately
233
+ if (!isProviderEnabledInConfig("twitter")) {
234
+ twitterDependenciesAvailable = false;
235
+ Log.d(LOG_TAG, "Twitter provider is disabled via config");
236
+ return false;
237
+ }
238
+
239
+ // Check multiple critical classes to be resilient
240
+ // Twitter uses OkHttp and standard Android APIs, but we check anyway for user control
241
+ String[] twitterClasses = { "okhttp3.OkHttpClient", "okhttp3.Request", "okhttp3.Response", "okhttp3.FormBody" };
242
+
243
+ boolean allAvailable = true;
244
+ for (String className : twitterClasses) {
245
+ if (!isClassAvailable(className)) {
246
+ allAvailable = false;
247
+ Log.w(LOG_TAG, "Twitter dependency class not available: " + className);
248
+ }
249
+ }
250
+
251
+ twitterDependenciesAvailable = allAvailable;
252
+
253
+ if (!allAvailable) {
254
+ Log.w(
255
+ LOG_TAG,
256
+ "Twitter OAuth dependencies are not available. " + "Ensure OkHttp dependencies are included in your app's build.gradle"
257
+ );
258
+ }
259
+
260
+ return allAvailable;
261
+ }
262
+
263
+ /**
264
+ * Check if a specific class is available using reflection.
265
+ */
266
+ private static boolean isClassAvailable(String className) {
267
+ try {
268
+ Class.forName(className);
269
+ return true;
270
+ } catch (ClassNotFoundException e) {
271
+ return false;
272
+ } catch (Exception e) {
273
+ Log.e(LOG_TAG, "Unexpected error checking class availability: " + className, e);
274
+ return false;
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Reset cached availability checks (useful for testing).
280
+ */
281
+ public static void resetCache() {
282
+ googleDependenciesAvailable = null;
283
+ facebookDependenciesAvailable = null;
284
+ appleDependenciesAvailable = null;
285
+ twitterDependenciesAvailable = null;
286
+ }
287
+ }
@@ -86,6 +86,7 @@ export class TwitterSocialLogin extends BaseSocialLogin {
86
86
  return;
87
87
  }
88
88
  cleanup(messageHandler, timeoutHandle, popupClosedInterval);
89
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
89
90
  const _e = event.data, { provider: _ignoredProvider } = _e, payload = __rest(_e, ["provider"]);
90
91
  resolve({
91
92
  provider: 'twitter',