Use fixed IDs for home sections (#8611)

### Description

Use fixed IDs for home sections. Otherwise view restoration can get
confused by non-existing views. Also, sneak in new agent instructions :)

### Checklist
<!-- 
To help us keep the issue tracker clean and work as efficient as
possible,
  please make sure that you have done all of the following.
You can tick the boxes below by placing an x inside the brackets like
this: [x]
-->
- [x] I have read the contribution guidelines:
https://github.com/AntennaPod/AntennaPod/blob/develop/CONTRIBUTING.md#submit-a-pull-request
- [x] I have performed a self-review of my code, going through my
changes line by line and carefully considering why this line change is
necessary
- [x] I have run the automated code checks using `./gradlew checkstyle
lint`
- [x] My code follows the style guidelines of the AntennaPod project:
https://antennapod.org/contribute/develop/app/code-style
- [x] I have mentioned the corresponding issue and the relevant keyword
(e.g., "Closes: #xy") in the description (see
https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
- [x] If it is a core feature, I have added automated tests
This commit is contained in:
Hans-Peter Lehmann
2026-07-20 21:59:12 +02:00
committed by GitHub
parent bfa37a3025
commit c4441c8348
3 changed files with 33 additions and 20 deletions

View File

@ -79,12 +79,12 @@ Only then run the application or the tests to verify it.
Usually you will need to run the application, but if there are existing tests that cover the code you wrote, you can run those instead. Usually you will need to run the application, but if there are existing tests that cover the code you wrote, you can run those instead.
For installing and running the application, use the command For installing and running the application, use the command
`./gradlew --console=plain :app:installPlayDebug && adb shell monkey -p de.danoeh.antennapod.debug 1`. `./gradlew --console=plain :app:installPlayDebug && adb shell monkey -p de.danoeh.antennapod.debug 1`.
Then confirm with the user that the application is running correctly. If needed, you can grab a textual representation of the screen using `adb shell uiautomator dump /sdcard/ui.xml; adb shell cat /sdcard/ui.xml`.
You can even control connected devices using `adb shell input tap <x> <y>` and `adb shell input swipe <x1> <y1> <x2> <y2> <duration ms>`.
If there is a crash, read the logs using `adb logcat -d | grep "de.danoeh.antennapod" | tail -20` and fix the issue. If there is a crash, read the logs using `adb logcat -d | grep "de.danoeh.antennapod" | tail -20` and fix the issue.
For running tests, use the command `./gradlew --console=plain` and use the task `:test` of the relevant module. For running tests, use the command `./gradlew --console=plain` and use the task `:test` of the relevant module.
As a final style check before opening a PR (or if a user explicitly asks for it), check the code style using: As a final style check before opening a PR (or if a user explicitly asks for it), check the code style using:
`./gradlew checkstyle lint`. `./gradlew checkstyle lint`.
If any command does not give any output, it is likely that it failed, so abort.
# PR Conventions # PR Conventions
When creating a PR, always read the PR template at `.github/pull_request_template.md` before starting and strictly follow it. When creating a PR, always read the PR template at `.github/pull_request_template.md` before starting and strictly follow it.

View File

@ -83,37 +83,42 @@ public class HomeFragment extends Fragment implements Toolbar.OnMenuItemClickLis
SharedPreferences prefs = getContext().getSharedPreferences(HomeFragment.PREF_NAME, Context.MODE_PRIVATE); SharedPreferences prefs = getContext().getSharedPreferences(HomeFragment.PREF_NAME, Context.MODE_PRIVATE);
if (EchoConfig.isCurrentlyVisible() && prefs.getInt(PREF_HIDE_ECHO, 0) != EchoConfig.RELEASE_YEAR) { if (EchoConfig.isCurrentlyVisible() && prefs.getInt(PREF_HIDE_ECHO, 0) != EchoConfig.RELEASE_YEAR) {
addSection(new EchoSection()); addSection(new EchoSection(), R.id.home_section_echo);
} }
List<String> sectionTags = HomePreferences.getSortedSectionTags(getContext()); List<String> sectionTags = HomePreferences.getSortedSectionTags(getContext());
for (String sectionTag : sectionTags) { for (String sectionTag : sectionTags) {
addSection(getSection(sectionTag)); addSection(getSection(sectionTag), getSectionContainerId(sectionTag));
} }
} }
private void addSection(Fragment section) { private void addSection(Fragment section, int id) {
FragmentContainerView containerView = new FragmentContainerView(getContext()); FragmentContainerView containerView = new FragmentContainerView(getContext());
containerView.setId(View.generateViewId()); containerView.setId(id);
viewBinding.homeContainer.addView(containerView); viewBinding.homeContainer.addView(containerView);
getChildFragmentManager().beginTransaction().replace(containerView.getId(), section).commit(); getChildFragmentManager().beginTransaction().replace(containerView.getId(), section).commit();
} }
private int getSectionContainerId(String sectionTag) {
return switch (sectionTag) {
case QueueSection.TAG -> R.id.home_section_queue;
case InboxSection.TAG -> R.id.home_section_inbox;
case EpisodesSurpriseSection.TAG -> R.id.home_section_surprise;
case SubscriptionsSection.TAG -> R.id.home_section_subscriptions;
case DownloadsSection.TAG -> R.id.home_section_downloads;
default -> throw new IllegalArgumentException("Unknown section tag: " + sectionTag);
};
}
private Fragment getSection(String tag) { private Fragment getSection(String tag) {
switch (tag) { return switch (tag) {
case QueueSection.TAG: case QueueSection.TAG -> new QueueSection();
return new QueueSection(); case InboxSection.TAG -> new InboxSection();
case InboxSection.TAG: case EpisodesSurpriseSection.TAG -> new EpisodesSurpriseSection();
return new InboxSection(); case SubscriptionsSection.TAG -> new SubscriptionsSection();
case EpisodesSurpriseSection.TAG: case DownloadsSection.TAG -> new DownloadsSection();
return new EpisodesSurpriseSection(); default -> null;
case SubscriptionsSection.TAG: };
return new SubscriptionsSection();
case DownloadsSection.TAG:
return new DownloadsSection();
default:
return null;
}
} }
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN) @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)

View File

@ -18,6 +18,14 @@
<item name="view_type_subscription_grid_without_title" type="id"/> <item name="view_type_subscription_grid_without_title" type="id"/>
<item name="view_type_subscription_list" type="id"/> <item name="view_type_subscription_list" type="id"/>
<!-- Home sections -->
<item name="home_section_echo" type="id"/>
<item name="home_section_queue" type="id"/>
<item name="home_section_inbox" type="id"/>
<item name="home_section_surprise" type="id"/>
<item name="home_section_subscriptions" type="id"/>
<item name="home_section_downloads" type="id"/>
<!-- Bottom navigation --> <!-- Bottom navigation -->
<item name="bottom_navigation_home" type="id"/> <item name="bottom_navigation_home" type="id"/>
<item name="bottom_navigation_queue" type="id"/> <item name="bottom_navigation_queue" type="id"/>