-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add 'send private read receipts' option in advanced settings #2290
Conversation
📱 Scan the QR code below to install the build (arm64 only) for this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, 2 remarks. Also I think the screenshots have to be recorded.
Text(text = "Send read receipts") | ||
}, | ||
supportingContent = { | ||
Text(text = "On disabling, others won't see your read receipt.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Text(text = "On disabling, others won't see your read receipt.") | |
Text(text = "On disabling, others won't see your read receipts.") |
Also I think those 2 strings should be defined in Localazy.
@@ -28,6 +28,9 @@ interface PreferencesStore { | |||
suspend fun setCustomElementCallBaseUrl(string: String?) | |||
fun getCustomElementCallBaseUrlFlow(): Flow<String?> | |||
|
|||
suspend fun setPrivateReadReceiptsEnabled(enabled: Boolean) | |||
fun isPrivateReadReceiptsEnabled(): Flow<Boolean> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit annoying me that this settings is stored in PreferencesStore
, which should be used for global settings only. The setting isPrivateReadReceiptsEnabled
should have a Session scope.
That said, IIRC, we do not have (yet) a store for session preferences, and we do not support multi sessions yet. But, I think logging out and logging in again will keep the setting, and it's probably an unexpected side effect from the user POV.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll see how difficult it is to create a session-scoped preference store.
421f113
to
7c90e47
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## develop #2290 +/- ##
===========================================
- Coverage 70.15% 70.14% -0.01%
===========================================
Files 1335 1337 +2
Lines 32802 32838 +36
Branches 6809 6811 +2
===========================================
+ Hits 23012 23035 +23
- Misses 6511 6524 +13
Partials 3279 3279 ☔ View full report in Codecov by Sentry. |
- Turn `sendPrivateReadReceipts` into `sendPublicReadReceipts`, make it true by default. - Create `SessionPreferencesStore` that stores the settings for the current use separate from those of the app. - Rename `PreferencesStore` to `AppPreferencesStore` to split the preferences. - Add and fix tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the change. There are a few remarks to handle.
@@ -6,6 +6,8 @@ | |||
<string name="screen_advanced_settings_developer_mode">"Developer mode"</string> | |||
<string name="screen_advanced_settings_developer_mode_description">"Enable to have access to features and functionality for developers."</string> | |||
<string name="screen_advanced_settings_rich_text_editor_description">"Disable the rich text editor to type Markdown manually."</string> | |||
<string name="screen_advanced_settings_send_read_receipts">"Read receipts"</string> | |||
<string name="screen_advanced_settings_send_read_receipts_description">"If turned off, your read receipts won\'t be sent to anyone. You will still receive read receipts from other users."</string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You will still receive read receipts from other users.
Except if they also disabled the public RR :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's kind of implicit, but please let's not bring back the discussion on the text used here, I already had enough of it 😅 .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sure, I was sort of kidding :).
It reminds me the old days where mobile phone users could pay an option to get incoming call number displayed, and others could pay an option to hide their phone number when they're doing call :)
@ApplicationContext context: Context, | ||
currentSessionIdHolder: CurrentSessionIdHolder, | ||
) : SessionPreferencesStore { | ||
private val privateReadReceiptsKey = booleanPreferencesKey("privateReadReceipts") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename to
private val privateReadReceiptsKey = booleanPreferencesKey("privateReadReceipts") | |
private val publicReadReceiptsKey = booleanPreferencesKey("publicReadReceipts") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private val privateReadReceiptsKey = booleanPreferencesKey("privateReadReceipts") | ||
|
||
private val store = PreferenceDataStoreFactory.create { | ||
context.preferencesDataStoreFile("session_${currentSessionIdHolder.current}_preferences") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have to use a hash of the user id here, because it will crash if the user name is too long. See #2237
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
override fun isSendPublicReadReceiptsEnabled(): Flow<Boolean> = get(privateReadReceiptsKey, true) | ||
|
||
override suspend fun clear() { | ||
store.edit { it.clear() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file may also be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any attempt to read/write the file creates and closes a FileInputStream or FileOutputStream and is capable of handling errors if they're not found.
Quality Gate passedKudos, no new issues were introduced! 0 New issues |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update! You can merge the PR like this.
private val hashedUserId = currentSessionIdHolder.current.value.hash().take(16) | ||
|
||
private val dataStoreFile = context.preferencesDataStoreFile("session_${hashedUserId}_preferences") | ||
private val store = PreferenceDataStoreFactory.create { dataStoreFile } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a small question, with this API, one can create a data store at any location, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm tempted to think so. This actually creates a File(dataStoreDir, filename)
with filename
being the string you pass here, and then calls mkdirs()
so it should work that way.
|
||
private fun <T> get(key: Preferences.Key<T>, default: T): Flow<T> { | ||
return store.data.map { prefs -> prefs[key] ?: default } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 nice functions! I am tempted to extract them and reuse them elsewhere. I'll draft a quick PR.
suspend fun setSendPublicReadReceipts(enabled: Boolean) | ||
fun isSendPublicReadReceiptsEnabled(): Flow<Boolean> | ||
|
||
suspend fun clear() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: this is never called. Not a big deal but should be fixed later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I need to figure out the right way to clean up this data when the user is logged out. I'll do it in another PR.
Type of change
Content
Motivation and context
Closes #2204.
Tests
Tested devices
Checklist