mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Apply new story list ordering rules.
Co-authored-by: Cody Henthorne <cody@signal.org>
This commit is contained in:
committed by
Greyson Parrelli
parent
3b07f4a8ca
commit
88a66b49ff
@@ -2,7 +2,13 @@ package org.thoughtcrime.securesms.keyvalue;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.SignalStoreList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
abstract class SignalStoreValues {
|
||||
|
||||
@@ -44,6 +50,25 @@ abstract class SignalStoreValues {
|
||||
return store.getBlob(key, defaultValue);
|
||||
}
|
||||
|
||||
<T> List<T> getList(@NonNull String key, @NonNull Serializer<T> serializer) {
|
||||
byte[] blob = getBlob(key, null);
|
||||
if (blob == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
try {
|
||||
SignalStoreList signalStoreList = SignalStoreList.parseFrom(blob);
|
||||
|
||||
return signalStoreList.getContentsList()
|
||||
.stream()
|
||||
.map(serializer::deserialize)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
void putBlob(@NonNull String key, byte[] value) {
|
||||
store.beginWrite().putBlob(key, value).apply();
|
||||
}
|
||||
@@ -68,7 +93,21 @@ abstract class SignalStoreValues {
|
||||
store.beginWrite().putString(key, value).apply();
|
||||
}
|
||||
|
||||
<T> void putList(@NonNull String key, @NonNull List<T> values, @NonNull Serializer<T> serializer) {
|
||||
putBlob(key, SignalStoreList.newBuilder()
|
||||
.addAllContents(values.stream()
|
||||
.map(serializer::serialize)
|
||||
.collect(Collectors.toList()))
|
||||
.build()
|
||||
.toByteArray());
|
||||
}
|
||||
|
||||
void remove(@NonNull String key) {
|
||||
store.beginWrite().remove(key).apply();
|
||||
}
|
||||
|
||||
interface Serializer<T> {
|
||||
@NonNull String serialize(@NonNull T data);
|
||||
T deserialize(@NonNull String data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
data class StorySend(
|
||||
val timestamp: Long,
|
||||
val identifier: Identifier
|
||||
) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newSend(recipient: Recipient): StorySend {
|
||||
return if (recipient.isGroup) {
|
||||
StorySend(System.currentTimeMillis(), Identifier.Group(recipient.requireGroupId()))
|
||||
} else {
|
||||
StorySend(System.currentTimeMillis(), Identifier.DistributionList(recipient.requireDistributionListId()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Identifier {
|
||||
data class Group(val groupId: GroupId) : Identifier() {
|
||||
override fun matches(recipient: Recipient) = recipient.groupId.orElse(null) == groupId
|
||||
}
|
||||
|
||||
data class DistributionList(val distributionListId: DistributionListId) : Identifier() {
|
||||
override fun matches(recipient: Recipient) = recipient.distributionListId.orElse(null) == distributionListId
|
||||
}
|
||||
|
||||
abstract fun matches(recipient: Recipient): Boolean
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import org.json.JSONObject
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
|
||||
internal class StoryValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
|
||||
companion object {
|
||||
@@ -14,6 +18,11 @@ internal class StoryValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
* Used to check whether we should display certain dialogs.
|
||||
*/
|
||||
private const val USER_HAS_ADDED_TO_A_STORY = "user.has.added.to.a.story"
|
||||
|
||||
/**
|
||||
* Rolling window of latest two private or group stories a user has sent to.
|
||||
*/
|
||||
private const val LATEST_STORY_SENDS = "latest.story.sends"
|
||||
}
|
||||
|
||||
override fun onFirstEverAppLaunch() = Unit
|
||||
@@ -25,4 +34,44 @@ internal class StoryValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
var lastFontVersionCheck: Long by longValue(LAST_FONT_VERSION_CHECK, 0)
|
||||
|
||||
var userHasBeenNotifiedAboutStories: Boolean by booleanValue(USER_HAS_ADDED_TO_A_STORY, false)
|
||||
|
||||
fun setLatestStorySend(storySend: StorySend) {
|
||||
synchronized(this) {
|
||||
val storySends: List<StorySend> = getList(LATEST_STORY_SENDS, StorySendSerializer)
|
||||
val newStorySends: List<StorySend> = listOf(storySend) + storySends.take(1)
|
||||
putList(LATEST_STORY_SENDS, newStorySends, StorySendSerializer)
|
||||
}
|
||||
}
|
||||
|
||||
fun getLatestActiveStorySendTimestamps(activeCutoffTimestamp: Long): List<StorySend> {
|
||||
val storySends: List<StorySend> = getList(LATEST_STORY_SENDS, StorySendSerializer)
|
||||
return storySends.filter { it.timestamp >= activeCutoffTimestamp }
|
||||
}
|
||||
|
||||
private object StorySendSerializer : Serializer<StorySend> {
|
||||
|
||||
override fun serialize(data: StorySend): String {
|
||||
return JSONObject()
|
||||
.put("timestamp", data.timestamp)
|
||||
.put("groupId", if (data.identifier is StorySend.Identifier.Group) data.identifier.groupId.toString() else null)
|
||||
.put("distributionListId", if (data.identifier is StorySend.Identifier.DistributionList) data.identifier.distributionListId.serialize() else null)
|
||||
.toString()
|
||||
}
|
||||
|
||||
override fun deserialize(data: String): StorySend {
|
||||
val jsonData = JSONObject(data)
|
||||
|
||||
val timestamp = jsonData.getLong("timestamp")
|
||||
|
||||
val identifier = if (jsonData.has("groupId")) {
|
||||
val group = jsonData.getString("groupId")
|
||||
StorySend.Identifier.Group(GroupId.parse(group))
|
||||
} else {
|
||||
val distributionListId = jsonData.getString("distributionListId")
|
||||
StorySend.Identifier.DistributionList(DistributionListId.from(distributionListId))
|
||||
}
|
||||
|
||||
return StorySend(timestamp, identifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user