fix: stabilize attachment upload and storage flows

This commit is contained in:
kris
2026-03-29 16:59:10 +08:00
parent 1e476a2097
commit 18dc7c6120
13 changed files with 733 additions and 183 deletions

View File

@@ -14,9 +14,10 @@ public class AttachmentComposerStateTest {
"现场照片.png",
"image/png",
4096L,
new byte[] {1, 2, 3}
null
);
assertTrue(ProjectChatUiState.requiresAttachmentConfirmation(attachment.sourceType));
assertTrue(attachment.requiresConfirmation());
}
@@ -28,9 +29,10 @@ public class AttachmentComposerStateTest {
"巡检录屏.mp4",
"video/mp4",
8192L,
new byte[] {4, 5, 6}
null
);
assertTrue(ProjectChatUiState.requiresAttachmentConfirmation(attachment.sourceType));
assertTrue(attachment.requiresConfirmation());
}
@@ -42,9 +44,10 @@ public class AttachmentComposerStateTest {
"日报.xlsx",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
16384L,
new byte[] {7, 8, 9}
null
);
assertFalse(ProjectChatUiState.requiresAttachmentConfirmation(attachment.sourceType));
assertFalse(attachment.requiresConfirmation());
}
}

View File

@@ -6,11 +6,14 @@ import static org.junit.Assert.assertTrue;
import android.content.Intent;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
@@ -75,6 +78,42 @@ public class ProjectDetailActivityUiTest {
assertEquals(View.VISIBLE, refreshButton.getVisibility());
}
@Test
public void manualAnalysisAttachmentShowsActionChip() throws Exception {
Intent intent = new Intent()
.putExtra(ProjectDetailActivity.EXTRA_PROJECT_ID, "project-1")
.putExtra(ProjectDetailActivity.EXTRA_PROJECT_NAME, "北区试产线回归");
TestProjectDetailActivity activity = Robolectric
.buildActivity(TestProjectDetailActivity.class, intent)
.setup()
.get();
JSONObject attachment = new JSONObject()
.put("attachmentId", "att-1")
.put("fileName", "巡检录像.mp4")
.put("mimeType", "video/mp4")
.put("attachmentKind", "video")
.put("analysisState", "ready_manual")
.put("fileSizeBytes", 2048);
JSONObject message = new JSONObject()
.put("id", "msg-1")
.put("kind", "attachment")
.put("body", "已发送附件")
.put("attachments", new JSONArray().put(attachment));
View attachmentView = ReflectionHelpers.callInstanceMethod(
activity,
"buildAttachmentMessageView",
ReflectionHelpers.ClassParameter.from(JSONObject.class, message),
ReflectionHelpers.ClassParameter.from(String.class, ""),
ReflectionHelpers.ClassParameter.from(String.class, "09:26"),
ReflectionHelpers.ClassParameter.from(boolean.class, true)
);
assertTrue(viewTreeContainsText(attachmentView, "让 AI 分析"));
assertTrue(viewTreeContainsText(attachmentView, "待分析"));
}
private static View buildBoundMessageView(TestProjectDetailActivity activity, String messageId, String body) {
TextView messageView = new TextView(activity);
messageView.setText(body);
@@ -84,11 +123,31 @@ public class ProjectDetailActivityUiTest {
"bindMessageInteractions",
ReflectionHelpers.ClassParameter.from(View.class, messageView),
ReflectionHelpers.ClassParameter.from(String.class, messageId),
ReflectionHelpers.ClassParameter.from(String.class, body)
ReflectionHelpers.ClassParameter.from(String.class, body),
ReflectionHelpers.ClassParameter.from(View.OnClickListener.class, null)
);
return messageView;
}
private static boolean viewTreeContainsText(View root, String expectedText) {
if (root instanceof TextView) {
CharSequence text = ((TextView) root).getText();
if (expectedText.contentEquals(text)) {
return true;
}
}
if (!(root instanceof ViewGroup)) {
return false;
}
ViewGroup group = (ViewGroup) root;
for (int index = 0; index < group.getChildCount(); index += 1) {
if (viewTreeContainsText(group.getChildAt(index), expectedText)) {
return true;
}
}
return false;
}
public static class TestProjectDetailActivity extends ProjectDetailActivity {
@Override
boolean shouldLoadOnCreate() {