2021-04-13 13:46:42 +02:00
//
// T h r e a d V i e w M o d e l + L o a d T h r e a d S t a t e . s w i f t
// M a s t o d o n
//
// C r e a t e d b y M a i n a s u K C i r n o o n 2 0 2 1 - 4 - 1 2 .
//
import os . log
import Foundation
import Combine
import GameplayKit
import CoreDataStack
import MastodonSDK
extension ThreadViewModel {
class LoadThreadState : GKState {
weak var viewModel : ThreadViewModel ?
init ( viewModel : ThreadViewModel ) {
self . viewModel = viewModel
}
override func didEnter ( from previousState : GKState ? ) {
os_log ( " %{public}s[%{public}ld], %{public}s: enter %s, previous: %s " , ( ( #file as NSString ) . lastPathComponent ) , #line , #function , self . debugDescription , previousState . debugDescription )
}
}
}
extension ThreadViewModel . LoadThreadState {
class Initial : ThreadViewModel . LoadThreadState {
override func isValidNextState ( _ stateClass : AnyClass ) -> Bool {
switch stateClass {
case is Loading . Type : return true
default : return false
}
}
}
class Loading : ThreadViewModel . LoadThreadState {
override func isValidNextState ( _ stateClass : AnyClass ) -> Bool {
switch stateClass {
case is Fail . Type : return true
case is NoMore . Type : return true
default : return false
}
}
override func didEnter ( from previousState : GKState ? ) {
super . didEnter ( from : previousState )
guard let viewModel = viewModel , let stateMachine = stateMachine else { return }
guard let mastodonAuthenticationBox = viewModel . context . authenticationService . activeMastodonAuthenticationBox . value else {
stateMachine . enter ( Fail . self )
return
}
guard let rootNode = viewModel . rootNode . value else {
stateMachine . enter ( Fail . self )
return
}
// t r i g g e r d a t a s o u r c e u p d a t e
viewModel . rootItem . value = viewModel . rootItem . value
let domain = rootNode . domain
let statusID = rootNode . statusID
let replyToID = rootNode . replyToID
viewModel . context . apiService . statusContext (
domain : domain ,
statusID : statusID ,
mastodonAuthenticationBox : mastodonAuthenticationBox
)
. sink { completion in
switch completion {
case . failure ( let error ) :
os_log ( . info , log : . debug , " %{public}s[%{public}ld], %{public}s: fetch status context for %s fail: %s " , ( ( #file as NSString ) . lastPathComponent ) , #line , #function , statusID , error . localizedDescription )
stateMachine . enter ( Fail . self )
case . finished :
break
}
} receiveValue : { response in
stateMachine . enter ( NoMore . self )
viewModel . ancestorNodes . value = ThreadViewModel . ReplyNode . replyToThread (
for : replyToID ,
from : response . value . ancestors ,
domain : domain ,
managedObjectContext : viewModel . context . managedObjectContext
)
viewModel . descendantNodes . value = ThreadViewModel . LeafNode . tree (
for : rootNode . statusID ,
from : response . value . descendants ,
domain : domain ,
managedObjectContext : viewModel . context . managedObjectContext
)
}
. store ( in : & viewModel . disposeBag )
}
}
class Fail : ThreadViewModel . LoadThreadState {
override func isValidNextState ( _ stateClass : AnyClass ) -> Bool {
switch stateClass {
case is Loading . Type : return true
default : return false
}
}
override func didEnter ( from previousState : GKState ? ) {
super . didEnter ( from : previousState )
2021-05-31 11:07:32 +02:00
guard let _ = viewModel , let stateMachine = stateMachine else { return }
2021-04-13 13:46:42 +02:00
DispatchQueue . main . asyncAfter ( deadline : . now ( ) + 3 ) {
stateMachine . enter ( Loading . self )
}
}
}
class NoMore : ThreadViewModel . LoadThreadState {
override func isValidNextState ( _ stateClass : AnyClass ) -> Bool {
return false
}
}
}