feat: add conversation quick actions fan menu
This commit is contained in:
@@ -46,17 +46,30 @@ public class GroupCreateActivityTest {
|
||||
JSONObject threadConversation = new StubJSONObject()
|
||||
.withString("projectId", "thread-1")
|
||||
.withString("projectTitle", "线程一")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject groupConversation = new StubJSONObject()
|
||||
.withString("projectId", "group-1")
|
||||
.withString("projectTitle", "已有群聊")
|
||||
.withString("conversationType", "group_chat")
|
||||
.withBoolean("isGroup", true);
|
||||
JSONObject sourceConversation = new StubJSONObject()
|
||||
.withString("projectId", "source-1")
|
||||
.withString("projectTitle", "来源线程")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject agentConversation = new StubJSONObject()
|
||||
.withString("projectId", "master-agent")
|
||||
.withString("projectTitle", "主Agent")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject consoleConversation = new StubJSONObject()
|
||||
.withString("projectId", "console-1")
|
||||
.withString("projectTitle", "BOSS移动控制台")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject conversationsPayload = new StubJSONObject()
|
||||
.withObjectArray("conversations", threadConversation, groupConversation, sourceConversation);
|
||||
.withObjectArray("conversations", threadConversation, groupConversation, sourceConversation, agentConversation, consoleConversation);
|
||||
|
||||
java.util.List<JSONObject> filtered = GroupCreateActivity.collectSelectableConversationItems(conversationsPayload, "source-1");
|
||||
|
||||
@@ -69,17 +82,25 @@ public class GroupCreateActivityTest {
|
||||
JSONObject threadConversation = new StubJSONObject()
|
||||
.withString("projectId", "thread-1")
|
||||
.withString("projectTitle", "线程一")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject secondThreadConversation = new StubJSONObject()
|
||||
.withString("projectId", "thread-2")
|
||||
.withString("projectTitle", "线程二")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject groupConversation = new StubJSONObject()
|
||||
.withString("projectId", "group-1")
|
||||
.withString("projectTitle", "已有群聊")
|
||||
.withString("conversationType", "group_chat")
|
||||
.withBoolean("isGroup", true);
|
||||
JSONObject auditConversation = new StubJSONObject()
|
||||
.withString("projectId", "audit-1")
|
||||
.withString("projectTitle", "硬件审计协作")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject conversationsPayload = new StubJSONObject()
|
||||
.withObjectArray("conversations", threadConversation, secondThreadConversation, groupConversation);
|
||||
.withObjectArray("conversations", threadConversation, secondThreadConversation, groupConversation, auditConversation);
|
||||
|
||||
java.util.List<JSONObject> filtered = GroupCreateActivity.collectSelectableConversationItems(conversationsPayload, null);
|
||||
|
||||
@@ -88,6 +109,70 @@ public class GroupCreateActivityTest {
|
||||
assertEquals("thread-2", filtered.get(1).optString("projectId", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectSelectableConversationItems_filtersOutSystemManagedConversations() {
|
||||
JSONObject agentConversation = new StubJSONObject()
|
||||
.withString("projectId", "master-agent")
|
||||
.withString("projectTitle", "主 Agent")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject auditConversation = new StubJSONObject()
|
||||
.withString("projectId", "audit-1")
|
||||
.withString("projectTitle", "硬件审计协作")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject consoleConversation = new StubJSONObject()
|
||||
.withString("projectId", "console-1")
|
||||
.withString("projectTitle", "BOSS移动控制台")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject workerConversation = new StubJSONObject()
|
||||
.withString("projectId", "thread-7")
|
||||
.withString("projectTitle", "树莓派查询线程")
|
||||
.withString("conversationType", "single_device")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject conversationsPayload = new StubJSONObject()
|
||||
.withObjectArray("conversations", agentConversation, auditConversation, consoleConversation, workerConversation);
|
||||
|
||||
List<JSONObject> filtered = GroupCreateActivity.collectSelectableConversationItems(conversationsPayload, null);
|
||||
|
||||
assertEquals(1, filtered.size());
|
||||
assertEquals("thread-7", filtered.get(0).optString("projectId", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectSelectableConversationItems_filtersOutSystemAutoJoinConversations() {
|
||||
JSONObject allowedThreadConversation = new StubJSONObject()
|
||||
.withString("projectId", "thread-1")
|
||||
.withString("projectTitle", "查询树莓派二代")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject masterAgentConversation = new StubJSONObject()
|
||||
.withString("projectId", "thread-2")
|
||||
.withString("projectTitle", "主Agent")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject auditConversation = new StubJSONObject()
|
||||
.withString("projectId", "thread-3")
|
||||
.withString("projectTitle", "硬件审计协作")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject consoleConversation = new StubJSONObject()
|
||||
.withString("projectId", "thread-4")
|
||||
.withString("projectTitle", "BOSS移动控制台")
|
||||
.withBoolean("isGroup", false);
|
||||
JSONObject conversationsPayload = new StubJSONObject()
|
||||
.withObjectArray(
|
||||
"conversations",
|
||||
allowedThreadConversation,
|
||||
masterAgentConversation,
|
||||
auditConversation,
|
||||
consoleConversation
|
||||
);
|
||||
|
||||
List<JSONObject> filtered = GroupCreateActivity.collectSelectableConversationItems(conversationsPayload, null);
|
||||
|
||||
assertEquals(1, filtered.size());
|
||||
assertEquals("thread-1", filtered.get(0).optString("projectId", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reconcileSelectedProjectIds_keepsManualDeselectionWhenCandidatesStayTheSame() {
|
||||
Set<String> previousCandidateIds = linkedSet("thread-1", "thread-2", "thread-3");
|
||||
|
||||
@@ -5,6 +5,7 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
@@ -31,7 +32,13 @@ public class MainActivityConversationSelectionTest {
|
||||
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(activity, "enterConversationSelectionMode");
|
||||
Button actionButton = activity.findViewById(R.id.refresh_button);
|
||||
actionButton.performClick();
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
assertEquals(View.VISIBLE, activity.findViewById(R.id.conversation_quick_actions_overlay).getVisibility());
|
||||
|
||||
activity.findViewById(R.id.quick_action_group_chat).performClick();
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
assertTrue(ReflectionHelpers.getField(activity, "conversationSelectionMode"));
|
||||
|
||||
RecyclerView list = ReflectionHelpers.getField(activity, "screenList");
|
||||
@@ -62,6 +69,23 @@ public class MainActivityConversationSelectionTest {
|
||||
assertTrue("多选模式应显示单选圆点", viewTreeContainsContentDescription(row, "未选中会话"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectionMode_hidesSystemManagedConversations() throws Exception {
|
||||
MainActivity activity = Robolectric.buildActivity(MainActivity.class).setup().get();
|
||||
ReflectionHelpers.setField(activity, "conversationsData", buildConversations());
|
||||
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(activity, "enterConversationSelectionMode");
|
||||
|
||||
RecyclerView list = ReflectionHelpers.getField(activity, "screenList");
|
||||
assertFalse(recyclerContainsText(list, "主Agent"));
|
||||
assertFalse(recyclerContainsText(list, "硬件审计协作"));
|
||||
assertFalse(recyclerContainsText(list, "BOSS移动控制台"));
|
||||
assertTrue(recyclerContainsText(list, "查询树莓派二代"));
|
||||
assertTrue(recyclerContainsText(list, "Boss 线程修复"));
|
||||
}
|
||||
|
||||
private static View getRecyclerChild(RecyclerView recyclerView, int position) {
|
||||
RecyclerView.Adapter adapter = recyclerView.getAdapter();
|
||||
int viewType = adapter.getItemViewType(position);
|
||||
@@ -84,20 +108,44 @@ public class MainActivityConversationSelectionTest {
|
||||
private static JSONArray buildConversations() throws Exception {
|
||||
return new JSONArray()
|
||||
.put(new JSONObject()
|
||||
.put("projectId", "thread-1")
|
||||
.put("projectTitle", "Boss 移动控制台")
|
||||
.put("threadTitle", "Boss 移动控制台")
|
||||
.put("projectId", "master-agent")
|
||||
.put("projectTitle", "主Agent")
|
||||
.put("threadTitle", "主Agent")
|
||||
.put("folderLabel", "Boss")
|
||||
.put("lastMessagePreview", "线程链路正常")
|
||||
.put("latestReplyLabel", "09:41")
|
||||
.put("conversationType", "single_device"))
|
||||
.put(new JSONObject()
|
||||
.put("projectId", "thread-2")
|
||||
.put("projectId", "audit-1")
|
||||
.put("projectTitle", "硬件审计协作")
|
||||
.put("threadTitle", "硬件审计协作")
|
||||
.put("folderLabel", "Mac Studio")
|
||||
.put("lastMessagePreview", "检查摄像头供电链路")
|
||||
.put("latestReplyLabel", "09:42")
|
||||
.put("conversationType", "single_device"))
|
||||
.put(new JSONObject()
|
||||
.put("projectId", "console-1")
|
||||
.put("projectTitle", "BOSS移动控制台")
|
||||
.put("threadTitle", "BOSS移动控制台")
|
||||
.put("folderLabel", "Boss")
|
||||
.put("lastMessagePreview", "统一顶部按钮样式")
|
||||
.put("latestReplyLabel", "09:43")
|
||||
.put("conversationType", "single_device"))
|
||||
.put(new JSONObject()
|
||||
.put("projectId", "thread-1")
|
||||
.put("projectTitle", "查询树莓派二代")
|
||||
.put("threadTitle", "查询树莓派二代")
|
||||
.put("folderLabel", "Mac Studio")
|
||||
.put("lastMessagePreview", "树莓派二代参数查询")
|
||||
.put("latestReplyLabel", "09:44")
|
||||
.put("conversationType", "single_device"))
|
||||
.put(new JSONObject()
|
||||
.put("projectId", "thread-2")
|
||||
.put("projectTitle", "Boss 线程修复")
|
||||
.put("threadTitle", "Boss 线程修复")
|
||||
.put("folderLabel", "Boss")
|
||||
.put("lastMessagePreview", "修复群聊回流")
|
||||
.put("latestReplyLabel", "09:45")
|
||||
.put("conversationType", "single_device"));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ public class WechatSurfaceMapperTopActionTest {
|
||||
assertEquals("+", action.label);
|
||||
assertFalse(action.primaryStyle);
|
||||
assertTrue(action.compactStyle);
|
||||
assertEquals("select_conversations", action.actionKey);
|
||||
assertEquals("open_conversation_quick_actions", action.actionKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user