Created
February 17, 2020 05:25
-
-
Save jackpal/292b8cfbbaf9a892ccdad980d2d573c1 to your computer and use it in GitHub Desktop.
Combine pipeline for an image board slideshow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public extension Publisher { | |
/// Perform requests after a delay. | |
func slowRequest(delay: DispatchQueue.SchedulerTimeType.Stride) | |
-> AnyPublisher<Self.Output, Self.Failure> { | |
var firstItem = true | |
let serialQueue = DispatchQueue(label: "slowRequest") | |
return self | |
.flatMap(maxPublishers: .max(1)) { (item: Self.Output) | |
-> AnyPublisher<Self.Output, Self.Failure> in | |
if firstItem { | |
firstItem = false | |
return Just(item) | |
.setFailureType(to: Self.Failure.self).eraseToAnyPublisher() | |
} | |
return Just(item) | |
.setFailureType(to: Self.Failure.self) | |
.delay(for: delay, scheduler:serialQueue).eraseToAnyPublisher() | |
} | |
.eraseToAnyPublisher() | |
} | |
/// Repeat the upstream publisher count times. | |
func repeating(_ count: Int) -> AnyPublisher<Self.Output, Self.Failure> { | |
Publishers.Sequence(sequence: 0..<count) | |
.flatMap(maxPublishers: .max(1)) { (_: Int) | |
-> AnyPublisher<Self.Output, Self.Failure> in | |
return self | |
.eraseToAnyPublisher() | |
} | |
.eraseToAnyPublisher() | |
} | |
} | |
// Publishes all the images in a board. | |
func publisher(board:BoardName, targetLength: CGFloat) -> AnyPublisher<UIImage?, Never> { | |
FourChanService.shared.posts(board:board) | |
.filter { post in | |
// Filter out posts that don't have renderable images. | |
guard let size = post.renderableImageSize else { | |
return false | |
} | |
// Filter out posts where the renderable image is too small | |
return min(size.width, size.height) >= targetLength/8 | |
} | |
// When we get to the end of the stream, repeat. | |
.repeating(Int.max) | |
// Slow down requests to the slideshow rate. | |
.slowRequest(delay: 5) | |
.flatMap(maxPublishers: .max(1)) { post in | |
FourChanService.shared.dataPublisher(endpoint:post.image!) | |
.map { | |
ImageDataInContext(post:post, imageData:$0) | |
} | |
} | |
.tryMap { | |
if let image = downsample(imageData:$0.imageData, to: targetLength) { | |
return image | |
} | |
throw ImageLoaderError.couldNotDecodeImage | |
} | |
.map { Optional($0) } | |
.replaceError(with: nil) | |
.receive(on: DispatchQueue.main) | |
.eraseToAnyPublisher() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment