2023-05-20 09:24:09 -07:00
//
// U n s t a b l e F e a t u r e s . s w i f t
// S i d e S t o r e
//
// C r e a t e d b y n a t u r e c o d e v o i d o n 5 / 2 0 / 2 3 .
// C o p y r i g h t © 2 0 2 3 S i d e S t o r e . A l l r i g h t s r e s e r v e d .
//
2023-05-20 14:23:25 -07:00
import SwiftUI
2023-05-20 09:24:09 -07:00
// I p r e f i x e d i t w i t h A v a i l a b l e t o m a k e U n s t a b l e F e a t u r e s c o m e u p f i r s t i n a u t o c o m p l e t e , f e e l f r e e t o r e n a m e i t i f y o u k n o w a b e t t e r n a m e
enum AvailableUnstableFeature : String , CaseIterable {
// T h e v a l u e w i l l b e t h e G i t H u b I s s u e n u m b e r . F o r e x a m p l e , " 1 2 3 " w o u l d c o r r e s p o n d t o h t t p s : / / g i t h u b . c o m / S i d e S t o r e / S i d e S t o r e / i s s u e s / 1 2 3
//
// U n s t a b l e f e a t u r e s m u s t h a v e a G i t H u b I s s u e f o r t r a c k i n g p r o g r e s s , P R s a n d f e e d b a c k / c o m m e n t i n g .
2023-05-20 09:51:45 -07:00
case jitUrlScheme = " 0 "
2023-05-20 09:24:09 -07:00
// / D u m m y v a r i a n t t o e n s u r e t h e r e i s a l w a y s a t l e a s t o n e v a r i a n t . D O N O T U S E !
case dummy = " dummy "
func availableOutsideDevMode ( ) -> Bool {
switch self {
// I f y o u r u n s t a b l e f e a t u r e i s s t a b l e e n o u g h t o b e u s e d b y n i g h t l y u s e r s w h o a r e n o t a l p h a t e s t e r s o r d e v e l o p e r s ,
// y o u m a y w a n t t o h a v e i t a v a i l a b l e i n t h e " U n s t a b l e F e a t u r e s " m e n u i n S e t t i n g s ( o u t s i d e o f d e v m o d e ) . T o d o s o , a d d t h i s :
// c a s e . y o u r F e a t u r e : r e t u r n t r u e
2023-05-20 09:51:45 -07:00
case . jitUrlScheme : return true
2023-05-20 09:24:09 -07:00
default : return false
}
}
}
2023-05-20 14:23:25 -07:00
class UnstableFeatures : ObservableObject {
2023-05-20 09:24:09 -07:00
#if UNSTABLE
2023-05-20 14:23:25 -07:00
static let shared = UnstableFeatures ( )
@ Published var features : [ AvailableUnstableFeature : Bool ] = [ : ]
2023-05-20 09:24:09 -07:00
static func load ( ) {
2023-05-20 14:23:25 -07:00
if shared . features . count > 0 { return print ( " It seems unstable features have already been loaded, skipping " ) }
2023-05-20 09:24:09 -07:00
if let rawFeatures = UserDefaults . shared . unstableFeatures ,
2023-05-20 10:47:55 -07:00
let rawFeatures = try ? JSONDecoder ( ) . decode ( [ String : Bool ] . self , from : rawFeatures ) {
2023-05-20 09:24:09 -07:00
for rawFeature in rawFeatures {
if let feature = AvailableUnstableFeature . allCases . first ( where : { feature in String ( describing : feature ) = = rawFeature . key } ) {
2023-05-20 14:23:25 -07:00
shared . features [ feature ] = rawFeature . value
2023-05-20 09:24:09 -07:00
} else {
print ( " Unknown unstable feature: \( rawFeature . key ) = \( rawFeature . value ) " )
}
}
2023-05-20 14:23:25 -07:00
for feature in AvailableUnstableFeature . allCases {
if shared . features [ feature ] = = nil {
shared . features [ feature ] = false
}
}
2023-05-20 09:24:09 -07:00
save ( load : true )
} else {
print ( " Setting all unstable features to false since we couldn't load them from UserDefaults (either they were never saved or there was an error decoding JSON) " )
for feature in AvailableUnstableFeature . allCases {
2023-05-20 14:23:25 -07:00
shared . features [ feature ] = false
2023-05-20 09:24:09 -07:00
}
save ( )
}
}
private static func save ( load : Bool = false ) {
var rawFeatures : [ String : Bool ] = [ : ]
2023-05-20 14:23:25 -07:00
for feature in shared . features {
2023-05-20 09:24:09 -07:00
rawFeatures [ String ( describing : feature . key ) ] = feature . value
}
UserDefaults . shared . unstableFeatures = try ! JSONEncoder ( ) . encode ( rawFeatures )
print ( " \( load ? " Loaded " : " Saved " ) unstable features: \( String ( describing : rawFeatures ) ) " )
}
static func set ( _ feature : AvailableUnstableFeature , enabled : Bool ) {
2023-05-20 14:23:25 -07:00
shared . features [ feature ] = enabled
2023-05-20 09:24:09 -07:00
save ( )
}
2023-05-20 14:23:25 -07:00
#endif
2023-05-20 09:24:09 -07:00
2023-05-20 14:28:33 -07:00
@ inline ( __always ) // h o p e f u l l y t h i s w i l l h e l p t h e c o m p i l e r r e a l i z e t h a t i f s t a t e m e n t s t h a t u s e t h i s f u n c t i o n s h o u l d b e r e m o v e d o n n o n - u n s t a b l e b u i l d s
2023-05-20 09:24:09 -07:00
static func enabled ( _ feature : AvailableUnstableFeature ) -> Bool {
#if UNSTABLE
2023-05-20 14:23:25 -07:00
shared . features [ feature ] ? ? false
2023-05-20 09:24:09 -07:00
#else
false
#endif
}
}