Refresh conversation info surfaces in realtime
This commit is contained in:
@@ -9,6 +9,10 @@ import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class ConversationFolderActivity extends BossScreenActivity {
|
||||
public static final String EXTRA_FOLDER_KEY = "folder_key";
|
||||
@@ -16,12 +20,16 @@ public class ConversationFolderActivity extends BossScreenActivity {
|
||||
public static final String EXTRA_TARGET_PROJECT_ID = "target_project_id";
|
||||
public static final String EXTRA_TARGET_PROJECT_IDS = "target_project_ids";
|
||||
public static final String EXTRA_TARGET_PROJECT_LABEL = "target_project_label";
|
||||
private static final long REALTIME_RELOAD_THROTTLE_MS = 900L;
|
||||
|
||||
private String folderKey;
|
||||
private String folderName;
|
||||
private String targetProjectId;
|
||||
private ArrayList<String> targetProjectIds;
|
||||
private String targetProjectLabel;
|
||||
private @Nullable BossRealtimeClient realtimeClient;
|
||||
private final Map<String, Long> recentRealtimeEventTimestamps = new LinkedHashMap<>();
|
||||
private final Set<String> trackedProjectIds = new LinkedHashSet<>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -45,9 +53,28 @@ public class ConversationFolderActivity extends BossScreenActivity {
|
||||
configureScreen(folderName == null || folderName.isEmpty() ? "项目线程" : folderName, "0 个线程");
|
||||
refreshButton.setVisibility(android.view.View.GONE);
|
||||
setHeaderAction("...", v -> showMoreMenu());
|
||||
realtimeClient = new BossRealtimeClient(apiClient, this::handleRealtimeEvent);
|
||||
reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
updateRealtimeSubscription();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
stopRealtimeUpdates();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
stopRealtimeUpdates();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reload() {
|
||||
if (folderKey == null || folderKey.isEmpty()) {
|
||||
@@ -72,9 +99,76 @@ public class ConversationFolderActivity extends BossScreenActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateRealtimeSubscription() {
|
||||
if (apiClient != null && apiClient.hasSessionHints() && realtimeClient != null) {
|
||||
realtimeClient.start();
|
||||
return;
|
||||
}
|
||||
stopRealtimeUpdates();
|
||||
}
|
||||
|
||||
private void stopRealtimeUpdates() {
|
||||
if (realtimeClient != null) {
|
||||
realtimeClient.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void handleRealtimeEvent(BossRealtimeEvent event) {
|
||||
if (event == null || event.eventName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!shouldReloadForRealtimeEvent(event)) {
|
||||
return;
|
||||
}
|
||||
String eventFingerprint = BossRealtimeClient.buildEventFingerprint(event);
|
||||
if (eventFingerprint.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
if (isDuplicateRealtimeEvent(eventFingerprint, now)) {
|
||||
return;
|
||||
}
|
||||
runOnUiThread(this::reload);
|
||||
}
|
||||
|
||||
private boolean shouldReloadForRealtimeEvent(BossRealtimeEvent event) {
|
||||
if (!"conversation.updated".equals(event.eventName)
|
||||
&& !"project.messages.updated".equals(event.eventName)) {
|
||||
return false;
|
||||
}
|
||||
String payloadProjectId = event.payload.optString("projectId", "").trim();
|
||||
if (payloadProjectId.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return trackedProjectIds.contains(payloadProjectId)
|
||||
|| (!targetProjectIds.isEmpty() && targetProjectIds.contains(payloadProjectId))
|
||||
|| (targetProjectId != null && targetProjectId.equals(payloadProjectId));
|
||||
}
|
||||
|
||||
private boolean isDuplicateRealtimeEvent(String eventFingerprint, long now) {
|
||||
pruneRecentRealtimeEvents(now);
|
||||
Long previousEventAt = recentRealtimeEventTimestamps.get(eventFingerprint);
|
||||
if (previousEventAt != null && now - previousEventAt < REALTIME_RELOAD_THROTTLE_MS) {
|
||||
return true;
|
||||
}
|
||||
recentRealtimeEventTimestamps.put(eventFingerprint, now);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void pruneRecentRealtimeEvents(long now) {
|
||||
java.util.Iterator<Map.Entry<String, Long>> iterator = recentRealtimeEventTimestamps.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, Long> entry = iterator.next();
|
||||
if (now - entry.getValue() >= REALTIME_RELOAD_THROTTLE_MS) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderFolder(@Nullable JSONObject folder) {
|
||||
replaceContent();
|
||||
if (folder == null) {
|
||||
trackedProjectIds.clear();
|
||||
appendContent(BossUi.buildEmptyCard(this, "未找到项目线程。"));
|
||||
setRefreshing(false);
|
||||
return;
|
||||
@@ -91,6 +185,7 @@ public class ConversationFolderActivity extends BossScreenActivity {
|
||||
));
|
||||
|
||||
JSONArray threads = folder.optJSONArray("threads");
|
||||
updateTrackedProjectIds(threads);
|
||||
if (threads == null || threads.length() == 0) {
|
||||
appendContent(BossUi.buildEmptyCard(this, "当前项目下没有线程。"));
|
||||
setRefreshing(false);
|
||||
@@ -127,6 +222,23 @@ public class ConversationFolderActivity extends BossScreenActivity {
|
||||
setRefreshing(false);
|
||||
}
|
||||
|
||||
private void updateTrackedProjectIds(@Nullable JSONArray threads) {
|
||||
trackedProjectIds.clear();
|
||||
if (threads == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < threads.length(); i++) {
|
||||
JSONObject item = threads.optJSONObject(i);
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String projectId = item.optString("projectId", "").trim();
|
||||
if (!projectId.isEmpty()) {
|
||||
trackedProjectIds.add(projectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderThreadAtIndex(JSONArray threads, int index, boolean highlighted) {
|
||||
JSONObject item = threads.optJSONObject(index);
|
||||
if (item == null) return;
|
||||
|
||||
@@ -12,9 +12,13 @@ import androidx.appcompat.widget.SwitchCompat;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConversationInfoActivity extends BossScreenActivity {
|
||||
public static final String EXTRA_PROJECT_ID = "project_id";
|
||||
public static final String EXTRA_PROJECT_NAME = "project_name";
|
||||
private static final long REALTIME_RELOAD_THROTTLE_MS = 900L;
|
||||
|
||||
private String projectId;
|
||||
private String projectName;
|
||||
@@ -22,6 +26,8 @@ public class ConversationInfoActivity extends BossScreenActivity {
|
||||
private int participantCount;
|
||||
private boolean takeoverEnabled;
|
||||
private boolean takeoverInheritedFromGlobal;
|
||||
private @Nullable BossRealtimeClient realtimeClient;
|
||||
private final Map<String, Long> recentRealtimeEventTimestamps = new LinkedHashMap<>();
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
@@ -36,9 +42,28 @@ public class ConversationInfoActivity extends BossScreenActivity {
|
||||
configureScreen("会话信息", projectName == null ? "单线程会话" : projectName);
|
||||
refreshButton.setVisibility(android.view.View.GONE);
|
||||
setHeaderAction("...", v -> showMoreMenu());
|
||||
realtimeClient = new BossRealtimeClient(apiClient, this::handleRealtimeEvent);
|
||||
reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
updateRealtimeSubscription();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
stopRealtimeUpdates();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
stopRealtimeUpdates();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reload() {
|
||||
if (projectId == null || projectId.isEmpty()) {
|
||||
@@ -72,6 +97,67 @@ public class ConversationInfoActivity extends BossScreenActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateRealtimeSubscription() {
|
||||
if (apiClient != null && apiClient.hasSessionHints() && realtimeClient != null) {
|
||||
realtimeClient.start();
|
||||
return;
|
||||
}
|
||||
stopRealtimeUpdates();
|
||||
}
|
||||
|
||||
private void stopRealtimeUpdates() {
|
||||
if (realtimeClient != null) {
|
||||
realtimeClient.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void handleRealtimeEvent(BossRealtimeEvent event) {
|
||||
if (event == null || event.eventName.isEmpty() || projectId == null || projectId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!shouldReloadForRealtimeEvent(event)) {
|
||||
return;
|
||||
}
|
||||
String eventFingerprint = BossRealtimeClient.buildEventFingerprint(event);
|
||||
if (eventFingerprint.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
if (isDuplicateRealtimeEvent(eventFingerprint, now)) {
|
||||
return;
|
||||
}
|
||||
runOnUiThread(this::reload);
|
||||
}
|
||||
|
||||
private boolean shouldReloadForRealtimeEvent(BossRealtimeEvent event) {
|
||||
String payloadProjectId = event.payload.optString("projectId", "").trim();
|
||||
if (payloadProjectId.isEmpty() || !payloadProjectId.equals(projectId)) {
|
||||
return false;
|
||||
}
|
||||
return "conversation.updated".equals(event.eventName)
|
||||
|| "project.messages.updated".equals(event.eventName);
|
||||
}
|
||||
|
||||
private boolean isDuplicateRealtimeEvent(String eventFingerprint, long now) {
|
||||
pruneRecentRealtimeEvents(now);
|
||||
Long previousEventAt = recentRealtimeEventTimestamps.get(eventFingerprint);
|
||||
if (previousEventAt != null && now - previousEventAt < REALTIME_RELOAD_THROTTLE_MS) {
|
||||
return true;
|
||||
}
|
||||
recentRealtimeEventTimestamps.put(eventFingerprint, now);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void pruneRecentRealtimeEvents(long now) {
|
||||
java.util.Iterator<Map.Entry<String, Long>> iterator = recentRealtimeEventTimestamps.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, Long> entry = iterator.next();
|
||||
if (now - entry.getValue() >= REALTIME_RELOAD_THROTTLE_MS) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderConversation(JSONObject detail, JSONObject participantsPayload, @Nullable JSONObject threadStatusPayload) {
|
||||
replaceContent();
|
||||
JSONObject project = detail.optJSONObject("project");
|
||||
|
||||
@@ -12,12 +12,18 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GroupInfoActivity extends BossScreenActivity {
|
||||
public static final String EXTRA_PROJECT_ID = "project_id";
|
||||
public static final String EXTRA_PROJECT_NAME = "project_name";
|
||||
private static final long REALTIME_RELOAD_THROTTLE_MS = 900L;
|
||||
|
||||
private String projectId;
|
||||
private String projectName;
|
||||
private @Nullable BossRealtimeClient realtimeClient;
|
||||
private final Map<String, Long> recentRealtimeEventTimestamps = new LinkedHashMap<>();
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
@@ -32,9 +38,28 @@ public class GroupInfoActivity extends BossScreenActivity {
|
||||
configureScreen("群资料", projectName == null ? "协作群聊" : projectName);
|
||||
refreshButton.setVisibility(android.view.View.GONE);
|
||||
setHeaderAction("...", v -> showMoreMenu());
|
||||
realtimeClient = new BossRealtimeClient(apiClient, this::handleRealtimeEvent);
|
||||
reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
updateRealtimeSubscription();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
stopRealtimeUpdates();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
stopRealtimeUpdates();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reload() {
|
||||
if (projectId == null || projectId.isEmpty()) {
|
||||
@@ -63,6 +88,67 @@ public class GroupInfoActivity extends BossScreenActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateRealtimeSubscription() {
|
||||
if (apiClient != null && apiClient.hasSessionHints() && realtimeClient != null) {
|
||||
realtimeClient.start();
|
||||
return;
|
||||
}
|
||||
stopRealtimeUpdates();
|
||||
}
|
||||
|
||||
private void stopRealtimeUpdates() {
|
||||
if (realtimeClient != null) {
|
||||
realtimeClient.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void handleRealtimeEvent(BossRealtimeEvent event) {
|
||||
if (event == null || event.eventName.isEmpty() || projectId == null || projectId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!shouldReloadForRealtimeEvent(event)) {
|
||||
return;
|
||||
}
|
||||
String eventFingerprint = BossRealtimeClient.buildEventFingerprint(event);
|
||||
if (eventFingerprint.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
if (isDuplicateRealtimeEvent(eventFingerprint, now)) {
|
||||
return;
|
||||
}
|
||||
runOnUiThread(this::reload);
|
||||
}
|
||||
|
||||
private boolean shouldReloadForRealtimeEvent(BossRealtimeEvent event) {
|
||||
String payloadProjectId = event.payload.optString("projectId", "").trim();
|
||||
if (payloadProjectId.isEmpty() || !payloadProjectId.equals(projectId)) {
|
||||
return false;
|
||||
}
|
||||
return "conversation.updated".equals(event.eventName)
|
||||
|| "project.messages.updated".equals(event.eventName);
|
||||
}
|
||||
|
||||
private boolean isDuplicateRealtimeEvent(String eventFingerprint, long now) {
|
||||
pruneRecentRealtimeEvents(now);
|
||||
Long previousEventAt = recentRealtimeEventTimestamps.get(eventFingerprint);
|
||||
if (previousEventAt != null && now - previousEventAt < REALTIME_RELOAD_THROTTLE_MS) {
|
||||
return true;
|
||||
}
|
||||
recentRealtimeEventTimestamps.put(eventFingerprint, now);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void pruneRecentRealtimeEvents(long now) {
|
||||
java.util.Iterator<Map.Entry<String, Long>> iterator = recentRealtimeEventTimestamps.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, Long> entry = iterator.next();
|
||||
if (now - entry.getValue() >= REALTIME_RELOAD_THROTTLE_MS) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderGroup(JSONObject detail, JSONObject participantsPayload) {
|
||||
renderGroup(detail, participantsPayload, null);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowDialog;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
@@ -117,6 +118,70 @@ public class ConversationFolderActivityTest {
|
||||
assertEquals(1, countTextOccurrences(content, "目标线程"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchingProjectMessagesUpdatedEventTriggersReload() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(ConversationFolderActivity.EXTRA_FOLDER_KEY, "talking")
|
||||
.putExtra(ConversationFolderActivity.EXTRA_FOLDER_NAME, "Talking");
|
||||
TestConversationFolderActivity activity = Robolectric
|
||||
.buildActivity(TestConversationFolderActivity.class, intent)
|
||||
.setup()
|
||||
.resume()
|
||||
.get();
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"renderFolder",
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildFolderPayload())
|
||||
);
|
||||
activity.reloadEnabled = true;
|
||||
activity.reloadCount = 0;
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("project.messages.updated", new JSONObject().put("projectId", "project-2"))
|
||||
)
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(1, activity.reloadCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unrelatedConversationEventDoesNotTriggerReload() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(ConversationFolderActivity.EXTRA_FOLDER_KEY, "talking")
|
||||
.putExtra(ConversationFolderActivity.EXTRA_FOLDER_NAME, "Talking");
|
||||
TestConversationFolderActivity activity = Robolectric
|
||||
.buildActivity(TestConversationFolderActivity.class, intent)
|
||||
.setup()
|
||||
.resume()
|
||||
.get();
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"renderFolder",
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildFolderPayload())
|
||||
);
|
||||
activity.reloadEnabled = true;
|
||||
activity.reloadCount = 0;
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("conversation.updated", new JSONObject().put("projectId", "project-9"))
|
||||
)
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(0, activity.reloadCount);
|
||||
}
|
||||
|
||||
private static JSONObject buildFolderPayload() throws Exception {
|
||||
JSONArray threads = new JSONArray()
|
||||
.put(new JSONObject()
|
||||
@@ -182,9 +247,17 @@ public class ConversationFolderActivityTest {
|
||||
}
|
||||
|
||||
public static class TestConversationFolderActivity extends ConversationFolderActivity {
|
||||
private boolean reloadEnabled;
|
||||
private int reloadCount;
|
||||
|
||||
@Override
|
||||
protected void reload() {
|
||||
// Tests render the folder state directly.
|
||||
if (!reloadEnabled) {
|
||||
return;
|
||||
}
|
||||
reloadCount += 1;
|
||||
replaceContent(BossUi.buildEmptyCard(this, "test reload"));
|
||||
setRefreshing(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +187,7 @@ public class ConversationInfoActivityTest {
|
||||
);
|
||||
ReflectionHelpers.setField(activity, "apiClient", apiClient);
|
||||
ReflectionHelpers.setField(activity, "reloadEnabled", true);
|
||||
ReflectionHelpers.setField(activity, "delegateReloadToSuper", true);
|
||||
ReflectionHelpers.setField(activity, "executor", new DirectExecutorService());
|
||||
|
||||
activity.reload();
|
||||
@@ -217,6 +218,7 @@ public class ConversationInfoActivityTest {
|
||||
apiClient.failFirstSave = true;
|
||||
ReflectionHelpers.setField(activity, "apiClient", apiClient);
|
||||
ReflectionHelpers.setField(activity, "reloadEnabled", true);
|
||||
ReflectionHelpers.setField(activity, "delegateReloadToSuper", true);
|
||||
ReflectionHelpers.setField(activity, "executor", new DirectExecutorService());
|
||||
|
||||
activity.reload();
|
||||
@@ -233,6 +235,58 @@ public class ConversationInfoActivityTest {
|
||||
assertEquals(1, apiClient.autoLoginCalls);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchingProjectMessagesUpdatedEventTriggersReload() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(ConversationInfoActivity.EXTRA_PROJECT_ID, "project-1")
|
||||
.putExtra(ConversationInfoActivity.EXTRA_PROJECT_NAME, "北区试产线回归");
|
||||
TestConversationInfoActivity activity = Robolectric
|
||||
.buildActivity(TestConversationInfoActivity.class, intent)
|
||||
.setup()
|
||||
.resume()
|
||||
.get();
|
||||
activity.reloadEnabled = true;
|
||||
activity.reloadCount = 0;
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("project.messages.updated", new JSONObject().put("projectId", "project-1"))
|
||||
)
|
||||
);
|
||||
ShadowLooper.shadowMainLooper().idle();
|
||||
|
||||
assertEquals(1, activity.reloadCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unrelatedConversationEventDoesNotTriggerReload() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(ConversationInfoActivity.EXTRA_PROJECT_ID, "project-1")
|
||||
.putExtra(ConversationInfoActivity.EXTRA_PROJECT_NAME, "北区试产线回归");
|
||||
TestConversationInfoActivity activity = Robolectric
|
||||
.buildActivity(TestConversationInfoActivity.class, intent)
|
||||
.setup()
|
||||
.resume()
|
||||
.get();
|
||||
activity.reloadEnabled = true;
|
||||
activity.reloadCount = 0;
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("conversation.updated", new JSONObject().put("projectId", "project-2"))
|
||||
)
|
||||
);
|
||||
ShadowLooper.shadowMainLooper().idle();
|
||||
|
||||
assertEquals(0, activity.reloadCount);
|
||||
}
|
||||
|
||||
private static JSONObject buildDetailPayload() throws Exception {
|
||||
JSONObject threadMeta = new JSONObject()
|
||||
.put("threadId", "thread-7")
|
||||
@@ -341,13 +395,21 @@ public class ConversationInfoActivityTest {
|
||||
|
||||
public static class TestConversationInfoActivity extends ConversationInfoActivity {
|
||||
private boolean reloadEnabled;
|
||||
private boolean delegateReloadToSuper;
|
||||
private int reloadCount;
|
||||
|
||||
@Override
|
||||
protected void reload() {
|
||||
if (!reloadEnabled) {
|
||||
return;
|
||||
}
|
||||
super.reload();
|
||||
reloadCount += 1;
|
||||
if (delegateReloadToSuper) {
|
||||
super.reload();
|
||||
return;
|
||||
}
|
||||
replaceContent(BossUi.buildEmptyCard(this, "test reload"));
|
||||
setRefreshing(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -286,6 +286,58 @@ public class GroupInfoActivityTest {
|
||||
assertEquals("{\"lightDispatchReminderEnabled\":true}", connection.requestBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchingConversationUpdatedEventTriggersReload() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(GroupInfoActivity.EXTRA_PROJECT_ID, "group-1")
|
||||
.putExtra(GroupInfoActivity.EXTRA_PROJECT_NAME, "巡检协作群");
|
||||
TestGroupInfoActivity activity = Robolectric
|
||||
.buildActivity(TestGroupInfoActivity.class, intent)
|
||||
.setup()
|
||||
.resume()
|
||||
.get();
|
||||
activity.reloadEnabled = true;
|
||||
activity.reloadCount = 0;
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("conversation.updated", new JSONObject().put("projectId", "group-1"))
|
||||
)
|
||||
);
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
assertEquals(1, activity.reloadCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unrelatedProjectMessagesEventDoesNotTriggerReload() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(GroupInfoActivity.EXTRA_PROJECT_ID, "group-1")
|
||||
.putExtra(GroupInfoActivity.EXTRA_PROJECT_NAME, "巡检协作群");
|
||||
TestGroupInfoActivity activity = Robolectric
|
||||
.buildActivity(TestGroupInfoActivity.class, intent)
|
||||
.setup()
|
||||
.resume()
|
||||
.get();
|
||||
activity.reloadEnabled = true;
|
||||
activity.reloadCount = 0;
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("project.messages.updated", new JSONObject().put("projectId", "project-2"))
|
||||
)
|
||||
);
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
assertEquals(0, activity.reloadCount);
|
||||
}
|
||||
|
||||
private static JSONObject buildDetailPayload() throws Exception {
|
||||
return buildDetailPayload(false);
|
||||
}
|
||||
@@ -425,9 +477,17 @@ public class GroupInfoActivityTest {
|
||||
}
|
||||
|
||||
public static class TestGroupInfoActivity extends GroupInfoActivity {
|
||||
private boolean reloadEnabled;
|
||||
private int reloadCount;
|
||||
|
||||
@Override
|
||||
protected void reload() {
|
||||
// Tests render the lightweight info state directly.
|
||||
if (!reloadEnabled) {
|
||||
return;
|
||||
}
|
||||
reloadCount += 1;
|
||||
replaceContent(BossUi.buildEmptyCard(this, "test reload"));
|
||||
setRefreshing(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user