2018-09-18 16:59:07 +00:00
//
// S t a t u s C a c h e . s w i f t
// T u s k e r
//
// C r e a t e d b y S h a d o w f a c t s o n 9 / 1 7 / 1 8 .
// C o p y r i g h t © 2 0 1 8 S h a d o w f a c t s . A l l r i g h t s r e s e r v e d .
//
import Foundation
2019-08-02 03:01:15 +00:00
import Combine
2018-09-18 16:59:07 +00:00
import Pachyderm
class MastodonCache {
2020-01-06 00:54:28 +00:00
private var statuses = CachedDictionary < Status > ( name : " Statuses " )
private var accounts = CachedDictionary < Account > ( name : " Accounts " )
private var relationships = CachedDictionary < Relationship > ( name : " Relationships " )
private var notifications = CachedDictionary < Pachyderm . Notification > ( name : " Notifications " )
2018-09-18 16:59:07 +00:00
2020-01-06 00:54:28 +00:00
let statusSubject = PassthroughSubject < Status , Never > ( )
let accountSubject = PassthroughSubject < Account , Never > ( )
2019-08-02 03:01:15 +00:00
2020-01-20 04:11:47 +00:00
weak var mastodonController : MastodonController ?
2020-01-06 00:54:28 +00:00
init ( mastodonController : MastodonController ) {
self . mastodonController = mastodonController
}
2020-01-05 20:25:07 +00:00
2018-09-18 16:59:07 +00:00
// MARK: - S t a t u s e s
2020-01-06 00:54:28 +00:00
func status ( for id : String ) -> Status ? {
2018-09-23 16:01:05 +00:00
return statuses [ id ]
2018-09-18 16:59:07 +00:00
}
2020-01-06 00:54:28 +00:00
func set ( status : Status , for id : String ) {
2018-09-23 16:01:05 +00:00
statuses [ id ] = status
2018-09-18 16:59:07 +00:00
add ( account : status . account )
if let reblog = status . reblog {
2018-10-31 02:07:54 +00:00
add ( status : reblog )
2018-09-18 16:59:07 +00:00
add ( account : reblog . account )
}
2019-08-02 03:01:15 +00:00
statusSubject . send ( status )
2018-09-18 16:59:07 +00:00
}
2020-01-06 00:54:28 +00:00
func status ( for id : String , completion : @ escaping ( Status ? ) -> Void ) {
2020-01-20 04:11:47 +00:00
guard let mastodonController = mastodonController else {
fatalError ( " The MastodonController for this cache has been deinitialized, so this cache should no longer exist. Are you storing a strong reference to it? " )
}
2020-01-05 19:00:39 +00:00
let request = Client . getStatus ( id : id )
2020-01-05 20:25:07 +00:00
mastodonController . run ( request ) { response in
2018-09-18 16:59:07 +00:00
guard case let . success ( status , _ ) = response else {
completion ( nil )
return
}
2020-01-06 00:54:28 +00:00
self . set ( status : status , for : id )
2018-09-18 16:59:07 +00:00
completion ( status )
}
}
2020-01-06 00:54:28 +00:00
func add ( status : Status ) {
2018-09-18 16:59:07 +00:00
set ( status : status , for : status . id )
}
2020-01-06 00:54:28 +00:00
func addAll ( statuses : [ Status ] ) {
2018-09-18 16:59:07 +00:00
statuses . forEach ( add )
}
// MARK: - A c c o u n t s
2020-01-06 00:54:28 +00:00
func account ( for id : String ) -> Account ? {
2018-09-23 16:01:05 +00:00
return accounts [ id ]
2018-09-18 16:59:07 +00:00
}
2020-01-06 00:54:28 +00:00
func set ( account : Account , for id : String ) {
2018-09-23 16:01:05 +00:00
accounts [ id ] = account
2019-08-02 03:01:15 +00:00
accountSubject . send ( account )
2018-09-18 16:59:07 +00:00
}
2020-01-06 00:54:28 +00:00
func account ( for id : String , completion : @ escaping ( Account ? ) -> Void ) {
2020-01-20 04:11:47 +00:00
guard let mastodonController = mastodonController else {
fatalError ( " The MastodonController for this cache has been deinitialized, so this cache should no longer exist. Are you storing a strong reference to it? " )
}
2020-01-05 19:00:39 +00:00
let request = Client . getAccount ( id : id )
2020-01-05 20:25:07 +00:00
mastodonController . run ( request ) { response in
2018-09-18 16:59:07 +00:00
guard case let . success ( account , _ ) = response else {
completion ( nil )
return
}
2020-01-06 00:54:28 +00:00
self . set ( account : account , for : account . id )
2018-09-18 16:59:07 +00:00
completion ( account )
}
}
2020-01-06 00:54:28 +00:00
func add ( account : Account ) {
2018-09-18 16:59:07 +00:00
set ( account : account , for : account . id )
}
2020-01-06 00:54:28 +00:00
func addAll ( accounts : [ Account ] ) {
2018-09-18 16:59:07 +00:00
accounts . forEach ( add )
}
2018-09-24 12:49:39 +00:00
// MARK: - R e l a t i o n s h i p s
2020-01-06 00:54:28 +00:00
func relationship ( for id : String ) -> Relationship ? {
2018-09-24 12:51:20 +00:00
return relationships [ id ]
2018-09-24 12:49:39 +00:00
}
2020-01-06 00:54:28 +00:00
func set ( relationship : Relationship , id : String ) {
2018-09-24 12:51:20 +00:00
relationships [ id ] = relationship
2018-09-24 12:49:39 +00:00
}
2020-01-06 00:54:28 +00:00
func relationship ( for id : String , completion : @ escaping ( Relationship ? ) -> Void ) {
2020-01-20 04:11:47 +00:00
guard let mastodonController = mastodonController else {
fatalError ( " The MastodonController for this cache has been deinitialized, so this cache should no longer exist. Are you storing a strong reference to it? " )
}
2020-01-05 19:00:39 +00:00
let request = Client . getRelationships ( accounts : [ id ] )
2020-01-05 20:25:07 +00:00
mastodonController . run ( request ) { response in
2018-09-24 12:49:39 +00:00
guard case let . success ( relationships , _ ) = response ,
let relationship = relationships . first else {
completion ( nil )
return
}
2020-01-06 00:54:28 +00:00
self . set ( relationship : relationship , id : relationship . id )
2018-09-24 12:49:39 +00:00
completion ( relationship )
}
}
2020-01-06 00:54:28 +00:00
func add ( relationship : Relationship ) {
2018-09-24 12:49:39 +00:00
set ( relationship : relationship , id : relationship . id )
}
2020-01-06 00:54:28 +00:00
func addAll ( relationships : [ Relationship ] ) {
2018-09-24 12:49:39 +00:00
relationships . forEach ( add )
}
2019-08-01 02:01:00 +00:00
// MARK: - N o t i f i c a t i o n s
2020-01-06 00:54:28 +00:00
func notification ( for id : String ) -> Pachyderm . Notification ? {
2019-08-01 02:01:00 +00:00
return notifications [ id ]
}
2020-01-06 00:54:28 +00:00
func set ( notification : Pachyderm . Notification , id : String ) {
2019-08-01 02:01:00 +00:00
notifications [ id ] = notification
}
2020-01-06 00:54:28 +00:00
func add ( notification : Pachyderm . Notification ) {
2019-08-01 02:01:00 +00:00
set ( notification : notification , id : notification . id )
}
2020-01-06 00:54:28 +00:00
func addAll ( notifications : [ Pachyderm . Notification ] ) {
2019-08-01 02:01:00 +00:00
notifications . forEach ( add )
}
2018-09-18 16:59:07 +00:00
}
2019-12-14 16:31:14 +00:00
class CachedDictionary < Value > {
private let name : String
private var dict = [ String : Value ] ( )
private let queue : DispatchQueue
init ( name : String ) {
self . name = name
self . queue = DispatchQueue ( label : " CachedDictionary ( \( name ) ) Coordinator " , attributes : . concurrent )
}
subscript ( key : String ) -> Value ? {
get {
var result : Value ? = nil
queue . sync {
result = dict [ key ]
}
return result
}
set ( value ) {
queue . async ( flags : . barrier ) {
self . dict [ key ] = value
}
}
}
}