feat: move conversation search into header mode
This commit is contained in:
@@ -61,6 +61,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private Button backButton;
|
private Button backButton;
|
||||||
private TextView topTitle;
|
private TextView topTitle;
|
||||||
private TextView topSubtitle;
|
private TextView topSubtitle;
|
||||||
|
private LinearLayout topTitleGroup;
|
||||||
|
private EditText topSearchInput;
|
||||||
|
private Button searchButton;
|
||||||
private Button refreshButton;
|
private Button refreshButton;
|
||||||
private Button tabConversations;
|
private Button tabConversations;
|
||||||
private Button tabDevices;
|
private Button tabDevices;
|
||||||
@@ -85,6 +88,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private String conversationSearchQuery = "";
|
private String conversationSearchQuery = "";
|
||||||
private boolean pinnedConversationsCollapsed = false;
|
private boolean pinnedConversationsCollapsed = false;
|
||||||
private boolean conversationSelectionMode = false;
|
private boolean conversationSelectionMode = false;
|
||||||
|
private boolean conversationSearchMode = false;
|
||||||
private boolean conversationAutoRefreshArmed = false;
|
private boolean conversationAutoRefreshArmed = false;
|
||||||
private boolean conversationAutoRefreshEnabled = false;
|
private boolean conversationAutoRefreshEnabled = false;
|
||||||
private final Set<String> selectedConversationProjectIds = new LinkedHashSet<>();
|
private final Set<String> selectedConversationProjectIds = new LinkedHashSet<>();
|
||||||
@@ -128,6 +132,10 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
|
if (contentPanel.getVisibility() == View.VISIBLE && conversationSearchMode) {
|
||||||
|
exitConversationSearchMode(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (contentPanel.getVisibility() == View.VISIBLE && !"conversations".equals(activeTab)) {
|
if (contentPanel.getVisibility() == View.VISIBLE && !"conversations".equals(activeTab)) {
|
||||||
setActiveTab("conversations", false);
|
setActiveTab("conversations", false);
|
||||||
persistLastRootTab("conversations");
|
persistLastRootTab("conversations");
|
||||||
@@ -179,6 +187,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
backButton = findViewById(R.id.back_button);
|
backButton = findViewById(R.id.back_button);
|
||||||
topTitle = findViewById(R.id.top_title);
|
topTitle = findViewById(R.id.top_title);
|
||||||
topSubtitle = findViewById(R.id.top_subtitle);
|
topSubtitle = findViewById(R.id.top_subtitle);
|
||||||
|
topTitleGroup = findViewById(R.id.top_title_group);
|
||||||
|
topSearchInput = findViewById(R.id.top_search_input);
|
||||||
|
searchButton = findViewById(R.id.search_button);
|
||||||
refreshButton = findViewById(R.id.refresh_button);
|
refreshButton = findViewById(R.id.refresh_button);
|
||||||
tabConversations = findViewById(R.id.tab_conversations);
|
tabConversations = findViewById(R.id.tab_conversations);
|
||||||
tabDevices = findViewById(R.id.tab_devices);
|
tabDevices = findViewById(R.id.tab_devices);
|
||||||
@@ -199,6 +210,16 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private void bindActions() {
|
private void bindActions() {
|
||||||
loginButton.setOnClickListener(v -> performAutoLogin());
|
loginButton.setOnClickListener(v -> performAutoLogin());
|
||||||
backButton.setVisibility(View.GONE);
|
backButton.setVisibility(View.GONE);
|
||||||
|
backButton.setOnClickListener(v -> {
|
||||||
|
if (conversationSearchMode) {
|
||||||
|
exitConversationSearchMode(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
searchButton.setOnClickListener(v -> {
|
||||||
|
if ("conversations".equals(activeTab) && !conversationSelectionMode) {
|
||||||
|
enterConversationSearchMode();
|
||||||
|
}
|
||||||
|
});
|
||||||
refreshButton.setOnClickListener(v -> handleTopAction());
|
refreshButton.setOnClickListener(v -> handleTopAction());
|
||||||
tabConversations.setOnClickListener(v -> setActiveTab("conversations", true));
|
tabConversations.setOnClickListener(v -> setActiveTab("conversations", true));
|
||||||
tabDevices.setOnClickListener(v -> setActiveTab("devices", true));
|
tabDevices.setOnClickListener(v -> setActiveTab("devices", true));
|
||||||
@@ -220,6 +241,26 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
renderCurrentTab();
|
renderCurrentTab();
|
||||||
updateConversationAutoRefresh();
|
updateConversationAutoRefresh();
|
||||||
});
|
});
|
||||||
|
topSearchInput.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable editable) {
|
||||||
|
if (!conversationSearchMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String nextQuery = editable == null ? "" : editable.toString();
|
||||||
|
if (nextQuery.equals(conversationSearchQuery)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
conversationSearchQuery = nextQuery;
|
||||||
|
renderConversationsRoot();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyInitialTab(@Nullable Intent intent) {
|
private void applyInitialTab(@Nullable Intent intent) {
|
||||||
@@ -436,6 +477,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private void setActiveTab(String tab, boolean fromUser) {
|
private void setActiveTab(String tab, boolean fromUser) {
|
||||||
if (!"conversations".equals(tab)) {
|
if (!"conversations".equals(tab)) {
|
||||||
exitConversationSelectionMode();
|
exitConversationSelectionMode();
|
||||||
|
exitConversationSearchMode(false);
|
||||||
}
|
}
|
||||||
activeTab = tab;
|
activeTab = tab;
|
||||||
if (fromUser) {
|
if (fromUser) {
|
||||||
@@ -465,18 +507,18 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
switch (activeTab) {
|
switch (activeTab) {
|
||||||
case "devices":
|
case "devices":
|
||||||
updateHeader("设备", "");
|
updateHeader("设备", "");
|
||||||
configureTopAction(WechatSurfaceMapper.rootTopAction(activeTab, false));
|
configureRootHeaderActions();
|
||||||
renderDevicesRoot();
|
renderDevicesRoot();
|
||||||
break;
|
break;
|
||||||
case "me":
|
case "me":
|
||||||
updateHeader("我的", "");
|
updateHeader("我的", "");
|
||||||
configureTopAction(WechatSurfaceMapper.rootTopAction(activeTab, false));
|
configureRootHeaderActions();
|
||||||
renderMeRoot();
|
renderMeRoot();
|
||||||
break;
|
break;
|
||||||
case "conversations":
|
case "conversations":
|
||||||
default:
|
default:
|
||||||
updateHeader("会话", WechatSurfaceMapper.conversationsHeaderSubtitle());
|
updateHeader("会话", WechatSurfaceMapper.conversationsHeaderSubtitle());
|
||||||
configureTopAction(WechatSurfaceMapper.rootTopAction(activeTab, false, conversationSelectionMode));
|
configureRootHeaderActions();
|
||||||
renderConversationsRoot();
|
renderConversationsRoot();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -512,13 +554,67 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void configureRootHeaderActions() {
|
||||||
|
if ("conversations".equals(activeTab)) {
|
||||||
|
configureConversationHeaderActions();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
topTitleGroup.setVisibility(View.VISIBLE);
|
||||||
|
topSearchInput.setVisibility(View.GONE);
|
||||||
|
backButton.setVisibility(View.GONE);
|
||||||
|
searchButton.setVisibility(View.GONE);
|
||||||
|
WechatSurfaceMapper.RootTopAction action = WechatSurfaceMapper.rootTopAction(activeTab, false);
|
||||||
|
refreshButton.setVisibility(View.VISIBLE);
|
||||||
|
configureTopAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureConversationHeaderActions() {
|
||||||
|
if (conversationSearchMode) {
|
||||||
|
topTitleGroup.setVisibility(View.GONE);
|
||||||
|
topSearchInput.setVisibility(View.VISIBLE);
|
||||||
|
backButton.setVisibility(View.VISIBLE);
|
||||||
|
backButton.setText("取消");
|
||||||
|
searchButton.setVisibility(View.GONE);
|
||||||
|
refreshButton.setVisibility(View.GONE);
|
||||||
|
if (!conversationSearchQuery.equals(topSearchInput.getText().toString())) {
|
||||||
|
topSearchInput.setText(conversationSearchQuery);
|
||||||
|
topSearchInput.setSelection(topSearchInput.getText().length());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
topTitleGroup.setVisibility(View.VISIBLE);
|
||||||
|
topSearchInput.setVisibility(View.GONE);
|
||||||
|
backButton.setVisibility(View.GONE);
|
||||||
|
searchButton.setVisibility(conversationSelectionMode ? View.GONE : View.VISIBLE);
|
||||||
|
refreshButton.setVisibility(View.VISIBLE);
|
||||||
|
BossUi.applyTopActionButtonStyle(this, searchButton, BossUi.TopActionButtonStyle.COMPACT_ICON);
|
||||||
|
WechatSurfaceMapper.RootTopAction action = WechatSurfaceMapper.rootTopAction(activeTab, false, conversationSelectionMode);
|
||||||
|
configureTopAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
private void syncTopActionVisualState(boolean refreshing) {
|
private void syncTopActionVisualState(boolean refreshing) {
|
||||||
|
if ("conversations".equals(activeTab)) {
|
||||||
|
configureConversationHeaderActions();
|
||||||
|
refreshButton.setEnabled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
WechatSurfaceMapper.RootTopAction action = WechatSurfaceMapper.rootTopAction(activeTab, refreshing, conversationSelectionMode);
|
WechatSurfaceMapper.RootTopAction action = WechatSurfaceMapper.rootTopAction(activeTab, refreshing, conversationSelectionMode);
|
||||||
configureTopAction(action);
|
configureTopAction(action);
|
||||||
refreshButton.setEnabled(!"refresh".equals(action.actionKey) || !refreshing);
|
refreshButton.setEnabled(!"refresh".equals(action.actionKey) || !refreshing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleTopAction() {
|
private void handleTopAction() {
|
||||||
|
if ("conversations".equals(activeTab)) {
|
||||||
|
if (conversationSearchMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (conversationSelectionMode) {
|
||||||
|
exitConversationSelectionMode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
enterConversationSelectionMode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
String actionKey = WechatSurfaceMapper.rootTopAction(activeTab, false, conversationSelectionMode).actionKey;
|
String actionKey = WechatSurfaceMapper.rootTopAction(activeTab, false, conversationSelectionMode).actionKey;
|
||||||
if ("add_device".equals(actionKey)) {
|
if ("add_device".equals(actionKey)) {
|
||||||
startActivity(new Intent(this, DeviceEnrollmentActivity.class));
|
startActivity(new Intent(this, DeviceEnrollmentActivity.class));
|
||||||
@@ -540,7 +636,6 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<RootListItem> items = new ArrayList<>();
|
List<RootListItem> items = new ArrayList<>();
|
||||||
items.add(() -> buildConversationSearchInput());
|
|
||||||
if (conversationSelectionMode) {
|
if (conversationSelectionMode) {
|
||||||
appendConversationSelectionControls(items);
|
appendConversationSelectionControls(items);
|
||||||
}
|
}
|
||||||
@@ -672,6 +767,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void enterConversationSelectionMode() {
|
private void enterConversationSelectionMode() {
|
||||||
|
exitConversationSearchMode(false);
|
||||||
conversationSelectionMode = true;
|
conversationSelectionMode = true;
|
||||||
selectedConversationProjectIds.clear();
|
selectedConversationProjectIds.clear();
|
||||||
syncTopActionVisualState(screenRefresh.isRefreshing());
|
syncTopActionVisualState(screenRefresh.isRefreshing());
|
||||||
@@ -690,6 +786,34 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enterConversationSearchMode() {
|
||||||
|
if (!"conversations".equals(activeTab)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
conversationSearchMode = true;
|
||||||
|
syncTopActionVisualState(screenRefresh.isRefreshing());
|
||||||
|
topSearchInput.post(() -> {
|
||||||
|
topSearchInput.requestFocus();
|
||||||
|
topSearchInput.setSelection(topSearchInput.getText().length());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exitConversationSearchMode(boolean clearQuery) {
|
||||||
|
if (!conversationSearchMode && (!clearQuery || conversationSearchQuery.isEmpty())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean queryChanged = clearQuery && !conversationSearchQuery.isEmpty();
|
||||||
|
conversationSearchMode = false;
|
||||||
|
if (clearQuery) {
|
||||||
|
conversationSearchQuery = "";
|
||||||
|
topSearchInput.setText("");
|
||||||
|
}
|
||||||
|
syncTopActionVisualState(screenRefresh != null && screenRefresh.isRefreshing());
|
||||||
|
if (queryChanged && "conversations".equals(activeTab) && contentPanel.getVisibility() == View.VISIBLE) {
|
||||||
|
renderConversationsRoot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void toggleConversationSelection(String projectId) {
|
private void toggleConversationSelection(String projectId) {
|
||||||
if (selectedConversationProjectIds.contains(projectId)) {
|
if (selectedConversationProjectIds.contains(projectId)) {
|
||||||
selectedConversationProjectIds.remove(projectId);
|
selectedConversationProjectIds.remove(projectId);
|
||||||
@@ -755,37 +879,6 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
setActiveTab(tab, true);
|
setActiveTab(tab, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EditText buildConversationSearchInput() {
|
|
||||||
EditText input = BossUi.buildInput(this, "搜索项目或线程", false);
|
|
||||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
);
|
|
||||||
params.leftMargin = BossUi.dp(this, 16);
|
|
||||||
params.rightMargin = BossUi.dp(this, 16);
|
|
||||||
params.bottomMargin = BossUi.dp(this, 10);
|
|
||||||
input.setLayoutParams(params);
|
|
||||||
input.setText(conversationSearchQuery);
|
|
||||||
input.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable editable) {
|
|
||||||
String nextQuery = editable == null ? "" : editable.toString();
|
|
||||||
if (nextQuery.equals(conversationSearchQuery)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
conversationSearchQuery = nextQuery;
|
|
||||||
renderConversationsRoot();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSONArray filterConversationItems(@Nullable JSONArray source, @Nullable String rawQuery) {
|
static JSONArray filterConversationItems(@Nullable JSONArray source, @Nullable String rawQuery) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ public final class WechatSurfaceMapper {
|
|||||||
if (selectionMode) {
|
if (selectionMode) {
|
||||||
return new RootTopAction("取消", false, false, "cancel_select_conversations");
|
return new RootTopAction("取消", false, false, "cancel_select_conversations");
|
||||||
}
|
}
|
||||||
return new RootTopAction("选择", false, false, "select_conversations");
|
return new RootTopAction("+", false, true, "select_conversations");
|
||||||
}
|
}
|
||||||
return new RootTopAction(refreshing ? "同步中" : "刷新", false, false, "refresh");
|
return new RootTopAction(refreshing ? "同步中" : "刷新", false, false, "refresh");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,7 @@
|
|||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/top_title_group"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
@@ -138,6 +139,40 @@
|
|||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/top_search_input"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_secondary_button"
|
||||||
|
android:hint="搜索项目或线程"
|
||||||
|
android:imeOptions="actionSearch"
|
||||||
|
android:inputType="text"
|
||||||
|
android:paddingLeft="14dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingRight="14dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:textColor="@color/boss_text_primary"
|
||||||
|
android:textColorHint="@color/boss_text_muted"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/search_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bg_secondary_button"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:minWidth="0dp"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingRight="12dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:text="⌕"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/boss_green"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/refresh_button"
|
android:id="@+id/refresh_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -148,7 +183,7 @@
|
|||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingRight="12dp"
|
android:paddingRight="12dp"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
android:text="刷"
|
android:text="+"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/boss_green"
|
android:textColor="@color/boss_green"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package com.hyzq.boss;
|
package com.hyzq.boss;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import android.view.View;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@@ -46,34 +46,63 @@ public class MainActivityConversationSearchTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void renderConversationsRootShowsSearchInputInsteadOfHintPill() throws Exception {
|
public void conversationsHeader_usesSearchIconAndPlusButton() throws Exception {
|
||||||
MainActivity activity = Robolectric.buildActivity(MainActivity.class).setup().get();
|
MainActivity activity = Robolectric.buildActivity(MainActivity.class).setup().get();
|
||||||
ReflectionHelpers.setField(activity, "conversationsData", new JSONArray()
|
ReflectionHelpers.setField(activity, "conversationsData", buildConversations());
|
||||||
.put(new JSONObject()
|
|
||||||
.put("projectId", "p1")
|
|
||||||
.put("projectTitle", "500Gcode")
|
|
||||||
.put("folderLabel", "Mac Studio")
|
|
||||||
.put("lastMessagePreview", "线程链路正常")
|
|
||||||
.put("latestReplyLabel", "09:40")));
|
|
||||||
|
|
||||||
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||||
ReflectionHelpers.callInstanceMethod(activity, "renderConversationsRoot");
|
ReflectionHelpers.callInstanceMethod(activity, "renderCurrentTab");
|
||||||
|
|
||||||
|
Button searchButton = activity.findViewById(R.id.search_button);
|
||||||
|
Button actionButton = activity.findViewById(R.id.refresh_button);
|
||||||
|
LinearLayout titleGroup = activity.findViewById(R.id.top_title_group);
|
||||||
|
EditText searchInput = activity.findViewById(R.id.top_search_input);
|
||||||
|
|
||||||
|
assertEquals("⌕", String.valueOf(searchButton.getText()));
|
||||||
|
assertEquals("+", String.valueOf(actionButton.getText()));
|
||||||
|
assertEquals(LinearLayout.VISIBLE, titleGroup.getVisibility());
|
||||||
|
assertEquals(EditText.GONE, searchInput.getVisibility());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchMode_keepsSameInputViewAndRetainsFocusWhileFiltering() throws Exception {
|
||||||
|
MainActivity activity = Robolectric.buildActivity(MainActivity.class).setup().get();
|
||||||
|
ReflectionHelpers.setField(activity, "conversationsData", buildConversations());
|
||||||
|
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||||
|
|
||||||
RecyclerView list = ReflectionHelpers.getField(activity, "screenList");
|
Button searchButton = activity.findViewById(R.id.search_button);
|
||||||
View firstItem = buildRecyclerItem(list, 0);
|
searchButton.performClick();
|
||||||
assertTrue(firstItem instanceof EditText);
|
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||||
EditText input = (EditText) firstItem;
|
|
||||||
assertEquals("搜索项目或线程", String.valueOf(input.getHint()));
|
EditText searchInput = activity.findViewById(R.id.top_search_input);
|
||||||
|
assertTrue(ReflectionHelpers.getField(activity, "conversationSearchMode"));
|
||||||
|
assertTrue(searchInput.isShown());
|
||||||
|
searchInput.requestFocus();
|
||||||
|
assertTrue(searchInput.isFocused());
|
||||||
|
|
||||||
|
searchInput.setText("树莓派");
|
||||||
|
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||||
|
|
||||||
|
EditText searchInputAfter = activity.findViewById(R.id.top_search_input);
|
||||||
|
assertSame(searchInput, searchInputAfter);
|
||||||
|
assertEquals("树莓派", searchInputAfter.getText().toString());
|
||||||
|
assertTrue(searchInputAfter.isFocused());
|
||||||
|
|
||||||
|
Button actionButton = activity.findViewById(R.id.refresh_button);
|
||||||
|
assertEquals(Button.GONE, actionButton.getVisibility());
|
||||||
|
assertFalse(activity.findViewById(R.id.search_button).isShown());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static View buildRecyclerItem(RecyclerView recyclerView, int position) {
|
private static JSONArray buildConversations() throws Exception {
|
||||||
RecyclerView.Adapter adapter = recyclerView.getAdapter();
|
return new JSONArray()
|
||||||
int viewType = adapter.getItemViewType(position);
|
.put(new JSONObject()
|
||||||
RecyclerView.ViewHolder holder = adapter.createViewHolder(recyclerView, viewType);
|
.put("projectId", "p1")
|
||||||
adapter.bindViewHolder(holder, position);
|
.put("projectTitle", "查询树莓派二代")
|
||||||
FrameLayout container = (FrameLayout) holder.itemView;
|
.put("threadTitle", "查询树莓派二代")
|
||||||
return container.getChildAt(0);
|
.put("folderLabel", "Mac Studio")
|
||||||
|
.put("lastMessagePreview", "线程链路正常")
|
||||||
|
.put("latestReplyLabel", "09:40")
|
||||||
|
.put("conversationType", "single_device"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public class MainActivityConversationSelectionTest {
|
|||||||
ReflectionHelpers.callInstanceMethod(activity, "enterConversationSelectionMode");
|
ReflectionHelpers.callInstanceMethod(activity, "enterConversationSelectionMode");
|
||||||
|
|
||||||
RecyclerView list = ReflectionHelpers.getField(activity, "screenList");
|
RecyclerView list = ReflectionHelpers.getField(activity, "screenList");
|
||||||
View row = getRecyclerChild(list, 3);
|
View row = getRecyclerChild(list, 2);
|
||||||
assertTrue("多选模式应显示单选圆点", viewTreeContainsContentDescription(row, "未选中会话"));
|
assertTrue("多选模式应显示单选圆点", viewTreeContainsContentDescription(row, "未选中会话"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ public class WechatSurfaceMapperTopActionTest {
|
|||||||
public void rootTopAction_usesSelectionForConversations() {
|
public void rootTopAction_usesSelectionForConversations() {
|
||||||
WechatSurfaceMapper.RootTopAction action = WechatSurfaceMapper.rootTopAction("conversations", false, false);
|
WechatSurfaceMapper.RootTopAction action = WechatSurfaceMapper.rootTopAction("conversations", false, false);
|
||||||
|
|
||||||
assertEquals("选择", action.label);
|
assertEquals("+", action.label);
|
||||||
assertFalse(action.primaryStyle);
|
assertFalse(action.primaryStyle);
|
||||||
assertFalse(action.compactStyle);
|
assertTrue(action.compactStyle);
|
||||||
assertEquals("select_conversations", action.actionKey);
|
assertEquals("select_conversations", action.actionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user