Track the first time a megaphone appeared.

This commit is contained in:
Greyson Parrelli 2020-01-30 11:33:34 -05:00
parent 22f9bfeceb
commit 9f7b2e2cfd
10 changed files with 67 additions and 26 deletions

View File

@ -475,6 +475,8 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
megaphone.getOnVisibleListener().onVisible(megaphone, this); megaphone.getOnVisibleListener().onVisible(megaphone, this);
} }
} }
viewModel.onMegaphoneVisible(megaphone);
} }
private void updateReminders() { private void updateReminders() {

View File

@ -14,7 +14,6 @@ import android.text.TextUtils;
import org.thoughtcrime.securesms.conversationlist.model.SearchResult; import org.thoughtcrime.securesms.conversationlist.model.SearchResult;
import org.thoughtcrime.securesms.database.DatabaseContentProviders; import org.thoughtcrime.securesms.database.DatabaseContentProviders;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.megaphone.Megaphone; import org.thoughtcrime.securesms.megaphone.Megaphone;
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository; import org.thoughtcrime.securesms.megaphone.MegaphoneRepository;
import org.thoughtcrime.securesms.megaphone.Megaphones; import org.thoughtcrime.securesms.megaphone.Megaphones;
@ -75,6 +74,10 @@ class ConversationListViewModel extends ViewModel {
megaphone.postValue(null); megaphone.postValue(null);
} }
void onMegaphoneVisible(@NonNull Megaphone visible) {
megaphoneRepository.markVisible(visible.getEvent());
}
void updateQuery(String query) { void updateQuery(String query) {
lastQuery = query; lastQuery = query;
debouncer.publish(() -> searchRepository.query(query, result -> { debouncer.publish(() -> searchRepository.query(query, result -> {

View File

@ -23,17 +23,19 @@ public class MegaphoneDatabase extends Database {
private static final String TABLE_NAME = "megaphone"; private static final String TABLE_NAME = "megaphone";
private static final String ID = "_id"; private static final String ID = "_id";
private static final String EVENT = "event"; private static final String EVENT = "event";
private static final String SEEN_COUNT = "seen_count"; private static final String SEEN_COUNT = "seen_count";
private static final String LAST_SEEN = "last_seen"; private static final String LAST_SEEN = "last_seen";
private static final String FINISHED = "finished"; private static final String FIRST_VISIBLE = "first_visible";
private static final String FINISHED = "finished";
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
EVENT + " TEXT UNIQUE, " + EVENT + " TEXT UNIQUE, " +
SEEN_COUNT + " INTEGER, " + SEEN_COUNT + " INTEGER, " +
LAST_SEEN + " INTEGER, " + LAST_SEEN + " INTEGER, " +
FINISHED + " INTEGER)"; FIRST_VISIBLE + " INTEGER, " +
FINISHED + " INTEGER)";
MegaphoneDatabase(Context context, SQLCipherOpenHelper databaseHelper) { MegaphoneDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
super(context, databaseHelper); super(context, databaseHelper);
@ -62,18 +64,29 @@ public class MegaphoneDatabase extends Database {
try (Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, null, null, null, null, null)) { try (Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, null, null, null, null, null)) {
while (cursor != null && cursor.moveToNext()) { while (cursor != null && cursor.moveToNext()) {
String event = cursor.getString(cursor.getColumnIndexOrThrow(EVENT)); String event = cursor.getString(cursor.getColumnIndexOrThrow(EVENT));
int seenCount = cursor.getInt(cursor.getColumnIndexOrThrow(SEEN_COUNT)); int seenCount = cursor.getInt(cursor.getColumnIndexOrThrow(SEEN_COUNT));
long lastSeen = cursor.getLong(cursor.getColumnIndexOrThrow(LAST_SEEN)); long lastSeen = cursor.getLong(cursor.getColumnIndexOrThrow(LAST_SEEN));
boolean finished = cursor.getInt(cursor.getColumnIndexOrThrow(FINISHED)) == 1; long firstVisible = cursor.getLong(cursor.getColumnIndexOrThrow(FIRST_VISIBLE));
boolean finished = cursor.getInt(cursor.getColumnIndexOrThrow(FINISHED)) == 1;
records.add(new MegaphoneRecord(Event.fromKey(event), seenCount, lastSeen, finished)); records.add(new MegaphoneRecord(Event.fromKey(event), seenCount, lastSeen, firstVisible, finished));
} }
} }
return records; return records;
} }
public void markFirstVisible(@NonNull Event event, long time) {
String query = EVENT + " = ?";
String[] args = new String[]{event.getKey()};
ContentValues values = new ContentValues();
values.put(FIRST_VISIBLE, time);
databaseHelper.getWritableDatabase().update(TABLE_NAME, values, query, args);
}
public void markSeen(@NonNull Event event, int seenCount, long lastSeen) { public void markSeen(@NonNull Event event, int seenCount, long lastSeen) {
String query = EVENT + " = ?"; String query = EVENT + " = ?";
String[] args = new String[]{event.getKey()}; String[] args = new String[]{event.getKey()};

View File

@ -104,8 +104,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int SPLIT_PROFILE_NAMES = 43; private static final int SPLIT_PROFILE_NAMES = 43;
private static final int STICKER_PACK_ORDER = 44; private static final int STICKER_PACK_ORDER = 44;
private static final int MEGAPHONES = 45; private static final int MEGAPHONES = 45;
private static final int MEGAPHONE_FIRST_APPEARANCE = 46;
private static final int DATABASE_VERSION = 45; private static final int DATABASE_VERSION = 46;
private static final String DATABASE_NAME = "signal.db"; private static final String DATABASE_NAME = "signal.db";
private final Context context; private final Context context;
@ -719,6 +720,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
"finished INTEGER)"); "finished INTEGER)");
} }
if (oldVersion < MEGAPHONE_FIRST_APPEARANCE) {
db.execSQL("ALTER TABLE megaphone ADD COLUMN first_visible INTEGER DEFAULT 0");
}
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();

View File

@ -9,13 +9,15 @@ public class MegaphoneRecord {
private final Megaphones.Event event; private final Megaphones.Event event;
private final int seenCount; private final int seenCount;
private final long lastSeen; private final long lastSeen;
private final long firstVisible;
private final boolean finished; private final boolean finished;
public MegaphoneRecord(@NonNull Megaphones.Event event, int seenCount, long lastSeen, boolean finished) { public MegaphoneRecord(@NonNull Megaphones.Event event, int seenCount, long lastSeen, long firstVisible, boolean finished) {
this.event = event; this.event = event;
this.seenCount = seenCount; this.seenCount = seenCount;
this.lastSeen = lastSeen; this.lastSeen = lastSeen;
this.finished = finished; this.firstVisible = firstVisible;
this.finished = finished;
} }
public @NonNull Megaphones.Event getEvent() { public @NonNull Megaphones.Event getEvent() {
@ -30,6 +32,10 @@ public class MegaphoneRecord {
return lastSeen; return lastSeen;
} }
public long getFirstVisible() {
return firstVisible;
}
public boolean isFinished() { public boolean isFinished() {
return finished; return finished;
} }

View File

@ -9,7 +9,7 @@ final class ForeverSchedule implements MegaphoneSchedule {
} }
@Override @Override
public boolean shouldDisplay(int seenCount, long lastSeen, long currentTime) { public boolean shouldDisplay(int seenCount, long lastSeen, long firstVisible, long currentTime) {
return enabled; return enabled;
} }
} }

View File

@ -69,6 +69,18 @@ public class MegaphoneRepository {
}); });
} }
@MainThread
public void markVisible(@NonNull Megaphones.Event event) {
long time = System.currentTimeMillis();
executor.execute(() -> {
if (getRecord(event).getFirstVisible() == 0) {
database.markFirstVisible(event, time);
resetDatabaseCache();
}
});
}
@MainThread @MainThread
public void markSeen(@NonNull Megaphone megaphone) { public void markSeen(@NonNull Megaphone megaphone) {
long lastSeen = System.currentTimeMillis(); long lastSeen = System.currentTimeMillis();

View File

@ -1,5 +1,5 @@
package org.thoughtcrime.securesms.megaphone; package org.thoughtcrime.securesms.megaphone;
public interface MegaphoneSchedule { public interface MegaphoneSchedule {
boolean shouldDisplay(int seenCount, long lastSeen, long currentTime); boolean shouldDisplay(int seenCount, long lastSeen, long firstVisible, long currentTime);
} }

View File

@ -45,7 +45,7 @@ public final class Megaphones {
MegaphoneRecord record = Objects.requireNonNull(records.get(e.getKey())); MegaphoneRecord record = Objects.requireNonNull(records.get(e.getKey()));
MegaphoneSchedule schedule = e.getValue(); MegaphoneSchedule schedule = e.getValue();
return !record.isFinished() && schedule.shouldDisplay(record.getSeenCount(), record.getLastSeen(), currentTime); return !record.isFinished() && schedule.shouldDisplay(record.getSeenCount(), record.getLastSeen(), record.getFirstVisible(), currentTime);
}) })
.map(Map.Entry::getKey) .map(Map.Entry::getKey)
.map(records::get) .map(records::get)

View File

@ -9,7 +9,7 @@ class RecurringSchedule implements MegaphoneSchedule {
} }
@Override @Override
public boolean shouldDisplay(int seenCount, long lastSeen, long currentTime) { public boolean shouldDisplay(int seenCount, long lastSeen, long firstVisible, long currentTime) {
if (seenCount == 0) { if (seenCount == 0) {
return true; return true;
} }