react-native-queue-player 1.0.8 → 1.0.9

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.
Files changed (39) hide show
  1. package/android/src/main/java/com/margelo/nitro/queueplayer/MediaItemBuilder.kt +21 -3
  2. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaceholderArtwork.kt +30 -0
  3. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaceholderFallbackBitmapLoader.kt +9 -6
  4. package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackService.kt +4 -1
  5. package/android/src/main/java/com/margelo/nitro/queueplayer/TrackPlayer.kt +9 -5
  6. package/android/src/test/java/com/margelo/nitro/queueplayer/MediaItemBuilderTest.kt +55 -0
  7. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaceholderArtworkTest.kt +72 -0
  8. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaceholderFallbackBitmapLoaderTest.kt +21 -9
  9. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceArtworkLoaderTest.kt +9 -9
  10. package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCallbackTest.kt +1 -1
  11. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerAirPlayMetadataWiringTest.kt +1 -1
  12. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerAudioFocusTest.kt +1 -1
  13. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerEventsTest.kt +3 -3
  14. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerLifecycleTest.kt +7 -7
  15. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerLookaheadConfigTest.kt +6 -6
  16. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerMutationTest.kt +2 -2
  17. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerProgressThrottleTest.kt +1 -1
  18. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerQueueChangeTest.kt +1 -1
  19. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerQueueTest.kt +1 -1
  20. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerReadersTest.kt +1 -1
  21. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSkipCapabilityTest.kt +2 -2
  22. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSkipTest.kt +1 -1
  23. package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerTransportTest.kt +1 -1
  24. package/ios/Cast/Core/CastNowPlayingController.swift +7 -4
  25. package/ios/NowPlayingInfo.swift +7 -9
  26. package/ios/PlaceholderArtwork.swift +24 -1
  27. package/ios/Tests/AVQueueBuilderTests.swift +9 -9
  28. package/ios/Tests/CastNowPlayingControllerTests.swift +33 -0
  29. package/ios/Tests/PlaceholderArtworkTests.swift +81 -0
  30. package/ios/TrackPlayer.swift +5 -1
  31. package/lib/module/types.js.map +1 -1
  32. package/lib/typescript/types.d.ts +17 -0
  33. package/lib/typescript/types.d.ts.map +1 -1
  34. package/nitrogen/generated/android/c++/JPlayerConfig.hpp +5 -1
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlayerConfig.kt +7 -2
  36. package/nitrogen/generated/ios/swift/PlayerConfig.swift +19 -1
  37. package/nitrogen/generated/shared/c++/PlayerConfig.hpp +5 -1
  38. package/package.json +1 -1
  39. package/src/types.ts +17 -0
@@ -26,6 +26,9 @@ data class PlayerConfig(
26
26
  val userAgent: String?,
27
27
  @DoNotStrip
28
28
  @Keep
29
+ val placeholderArtworkUri: String?,
30
+ @DoNotStrip
31
+ @Keep
29
32
  val autoRetries: Double?,
30
33
  @DoNotStrip
31
34
  @Keep
@@ -65,6 +68,7 @@ data class PlayerConfig(
65
68
  if (other !is PlayerConfig) return false
66
69
  return Objects.deepEquals(this.httpHeaders, other.httpHeaders)
67
70
  && Objects.deepEquals(this.userAgent, other.userAgent)
71
+ && Objects.deepEquals(this.placeholderArtworkUri, other.placeholderArtworkUri)
68
72
  && Objects.deepEquals(this.autoRetries, other.autoRetries)
69
73
  && Objects.deepEquals(this.retryBackoffMs, other.retryBackoffMs)
70
74
  && Objects.deepEquals(this.networkTimeoutMs, other.networkTimeoutMs)
@@ -82,6 +86,7 @@ data class PlayerConfig(
82
86
  return arrayOf<Any?>(
83
87
  httpHeaders,
84
88
  userAgent,
89
+ placeholderArtworkUri,
85
90
  autoRetries,
86
91
  retryBackoffMs,
87
92
  networkTimeoutMs,
@@ -104,8 +109,8 @@ data class PlayerConfig(
104
109
  @Keep
105
110
  @Suppress("unused")
106
111
  @JvmStatic
107
- private fun fromCpp(httpHeaders: Map<String, String>?, userAgent: String?, autoRetries: Double?, retryBackoffMs: Double?, networkTimeoutMs: Double?, audioContentType: AudioContentType?, audioCategoryOptions: AudioCategoryOptions?, visualizationEnabled: Boolean?, clampSeekToBuffered: Boolean?, lookaheadCacheMaxSizeMb: Double?, lookaheadCacheEvictionPolicy: EvictionPolicy?, progressUpdateIntervalMs: Double?, backgroundProgressUpdateIntervalMs: Double?): PlayerConfig {
108
- return PlayerConfig(httpHeaders, userAgent, autoRetries, retryBackoffMs, networkTimeoutMs, audioContentType, audioCategoryOptions, visualizationEnabled, clampSeekToBuffered, lookaheadCacheMaxSizeMb, lookaheadCacheEvictionPolicy, progressUpdateIntervalMs, backgroundProgressUpdateIntervalMs)
112
+ private fun fromCpp(httpHeaders: Map<String, String>?, userAgent: String?, placeholderArtworkUri: String?, autoRetries: Double?, retryBackoffMs: Double?, networkTimeoutMs: Double?, audioContentType: AudioContentType?, audioCategoryOptions: AudioCategoryOptions?, visualizationEnabled: Boolean?, clampSeekToBuffered: Boolean?, lookaheadCacheMaxSizeMb: Double?, lookaheadCacheEvictionPolicy: EvictionPolicy?, progressUpdateIntervalMs: Double?, backgroundProgressUpdateIntervalMs: Double?): PlayerConfig {
113
+ return PlayerConfig(httpHeaders, userAgent, placeholderArtworkUri, autoRetries, retryBackoffMs, networkTimeoutMs, audioContentType, audioCategoryOptions, visualizationEnabled, clampSeekToBuffered, lookaheadCacheMaxSizeMb, lookaheadCacheEvictionPolicy, progressUpdateIntervalMs, backgroundProgressUpdateIntervalMs)
109
114
  }
110
115
  }
111
116
  }
@@ -18,7 +18,7 @@ public extension PlayerConfig {
18
18
  /**
19
19
  * Create a new instance of `PlayerConfig`.
20
20
  */
21
- init(httpHeaders: Dictionary<String, String>?, userAgent: String?, autoRetries: Double?, retryBackoffMs: Double?, networkTimeoutMs: Double?, audioContentType: AudioContentType?, audioCategoryOptions: AudioCategoryOptions?, visualizationEnabled: Bool?, clampSeekToBuffered: Bool?, lookaheadCacheMaxSizeMb: Double?, lookaheadCacheEvictionPolicy: EvictionPolicy?, progressUpdateIntervalMs: Double?, backgroundProgressUpdateIntervalMs: Double?) {
21
+ init(httpHeaders: Dictionary<String, String>?, userAgent: String?, placeholderArtworkUri: String?, autoRetries: Double?, retryBackoffMs: Double?, networkTimeoutMs: Double?, audioContentType: AudioContentType?, audioCategoryOptions: AudioCategoryOptions?, visualizationEnabled: Bool?, clampSeekToBuffered: Bool?, lookaheadCacheMaxSizeMb: Double?, lookaheadCacheEvictionPolicy: EvictionPolicy?, progressUpdateIntervalMs: Double?, backgroundProgressUpdateIntervalMs: Double?) {
22
22
  self.init({ () -> bridge.std__optional_std__unordered_map_std__string__std__string__ in
23
23
  if let __unwrappedValue = httpHeaders {
24
24
  return bridge.create_std__optional_std__unordered_map_std__string__std__string__({ () -> bridge.std__unordered_map_std__string__std__string_ in
@@ -37,6 +37,12 @@ public extension PlayerConfig {
37
37
  } else {
38
38
  return .init()
39
39
  }
40
+ }(), { () -> bridge.std__optional_std__string_ in
41
+ if let __unwrappedValue = placeholderArtworkUri {
42
+ return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
43
+ } else {
44
+ return .init()
45
+ }
40
46
  }(), { () -> bridge.std__optional_double_ in
41
47
  if let __unwrappedValue = autoRetries {
42
48
  return bridge.create_std__optional_double_(__unwrappedValue)
@@ -138,6 +144,18 @@ public extension PlayerConfig {
138
144
  }()
139
145
  }
140
146
 
147
+ @inline(__always)
148
+ var placeholderArtworkUri: String? {
149
+ return { () -> String? in
150
+ if bridge.has_value_std__optional_std__string_(self.__placeholderArtworkUri) {
151
+ let __unwrapped = bridge.get_std__optional_std__string_(self.__placeholderArtworkUri)
152
+ return String(__unwrapped)
153
+ } else {
154
+ return nil
155
+ }
156
+ }()
157
+ }
158
+
141
159
  @inline(__always)
142
160
  var autoRetries: Double? {
143
161
  return { () -> Double? in
@@ -51,6 +51,7 @@ namespace margelo::nitro::queueplayer {
51
51
  public:
52
52
  std::optional<std::unordered_map<std::string, std::string>> httpHeaders SWIFT_PRIVATE;
53
53
  std::optional<std::string> userAgent SWIFT_PRIVATE;
54
+ std::optional<std::string> placeholderArtworkUri SWIFT_PRIVATE;
54
55
  std::optional<double> autoRetries SWIFT_PRIVATE;
55
56
  std::optional<double> retryBackoffMs SWIFT_PRIVATE;
56
57
  std::optional<double> networkTimeoutMs SWIFT_PRIVATE;
@@ -65,7 +66,7 @@ namespace margelo::nitro::queueplayer {
65
66
 
66
67
  public:
67
68
  PlayerConfig() = default;
68
- explicit PlayerConfig(std::optional<std::unordered_map<std::string, std::string>> httpHeaders, std::optional<std::string> userAgent, std::optional<double> autoRetries, std::optional<double> retryBackoffMs, std::optional<double> networkTimeoutMs, std::optional<AudioContentType> audioContentType, std::optional<AudioCategoryOptions> audioCategoryOptions, std::optional<bool> visualizationEnabled, std::optional<bool> clampSeekToBuffered, std::optional<double> lookaheadCacheMaxSizeMb, std::optional<EvictionPolicy> lookaheadCacheEvictionPolicy, std::optional<double> progressUpdateIntervalMs, std::optional<double> backgroundProgressUpdateIntervalMs): httpHeaders(httpHeaders), userAgent(userAgent), autoRetries(autoRetries), retryBackoffMs(retryBackoffMs), networkTimeoutMs(networkTimeoutMs), audioContentType(audioContentType), audioCategoryOptions(audioCategoryOptions), visualizationEnabled(visualizationEnabled), clampSeekToBuffered(clampSeekToBuffered), lookaheadCacheMaxSizeMb(lookaheadCacheMaxSizeMb), lookaheadCacheEvictionPolicy(lookaheadCacheEvictionPolicy), progressUpdateIntervalMs(progressUpdateIntervalMs), backgroundProgressUpdateIntervalMs(backgroundProgressUpdateIntervalMs) {}
69
+ explicit PlayerConfig(std::optional<std::unordered_map<std::string, std::string>> httpHeaders, std::optional<std::string> userAgent, std::optional<std::string> placeholderArtworkUri, std::optional<double> autoRetries, std::optional<double> retryBackoffMs, std::optional<double> networkTimeoutMs, std::optional<AudioContentType> audioContentType, std::optional<AudioCategoryOptions> audioCategoryOptions, std::optional<bool> visualizationEnabled, std::optional<bool> clampSeekToBuffered, std::optional<double> lookaheadCacheMaxSizeMb, std::optional<EvictionPolicy> lookaheadCacheEvictionPolicy, std::optional<double> progressUpdateIntervalMs, std::optional<double> backgroundProgressUpdateIntervalMs): httpHeaders(httpHeaders), userAgent(userAgent), placeholderArtworkUri(placeholderArtworkUri), autoRetries(autoRetries), retryBackoffMs(retryBackoffMs), networkTimeoutMs(networkTimeoutMs), audioContentType(audioContentType), audioCategoryOptions(audioCategoryOptions), visualizationEnabled(visualizationEnabled), clampSeekToBuffered(clampSeekToBuffered), lookaheadCacheMaxSizeMb(lookaheadCacheMaxSizeMb), lookaheadCacheEvictionPolicy(lookaheadCacheEvictionPolicy), progressUpdateIntervalMs(progressUpdateIntervalMs), backgroundProgressUpdateIntervalMs(backgroundProgressUpdateIntervalMs) {}
69
70
 
70
71
  public:
71
72
  friend bool operator==(const PlayerConfig& lhs, const PlayerConfig& rhs) = default;
@@ -83,6 +84,7 @@ namespace margelo::nitro {
83
84
  return margelo::nitro::queueplayer::PlayerConfig(
84
85
  JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "httpHeaders"))),
85
86
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "userAgent"))),
87
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "placeholderArtworkUri"))),
86
88
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "autoRetries"))),
87
89
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "retryBackoffMs"))),
88
90
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "networkTimeoutMs"))),
@@ -100,6 +102,7 @@ namespace margelo::nitro {
100
102
  jsi::Object obj(runtime);
101
103
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "httpHeaders"), JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::toJSI(runtime, arg.httpHeaders));
102
104
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "userAgent"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.userAgent));
105
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "placeholderArtworkUri"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.placeholderArtworkUri));
103
106
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "autoRetries"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.autoRetries));
104
107
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "retryBackoffMs"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.retryBackoffMs));
105
108
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "networkTimeoutMs"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.networkTimeoutMs));
@@ -123,6 +126,7 @@ namespace margelo::nitro {
123
126
  }
124
127
  if (!JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "httpHeaders")))) return false;
125
128
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "userAgent")))) return false;
129
+ if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "placeholderArtworkUri")))) return false;
126
130
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "autoRetries")))) return false;
127
131
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "retryBackoffMs")))) return false;
128
132
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "networkTimeoutMs")))) return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-queue-player",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Nitro Modules audio playback library for React Native — gapless, EQ, crossfade, automotive, voice, casting",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/index.d.ts",
package/src/types.ts CHANGED
@@ -69,6 +69,23 @@ export interface PlayerConfig {
69
69
  httpHeaders?: Record<string, string>;
70
70
  /** Overrides the default UA on network requests. */
71
71
  userAgent?: string;
72
+ /**
73
+ * Replacement for the built-in RNQP cover-art placeholder (the image
74
+ * shown before real artwork loads and when a track has no artwork).
75
+ * MUST be a **local `file://` URI** — the built-in placeholder is a
76
+ * local file, so this must be too; remote URLs are not loaded (they
77
+ * would break offline playback and change behaviour). When set, this
78
+ * image is used in place of the built-in everywhere the built-in is
79
+ * used; unset, non-`file://`, or unloadable falls back to the built-in.
80
+ * Resolve a bundled asset to a `file://` path with expo-asset —
81
+ * `const a = Asset.fromModule(require('./logo.png')); await
82
+ * a.downloadAsync();` then pass `a.localUri` — which copies the packaged
83
+ * image onto the filesystem across dev and release.
84
+ * (`Image.resolveAssetSource(...).uri` is not suitable: it is an
85
+ * `http://` Metro URL in dev and a drawable resource name on Android
86
+ * release, neither of which is a `file://` path.)
87
+ */
88
+ placeholderArtworkUri?: string;
72
89
  /**
73
90
  * Auto-retry attempts on transient errors (TIMEOUT / CONNECTION_LOST /
74
91
  * NETWORK_UNREACHABLE / SOURCE_UNREACHABLE / CANNOT_OPEN). Clamped