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 {
2022-10-10 13:14:52 +02:00
class LoadThreadState : GKState {
2022-01-27 14:23:39 +01:00
let logger = Logger ( subsystem : " ThreadViewModel.LoadThreadState " , category : " StateMachine " )
let id = UUID ( )
2021-04-13 13:46:42 +02:00
weak var viewModel : ThreadViewModel ?
init ( viewModel : ThreadViewModel ) {
self . viewModel = viewModel
}
override func didEnter ( from previousState : GKState ? ) {
2022-01-27 14:23:39 +01:00
super . didEnter ( from : previousState )
2022-10-10 13:14:52 +02:00
let from = previousState . flatMap { String ( describing : $0 ) } ? ? " nil "
let to = String ( describing : self )
logger . log ( level : . debug , " \( ( #file as NSString ) . lastPathComponent , privacy : . public ) [ \( #line , privacy : . public ) ], \( #function , privacy : . public ) : \( from ) -> \( to ) " )
2022-01-27 14:23:39 +01:00
}
@ MainActor
func enter ( state : LoadThreadState . Type ) {
stateMachine ? . enter ( state )
}
deinit {
2022-10-10 13:14:52 +02:00
logger . log ( level : . debug , " \( ( #file as NSString ) . lastPathComponent , privacy : . public ) [ \( #line , privacy : . public ) ], \( #function , privacy : . public ) : [ \( self . id . uuidString ) ] \( String ( describing : self ) ) " )
2021-04-13 13:46:42 +02:00
}
}
}
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
2022-01-27 14:23:39 +01:00
case is NoMore . Type : return true
2021-04-13 13:46:42 +02:00
default : return false
}
}
override func didEnter ( from previousState : GKState ? ) {
super . didEnter ( from : previousState )
2022-01-27 14:23:39 +01:00
2021-04-13 13:46:42 +02:00
guard let viewModel = viewModel , let stateMachine = stateMachine else { return }
2022-10-09 14:07:57 +02:00
2022-01-27 14:23:39 +01:00
guard let threadContext = viewModel . threadContext else {
2021-04-13 13:46:42 +02:00
stateMachine . enter ( Fail . self )
return
}
2023-01-01 10:00:00 +01:00
Task { @ MainActor in
2022-01-27 14:23:39 +01:00
do {
let response = try await viewModel . context . apiService . statusContext (
statusID : threadContext . statusID ,
2023-01-02 00:55:54 +01:00
authenticationBox : viewModel . authContext . mastodonAuthenticationBox
2022-01-27 14:23:39 +01:00
)
await enter ( state : NoMore . self )
// a s s e r t ( ! T h r e a d . i s M a i n T h r e a d )
// a w a i t T a s k . s l e e p ( 1 _ 0 0 0 _ 0 0 0 _ 0 0 0 ) / / 1 s d e l a y t o p r e v e n t U I r e n d e r i s s u e
viewModel . mastodonStatusThreadViewModel . appendAncestor (
domain : threadContext . domain ,
nodes : MastodonStatusThreadViewModel . Node . replyToThread (
for : threadContext . replyToID ,
from : response . value . ancestors
)
)
2022-11-17 17:16:21 +01:00
// d e p r e c a t e d : T r e e m o d e r e p l i e s
// v i e w M o d e l . m a s t o d o n S t a t u s T h r e a d V i e w M o d e l . a p p e n d D e s c e n d a n t (
// d o m a i n : t h r e a d C o n t e x t . d o m a i n ,
// n o d e s : M a s t o d o n S t a t u s T h r e a d V i e w M o d e l . N o d e . c h i l d r e n (
// o f : t h r e a d C o n t e x t . s t a t u s I D ,
// f r o m : r e s p o n s e . v a l u e . d e s c e n d a n t s
// )
// )
// n e w : t h e s a m e o r d e r f r o m A P I
2022-01-27 14:23:39 +01:00
viewModel . mastodonStatusThreadViewModel . appendDescendant (
domain : threadContext . domain ,
2022-11-17 17:16:21 +01:00
nodes : response . value . descendants . map { status in
return . init ( statusID : status . id , children : [ ] )
}
2022-01-27 14:23:39 +01:00
)
} catch {
logger . log ( level : . debug , " \( ( #file as NSString ) . lastPathComponent , privacy : . public ) [ \( #line , privacy : . public ) ], \( #function , privacy : . public ) : fetch status context for \( threadContext . statusID ) fail: \( error . localizedDescription ) " )
await enter ( state : Fail . self )
2021-04-13 13:46:42 +02:00
}
2022-11-17 17:16:21 +01:00
} // e n d T a s k
2021-04-13 13:46:42 +02:00
}
}
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
}
}
}