Skip to content

Commit f8a98c5

Browse files
committed
fix: improve splash screen messages for better user experience
1 parent 15de1b9 commit f8a98c5

5 files changed

Lines changed: 85 additions & 13 deletions

File tree

easy-postman-app/src/main/java/com/laker/postman/panel/collections/right/request/RequestEditSubPanel.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ private void initializeEditorUiIfNeeded(boolean animatePlaceholderTransition) {
312312
this::sendRequest,
313313
this::isBaseHttpProtocol,
314314
this::isEffectiveHttpProtocol,
315+
this::isEffectiveSseProtocol,
315316
this::isEffectiveWebSocketProtocol
316317
);
317318
requestStreamUiHelper = new RequestStreamUiHelper(responsePanel, TIME_FORMATTER);
@@ -385,6 +386,7 @@ private void initializeEditorUiIfNeeded(boolean animatePlaceholderTransition) {
385386
this::isDisposed
386387
);
387388
requestProtocolDispatchHelper = new RequestProtocolDispatchHelper(
389+
responsePanel,
388390
httpRequestExecutionHelper,
389391
sseRequestExecutionHelper,
390392
webSocketRequestExecutionHelper,

easy-postman-app/src/main/java/com/laker/postman/panel/collections/right/request/RequestExecutionUiHelper.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ final class RequestExecutionUiHelper {
1717
private final ActionListener sendAction;
1818
private final BooleanSupplier baseHttpProtocol;
1919
private final BooleanSupplier effectiveHttpProtocol;
20+
private final BooleanSupplier effectiveSseProtocol;
2021
private final BooleanSupplier effectiveWebSocketProtocol;
2122

2223
RequestExecutionUiHelper(ResponsePanel responsePanel,
@@ -26,6 +27,7 @@ final class RequestExecutionUiHelper {
2627
ActionListener sendAction,
2728
BooleanSupplier baseHttpProtocol,
2829
BooleanSupplier effectiveHttpProtocol,
30+
BooleanSupplier effectiveSseProtocol,
2931
BooleanSupplier effectiveWebSocketProtocol) {
3032
this.responsePanel = responsePanel;
3133
this.requestLinePanel = requestLinePanel;
@@ -34,28 +36,36 @@ final class RequestExecutionUiHelper {
3436
this.sendAction = sendAction;
3537
this.baseHttpProtocol = baseHttpProtocol;
3638
this.effectiveHttpProtocol = effectiveHttpProtocol;
39+
this.effectiveSseProtocol = effectiveSseProtocol;
3740
this.effectiveWebSocketProtocol = effectiveWebSocketProtocol;
3841
}
3942

4043
void updateUIForRequesting() {
4144
requestLinePanel.setSendButtonToCancel(sendAction);
42-
43-
if (responsePanel.getNetworkLogPanel() != null) {
44-
responsePanel.getNetworkLogPanel().clearLog();
45-
responsePanel.getNetworkLogPanel().clearAllDetails();
45+
responsePanel.clearInFlightRequestDetails();
46+
boolean keepResponseTabsEnabled = baseHttpProtocol.getAsBoolean()
47+
&& !effectiveSseProtocol.getAsBoolean()
48+
&& !effectiveWebSocketProtocol.getAsBoolean()
49+
&& responsePanel.hasResponseData();
50+
if (!keepResponseTabsEnabled) {
51+
responsePanel.setResponseTabButtonsEnable(false);
4652
}
47-
responsePanel.setResponseTabButtonsEnable(false);
4853
if (baseHttpProtocol.getAsBoolean()) {
4954
responsePanel.setResponseBodyEnabled(false);
5055
}
51-
responsePanel.clearAll();
56+
// 普通 HTTP 请求发送时保留上一份响应内容,避免当前响应标签页先被清空后再重绘造成闪烁。
57+
// 流式协议仍沿用清空策略,防止新旧消息混在一起。
58+
if (!baseHttpProtocol.getAsBoolean() || effectiveSseProtocol.getAsBoolean() || effectiveWebSocketProtocol.getAsBoolean()) {
59+
responsePanel.clearAll();
60+
}
5261
responsePanel.showLoadingOverlay();
5362
}
5463

5564
void updateUIForResponse(HttpResponse resp) {
5665
responsePanel.hideLoadingOverlay();
5766

5867
if (resp == null) {
68+
responsePanel.clearAll();
5969
responsePanel.setStatus(0);
6070
if (baseHttpProtocol.getAsBoolean()) {
6171
responsePanel.setResponseBodyEnabled(effectiveHttpProtocol.getAsBoolean());
@@ -76,6 +86,7 @@ void updateUIForResponse(HttpResponse resp) {
7686
responsePanel.setStatus(resp.code);
7787
responsePanel.setResponseTime(resp.costMs);
7888
responsePanel.setResponseSize(resp.bodySize, resp);
89+
responsePanel.markResponseDataLoaded();
7990
}
8091

8192
void resetSendButton() {

easy-postman-app/src/main/java/com/laker/postman/panel/collections/right/request/RequestProtocolDispatchHelper.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,30 @@
22

33
import com.laker.postman.model.PreparedRequest;
44
import com.laker.postman.model.RequestItemProtocolEnum;
5+
import com.laker.postman.panel.collections.right.request.sub.ResponsePanel;
6+
import com.laker.postman.service.http.HttpUtil;
57
import com.laker.postman.service.js.ScriptExecutionPipeline;
68

79
import javax.swing.*;
810
import java.util.function.Consumer;
911

1012
final class RequestProtocolDispatchHelper {
13+
private final ResponsePanel responsePanel;
1114
private final HttpRequestExecutionHelper httpRequestExecutionHelper;
1215
private final SseRequestExecutionHelper sseRequestExecutionHelper;
1316
private final WebSocketRequestExecutionHelper webSocketRequestExecutionHelper;
1417
private final Consumer<Boolean> httpSseStreamOpenedSetter;
1518
private final Consumer<SwingWorker<Void, Void>> currentWorkerSetter;
1619
private final int maxRedirectCount;
1720

18-
RequestProtocolDispatchHelper(HttpRequestExecutionHelper httpRequestExecutionHelper,
21+
RequestProtocolDispatchHelper(ResponsePanel responsePanel,
22+
HttpRequestExecutionHelper httpRequestExecutionHelper,
1923
SseRequestExecutionHelper sseRequestExecutionHelper,
2024
WebSocketRequestExecutionHelper webSocketRequestExecutionHelper,
2125
Consumer<Boolean> httpSseStreamOpenedSetter,
2226
Consumer<SwingWorker<Void, Void>> currentWorkerSetter,
2327
int maxRedirectCount) {
28+
this.responsePanel = responsePanel;
2429
this.httpRequestExecutionHelper = httpRequestExecutionHelper;
2530
this.sseRequestExecutionHelper = sseRequestExecutionHelper;
2631
this.webSocketRequestExecutionHelper = webSocketRequestExecutionHelper;
@@ -33,6 +38,7 @@ void dispatch(RequestPreparationResult result) {
3338
RequestItemProtocolEnum protocol = result.getItem().getProtocol();
3439
PreparedRequest request = result.getRequest();
3540
ScriptExecutionPipeline pipeline = result.getPipeline();
41+
boolean expectedHttpSse = protocol.isHttpProtocol() && HttpUtil.isSSERequest(request);
3642

3743
SwingWorker<Void, Void> worker;
3844
// 这里是协议分发的唯一出口:上游不用关心 HTTP / SSE / WebSocket 的执行细节。
@@ -42,6 +48,10 @@ void dispatch(RequestPreparationResult result) {
4248
worker = sseRequestExecutionHelper.createWorker(request, pipeline);
4349
} else {
4450
httpSseStreamOpenedSetter.accept(false);
51+
if (expectedHttpSse) {
52+
responsePanel.clearAll();
53+
responsePanel.setResponseTabButtonsEnable(false);
54+
}
4555
worker = httpRequestExecutionHelper.createWorker(request, pipeline, maxRedirectCount);
4656
}
4757

easy-postman-app/src/main/java/com/laker/postman/panel/collections/right/request/sub/ResponsePanel.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public class ResponsePanel extends JPanel {
6666
private final SSEResponsePanel sseResponsePanel;
6767
private final LoadingOverlay loadingOverlay;
6868
private boolean isHorizontalLayout = false; // 标记当前是否为水平布局
69+
private boolean hasResponseData = false;
6970

7071
public ResponsePanel(RequestItemProtocolEnum protocol, boolean enableSaveButton) {
7172
this.protocol = protocol;
@@ -438,6 +439,14 @@ private JLabel createSeparator() {
438439
}
439440

440441
public void setResponseTabButtonsEnable(boolean enable) {
442+
if (!SwingUtilities.isEventDispatchThread()) {
443+
SwingUtilities.invokeLater(() -> setResponseTabButtonsEnable(enable));
444+
return;
445+
}
446+
if (tabButtons.length > 0 && tabButtons[0].isEnabled() == enable
447+
&& (tabComboBox == null || tabComboBox.isEnabled() == enable)) {
448+
return;
449+
}
441450
for (JButton btn : tabButtons) {
442451
btn.setEnabled(enable);
443452
}
@@ -586,6 +595,7 @@ public void setTestResults(List<TestResult> testResults) {
586595
}
587596

588597
public void clearAll() {
598+
hasResponseData = false;
589599
// 清空状态栏
590600
setStatus(0); // 清空状态码
591601
responseTimeLabel.setText("");
@@ -614,6 +624,22 @@ public void clearAll() {
614624
}
615625
}
616626

627+
public void clearInFlightRequestDetails() {
628+
if (networkLogPanel != null) {
629+
networkLogPanel.clearLog();
630+
networkLogPanel.clearAllDetails();
631+
}
632+
clearTiming();
633+
}
634+
635+
public boolean hasResponseData() {
636+
return hasResponseData;
637+
}
638+
639+
public void markResponseDataLoaded() {
640+
hasResponseData = true;
641+
}
642+
617643
private void updateResponseHeadersTabLabel(int count) {
618644
if (tabButtons.length <= TAB_INDEX_RESPONSE_HEADERS) {
619645
return;
@@ -635,6 +661,10 @@ private void updateResponseHeadersTabLabel(int count) {
635661
* @param type "http" 显示HTTP相关tabs,"sse" 显示SSE相关tabs
636662
*/
637663
public void switchTabButtonHttpOrSse(String type) {
664+
if (!SwingUtilities.isEventDispatchThread()) {
665+
SwingUtilities.invokeLater(() -> switchTabButtonHttpOrSse(type));
666+
return;
667+
}
638668
if (!protocol.isHttpProtocol()) {
639669
return;
640670
}
@@ -652,7 +682,7 @@ private void showHttpTabs() {
652682
tabButtons[TAB_INDEX_RESPONSE_BODY].setVisible(true);
653683
tabButtons[TAB_INDEX_LOG].setVisible(false);
654684
refreshTabSelector();
655-
tabButtons[TAB_INDEX_RESPONSE_BODY].doClick();
685+
selectVisibleTabIfNeeded(TAB_INDEX_RESPONSE_BODY);
656686
}
657687

658688
/**
@@ -662,7 +692,23 @@ private void showSSETabs() {
662692
tabButtons[TAB_INDEX_RESPONSE_BODY].setVisible(false);
663693
tabButtons[TAB_INDEX_LOG].setVisible(true);
664694
refreshTabSelector();
665-
tabButtons[TAB_INDEX_LOG].doClick();
695+
selectVisibleTabIfNeeded(TAB_INDEX_LOG);
696+
}
697+
698+
private void selectVisibleTabIfNeeded(int fallbackTabIndex) {
699+
if (selectedTabIndex >= 0 && selectedTabIndex < tabButtons.length && tabButtons[selectedTabIndex].isVisible()) {
700+
CardLayout cl = (CardLayout) cardPanel.getLayout();
701+
cl.show(cardPanel, tabNames[selectedTabIndex]);
702+
return;
703+
}
704+
if (fallbackTabIndex >= 0 && fallbackTabIndex < tabButtons.length && tabButtons[fallbackTabIndex].isVisible()) {
705+
if (selectedTabIndex == fallbackTabIndex) {
706+
CardLayout cl = (CardLayout) cardPanel.getLayout();
707+
cl.show(cardPanel, tabNames[fallbackTabIndex]);
708+
return;
709+
}
710+
tabButtons[fallbackTabIndex].doClick();
711+
}
666712
}
667713

668714
private void clearTiming() {

easy-postman-app/src/main/java/com/laker/postman/service/collections/DefaultRequestsFactory.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
@Slf4j
1919
public class DefaultRequestsFactory {
20+
private static final String BASIC_HTTP_EXAMPLES_GROUP_NAME = "Basic HTTP Examples";
21+
private static final String SCRIPT_EXAMPLES_EN_GROUP_NAME = "Script Examples (EN)";
22+
private static final String SCRIPT_EXAMPLES_ZH_GROUP_NAME = "脚本示例(中文)";
2023

2124
public static final String REQUEST = "request";
2225
public static final String APPLICATION_JSON = "application/json";
@@ -30,17 +33,17 @@ private DefaultRequestsFactory() {
3033

3134
public static void create(DefaultMutableTreeNode rootTreeNode, DefaultTreeModel treeModel) {
3235
try {
36+
createBasicHttpExamples(rootTreeNode);
3337
createEnglishScriptExamples(rootTreeNode);
3438
createChineseScriptExamples(rootTreeNode);
35-
createBasicHttpExamples(rootTreeNode);
3639
treeModel.reload();
3740
} catch (Exception ex) {
3841
log.error("Failed to create default request groups", ex);
3942
}
4043
}
4144

4245
private static void createEnglishScriptExamples(DefaultMutableTreeNode rootTreeNode) {
43-
RequestGroup group = new RequestGroup("Script Examples (EN)");
46+
RequestGroup group = new RequestGroup(SCRIPT_EXAMPLES_EN_GROUP_NAME);
4447
group.setDescription("""
4548
Run request 1 first, then request 2.
4649
@@ -135,7 +138,7 @@ private static void createEnglishScriptExamples(DefaultMutableTreeNode rootTreeN
135138
}
136139

137140
private static void createChineseScriptExamples(DefaultMutableTreeNode rootTreeNode) {
138-
RequestGroup group = new RequestGroup("脚本示例(中文)");
141+
RequestGroup group = new RequestGroup(SCRIPT_EXAMPLES_ZH_GROUP_NAME);
139142
group.setDescription("""
140143
先执行请求 1,再执行请求 2。
141144
@@ -230,7 +233,7 @@ private static void createChineseScriptExamples(DefaultMutableTreeNode rootTreeN
230233
}
231234

232235
private static void createBasicHttpExamples(DefaultMutableTreeNode rootTreeNode) {
233-
RequestGroup defaultGroup = new RequestGroup("Basic HTTP Examples");
236+
RequestGroup defaultGroup = new RequestGroup(BASIC_HTTP_EXAMPLES_GROUP_NAME);
234237
defaultGroup.setDescription("""
235238
General-purpose examples for common request types.
236239
These requests are independent from the official script examples.

0 commit comments

Comments
 (0)