react-native-audio-browser 0.2.0-next.28 → 0.2.0-next.29
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/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +3 -4
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +2 -2
- package/ios/AVPlayerEngine.swift +334 -0
- package/ios/AVPlayerEngineCallbacks.swift +15 -0
- package/ios/Browser/BrowseGate.swift +58 -0
- package/ios/Browser/BrowserConfig.swift +31 -89
- package/ios/Browser/BrowserManager.swift +68 -487
- package/ios/Browser/NavigationErrorState.swift +41 -0
- package/ios/Browser/PageResolver.swift +227 -0
- package/ios/Browser/RequestLayer.swift +90 -0
- package/ios/Browser/{BrowserManager+URLResolution.swift → RequestPipeline.swift} +175 -107
- package/ios/CarPlay/CPInterfaceController+Safe.swift +11 -24
- package/ios/CarPlay/CarPlayArtworkResolver.swift +35 -83
- package/ios/CarPlay/CarPlayController.swift +42 -1442
- package/ios/CarPlay/CarPlayImageLoader.swift +42 -83
- package/ios/CarPlay/CarPlayListItemFactory.swift +9 -23
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +119 -129
- package/ios/CarPlay/CarPlaySession+Navigator.swift +114 -0
- package/ios/CarPlay/CarPlaySession+PageLoader.swift +92 -0
- package/ios/CarPlay/CarPlaySession+Refresher.swift +43 -0
- package/ios/CarPlay/CarPlaySession+TabBar.swift +193 -0
- package/ios/CarPlay/CarPlaySession.swift +209 -0
- package/ios/CarPlay/CarPlayTemplates.swift +63 -0
- package/ios/CarPlay/HybridAudioBrowser+IntentFavorite.swift +20 -0
- package/ios/CarPlay/MediaIntentPlayback.swift +74 -0
- package/ios/CarPlay/RNABMediaAddHandler.swift +2 -18
- package/ios/CarPlay/RNABMediaAffinityHandler.swift +5 -21
- package/ios/CarPlay/RNABMediaIntentHandler.swift +2 -3
- package/ios/Extension/NavigationError+Conversion.swift +7 -4
- package/ios/Extension/UIImage+Adaptive.swift +12 -0
- package/ios/Extension/URLError+Connectivity.swift +15 -0
- package/ios/Http/HttpClient.swift +63 -145
- package/ios/HybridAudioBrowser+Browser.swift +153 -0
- package/ios/HybridAudioBrowser+Options.swift +144 -0
- package/ios/HybridAudioBrowser+Player.swift +397 -0
- package/ios/HybridAudioBrowser+PlayerCallbacks.swift +190 -0
- package/ios/HybridAudioBrowser+Stubs.swift +46 -0
- package/ios/HybridAudioBrowser.swift +74 -1687
- package/ios/Model/NitroTypeStubs.swift +18 -1
- package/ios/Model/PlayerUpdateOptions.swift +1 -1
- package/ios/NowPlayingInfo/NowPlayingInfoController.swift +18 -53
- package/ios/Observer/ItemObserver.swift +90 -0
- package/ios/Observer/PlayerObserver.swift +59 -0
- package/ios/Option/SessionCategories.swift +41 -92
- package/ios/Player/AudioSessionController.swift +177 -0
- package/ios/Player/DeferredSeek.swift +70 -0
- package/ios/Player/ErrorStatus.swift +27 -0
- package/ios/Player/MediaLoader.swift +24 -11
- package/ios/Player/NowPlayingUpdater.swift +157 -58
- package/ios/Player/PlaybackFailure.swift +125 -0
- package/ios/Player/PlaybackPersistence.swift +73 -0
- package/ios/Player/Player.swift +1083 -0
- package/ios/Player/{PlaybackCoordinatorCallbacks.swift → PlayerCallbacks.swift} +3 -4
- package/ios/Player/PlayerEngine.swift +89 -0
- package/ios/Player/PlayerStatusTypes.swift +2 -6
- package/ios/Player/QueueManager.swift +52 -59
- package/ios/Player/RetryLoop.swift +261 -0
- package/ios/Player/SleepTimerManager.swift +1 -1
- package/ios/RemoteCommand/RemoteCommandCallbacks.swift +2 -3
- package/ios/RemoteCommand/RemoteCommandController.swift +85 -367
- package/ios/Tests/CarPlayArtworkResolverTests.swift +60 -356
- package/ios/Tests/DeferredSeekTests.swift +70 -0
- package/ios/Tests/EmitterTests.swift +29 -0
- package/ios/Tests/GenerationMemoTests.swift +121 -0
- package/ios/Tests/LRUCacheTests.swift +4 -5
- package/ios/Tests/MediaLoaderTests.swift +12 -33
- package/ios/Tests/ObserverTests.swift +88 -0
- package/ios/Tests/PlaybackErrorTests.swift +76 -0
- package/ios/Tests/PlaybackFailureTests.swift +189 -0
- package/ios/Tests/PlaybackPersistenceTests.swift +93 -0
- package/ios/Tests/PlayerPolicyTests.swift +405 -0
- package/ios/Tests/{PlaybackCoordinatorTests.swift → PlayerTests.swift} +298 -248
- package/ios/Tests/PlayingStateTests.swift +42 -0
- package/ios/Tests/QueueManagerTests.swift +76 -107
- package/ios/Tests/ReadyValueTests.swift +73 -0
- package/ios/Tests/RemoteCommandControllerTests.swift +10 -30
- package/ios/Tests/RemoteCommandTests.swift +2 -4
- package/ios/Tests/RequestLayerTests.swift +112 -0
- package/ios/Tests/RetryLoopTests.swift +270 -0
- package/ios/Tests/Support/TestTypes.swift +111 -112
- package/ios/Tests/TrackIdTemplateTests.swift +1 -1
- package/ios/Tests/URLErrorConnectivityTests.swift +20 -0
- package/ios/TrackSelector.swift +1 -1
- package/ios/Util/ArtworkImageFetcher.swift +42 -0
- package/ios/Util/Emitter.swift +42 -0
- package/ios/Util/GenerationMemo.swift +36 -0
- package/ios/Util/LRUCache.swift +23 -162
- package/ios/Util/NetworkMonitor.swift +1 -1
- package/ios/Util/ReadyValue.swift +56 -0
- package/ios/Util/SFSymbolRenderer.swift +35 -29
- package/ios/Util/SVGProcessor.swift +0 -10
- package/lib/commonjs/web/NativeAudioBrowser.js +1 -1
- package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +1 -1
- package/lib/module/web/NativeAudioBrowser.js +1 -1
- package/lib/module/web/TrackPlayer/PlayingStateFactory.js +1 -1
- package/lib/typescript/src/types/browser.d.ts +3 -3
- package/package.json +1 -1
- package/src/types/browser.ts +3 -3
- package/src/web/NativeAudioBrowser.ts +1 -1
- package/src/web/TrackPlayer/PlayingStateFactory.test.ts +1 -1
- package/src/web/TrackPlayer/PlayingStateFactory.ts +1 -1
- package/ios/Bridge.h +0 -8
- package/ios/Browser/MediaResolveComposer.swift +0 -114
- package/ios/NowPlayingInfo/MediaItemProperty.swift +0 -78
- package/ios/NowPlayingInfo/NowPlayingInfoKeyValue.swift +0 -6
- package/ios/NowPlayingInfo/NowPlayingInfoProperty.swift +0 -220
- package/ios/Observer/PlayerItemNotificationObserver.swift +0 -119
- package/ios/Observer/PlayerItemPropertyObserver.swift +0 -133
- package/ios/Observer/PlayerStateObserver.swift +0 -50
- package/ios/Observer/PlayerTimeObserver.swift +0 -55
- package/ios/Option/PitchAlgorithms.swift +0 -17
- package/ios/Option/TimeEventFrequency.swift +0 -18
- package/ios/Player/LoadSeekCoordinator.swift +0 -99
- package/ios/Player/MediaLoaderDelegate.swift +0 -11
- package/ios/Player/PlaybackCoordinator.swift +0 -761
- package/ios/Player/PlaybackEffectHandler.swift +0 -54
- package/ios/Player/PlaybackErrorHandler.swift +0 -175
- package/ios/Player/PlaybackStateStore.swift +0 -27
- package/ios/Player/PlayingStateManager.swift +0 -33
- package/ios/Player/RetryManager.swift +0 -384
- package/ios/Player/SeekCompletionHandler.swift +0 -5
- package/ios/Player/SleepTimerHandling.swift +0 -28
- package/ios/Support/RNTrackPlayer-Bridging-Header.h +0 -7
- package/ios/Tests/LoadSeekCoordinatorTests.swift +0 -327
- package/ios/Tests/MediaResolveTests.swift +0 -126
- package/ios/Tests/OnceValueTests.swift +0 -79
- package/ios/Tests/PlaybackErrorHandlerTests.swift +0 -549
- package/ios/Tests/PlaybackStateStoreTests.swift +0 -49
- package/ios/Tests/PlayerTimeObserverTests.swift +0 -37
- package/ios/Tests/PlayingStateManagerTests.swift +0 -57
- package/ios/Tests/RetryManagerTests.swift +0 -178
- package/ios/TrackPlayer.swift +0 -1042
- package/ios/TrackPlayerCallbacks.swift +0 -53
- package/ios/Util/MetadataAdapter.swift +0 -131
- package/ios/Util/OnceValue.swift +0 -104
- /package/ios/{Player → CarPlay}/MediaIntentCriteria.swift +0 -0
- /package/ios/{Browser → CarPlay}/SectionPresentation.swift +0 -0
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import AVFoundation
|
|
2
|
-
import MediaPlayer
|
|
3
|
-
import NitroModules
|
|
4
|
-
|
|
5
|
-
/// Callbacks for all player events.
|
|
6
|
-
///
|
|
7
|
-
/// This protocol defines the interface for receiving events from TrackPlayer.
|
|
8
|
-
/// HybridAudioBrowser implements this protocol to bridge events to JavaScript.
|
|
9
|
-
/// Note: Method names are prefixed to avoid conflicts with JS callback property names.
|
|
10
|
-
/// All callbacks are called from the main actor since TrackPlayer is @MainActor.
|
|
11
|
-
///
|
|
12
|
-
/// Extends PlaybackCoordinatorCallbacks for the state machine / coordinator callbacks
|
|
13
|
-
/// and RemoteCommandCallbacks for the remote-command events, then adds metadata,
|
|
14
|
-
/// seek, and configuration callbacks that are TrackPlayer-specific.
|
|
15
|
-
@MainActor
|
|
16
|
-
protocol TrackPlayerCallbacks: PlaybackCoordinatorCallbacks, RemoteCommandCallbacks {
|
|
17
|
-
// MARK: - Metadata Events
|
|
18
|
-
|
|
19
|
-
/// Called when common metadata is received.
|
|
20
|
-
func playerDidReceiveCommonMetadata(_ metadata: [AVMetadataItem])
|
|
21
|
-
|
|
22
|
-
/// Called when timed metadata is received.
|
|
23
|
-
func playerDidReceiveTimedMetadata(_ metadata: [AVTimedMetadataGroup])
|
|
24
|
-
|
|
25
|
-
/// Called when chapter metadata is received.
|
|
26
|
-
func playerDidReceiveChapterMetadata(_ metadata: [AVTimedMetadataGroup])
|
|
27
|
-
|
|
28
|
-
// MARK: - Playback Events
|
|
29
|
-
|
|
30
|
-
/// Called when a seek operation completes.
|
|
31
|
-
func playerDidCompleteSeek(position: Double, didFinish: Bool)
|
|
32
|
-
|
|
33
|
-
/// Called when the duration is updated.
|
|
34
|
-
func playerDidUpdateDuration(_ duration: Double)
|
|
35
|
-
|
|
36
|
-
// MARK: - Remote Control Events
|
|
37
|
-
|
|
38
|
-
// The command-center events live in RemoteCommandCallbacks, inherited above.
|
|
39
|
-
|
|
40
|
-
/// Called when change playback position is triggered remotely.
|
|
41
|
-
func remoteChangePlaybackPosition(position: Double)
|
|
42
|
-
|
|
43
|
-
/// Called when play from ID is triggered remotely.
|
|
44
|
-
func remotePlayId(id: String, index: Int?)
|
|
45
|
-
|
|
46
|
-
/// Called when play from search is triggered remotely.
|
|
47
|
-
func remotePlaySearch(query: String)
|
|
48
|
-
|
|
49
|
-
// MARK: - Configuration Events
|
|
50
|
-
|
|
51
|
-
/// Called when options are changed.
|
|
52
|
-
func playerDidChangeOptions(_ options: PlayerUpdateOptions)
|
|
53
|
-
}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import AVFoundation
|
|
2
|
-
import Foundation
|
|
3
|
-
|
|
4
|
-
typealias RawMetadataGroup = [[String: Any]]
|
|
5
|
-
|
|
6
|
-
class MetadataAdapter {
|
|
7
|
-
private static func getMetadataItem(
|
|
8
|
-
metadata: [AVMetadataItem],
|
|
9
|
-
forIdentifier: AVMetadataIdentifier,
|
|
10
|
-
) -> String? {
|
|
11
|
-
AVMetadataItem.metadataItems(from: metadata, filteredByIdentifier: forIdentifier).first?
|
|
12
|
-
.stringValue
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
private static func convertToSerializableItems(items: [AVMetadataItem]) -> RawMetadataGroup {
|
|
16
|
-
var rawGroup: RawMetadataGroup = []
|
|
17
|
-
|
|
18
|
-
for metadataItem in items {
|
|
19
|
-
var rawMetadataItem: [String: Any] = [:]
|
|
20
|
-
|
|
21
|
-
if CMTIME_IS_VALID(metadataItem.time), CMTIME_IS_NUMERIC(metadataItem.time) {
|
|
22
|
-
rawMetadataItem["time"] = metadataItem.time.seconds
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
rawMetadataItem["value"] = metadataItem.value
|
|
26
|
-
rawMetadataItem["key"] = metadataItem.key
|
|
27
|
-
if let commonKey = metadataItem.commonKey?.rawValue {
|
|
28
|
-
rawMetadataItem["commonKey"] = commonKey
|
|
29
|
-
}
|
|
30
|
-
if let keySpace = metadataItem.keySpace?.rawValue {
|
|
31
|
-
rawMetadataItem["keySpace"] = keySpace
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
rawGroup.append(rawMetadataItem)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return rawGroup
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// MARK: - Public
|
|
41
|
-
|
|
42
|
-
static func convertToGroupedMetadata(metadataGroups: [AVTimedMetadataGroup]) -> RawMetadataGroup {
|
|
43
|
-
var ret: RawMetadataGroup = []
|
|
44
|
-
|
|
45
|
-
for metadataGroup in metadataGroups {
|
|
46
|
-
let entry = convertToCommonMetadata(metadata: metadataGroup.items)
|
|
47
|
-
ret.append(entry)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return ret
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static func convertToCommonMetadata(
|
|
54
|
-
metadata: [AVMetadataItem],
|
|
55
|
-
skipRaw: Bool = false,
|
|
56
|
-
) -> [String: Any] {
|
|
57
|
-
var rawMetadataItem: [String: Any] = [:]
|
|
58
|
-
rawMetadataItem["title"] = getMetadataItem(
|
|
59
|
-
metadata: metadata,
|
|
60
|
-
forIdentifier: .commonIdentifierTitle,
|
|
61
|
-
)
|
|
62
|
-
rawMetadataItem["artist"] = getMetadataItem(
|
|
63
|
-
metadata: metadata,
|
|
64
|
-
forIdentifier: .commonIdentifierArtist,
|
|
65
|
-
)
|
|
66
|
-
rawMetadataItem["albumName"] = getMetadataItem(
|
|
67
|
-
metadata: metadata,
|
|
68
|
-
forIdentifier: .commonIdentifierAlbumName,
|
|
69
|
-
)
|
|
70
|
-
rawMetadataItem["subtitle"] = getMetadataItem(
|
|
71
|
-
metadata: metadata,
|
|
72
|
-
forIdentifier: .id3MetadataSetSubtitle,
|
|
73
|
-
)
|
|
74
|
-
?? getMetadataItem(metadata: metadata, forIdentifier: .iTunesMetadataTrackSubTitle)
|
|
75
|
-
rawMetadataItem["description"] = getMetadataItem(
|
|
76
|
-
metadata: metadata,
|
|
77
|
-
forIdentifier: .commonIdentifierDescription,
|
|
78
|
-
)
|
|
79
|
-
rawMetadataItem["artworkUri"] = getMetadataItem(
|
|
80
|
-
metadata: metadata,
|
|
81
|
-
forIdentifier: .commonIdentifierArtwork,
|
|
82
|
-
)
|
|
83
|
-
rawMetadataItem["trackNumber"] = getMetadataItem(
|
|
84
|
-
metadata: metadata,
|
|
85
|
-
forIdentifier: .id3MetadataTrackNumber,
|
|
86
|
-
)
|
|
87
|
-
?? getMetadataItem(metadata: metadata, forIdentifier: .iTunesMetadataTrackNumber)
|
|
88
|
-
rawMetadataItem["composer"] = getMetadataItem(
|
|
89
|
-
metadata: metadata,
|
|
90
|
-
forIdentifier: .id3MetadataComposer,
|
|
91
|
-
)
|
|
92
|
-
?? getMetadataItem(metadata: metadata, forIdentifier: .iTunesMetadataComposer)
|
|
93
|
-
?? getMetadataItem(metadata: metadata, forIdentifier: .quickTimeMetadataComposer)
|
|
94
|
-
rawMetadataItem["conductor"] = getMetadataItem(
|
|
95
|
-
metadata: metadata,
|
|
96
|
-
forIdentifier: .id3MetadataConductor,
|
|
97
|
-
)
|
|
98
|
-
?? getMetadataItem(metadata: metadata, forIdentifier: .iTunesMetadataConductor)
|
|
99
|
-
rawMetadataItem["genre"] = getMetadataItem(
|
|
100
|
-
metadata: metadata,
|
|
101
|
-
forIdentifier: .quickTimeMetadataGenre,
|
|
102
|
-
)
|
|
103
|
-
rawMetadataItem["compilation"] = getMetadataItem(
|
|
104
|
-
metadata: metadata,
|
|
105
|
-
forIdentifier: .iTunesMetadataDiscCompilation,
|
|
106
|
-
)
|
|
107
|
-
rawMetadataItem["station"] = getMetadataItem(
|
|
108
|
-
metadata: metadata,
|
|
109
|
-
forIdentifier: .id3MetadataInternetRadioStationName,
|
|
110
|
-
)
|
|
111
|
-
rawMetadataItem["mediaType"] = getMetadataItem(
|
|
112
|
-
metadata: metadata,
|
|
113
|
-
forIdentifier: .id3MetadataMediaType,
|
|
114
|
-
)
|
|
115
|
-
rawMetadataItem["creationDate"] = getMetadataItem(
|
|
116
|
-
metadata: metadata,
|
|
117
|
-
forIdentifier: .commonIdentifierCreationDate,
|
|
118
|
-
)
|
|
119
|
-
rawMetadataItem["creationYear"] = getMetadataItem(
|
|
120
|
-
metadata: metadata,
|
|
121
|
-
forIdentifier: .id3MetadataYear,
|
|
122
|
-
)
|
|
123
|
-
?? getMetadataItem(metadata: metadata, forIdentifier: .quickTimeMetadataYear)
|
|
124
|
-
|
|
125
|
-
if !skipRaw {
|
|
126
|
-
rawMetadataItem["raw"] = convertToSerializableItems(items: metadata)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return rawMetadataItem
|
|
130
|
-
}
|
|
131
|
-
}
|
package/ios/Util/OnceValue.swift
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
|
|
3
|
-
/// Guards a continuation that two racing tasks may try to resume, so exactly
|
|
4
|
-
/// one wins (see `OnceValue.wait(timeout:)`).
|
|
5
|
-
private final class OneShot: @unchecked Sendable {
|
|
6
|
-
private let lock = NSLock()
|
|
7
|
-
private var claimed = false
|
|
8
|
-
func claim() -> Bool {
|
|
9
|
-
lock.lock()
|
|
10
|
-
defer { lock.unlock() }
|
|
11
|
-
if claimed { return false }
|
|
12
|
-
claimed = true
|
|
13
|
-
return true
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/// A thread-safe primitive that resolves to a value once, allowing multiple waiters.
|
|
18
|
-
/// Once resolved, all current and future `wait()` calls return immediately with the value.
|
|
19
|
-
final class OnceValue<T: Sendable>: @unchecked Sendable {
|
|
20
|
-
private var continuations: [CheckedContinuation<T, Never>] = []
|
|
21
|
-
private var value: T?
|
|
22
|
-
private let lock = NSLock()
|
|
23
|
-
private let provider: (() -> T?)?
|
|
24
|
-
|
|
25
|
-
/// Creates a OnceValue with a provider closure that returns the value when ready.
|
|
26
|
-
/// Call `check()` to attempt resolution using the provider.
|
|
27
|
-
init(provider: @escaping () -> T?) {
|
|
28
|
-
self.provider = provider
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/// Creates a OnceValue without a provider. Use `resolve(_:)` to set the value manually.
|
|
32
|
-
init() {
|
|
33
|
-
self.provider = nil
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/// Checks if the value is ready using the provider closure.
|
|
37
|
-
/// If the provider returns a value, resolves and resumes all waiters.
|
|
38
|
-
func check() {
|
|
39
|
-
guard let provider, let value = provider() else { return }
|
|
40
|
-
resolve(value)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/// Resolves the value, resuming all waiting continuations.
|
|
44
|
-
/// Subsequent calls are ignored if already resolved.
|
|
45
|
-
func resolve(_ value: T) {
|
|
46
|
-
lock.lock()
|
|
47
|
-
guard self.value == nil else {
|
|
48
|
-
lock.unlock()
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
self.value = value
|
|
52
|
-
let pending = continuations
|
|
53
|
-
continuations.removeAll()
|
|
54
|
-
lock.unlock()
|
|
55
|
-
|
|
56
|
-
for continuation in pending {
|
|
57
|
-
continuation.resume(returning: value)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/// Waits for the value to be resolved. Returns immediately if already resolved.
|
|
62
|
-
func wait() async -> T {
|
|
63
|
-
// All lock operations happen inside the synchronous continuation closure
|
|
64
|
-
// to avoid Swift concurrency warnings about locks in async contexts
|
|
65
|
-
await withCheckedContinuation { continuation in
|
|
66
|
-
lock.lock()
|
|
67
|
-
if let value {
|
|
68
|
-
lock.unlock()
|
|
69
|
-
continuation.resume(returning: value)
|
|
70
|
-
} else {
|
|
71
|
-
continuations.append(continuation)
|
|
72
|
-
lock.unlock()
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/// Waits for the value to be resolved, giving up after `timeout`.
|
|
78
|
-
/// Returns the value, or nil if the timeout elapses first.
|
|
79
|
-
///
|
|
80
|
-
/// Continuations aren't cancellable, so the internal waiter stays registered
|
|
81
|
-
/// past a timeout; it resumes harmlessly (into a one-shot guard) if the value
|
|
82
|
-
/// resolves later.
|
|
83
|
-
func wait(timeout: Duration) async -> T? {
|
|
84
|
-
let oneShot = OneShot()
|
|
85
|
-
return await withCheckedContinuation { continuation in
|
|
86
|
-
Task {
|
|
87
|
-
let value = await self.wait()
|
|
88
|
-
if oneShot.claim() { continuation.resume(returning: value) }
|
|
89
|
-
}
|
|
90
|
-
Task {
|
|
91
|
-
try? await Task.sleep(for: timeout)
|
|
92
|
-
if oneShot.claim() { continuation.resume(returning: nil) }
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/// Resets the value, allowing it to be resolved again.
|
|
98
|
-
/// Any pending waiters will continue waiting for the next resolve.
|
|
99
|
-
func reset() {
|
|
100
|
-
lock.lock()
|
|
101
|
-
value = nil
|
|
102
|
-
lock.unlock()
|
|
103
|
-
}
|
|
104
|
-
}
|
|
File without changes
|
|
File without changes
|