1 // Copyright 2015-present 650 Industries. All rights reserved.
2 package host.exp.exponent.storage
3 
4 import android.content.Context
5 import host.exp.exponent.analytics.EXL
6 import host.exp.exponent.kernel.ExperienceKey
7 import host.exp.expoview.ExpoViewBuildConfig
8 import host.exp.expoview.R
9 import org.json.JSONException
10 import org.json.JSONObject
11 import javax.inject.Singleton
12 
13 @Singleton
14 class ExponentSharedPreferences constructor(val context: Context) {
15   private val sharedPreferences = context.getSharedPreferences(
16     context.getString(R.string.preference_file_key),
17     Context.MODE_PRIVATE
18   )
19 
20   private val exponentInstallationId = ExponentInstallationId(context, sharedPreferences)
21 
getBooleannull22   fun getBoolean(key: ExponentSharedPreferencesKey): Boolean {
23     return sharedPreferences.getBoolean(key.preferenceKey, DEFAULT_VALUES[key] ?: false)
24   }
25 
getBooleannull26   fun getBoolean(key: ExponentSharedPreferencesKey, defaultValue: Boolean): Boolean {
27     return sharedPreferences.getBoolean(key.preferenceKey, defaultValue)
28   }
29 
setBooleannull30   fun setBoolean(key: ExponentSharedPreferencesKey, value: Boolean) {
31     sharedPreferences.edit().putBoolean(key.preferenceKey, value).apply()
32   }
33 
getIntegernull34   fun getInteger(key: ExponentSharedPreferencesKey): Int {
35     return getInteger(key, 0)
36   }
37 
getIntegernull38   fun getInteger(key: ExponentSharedPreferencesKey, defaultValue: Int): Int {
39     return sharedPreferences.getInt(key.preferenceKey, defaultValue)
40   }
41 
setIntegernull42   fun setInteger(key: ExponentSharedPreferencesKey, value: Int) {
43     sharedPreferences.edit().putInt(key.preferenceKey, value).apply()
44   }
45 
getStringnull46   fun getString(key: ExponentSharedPreferencesKey): String? {
47     return getString(key, null)
48   }
49 
getStringnull50   fun getString(key: ExponentSharedPreferencesKey, defaultValue: String?): String? {
51     return sharedPreferences.getString(key.preferenceKey, defaultValue)
52   }
53 
setStringnull54   fun setString(key: ExponentSharedPreferencesKey, value: String?) {
55     sharedPreferences.edit().putString(key.preferenceKey, value).apply()
56   }
57 
deletenull58   fun delete(key: ExponentSharedPreferencesKey) {
59     sharedPreferences.edit().remove(key.preferenceKey).apply()
60   }
61 
shouldUseEmbeddedKernelnull62   fun shouldUseEmbeddedKernel(): Boolean {
63     return getBoolean(ExponentSharedPreferencesKey.USE_EMBEDDED_KERNEL_KEY)
64   }
65 
getUUIDnull66   fun getUUID(): String? {
67     return exponentInstallationId.getUUID()
68   }
69 
getOrCreateUUIDnull70   fun getOrCreateUUID(): String {
71     return exponentInstallationId.getOrCreateUUID()
72   }
73 
updateSessionnull74   fun updateSession(session: JSONObject) {
75     setString(ExponentSharedPreferencesKey.EXPO_AUTH_SESSION, session.toString())
76   }
77 
removeSessionnull78   fun removeSession() {
79     setString(ExponentSharedPreferencesKey.EXPO_AUTH_SESSION, null)
80   }
81 
82   val sessionSecret: String?
83     get() {
84       val sessionString = getString(ExponentSharedPreferencesKey.EXPO_AUTH_SESSION)
85         ?: return null
86       return try {
87         val session = JSONObject(sessionString)
88         session.getString(EXPO_AUTH_SESSION_SECRET_KEY)
89       } catch (e: Exception) {
90         EXL.e(TAG, e)
91         null
92       }
93     }
94 
removeLegacyManifestnull95   fun removeLegacyManifest(manifestUrl: String) {
96     sharedPreferences.edit().remove(manifestUrl).apply()
97   }
98 
updateExperienceMetadatanull99   fun updateExperienceMetadata(experienceKey: ExperienceKey, metadata: JSONObject) {
100     sharedPreferences.edit()
101       .putString(EXPERIENCE_METADATA_PREFIX + experienceKey.scopeKey, metadata.toString()).apply()
102   }
103 
getExperienceMetadatanull104   fun getExperienceMetadata(experienceKey: ExperienceKey): JSONObject? {
105     val jsonString =
106       sharedPreferences.getString(EXPERIENCE_METADATA_PREFIX + experienceKey.scopeKey, null)
107         ?: return null
108     return try {
109       JSONObject(jsonString)
110     } catch (e: JSONException) {
111       EXL.e(TAG, e)
112       null
113     }
114   }
115 
116   companion object {
117     private val TAG = ExponentSharedPreferences::class.java.simpleName
118 
119     const val EXPO_AUTH_SESSION_SECRET_KEY = "sessionSecret"
120 
121     // Metadata
122     const val EXPERIENCE_METADATA_PREFIX = "experience_metadata_"
123     const val EXPERIENCE_METADATA_UNREAD_REMOTE_NOTIFICATIONS = "unreadNotifications"
124     const val EXPERIENCE_METADATA_ALL_NOTIFICATION_IDS = "allNotificationIds"
125     const val EXPERIENCE_METADATA_ALL_SCHEDULED_NOTIFICATION_IDS = "allScheduledNotificationIds"
126     const val EXPERIENCE_METADATA_LOADING_ERROR = "loadingError"
127     const val EXPERIENCE_METADATA_PERMISSIONS = "permissions"
128     const val EXPERIENCE_METADATA_NOTIFICATION_CHANNELS = "notificationChannels"
129 
130     private val DEFAULT_VALUES = mutableMapOf(
131       ExponentSharedPreferencesKey.USE_EMBEDDED_KERNEL_KEY to ExpoViewBuildConfig.USE_EMBEDDED_KERNEL,
132       ExponentSharedPreferencesKey.IS_ONBOARDING_FINISHED_KEY to false,
133       ExponentSharedPreferencesKey.NUX_HAS_FINISHED_FIRST_RUN_KEY to false,
134       ExponentSharedPreferencesKey.SHOULD_NOT_USE_KERNEL_CACHE to false
135     )
136   }
137 
138   init {
139     // We renamed `nux` to `onboarding` in January 2020 - the old preference key can be removed from here after some time,
140     // but since then we need to rewrite nux setting to the new key.
141     if (!sharedPreferences.contains(ExponentSharedPreferencesKey.IS_ONBOARDING_FINISHED_KEY.preferenceKey)) {
142       setBoolean(ExponentSharedPreferencesKey.IS_ONBOARDING_FINISHED_KEY, getBoolean(ExponentSharedPreferencesKey.NUX_HAS_FINISHED_FIRST_RUN_KEY))
143     }
144   }
145 
146   enum class ExponentSharedPreferencesKey(val preferenceKey: String) {
147     // Dev options
148     USE_EMBEDDED_KERNEL_KEY("use_embedded_kernel"),
149 
150     // Other
151     FCM_TOKEN_KEY("fcm_token"),
152     REFERRER_KEY("referrer"),
153     NUX_HAS_FINISHED_FIRST_RUN_KEY("nux_has_finished_first_run"),
154     IS_ONBOARDING_FINISHED_KEY("is_onboarding_finished"),
155     SHOULD_NOT_USE_KERNEL_CACHE("should_not_use_kernel_cache"),
156     KERNEL_REVISION_ID("kernel_revision_id"),
157     EXPO_AUTH_SESSION("expo_auth_session"),
158     OKHTTP_CACHE_VERSION_KEY("okhttp_cache_version"),
159   }
160 }
161