@superfan-app/spotify-auth 0.1.79 → 0.1.81

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.
@@ -492,26 +492,40 @@ final class SpotifyAuthAuth: NSObject, SPTSessionManagerDelegate {
492
492
  // URLComponents.percentEncodedQuery properly encodes the values
493
493
  request.httpBody = components.percentEncodedQuery?.data(using: .utf8)
494
494
 
495
+ print("[SpotifyDebug] exchangeCodeForToken: sending request to \(url)")
495
496
  let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
497
+ print("[SpotifyDebug] exchangeCodeForToken: dataTask callback fired, self=\(self != nil), error=\(String(describing: error))")
498
+ if let http = response as? HTTPURLResponse {
499
+ print("[SpotifyDebug] exchangeCodeForToken: HTTP status \(http.statusCode)")
500
+ }
501
+ if let data = data, let body = String(data: data, encoding: .utf8) {
502
+ print("[SpotifyDebug] exchangeCodeForToken: response body = \(body)")
503
+ }
496
504
  do {
497
505
  let responseData = try self?.validateHTTPResponse(data: data, response: response, error: error)
498
- guard let responseData = responseData else { return }
506
+ guard let responseData = responseData else {
507
+ print("[SpotifyDebug] exchangeCodeForToken: responseData is nil (self may be nil)")
508
+ return
509
+ }
499
510
  let parsed = try Self.parseTokenJSON(from: responseData)
500
-
511
+ print("[SpotifyDebug] exchangeCodeForToken: parsed token OK, hasRefreshToken=\(parsed.refreshToken != nil)")
512
+
501
513
  guard let refreshToken = parsed.refreshToken else {
502
514
  throw SpotifyAuthError.tokenError("Missing refresh_token in response")
503
515
  }
504
-
516
+
505
517
  let expirationDate = Date(timeIntervalSinceNow: parsed.expiresIn)
506
518
  let sessionData = SpotifySessionData(accessToken: parsed.accessToken, refreshToken: refreshToken, expirationDate: expirationDate, scope: parsed.scope)
507
519
  DispatchQueue.main.async {
520
+ print("[SpotifyDebug] exchangeCodeForToken: setting currentSession on main thread")
508
521
  self?.currentSession = sessionData
509
522
  }
510
523
  } catch {
524
+ print("[SpotifyDebug] exchangeCodeForToken: caught error: \(error)")
511
525
  self?.handleError(error, context: "token_exchange")
512
526
  }
513
527
  }
514
-
528
+
515
529
  task.resume()
516
530
  }
517
531
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superfan-app/spotify-auth",
3
- "version": "0.1.79",
3
+ "version": "0.1.81",
4
4
  "description": "Spotify OAuth module for Expo",
5
5
  "main": "src/index.tsx",
6
6
  "types": "build/index.d.ts",
@@ -111,8 +111,16 @@ const withSpotifyAndroidManifest = (config, props) => {
111
111
  if (!mainActivity['intent-filter']) {
112
112
  mainActivity['intent-filter'] = [];
113
113
  }
114
- // Check if we already have a Spotify redirect intent filter
115
- const hasSpotifyIntentFilter = mainActivity['intent-filter'].some((filter) => filter.data?.some((d) => d.$?.['android:scheme'] === props.scheme && d.$?.['android:host'] === callbackHost));
114
+ // Check if we already have an intent filter covering the Spotify redirect.
115
+ // A broad scheme-only filter (no android:host) already covers superfan://callback,
116
+ // so we must treat it as sufficient to avoid registering two overlapping filters
117
+ // (which causes Android to show the app twice in the disambiguation dialog).
118
+ const hasSpotifyIntentFilter = mainActivity['intent-filter'].some((filter) => filter.data?.some((d) => {
119
+ const scheme = d.$?.['android:scheme'];
120
+ const host = d.$?.['android:host'];
121
+ // Matches if same scheme + matching host, OR same scheme with no host restriction
122
+ return scheme === props.scheme && (!host || host === callbackHost);
123
+ }));
116
124
  if (!hasSpotifyIntentFilter) {
117
125
  // Build the data element: android:host must be the hostname only (no path).
118
126
  // If the callback has a path component (e.g. "auth/spotify"), add android:pathPrefix.
@@ -128,12 +128,18 @@ const withSpotifyAndroidManifest: ConfigPlugin<SpotifyConfig> = (config, props)
128
128
  mainActivity['intent-filter'] = [];
129
129
  }
130
130
 
131
- // Check if we already have a Spotify redirect intent filter
131
+ // Check if we already have an intent filter covering the Spotify redirect.
132
+ // A broad scheme-only filter (no android:host) already covers superfan://callback,
133
+ // so we must treat it as sufficient to avoid registering two overlapping filters
134
+ // (which causes Android to show the app twice in the disambiguation dialog).
132
135
  const hasSpotifyIntentFilter = mainActivity['intent-filter'].some(
133
136
  (filter: any) =>
134
- filter.data?.some(
135
- (d: any) => d.$?.['android:scheme'] === props.scheme && d.$?.['android:host'] === callbackHost
136
- )
137
+ filter.data?.some((d: any) => {
138
+ const scheme = d.$?.['android:scheme'];
139
+ const host = d.$?.['android:host'];
140
+ // Matches if same scheme + matching host, OR same scheme with no host restriction
141
+ return scheme === props.scheme && (!host || host === callbackHost);
142
+ })
137
143
  );
138
144
 
139
145
  if (!hasSpotifyIntentFilter) {