diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
new file mode 100644
index 000000000..0c0237e9c
--- /dev/null
+++ b/.idea/deploymentTargetDropDown.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 641da01bb..5a3417398 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -13,6 +13,7 @@
String = { route -> "last_read_route_$route" }
+}
- private fun prefKeysForAccount(npub: String) = object {
- val NOSTR_PRIVKEY = "$npub/nostr_privkey"
- val NOSTR_PUBKEY = "$npub/nostr_pubkey"
- val DISPLAY_NAME = "$npub/display_name"
- val PROFILE_PICTURE_URL = "$npub/profile_picture"
- val FOLLOWING_CHANNELS = "$npub/following_channels"
- val HIDDEN_USERS = "$npub/hidden_users"
- val RELAYS = "$npub/relays"
- val DONT_TRANSLATE_FROM = "$npub/dontTranslateFrom"
- val LANGUAGE_PREFS = "$npub/languagePreferences"
- val TRANSLATE_TO = "$npub/translateTo"
- val ZAP_AMOUNTS = "$npub/zapAmounts"
- val LATEST_CONTACT_LIST = "$npub/latestContactList"
- val HIDE_DELETE_REQUEST_INFO = "$npub/hideDeleteRequestInfo"
-// val LAST_READ: (String) -> String = { route -> "$npub/last_read_route_$route" }
+private val gson = GsonBuilder().create()
+
+object LocalPreferences {
+ private var currentAccount: String?
+ get() = encryptedPreferences().getString(PrefKeys.CURRENT_ACCOUNT, null)
+ set(npub) {
+ val prefs = encryptedPreferences()
+ prefs.edit().apply {
+ putString(PrefKeys.CURRENT_ACCOUNT, npub)
+ }.apply()
+ }
+
+ private val savedAccounts: Set
+ get() = encryptedPreferences().getStringSet(PrefKeys.SAVED_ACCOUNTS, null) ?: setOf()
+
+ private fun addAccount(npub: String) {
+ val accounts = savedAccounts.toMutableSet()
+ accounts.add(npub)
+ val prefs = encryptedPreferences()
+ prefs.edit().apply {
+ putStringSet(PrefKeys.SAVED_ACCOUNTS, accounts)
+ }.apply()
}
- private object PrefKeys {
- const val CURRENT_ACCOUNT = "currentlyLoggedInAccount"
-
-// val NOSTR_PRIVKEY = "nostr_privkey"
-// val NOSTR_PUBKEY = "nostr_pubkey"
-// val FOLLOWING_CHANNELS = "following_channels"
-// val HIDDEN_USERS = "hidden_users"
-// val RELAYS = "relays"
-// val DONT_TRANSLATE_FROM = "dontTranslateFrom"
-// val LANGUAGE_PREFS = "languagePreferences"
-// val TRANSLATE_TO = "translateTo"
-// val ZAP_AMOUNTS = "zapAmounts"
-// val LATEST_CONTACT_LIST = "latestContactList"
-// val HIDE_DELETE_REQUEST_INFO = "hideDeleteRequestInfo"
- val LAST_READ: (String) -> String = { route -> "last_read_route_$route" }
+ private fun removeAccount(npub: String) {
+ val accounts = savedAccounts.toMutableSet()
+ accounts.remove(npub)
+ val prefs = encryptedPreferences()
+ prefs.edit().apply {
+ putStringSet(PrefKeys.SAVED_ACCOUNTS, accounts)
+ }.apply()
}
- private val encryptedPreferences = EncryptedStorage.preferences(context)
- private val gson = GsonBuilder().create()
+ private fun encryptedPreferences(npub: String? = null): SharedPreferences {
+ return if (DEBUG_PLAINTEXT_PREFERENCES) {
+ val preferenceFile = if (npub == null) "testing_only" else "testing_only_$npub"
+ Amethyst.instance.getSharedPreferences(preferenceFile, Context.MODE_PRIVATE)
+ } else {
+ return EncryptedStorage.preferences(npub)
+ }
+ }
- fun clearEncryptedStorage() {
- encryptedPreferences.edit().apply {
- encryptedPreferences.all.keys.forEach {
+ fun clearEncryptedStorage(npub: String? = null) {
+ val encPrefs = encryptedPreferences(npub)
+ encPrefs.edit().apply {
+ encPrefs.all.keys.forEach {
remove(it)
}
// encryptedPreferences.all.keys.filter {
@@ -69,76 +94,64 @@ class LocalPreferences(context: Context) {
}
fun findAllLocalAccounts(): List {
- encryptedPreferences.apply {
- val currentAccount = getString(PrefKeys.CURRENT_ACCOUNT, null)
- return encryptedPreferences.all.keys.filter {
- it.endsWith("nostr_pubkey")
- }.map {
- val npub = it.substringBefore("/")
- val myPrefs = prefKeysForAccount(npub)
- AccountInfo(
- npub,
- npub == currentAccount,
- getString(myPrefs.DISPLAY_NAME, null),
- getString(myPrefs.PROFILE_PICTURE_URL, null)
- )
- }
+ return savedAccounts.map { npub ->
+ val prefs = encryptedPreferences(npub)
+
+ AccountInfo(
+ npub = npub,
+ current = npub == currentAccount,
+ displayName = prefs.getString(PrefKeys.DISPLAY_NAME, null),
+ profilePicture = prefs.getString(PrefKeys.PROFILE_PICTURE_URL, null)
+ )
}
}
- fun saveToEncryptedStorage(account: Account) {
- val npub = account.loggedIn.pubKey.toNpub()
- val myPrefs = prefKeysForAccount(npub)
-
- encryptedPreferences.edit().apply {
- putString(PrefKeys.CURRENT_ACCOUNT, npub)
- account.loggedIn.privKey?.let { putString(myPrefs.NOSTR_PRIVKEY, it.toHex()) }
- account.loggedIn.pubKey.let { putString(myPrefs.NOSTR_PUBKEY, it.toHex()) }
- putStringSet(myPrefs.FOLLOWING_CHANNELS, account.followingChannels)
- putStringSet(myPrefs.HIDDEN_USERS, account.hiddenUsers)
- putString(myPrefs.RELAYS, gson.toJson(account.localRelays))
- putStringSet(myPrefs.DONT_TRANSLATE_FROM, account.dontTranslateFrom)
- putString(myPrefs.LANGUAGE_PREFS, gson.toJson(account.languagePreferences))
- putString(myPrefs.TRANSLATE_TO, account.translateTo)
- putString(myPrefs.ZAP_AMOUNTS, gson.toJson(account.zapAmountChoices))
- putString(myPrefs.LATEST_CONTACT_LIST, Event.gson.toJson(account.backupContactList))
- putBoolean(myPrefs.HIDE_DELETE_REQUEST_INFO, account.hideDeleteRequestInfo)
- }.apply()
+ fun setCurrentAccount(account: Account) {
+ val npub = account.userProfile().pubkeyNpub()
+ currentAccount = npub
+ addAccount(npub)
}
- fun saveCurrentAccountMetadata(account: Account) {
- val myPrefs = prefKeysForAccount(account.loggedIn.pubKey.toNpub())
-
- encryptedPreferences.edit().apply {
- putString(myPrefs.DISPLAY_NAME, account.userProfile().toBestDisplayName())
- putString(myPrefs.PROFILE_PICTURE_URL, account.userProfile().profilePicture())
+ fun saveToEncryptedStorage(account: Account) {
+ val prefs = encryptedPreferences(account.userProfile().pubkeyNpub())
+ prefs.edit().apply {
+ account.loggedIn.privKey?.let { putString(PrefKeys.NOSTR_PRIVKEY, it.toHex()) }
+ account.loggedIn.pubKey.let { putString(PrefKeys.NOSTR_PUBKEY, it.toHex()) }
+ putStringSet(PrefKeys.FOLLOWING_CHANNELS, account.followingChannels)
+ putStringSet(PrefKeys.HIDDEN_USERS, account.hiddenUsers)
+ putString(PrefKeys.RELAYS, gson.toJson(account.localRelays))
+ putStringSet(PrefKeys.DONT_TRANSLATE_FROM, account.dontTranslateFrom)
+ putString(PrefKeys.LANGUAGE_PREFS, gson.toJson(account.languagePreferences))
+ putString(PrefKeys.TRANSLATE_TO, account.translateTo)
+ putString(PrefKeys.ZAP_AMOUNTS, gson.toJson(account.zapAmountChoices))
+ putString(PrefKeys.LATEST_CONTACT_LIST, Event.gson.toJson(account.backupContactList))
+ putBoolean(PrefKeys.HIDE_DELETE_REQUEST_INFO, account.hideDeleteRequestInfo)
+ putString(PrefKeys.DISPLAY_NAME, account.userProfile().toBestDisplayName())
+ putString(PrefKeys.PROFILE_PICTURE_URL, account.userProfile().profilePicture())
}.apply()
}
fun loadFromEncryptedStorage(): Account? {
- encryptedPreferences.apply {
- val npub = getString(PrefKeys.CURRENT_ACCOUNT, null) ?: return null
- val myPrefs = prefKeysForAccount(npub)
-
- val pubKey = getString(myPrefs.NOSTR_PUBKEY, null) ?: return null
- val privKey = getString(myPrefs.NOSTR_PRIVKEY, null)
- val followingChannels = getStringSet(myPrefs.FOLLOWING_CHANNELS, null) ?: setOf()
- val hiddenUsers = getStringSet(myPrefs.HIDDEN_USERS, emptySet()) ?: setOf()
+ encryptedPreferences(currentAccount).apply {
+ val pubKey = getString(PrefKeys.NOSTR_PUBKEY, null) ?: return null
+ val privKey = getString(PrefKeys.NOSTR_PRIVKEY, null)
+ val followingChannels = getStringSet(PrefKeys.FOLLOWING_CHANNELS, null) ?: setOf()
+ val hiddenUsers = getStringSet(PrefKeys.HIDDEN_USERS, emptySet()) ?: setOf()
val localRelays = gson.fromJson(
- getString(myPrefs.RELAYS, "[]"),
+ getString(PrefKeys.RELAYS, "[]"),
object : TypeToken>() {}.type
) ?: setOf()
- val dontTranslateFrom = getStringSet(myPrefs.DONT_TRANSLATE_FROM, null) ?: setOf()
- val translateTo = getString(myPrefs.TRANSLATE_TO, null) ?: Locale.getDefault().language
+ val dontTranslateFrom = getStringSet(PrefKeys.DONT_TRANSLATE_FROM, null) ?: setOf()
+ val translateTo = getString(PrefKeys.TRANSLATE_TO, null) ?: Locale.getDefault().language
val zapAmountChoices = gson.fromJson(
- getString(myPrefs.ZAP_AMOUNTS, "[]"),
+ getString(PrefKeys.ZAP_AMOUNTS, "[]"),
object : TypeToken>() {}.type
) ?: listOf(500L, 1000L, 5000L)
val latestContactList = try {
- getString(myPrefs.LATEST_CONTACT_LIST, null)?.let {
+ getString(PrefKeys.LATEST_CONTACT_LIST, null)?.let {
Event.gson.fromJson(it, Event::class.java).getRefinedEvent(true) as ContactListEvent
}
} catch (e: Throwable) {
@@ -147,7 +160,7 @@ class LocalPreferences(context: Context) {
}
val languagePreferences = try {
- getString(myPrefs.LANGUAGE_PREFS, null)?.let {
+ getString(PrefKeys.LANGUAGE_PREFS, null)?.let {
gson.fromJson(it, object : TypeToken