Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@
## 2025-10-29 - [Stream Allocation and O(N^2) trap in HomeTimelineFragment]
**Learning:** `HomeTimelineFragment.loadNewPosts` used a Java Stream to collect `existingIds` into a `List`, and then called `toAdd.removeIf(s -> existingIds.contains(s.getID()))`. Since `List.contains` is O(N), this created an O(N * M) operation in a hot path, causing both allocation overhead from Streams and quadratic performance degradation for duplicate checking.
**Action:** Replaced the Stream with a simple `for` loop that populates a `HashSet<String>`. This eliminates the Stream allocations and reduces the time complexity of the duplicate check from O(N * M) to O(N + M) because `HashSet.contains` is O(1). Additionally, replaced other `Optional` and `Stream` usages in `loadNewPosts` and `onGapClick` with simple loops to further reduce GC pressure.
## 2025-02-12 - [Dynamic TooltipText Parity for Icon-only Buttons]
**Learning:** When dynamically updating the `contentDescription` of icon-only buttons (like play/pause states) in Java code, the `tooltipText` attribute must also be updated to ensure continued accessibility support for hover and long-press interactions.
**Action:** Always mirror `setContentDescription()` calls with `setTooltipText()` (wrapped in `Build.VERSION.SDK_INT >= Build.VERSION_CODES.O`) for icon-only interactive elements.
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,11 @@ private void updateColors(int mainColor){

private void setPlayButtonPlaying(boolean playing, boolean animated){
playPauseBtn.setImageResource(playing ? R.drawable.ic_fluent_pause_48_regular : R.drawable.ic_fluent_play_48_regular);
playPauseBtn.setContentDescription(item.parentFragment.getString(playing ? R.string.pause : R.string.play));
String desc = item.parentFragment.getString(playing ? R.string.pause : R.string.play);
playPauseBtn.setContentDescription(desc);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
playPauseBtn.setTooltipText(desc);
}
if(playing)
bgDrawable.startAnimation();
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,11 @@ private void pauseVideo(){
return;
holder.player.pause();
videoPlayPauseButton.setImageResource(R.drawable.ic_fluent_play_24_filled);
videoPlayPauseButton.setContentDescription(activity.getString(R.string.play));
String desc = activity.getString(R.string.play);
videoPlayPauseButton.setContentDescription(desc);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
videoPlayPauseButton.setTooltipText(desc);
}
stopUpdatingVideoPosition();
windowView.removeCallbacks(uiAutoHider);
// Some MediaPlayer implementations clear the texture when the app goes into background.
Expand All @@ -706,7 +710,11 @@ private void resumeVideo(){
return;
player.start();
videoPlayPauseButton.setImageResource(R.drawable.ic_fluent_pause_24_filled);
videoPlayPauseButton.setContentDescription(activity.getString(R.string.pause));
String desc = activity.getString(R.string.pause);
videoPlayPauseButton.setContentDescription(desc);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
videoPlayPauseButton.setTooltipText(desc);
}
startUpdatingVideoPosition(player);
}

Expand Down Expand Up @@ -1161,7 +1169,11 @@ public void onSeekComplete(MediaPlayer mp){
@Override
public void onCompletion(MediaPlayer mp){
videoPlayPauseButton.setImageResource(R.drawable.ic_fluent_play_24_filled);
videoPlayPauseButton.setContentDescription(activity.getString(R.string.play));
String desc = activity.getString(R.string.play);
videoPlayPauseButton.setContentDescription(desc);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
videoPlayPauseButton.setTooltipText(desc);
}
stopUpdatingVideoPosition();
if(!uiVisible)
toggleUI();
Expand Down
3 changes: 3 additions & 0 deletions mastodon/src/main/res/layout/display_item_audio.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@
android:layout_height="96dp"
android:background="@drawable/bg_audio_play_button"
android:contentDescription="@string/play"
android:tooltipText="@string/play"
android:layout_gravity="center"
android:tint="?colorM3DarkOnSurface"
android:src="@drawable/ic_fluent_play_48_regular"/>

<ImageButton
android:id="@+id/forward_btn"
android:contentDescription="@string/seek_forward_10_seconds"
android:tooltipText="@string/seek_forward_10_seconds"
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_gravity="center_vertical|end"
Expand All @@ -56,6 +58,7 @@
<ImageButton
android:id="@+id/rewind_btn"
android:contentDescription="@string/seek_rewind_5_seconds"
android:tooltipText="@string/seek_rewind_5_seconds"
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_gravity="center_vertical|start"
Expand Down
1 change: 1 addition & 0 deletions mastodon/src/main/res/layout/photo_viewer_ui.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
android:src="@drawable/ic_fluent_pause_24_filled"
android:tint="?colorGray50"
android:contentDescription="@string/pause"
android:tooltipText="@string/pause"
android:background="?android:selectableItemBackgroundBorderless"/>

<TextView
Expand Down
Loading