139 lines
4.4 KiB
Swift
139 lines
4.4 KiB
Swift
//
|
|
// MastodonAttachmentService.swift
|
|
// Mastodon
|
|
//
|
|
// Created by MainasuK Cirno on 2021-3-17.
|
|
//
|
|
|
|
import UIKit
|
|
import Combine
|
|
import PhotosUI
|
|
import Kingfisher
|
|
import GameplayKit
|
|
import MastodonSDK
|
|
|
|
protocol MastodonAttachmentServiceDelegate: class {
|
|
func mastodonAttachmentService(_ service: MastodonAttachmentService, uploadStateDidChange state: MastodonAttachmentService.UploadState?)
|
|
}
|
|
|
|
final class MastodonAttachmentService {
|
|
|
|
var disposeBag = Set<AnyCancellable>()
|
|
weak var delegate: MastodonAttachmentServiceDelegate?
|
|
|
|
let identifier = UUID()
|
|
|
|
// input
|
|
let context: AppContext
|
|
var authenticationBox: AuthenticationService.MastodonAuthenticationBox?
|
|
|
|
// output
|
|
// TODO: handle video/GIF/Audio data
|
|
let imageData = CurrentValueSubject<Data?, Never>(nil)
|
|
let attachment = CurrentValueSubject<Mastodon.Entity.Attachment?, Never>(nil)
|
|
let description = CurrentValueSubject<String?, Never>(nil)
|
|
let error = CurrentValueSubject<Error?, Never>(nil)
|
|
|
|
private(set) lazy var uploadStateMachine: GKStateMachine = {
|
|
// exclude timeline middle fetcher state
|
|
let stateMachine = GKStateMachine(states: [
|
|
UploadState.Initial(service: self),
|
|
UploadState.Uploading(service: self),
|
|
UploadState.Fail(service: self),
|
|
UploadState.Finish(service: self),
|
|
])
|
|
stateMachine.enter(UploadState.Initial.self)
|
|
return stateMachine
|
|
}()
|
|
lazy var uploadStateMachineSubject = CurrentValueSubject<MastodonAttachmentService.UploadState?, Never>(nil)
|
|
|
|
init(
|
|
context: AppContext,
|
|
pickerResult: PHPickerResult,
|
|
initalAuthenticationBox: AuthenticationService.MastodonAuthenticationBox?
|
|
) {
|
|
self.context = context
|
|
self.authenticationBox = initalAuthenticationBox
|
|
// end init
|
|
|
|
setupServiceObserver()
|
|
|
|
PHPickerResultLoader.loadImageData(from: pickerResult)
|
|
.sink { [weak self] completion in
|
|
guard let self = self else { return }
|
|
switch completion {
|
|
case .failure(let error):
|
|
self.error.value = error
|
|
self.uploadStateMachine.enter(UploadState.Fail.self)
|
|
case .finished:
|
|
break
|
|
}
|
|
} receiveValue: { [weak self] imageData in
|
|
guard let self = self else { return }
|
|
self.imageData.value = imageData
|
|
self.uploadStateMachine.enter(UploadState.Initial.self)
|
|
}
|
|
.store(in: &disposeBag)
|
|
}
|
|
|
|
init(
|
|
context: AppContext,
|
|
image: UIImage,
|
|
initalAuthenticationBox: AuthenticationService.MastodonAuthenticationBox?
|
|
) {
|
|
self.context = context
|
|
self.authenticationBox = initalAuthenticationBox
|
|
// end init
|
|
|
|
setupServiceObserver()
|
|
|
|
imageData.value = image.jpegData(compressionQuality: 0.75)
|
|
uploadStateMachine.enter(UploadState.Initial.self)
|
|
}
|
|
|
|
init(
|
|
context: AppContext,
|
|
imageData: Data,
|
|
initalAuthenticationBox: AuthenticationService.MastodonAuthenticationBox?
|
|
) {
|
|
self.context = context
|
|
self.authenticationBox = initalAuthenticationBox
|
|
// end init
|
|
|
|
setupServiceObserver()
|
|
|
|
self.imageData.value = imageData
|
|
uploadStateMachine.enter(UploadState.Initial.self)
|
|
}
|
|
|
|
private func setupServiceObserver() {
|
|
uploadStateMachineSubject
|
|
.sink { [weak self] state in
|
|
guard let self = self else { return }
|
|
self.delegate?.mastodonAttachmentService(self, uploadStateDidChange: state)
|
|
}
|
|
.store(in: &disposeBag)
|
|
}
|
|
|
|
}
|
|
|
|
extension MastodonAttachmentService {
|
|
// FIXME: needs reset state for multiple account posting support
|
|
func uploading(mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox) -> Bool {
|
|
authenticationBox = mastodonAuthenticationBox
|
|
return uploadStateMachine.enter(UploadState.self)
|
|
}
|
|
}
|
|
|
|
extension MastodonAttachmentService: Equatable, Hashable {
|
|
|
|
static func == (lhs: MastodonAttachmentService, rhs: MastodonAttachmentService) -> Bool {
|
|
return lhs.identifier == rhs.identifier
|
|
}
|
|
|
|
func hash(into hasher: inout Hasher) {
|
|
hasher.combine(identifier)
|
|
}
|
|
|
|
}
|