Patch folder realtime threads locally
This commit is contained in:
@@ -32,6 +32,7 @@ public class ConversationFolderActivity extends BossScreenActivity {
|
||||
private ArrayList<String> targetProjectIds;
|
||||
private String targetProjectLabel;
|
||||
private @Nullable BossRealtimeClient realtimeClient;
|
||||
private @Nullable JSONObject currentFolderPayload;
|
||||
private final Handler uiHandler = new Handler(Looper.getMainLooper());
|
||||
private final Map<String, Long> recentRealtimeEventTimestamps = new LinkedHashMap<>();
|
||||
private final Set<String> trackedProjectIds = new LinkedHashSet<>();
|
||||
@@ -144,9 +145,48 @@ public class ConversationFolderActivity extends BossScreenActivity {
|
||||
if (isDuplicateRealtimeEvent(eventFingerprint, now)) {
|
||||
return;
|
||||
}
|
||||
if (tryApplyFolderRealtimePatch(event)) {
|
||||
return;
|
||||
}
|
||||
runOnUiThread(this::scheduleRealtimeReload);
|
||||
}
|
||||
|
||||
private boolean tryApplyFolderRealtimePatch(BossRealtimeEvent event) {
|
||||
if (event == null || currentFolderPayload == 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() || !trackedProjectIds.contains(affectedProjectId)) {
|
||||
return false;
|
||||
}
|
||||
JSONObject threadConversationItem = event.payload.optJSONObject("threadConversationItem");
|
||||
if (threadConversationItem == null) {
|
||||
return false;
|
||||
}
|
||||
String patchedFolderKey = threadConversationItem.optString("folderKey", "").trim();
|
||||
if (folderKey == null || folderKey.isEmpty() || !folderKey.equals(patchedFolderKey)) {
|
||||
return false;
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
if (currentFolderPayload == null) {
|
||||
scheduleRealtimeReload();
|
||||
return;
|
||||
}
|
||||
JSONObject mergedFolder = replaceThreadConversationItem(
|
||||
currentFolderPayload,
|
||||
affectedProjectId,
|
||||
threadConversationItem
|
||||
);
|
||||
currentFolderPayload = mergedFolder;
|
||||
renderFolder(mergedFolder);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void scheduleRealtimeReload() {
|
||||
if (realtimeReloadScheduled) {
|
||||
return;
|
||||
@@ -201,12 +241,14 @@ public class ConversationFolderActivity extends BossScreenActivity {
|
||||
private void renderFolder(@Nullable JSONObject folder) {
|
||||
replaceContent();
|
||||
if (folder == null) {
|
||||
currentFolderPayload = null;
|
||||
trackedProjectIds.clear();
|
||||
appendContent(BossUi.buildEmptyCard(this, "未找到项目线程。"));
|
||||
setRefreshing(false);
|
||||
return;
|
||||
}
|
||||
|
||||
currentFolderPayload = copyJson(folder);
|
||||
String resolvedFolderName = folder.optString("folderLabel", folderName == null ? "项目线程" : folderName);
|
||||
folderDeviceId = folder.optString("deviceId", folderDeviceId == null ? "" : folderDeviceId).trim();
|
||||
int threadCount = folder.optInt("threadCount", 0);
|
||||
@@ -273,6 +315,47 @@ public class ConversationFolderActivity extends BossScreenActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private JSONObject replaceThreadConversationItem(JSONObject folder, String affectedProjectId, JSONObject threadConversationItem) {
|
||||
JSONObject mergedFolder = copyJson(folder);
|
||||
JSONArray existingThreads = mergedFolder.optJSONArray("threads");
|
||||
JSONArray mergedThreads = new JSONArray();
|
||||
boolean replaced = false;
|
||||
if (existingThreads != null) {
|
||||
for (int i = 0; i < existingThreads.length(); i++) {
|
||||
JSONObject item = existingThreads.optJSONObject(i);
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
if (affectedProjectId.equals(item.optString("projectId", "").trim())) {
|
||||
mergedThreads.put(copyJson(threadConversationItem));
|
||||
replaced = true;
|
||||
continue;
|
||||
}
|
||||
mergedThreads.put(copyJson(item));
|
||||
}
|
||||
}
|
||||
if (!replaced) {
|
||||
mergedThreads.put(copyJson(threadConversationItem));
|
||||
}
|
||||
try {
|
||||
mergedFolder.put("threads", mergedThreads);
|
||||
mergedFolder.put("threadCount", mergedThreads.length());
|
||||
} catch (org.json.JSONException ignored) {
|
||||
}
|
||||
return mergedFolder;
|
||||
}
|
||||
|
||||
private JSONObject copyJson(@Nullable JSONObject source) {
|
||||
if (source == null) {
|
||||
return new JSONObject();
|
||||
}
|
||||
try {
|
||||
return new JSONObject(source.toString());
|
||||
} catch (org.json.JSONException ignored) {
|
||||
return new JSONObject();
|
||||
}
|
||||
}
|
||||
|
||||
private String parseFolderDeviceId(@Nullable String candidateFolderKey) {
|
||||
if (candidateFolderKey == null) {
|
||||
return "";
|
||||
|
||||
Reference in New Issue
Block a user