Patch conversation home from realtime events

This commit is contained in:
kris
2026-04-10 19:21:36 +08:00
parent 7131ee9eb1
commit 0781a56aad
7 changed files with 255 additions and 7 deletions

View File

@@ -581,9 +581,43 @@ public class MainActivity extends AppCompatActivity {
if (isDuplicateRealtimeEvent(eventFingerprint, now)) {
return;
}
if ("conversations".equals(activeTab) && tryApplyConversationRealtimePatch(event)) {
return;
}
runOnUiThread(this::scheduleRealtimeRefresh);
}
private boolean tryApplyConversationRealtimePatch(BossRealtimeEvent event) {
if (event == null || conversationsData == null) {
return false;
}
if (!"conversation.updated".equals(event.eventName)
&& !"project.messages.updated".equals(event.eventName)) {
return false;
}
String affectedProjectId = event.payload.optString("projectId", "").trim();
if (affectedProjectId.isEmpty()) {
return false;
}
JSONObject conversationItem = event.payload.optJSONObject("conversationItem");
if (conversationItem == null) {
return false;
}
runOnUiThread(() -> {
if (conversationsData == null) {
scheduleRealtimeRefresh();
return;
}
conversationsData = WechatSurfaceMapper.mergeConversationHomeItem(
conversationsData,
conversationItem,
affectedProjectId
);
renderCurrentTab();
});
return true;
}
private void scheduleRealtimeRefresh() {
if (realtimeRefreshScheduled) {
return;

View File

@@ -383,6 +383,35 @@ public final class WechatSurfaceMapper {
return sortConversationItems(passthrough);
}
public static JSONArray mergeConversationHomeItem(JSONArray source, JSONObject item, String affectedProjectId) {
if (source == null) {
return null;
}
JSONArray merged = new JSONArray();
String normalizedAffectedProjectId = affectedProjectId == null ? "" : affectedProjectId.trim();
String replacementConversationId = item == null ? "" : item.optString("conversationId", "").trim();
String replacementFolderKey = item == null ? "" : item.optString("folderKey", "").trim();
for (int index = 0; index < source.length(); index += 1) {
JSONObject existing = source.optJSONObject(index);
if (existing == null) {
continue;
}
if (shouldReplaceConversationItem(
existing,
normalizedAffectedProjectId,
replacementConversationId,
replacementFolderKey
)) {
continue;
}
merged.put(copyJson(existing));
}
if (item != null) {
merged.put(copyJson(item));
}
return sortConversationItems(merged);
}
private static JSONObject buildFolderArchiveItem(String folderKey, List<JSONObject> items) {
List<JSONObject> sortedByLatest = new ArrayList<>(items);
sortedByLatest.sort((left, right) -> compareConversationFreshness(right, left));
@@ -488,6 +517,42 @@ public final class WechatSurfaceMapper {
return sorted;
}
private static boolean shouldReplaceConversationItem(
JSONObject existing,
String affectedProjectId,
String replacementConversationId,
String replacementFolderKey
) {
if (!replacementConversationId.isEmpty()
&& replacementConversationId.equals(existing.optString("conversationId", "").trim())) {
return true;
}
if (!replacementFolderKey.isEmpty()
&& replacementFolderKey.equals(existing.optString("folderKey", "").trim())) {
return true;
}
if (affectedProjectId.isEmpty()) {
return false;
}
if (affectedProjectId.equals(existing.optString("projectId", "").trim())) {
return true;
}
return arrayContainsString(existing.optJSONArray("searchTargetProjectIds"), affectedProjectId);
}
private static boolean arrayContainsString(JSONArray source, String target) {
if (source == null || target == null || target.trim().isEmpty()) {
return false;
}
String normalizedTarget = target.trim();
for (int index = 0; index < source.length(); index += 1) {
if (normalizedTarget.equals(source.optString(index, "").trim())) {
return true;
}
}
return false;
}
private static int compareConversationFreshness(JSONObject left, JSONObject right) {
String leftAt = left.optString("latestReplyAt", "");
String rightAt = right.optString("latestReplyAt", "");