Skip to content
Open
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/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@
## 2025-10-21 - Destructive Action Confirmation
**Learning:** The "STOP" button terminated the camera stream and app immediately without confirmation, posing a risk of accidental interruption.
**Action:** Always wrap destructive actions (like stopping a server or deleting data) in a confirmation dialog (e.g., `AlertDialog`) to prevent data loss or unintended service stoppage.
## 2024-05-23 - [Dynamic Metric Accessibility]
**Learning:** Dense technical metrics (like '33ms' or '500kB/s') in tight layouts are often inaccessible to screen readers because they lack context labels. Adding visible labels would break the layout.
**Action:** Use programmatic `contentDescription` updates in the data binding loop (e.g., 'Frame time: 33 milliseconds') to provide rich context to screen readers without altering the visual design.
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ class CameraFragment : Fragment() {
binding.textView6.setOnClickListener {
// Copy the ip address to the clipboard
ClipboardUtil.copyToClipboard(context, "ip", binding.textView6.text.toString())
// Perform haptic feedback
binding.textView6.performHapticFeedback(android.view.HapticFeedbackConstants.CONTEXT_CLICK)
// Toast to notify the user
Toast.makeText(context, "Copied to clipboard", Toast.LENGTH_SHORT).show()
}
Expand All @@ -108,8 +110,12 @@ class CameraFragment : Fragment() {
// Stuff that updates the UI
fragmentCameraBinding.qualFeedback?.text =
" " + this.rateKbs + "kB/sec"
fragmentCameraBinding.qualFeedback?.contentDescription =
getString(R.string.bitrate_description_template, this.rateKbs)
fragmentCameraBinding.ftFeedback?.text =
" " + this.ms + "ms"
fragmentCameraBinding.ftFeedback?.contentDescription =
getString(R.string.frametime_description_template, this.ms)
})

}
Expand Down
6 changes: 1 addition & 5 deletions app/src/main/res/layout/fragment_camera.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
android:id="@+id/view_finder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/camera_preview_description"
android:layout_gravity="center"
android:layout_weight="1" />
</FrameLayout>
Expand Down Expand Up @@ -101,7 +102,6 @@
android:layout_marginTop="0pt"
android:layout_marginBottom="4pt"
android:background="#FFAA00"
android:importantForAccessibility="no"
android:paddingTop="5pt" />

</TableRow>
Expand Down Expand Up @@ -158,7 +158,6 @@
android:layout_height="wrap_content"
android:labelFor="@+id/spinnerEncoding"
android:text="@string/encoding_label"
android:labelFor="@+id/spinnerEncoding"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

<Spinner
Expand All @@ -182,7 +181,6 @@
android:layout_height="wrap_content"
android:labelFor="@+id/spinnerCam"
android:text="@string/sensor_label"
android:labelFor="@+id/spinnerCam"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

<Spinner
Expand All @@ -205,7 +203,6 @@
android:layout_height="wrap_content"
android:labelFor="@+id/spinnerRes"
android:text="@string/resolution_label"
android:labelFor="@+id/spinnerRes"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

<Spinner
Expand All @@ -230,7 +227,6 @@
android:layout_gravity="center_vertical"
android:labelFor="@+id/spinnerQua"
android:text="@string/quality_label"
android:labelFor="@+id/spinnerQua"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

<LinearLayout
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@
<string name="stop_confirmation_message">This will stop the camera stream and close the application.</string>
<string name="stop_confirmation_positive">Stop</string>
<string name="stop_confirmation_negative">Cancel</string>

<!-- Accessibility Strings -->
<string name="camera_preview_description">Camera viewfinder</string>
<string name="bitrate_description_template">Bitrate: %1$d kilobytes per second</string>
<string name="frametime_description_template">Frame time: %1$d milliseconds</string>
</resources>