From f32c1a7c802a66c2b4a751d10d0953b3f526d16c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:21:33 +0000 Subject: [PATCH 1/4] Initial plan From ad0249500083ad96870f3d5e2449fe653c39222a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:29:47 +0000 Subject: [PATCH 2/4] Fix posting navigation: handle successful topic creation in error handler Co-authored-by: graycreate <5203798+graycreate@users.noreply.github.com> --- .../v2er/module/create/CreateTopicActivity.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/me/ghui/v2er/module/create/CreateTopicActivity.java b/app/src/main/java/me/ghui/v2er/module/create/CreateTopicActivity.java index f8fe2b37..a0500988 100644 --- a/app/src/main/java/me/ghui/v2er/module/create/CreateTopicActivity.java +++ b/app/src/main/java/me/ghui/v2er/module/create/CreateTopicActivity.java @@ -203,7 +203,14 @@ public void handleError(GeneralError generalError) { Observable.just(response) .compose(rx(null)) .map(s -> { - BaseInfo resultInfo = APIService.fruit().fromHtml(s, CreateTopicPageInfo.class); + // First, check if this is actually a successful topic creation + // (V2EX may return the topic page on success, which triggers error handler due to redirects) + BaseInfo resultInfo = APIService.fruit().fromHtml(s, TopicInfo.class); + if (resultInfo.isValid()) { + return resultInfo; + } + // If not a valid topic, try parsing as error pages + resultInfo = APIService.fruit().fromHtml(s, CreateTopicPageInfo.class); if (!resultInfo.isValid()) { resultInfo = APIService.fruit().fromHtml(s, NewUserBannedCreateInfo.class); } @@ -212,7 +219,10 @@ public void handleError(GeneralError generalError) { .subscribe(new GeneralConsumer(this) { @Override public void onConsume(BaseInfo baseInfo) { - if (baseInfo instanceof CreateTopicPageInfo) { + if (baseInfo instanceof TopicInfo) { + // Actually a success! Treat it as such + onPostSuccess((TopicInfo) baseInfo); + } else if (baseInfo instanceof CreateTopicPageInfo) { onPostFailure((CreateTopicPageInfo) baseInfo); } else { onBannedCreateTopic((NewUserBannedCreateInfo) baseInfo); From 9474165da8022825e574b45337b5a657f8879245 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:32:08 +0000 Subject: [PATCH 3/4] Apply same fix to AppendTopicActivity for consistency Co-authored-by: graycreate <5203798+graycreate@users.noreply.github.com> --- .../module/append/AppendTopicActivity.java | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/me/ghui/v2er/module/append/AppendTopicActivity.java b/app/src/main/java/me/ghui/v2er/module/append/AppendTopicActivity.java index d282dace..33171f32 100644 --- a/app/src/main/java/me/ghui/v2er/module/append/AppendTopicActivity.java +++ b/app/src/main/java/me/ghui/v2er/module/append/AppendTopicActivity.java @@ -134,21 +134,36 @@ public void handleError(GeneralError generalError) { if (Check.isEmpty(response)) return; Observable.just(response) .compose(rx(null)) - .map(s -> APIService.fruit().fromHtml(s, AppendTopicPageInfo.class)) - .subscribe(new GeneralConsumer() { + .map(s -> { + // First, check if this is actually a successful append + // (V2EX may return the topic page on success, which triggers error handler due to redirects) + BaseInfo resultInfo = APIService.fruit().fromHtml(s, TopicInfo.class); + if (resultInfo.isValid()) { + return resultInfo; + } + // If not a valid topic, try parsing as error page + return APIService.fruit().fromHtml(s, AppendTopicPageInfo.class); + }) + .subscribe(new GeneralConsumer() { @Override - public void onConsume(AppendTopicPageInfo pageInfo) { - AppendTopicPageInfo.Problem problem = pageInfo.getProblem(); - if (problem != null) { - StringBuilder msg = new StringBuilder(); - for (int i = 0; i < problem.getTips().size(); i++) { - msg.append(i + 1).append(". ").append(problem.getTips().get(i)).append("\n"); + public void onConsume(BaseInfo baseInfo) { + if (baseInfo instanceof TopicInfo) { + // Actually a success! Treat it as such + onAfterAppendTopic((TopicInfo) baseInfo); + } else if (baseInfo instanceof AppendTopicPageInfo) { + AppendTopicPageInfo pageInfo = (AppendTopicPageInfo) baseInfo; + AppendTopicPageInfo.Problem problem = pageInfo.getProblem(); + if (problem != null) { + StringBuilder msg = new StringBuilder(); + for (int i = 0; i < problem.getTips().size(); i++) { + msg.append(i + 1).append(". ").append(problem.getTips().get(i)).append("\n"); + } + new ConfirmDialog.Builder(getActivity()) + .title(problem.getTitle()) + .msg(msg.toString()) + .positiveText(R.string.ok) + .build().show(); } - new ConfirmDialog.Builder(getActivity()) - .title(problem.getTitle()) - .msg(msg.toString()) - .positiveText(R.string.ok) - .build().show(); } } }); From cb7bc17d7350e241f476d96fee9438ef7528327b Mon Sep 17 00:00:00 2001 From: Gray Zhang Date: Fri, 17 Oct 2025 15:18:34 +0800 Subject: [PATCH 4/4] Guard topic success detection in append/create flows --- .../v2er/module/append/AppendTopicActivity.java | 14 +++++++++++--- .../v2er/module/create/CreateTopicActivity.java | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/me/ghui/v2er/module/append/AppendTopicActivity.java b/app/src/main/java/me/ghui/v2er/module/append/AppendTopicActivity.java index 33171f32..a3474a53 100644 --- a/app/src/main/java/me/ghui/v2er/module/append/AppendTopicActivity.java +++ b/app/src/main/java/me/ghui/v2er/module/append/AppendTopicActivity.java @@ -137,9 +137,9 @@ public void handleError(GeneralError generalError) { .map(s -> { // First, check if this is actually a successful append // (V2EX may return the topic page on success, which triggers error handler due to redirects) - BaseInfo resultInfo = APIService.fruit().fromHtml(s, TopicInfo.class); - if (resultInfo.isValid()) { - return resultInfo; + TopicInfo topicInfo = APIService.fruit().fromHtml(s, TopicInfo.class); + if (isSuccessfulTopicResponse(topicInfo)) { + return topicInfo; } // If not a valid topic, try parsing as error page return APIService.fruit().fromHtml(s, AppendTopicPageInfo.class); @@ -169,6 +169,14 @@ public void onConsume(BaseInfo baseInfo) { }); } + private boolean isSuccessfulTopicResponse(TopicInfo topicInfo) { + if (topicInfo == null || !topicInfo.isValid()) { + return false; + } + TopicInfo.Problem problem = topicInfo.getProblem(); + return (problem == null || problem.isEmpty()) && Check.notEmpty(topicInfo.getTopicLink()); + } + @Override public void onAfterAppendTopic(TopicInfo topicInfo) { Utils.toggleKeyboard(false, mContentET); diff --git a/app/src/main/java/me/ghui/v2er/module/create/CreateTopicActivity.java b/app/src/main/java/me/ghui/v2er/module/create/CreateTopicActivity.java index a0500988..1b78c95b 100644 --- a/app/src/main/java/me/ghui/v2er/module/create/CreateTopicActivity.java +++ b/app/src/main/java/me/ghui/v2er/module/create/CreateTopicActivity.java @@ -205,12 +205,12 @@ public void handleError(GeneralError generalError) { .map(s -> { // First, check if this is actually a successful topic creation // (V2EX may return the topic page on success, which triggers error handler due to redirects) - BaseInfo resultInfo = APIService.fruit().fromHtml(s, TopicInfo.class); - if (resultInfo.isValid()) { - return resultInfo; + TopicInfo topicInfo = APIService.fruit().fromHtml(s, TopicInfo.class); + if (isSuccessfulTopicResponse(topicInfo)) { + return topicInfo; } // If not a valid topic, try parsing as error pages - resultInfo = APIService.fruit().fromHtml(s, CreateTopicPageInfo.class); + BaseInfo resultInfo = APIService.fruit().fromHtml(s, CreateTopicPageInfo.class); if (!resultInfo.isValid()) { resultInfo = APIService.fruit().fromHtml(s, NewUserBannedCreateInfo.class); } @@ -244,4 +244,12 @@ private void onBannedCreateTopic(NewUserBannedCreateInfo bannedCreateInfo) { }).build().show(); } + private boolean isSuccessfulTopicResponse(TopicInfo topicInfo) { + if (topicInfo == null || !topicInfo.isValid()) { + return false; + } + TopicInfo.Problem problem = topicInfo.getProblem(); + return (problem == null || problem.isEmpty()) && Check.notEmpty(topicInfo.getTopicLink()); + } + }