diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsDatabaseTest_stories.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsDatabaseTest_stories.kt index f56328ba7f..b5ecf7acca 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsDatabaseTest_stories.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsDatabaseTest_stories.kt @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.database import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse +import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test @@ -18,6 +19,7 @@ import org.whispersystems.signalservice.api.push.ACI import org.whispersystems.signalservice.api.push.PNI import org.whispersystems.signalservice.api.push.ServiceId import java.util.UUID +import java.util.concurrent.TimeUnit @Suppress("ClassName") @RunWith(AndroidJUnit4::class) @@ -30,6 +32,7 @@ class MmsDatabaseTest_stories { private lateinit var myStory: Recipient private lateinit var recipients: List + private lateinit var releaseChannelRecipient: Recipient @Before fun setUp() { @@ -42,6 +45,9 @@ class MmsDatabaseTest_stories { myStory = Recipient.resolved(SignalDatabase.recipients.getOrInsertFromDistributionListId(DistributionListId.MY_STORY)) recipients = (0 until 5).map { SignalDatabase.recipients.getOrInsertFromServiceId(ServiceId.from(UUID.randomUUID())) } + releaseChannelRecipient = Recipient.resolved(SignalDatabase.recipients.insertReleaseChannelRecipient()) + + SignalStore.releaseChannelValues().setReleaseChannelRecipientId(releaseChannelRecipient.id) } @Test @@ -333,4 +339,41 @@ class MmsDatabaseTest_stories { // THEN assertFalse(result) } + + @Test + fun givenNotViewedOnboardingAndOnlyStoryIsOnboardingAndAdded2DaysAgo_whenIGetOldestStoryTimestamp_thenIExpectNull() { + // GIVEN + val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(releaseChannelRecipient) + MmsHelper.insert( + recipient = releaseChannelRecipient, + sentTimeMillis = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2), + storyType = StoryType.STORY_WITH_REPLIES, + threadId = threadId + ) + + // WHEN + val oldestTimestamp = SignalDatabase.mms.getOldestStorySendTimestamp(false) + + // THEN + assertNull(oldestTimestamp) + } + + @Test + fun givenViewedOnboardingAndOnlyStoryIsOnboardingAndAdded2DaysAgo_whenIGetOldestStoryTimestamp_thenIExpectNotNull() { + // GIVEN + val expected = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2) + val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(releaseChannelRecipient) + MmsHelper.insert( + recipient = releaseChannelRecipient, + sentTimeMillis = expected, + storyType = StoryType.STORY_WITH_REPLIES, + threadId = threadId + ) + + // WHEN + val oldestTimestamp = SignalDatabase.mms.getOldestStorySendTimestamp(true) + + // THEN + assertEquals(expected, oldestTimestamp) + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MessageDatabase.java index f39c0924d4..789f171899 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageDatabase.java @@ -200,7 +200,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns public abstract boolean hasSelfReplyInStory(long parentStoryId); public abstract boolean hasSelfReplyInGroupStory(long parentStoryId); public abstract @NonNull Cursor getStoryReplies(long parentStoryId); - public abstract @Nullable Long getOldestStorySendTimestamp(); + public abstract @Nullable Long getOldestStorySendTimestamp(boolean hasSeenReleaseChannelStories); public abstract int deleteStoriesOlderThan(long timestamp, boolean hasSeenReleaseChannelStories); public abstract @NonNull MessageDatabase.Reader getUnreadStories(@NonNull RecipientId recipientId, int limit); public abstract @Nullable ParentStoryId.GroupReply getParentStoryIdForGroupReply(long messageId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java index aa847f7f20..b8d431616b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -898,18 +898,37 @@ public class MmsDatabase extends MessageDatabase { } @Override - public @Nullable Long getOldestStorySendTimestamp() { - SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); - String[] columns = new String[]{DATE_SENT}; - String where = IS_STORY_CLAUSE; - String orderBy = DATE_SENT + " ASC"; - String limit = "1"; + public @Nullable Long getOldestStorySendTimestamp(boolean hasSeenReleaseChannelStories) { + long releaseChannelThreadId = getReleaseChannelThreadId(hasSeenReleaseChannelStories); + SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); + String[] columns = new String[] { DATE_SENT }; + String where = IS_STORY_CLAUSE + " AND " + THREAD_ID + " != ?"; + String orderBy = DATE_SENT + " ASC"; + String limit = "1"; - try (Cursor cursor = db.query(TABLE_NAME, columns, where, null, null, null, orderBy, limit)) { + try (Cursor cursor = db.query(TABLE_NAME, columns, where, SqlUtil.buildArgs(releaseChannelThreadId), null, null, orderBy, limit)) { return cursor != null && cursor.moveToNext() ? cursor.getLong(0) : null; } } + private static long getReleaseChannelThreadId(boolean hasSeenReleaseChannelStories) { + if (hasSeenReleaseChannelStories) { + return -1L; + } + + RecipientId releaseChannelRecipientId = SignalStore.releaseChannelValues().getReleaseChannelRecipientId(); + if (releaseChannelRecipientId == null) { + return -1L; + } + + Long releaseChannelThreadId = SignalDatabase.threads().getThreadIdFor(releaseChannelRecipientId); + if (releaseChannelThreadId == null) { + return -1L; + } + + return releaseChannelThreadId; + } + @Override public void deleteGroupStoryReplies(long parentStoryId) { SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); @@ -924,8 +943,7 @@ public class MmsDatabase extends MessageDatabase { db.beginTransaction(); try { - RecipientId releaseChannelRecipient = hasSeenReleaseChannelStories ? null : SignalStore.releaseChannelValues().getReleaseChannelRecipientId(); - long releaseChannelThreadId = releaseChannelRecipient != null ? SignalDatabase.threads().getOrCreateThreadIdFor(Recipient.resolved(releaseChannelRecipient)) : -1; + long releaseChannelThreadId = getReleaseChannelThreadId(hasSeenReleaseChannelStories); String storiesBeforeTimestampWhere = IS_STORY_CLAUSE + " AND " + DATE_SENT + " < ? AND " + THREAD_ID + " != ?"; String[] sharedArgs = SqlUtil.buildArgs(timestamp, releaseChannelThreadId); String deleteStoryRepliesQuery = "DELETE FROM " + TABLE_NAME + " " + diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 21331ef85d..10c60e27eb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -1462,7 +1462,7 @@ public class SmsDatabase extends MessageDatabase { } @Override - public @Nullable Long getOldestStorySendTimestamp() { + public @Nullable Long getOldestStorySendTimestamp(boolean hasSeenReleaseChannelStories) { throw new UnsupportedOperationException(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringStoriesManager.kt b/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringStoriesManager.kt index 3a188a2388..cd1729db50 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringStoriesManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringStoriesManager.kt @@ -32,7 +32,7 @@ class ExpiringStoriesManager( @WorkerThread override fun getNextClosestEvent(): Event? { - val oldestTimestamp = mmsDatabase.oldestStorySendTimestamp ?: return null + val oldestTimestamp = mmsDatabase.getOldestStorySendTimestamp(SignalStore.storyValues().userHasSeenOnboardingStory) ?: return null val timeSinceSend = System.currentTimeMillis() - oldestTimestamp val delay = (STORY_LIFESPAN - timeSinceSend).coerceAtLeast(0)