Skip to content

Fix printer Wi-Fi config flow to match working v1.0 behavior#3

Open
Karimrekiki wants to merge 11 commits into
Arieboomsma:mainfrom
Karimrekiki:main
Open

Fix printer Wi-Fi config flow to match working v1.0 behavior#3
Karimrekiki wants to merge 11 commits into
Arieboomsma:mainfrom
Karimrekiki:main

Conversation

@Karimrekiki
Copy link
Copy Markdown

@Karimrekiki Karimrekiki commented Feb 26, 2026

Summary\n- switch Wi-Fi push to printer-reported network flow (Sunmi SDK + with router ESSID)\n- fix long configuring state with explicit timeout handling\n- stabilize BLE handoff sequence before Wi-Fi config\n- fix SSID selection/manual-entry behavior\n- release version bumped through internal test to (code 8)\n\n## Validation\n- \n- \n- internal testing release published and confirmed working

Summary by CodeRabbit

  • New Features

    • Printer-driven Wi‑Fi scanning and configuration flow with improved Sunmi device identification.
    • Manual SSID entry UI when networks aren’t listed.
    • Connection timeout handling and bundled Bluetooth binding support for printer interactions.
  • Bug Fixes

    • Improved permission handling across Android versions and clearer error/status feedback during Wi‑Fi setup.
  • Refactor

    • Replaced direct Bluetooth configuration path with a printer-client driven flow.
  • Chores

    • App version bumped to 1.0.8.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

Warning

Rate limit exceeded

@Karimrekiki has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 56 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 310a152 and a2f1b23.

📒 Files selected for processing (5)
  • app/build.gradle
  • app/src/main/java/com/sunmi/printerconfig/DiscoveredPrinter.java
  • app/src/main/java/com/sunmi/printerconfig/DiscoveredPrinterAdapter.java
  • app/src/main/java/com/sunmi/printerconfig/MainActivity.java
  • app/src/main/res/values/strings.xml
📝 Walkthrough

Walkthrough

Refactors printer Wi‑Fi configuration to use a SunmiPrinterClient SDK (BluetoothBinding.aar). Adds client-driven connection and timeout flows in MainActivity and WifiConfigActivity, removes direct RFCOMM-based PrinterConfigHelper, adds device classification and receiver wrapper, UI for manual SSID entry, proguard/build/manifest updates, and many new strings.

Changes

Cohort / File(s) Summary
Build & Ignore
\.gitignore, app/build.gradle
Adds negation to un-ignore app/libs/BluetoothBinding.aar; bumps app versionCode 2→9 and versionName "1.0.1"→"1.0.8"; adds implementation files('libs/BluetoothBinding.aar').
Manifest & ProGuard
app/src/main/AndroidManifest.xml, app/proguard-rules.pro
Removes maxSdkVersion="30" from ACCESS_FINE_LOCATION; adds NEARBY_WIFI_DEVICES permission with neverForLocation. Replaces broad android.bluetooth.** keep with Sunmi SDK and related library keep rules.
Core Activities
app/src/main/java/.../MainActivity.java, app/src/main/java/.../WifiConfigActivity.java
Both now implement SunmiPrinterClient.IPrinterClient; introduce connection/config timeouts, handler/runnable logic, SunmiPrinterClient usage, pending printer state, new callbacks, navigation to WifiConfigActivity, and printer-driven Wi‑Fi discovery/config flows.
Removed Legacy Implementation
app/src/main/java/.../PrinterConfigHelper.java
Entire class removed — eliminates RFCOMM socket creation, OutputStream Wi‑Fi payload logic, permission/socket helpers, and related utilities.
Adapter & Utilities
app/src/main/java/.../BluetoothDeviceAdapter.java, app/src/main/java/.../PrinterDeviceClassifier.java, app/src/main/java/.../ReceiverSafeContext.java
Adapter: improved device-name display and Sunmi detection hints. Added PrinterDeviceClassifier.isLikelySunmi(String). Added ReceiverSafeContext wrapper to safely register receivers on newer Android versions.
Layout & Resources
app/src/main/res/layout/activity_wifi_config.xml, app/src/main/res/values/strings.xml
Adds hidden manual SSID entry views to layout and 26 new string resources for device prompts, Wi‑Fi scanning, timeouts, errors, and UI text.

Sequence Diagram

sequenceDiagram
    actor User
    participant MA as MainActivity
    participant SPC as SunmiPrinterClient
    participant BT as BluetoothDevice
    participant WCA as WifiConfigActivity
    participant Router as Router/Network

    User->>MA: Select device from discovery list
    MA->>MA: store address/name, show connecting UI, start 10s timeout
    MA->>SPC: getPrinterSn(device)
    SPC->>BT: perform BLE connection
    SPC->>MA: onSnReceived(sn)
    MA->>MA: cancel timeout, open WifiConfigActivity with device details
    WCA->>SPC: request printer WiFi list
    SPC->>Router: scan networks
    SPC->>WCA: routerFound()... onGetWifiListFinish()
    WCA->>User: populate spinner (or manual entry)
    User->>WCA: select network & submit password
    WCA->>SPC: setWifi(router, password)
    SPC->>BT: send WiFi config to printer
    SPC->>WCA: onSetWifiSuccess() / onWifiConfigFail()
    WCA->>User: show success or error
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

Poem

🐰 A rabbit hops through printer land,
No more sockets in its hand!
Sunmi's client hums a tune,
Timeouts tap the silver moon,
Routers bloom — hop, click, and stand. 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix printer Wi-Fi config flow to match working v1.0 behavior' directly and clearly summarizes the main objective of the changeset: refactoring the Wi-Fi configuration flow to align with a previously working version.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e55103533c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +311 to +315
progressBar.setVisibility(View.GONE);
scanButton.setEnabled(true);
scanButton.setText(R.string.scan_bluetooth);
statusText.setText("");
openWifiConfigScreen();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore stale SN callbacks after timeout

This callback always transitions to the Wi-Fi screen, even if the request has already timed out or a newer connection attempt is underway. connectionTimeoutRunnable only flips state; it does not cancel the in-flight SDK request, so a late onSnReceived can still arrive and trigger navigation with whatever pendingPrinterAddress currently contains, which can reopen the flow unexpectedly or target the wrong printer after retries. Guard this path with the active request state (and ideally a request token/address check) before opening the next activity.

Useful? React with 👍 / 👎.

Comment on lines +211 to +213
if (!availableRouters.isEmpty()) {
wifiSpinner.setSelection(0);
manualSsidContainer.setVisibility(View.GONE);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve user-selected SSID when refreshing router list

routerFound() refreshes the spinner on every discovered network, and this branch always resets selection to index 0 when any routers exist. While scanning is still streaming results, a user's manual choice (including manual-entry option) can be overwritten by a later callback, so tapping Configure may send credentials for a different SSID than the one they picked. Keep/restoring the prior selection during updates avoids this misconfiguration risk.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
app/proguard-rules.pro (1)

20-20: Overly broad package pattern library.** may cause unintended side effects.

The pattern library.** is extremely generic and could match any package starting with "library" across all dependencies, not just the intended one. This risks:

  • Keeping unrelated classes, bloating the final APK
  • Masking issues where actual required classes aren't properly kept

If this is meant to complement the inuker Bluetooth library on line 21, it may be redundant. Otherwise, specify the full package path (e.g., com.somevendor.library.**).

♻️ Suggested fix: Remove or qualify the rule
 # Keep callback implementers and SDK internals that may be invoked reflectively.
 -keep class * implements com.sunmi.cloudprinter.presenter.SunmiPrinterClient$IPrinterClient { *; }
--keep class library.** { *; }
 -keep class com.inuker.bluetooth.library.** { *; }

If a specific library package is needed, use its fully qualified name instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/proguard-rules.pro` at line 20, The ProGuard rule "keep class library.**
{ *; }" is too broad and may retain unintended classes; update the rule in
proguard-rules.pro by either removing this line if it's redundant with the
inuker Bluetooth rule on the next line, or replace "library.**" with the
library's full package (e.g., com.vendor.library.**) so only the intended
package is retained; ensure the rule references the exact package used by the
inuker Bluetooth dependency rather than the generic "library.**".
app/src/main/java/com/sunmi/printerconfig/BluetoothDeviceAdapter.java (1)

50-57: Prefer a formatted string resource over runtime concatenation.

Line 56 builds user-facing text with " • " in code. Using a formatted resource keeps localization flexible.

🌐 Suggested refactor
-            if (PrinterDeviceClassifier.isLikelySunmi(name)) {
-                baseName = baseName + " \u2022 " + holder.itemView.getContext().getString(R.string.likely_sunmi);
-            }
+            if (PrinterDeviceClassifier.isLikelySunmi(name)) {
+                baseName = holder.itemView.getContext().getString(
+                    R.string.device_name_with_hint,
+                    baseName,
+                    holder.itemView.getContext().getString(R.string.likely_sunmi)
+                );
+            }

Also add in app/src/main/res/values/strings.xml:

<string name="device_name_with_hint">%1$s • %2$s</string>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/sunmi/printerconfig/BluetoothDeviceAdapter.java` around
lines 50 - 57, Replace the runtime concatenation of the hint bullet in
BluetoothDeviceAdapter with a formatted string resource: when
PrinterDeviceClassifier.isLikelySunmi(name) is true, call
holder.itemView.getContext().getString(R.string.device_name_with_hint, baseName,
holder.itemView.getContext().getString(R.string.likely_sunmi)) instead of
baseName + " • " + ...; add the suggested <string
name="device_name_with_hint">%1$s • %2$s</string> to strings.xml so localization
uses the formatted resource and remove the hard-coded " • " from the adapter.
app/src/main/res/layout/activity_wifi_config.xml (1)

58-67: Link the manual SSID label to its input for accessibility.

Line 59 should set android:labelFor="@id/manualSsidInput" so screen readers associate the label with Line 66 input.

♿ Suggested tweak
         <TextView
             android:id="@+id/manualSsidLabel"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:labelFor="@id/manualSsidInput"
             android:text="@string/wifi_ssid"
             android:textSize="16sp" />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/res/layout/activity_wifi_config.xml` around lines 58 - 67, The
TextView with id manualSsidLabel should be linked to the EditText
manualSsidInput for accessibility: add the attribute
android:labelFor="@id/manualSsidInput" to the manualSsidLabel element so screen
readers associate the label (manualSsidLabel) with the input field
(manualSsidInput).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/build.gradle`:
- Line 59: The dependency declaration implementation
files('libs/BluetoothBinding.aar') should be protected by pinning its SHA-256
and documenting its origin; update CI to compute and verify the artifact's
SHA-256 before build (reject if mismatch) and add the expected hex hash to the
CI job or a repository file, and also add vendor/source and download provenance
for BluetoothBinding.aar to CONTRIBUTING.md or the build README; alternatively,
generate/commit a gradle verification-metadata.xml entry for
BluetoothBinding.aar and have CI validate it prior to invoking the Gradle build.

In `@app/src/main/AndroidManifest.xml`:
- Line 16: Scope the ACCESS_FINE_LOCATION permission to Android 11 and earlier
by adding maxSdkVersion="30" to the uses-permission element named
android.permission.ACCESS_FINE_LOCATION; locate the uses-permission with
android:name="android.permission.ACCESS_FINE_LOCATION" and update it to mirror
the ACCESS_COARSE_LOCATION entry (which uses maxSdkVersion="30") so the precise
location permission is not requested on Android 12+ where NEARBY_WIFI_DEVICES
with neverForLocation is used.

In `@app/src/main/java/com/sunmi/printerconfig/MainActivity.java`:
- Around line 188-220: onDeviceClick currently allows multiple taps to start
overlapping connections; add an early guard that checks the
waitingForPrinterConnection flag (or set it atomically) at the start of
onDeviceClick and if true show a brief Toast (or ignore) and return to prevent
overwriting pendingPrinterAddress/pendingPrinterName and racing
sunmiPrinterClient.getPrinterSn; ensure the flag is set to true only once before
posting the connection timeout and cleared by all failure/success paths that
call handlePrinterConnectionFailure or the success handler so subsequent taps
are allowed.
- Around line 295-317: Add an early guard in the asynchronous callback handlers
so they no-op if the connection attempt is already finished: at the start of
sendDataFail(int code, String msg) and onSnReceived(String sn) check the
waitingForPrinterConnection boolean and return immediately if it is false; this
prevents delayed callbacks from executing UI/state changes (like
handlePrinterConnectionFailure(...) or openWifiConfigScreen()) after a timeout
or competing result, while leaving existing cleanup calls (e.g.,
connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable)) intact
where appropriate.

In `@app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java`:
- Around line 341-358: Add an early guard that checks the boolean
waitingForWifiConfigResult at the start of each callback (onSetWifiSuccess,
wifiConfigSuccess, onWifiConfigFail, sendDataFail) and return immediately if
it's false so late SDK callbacks cannot overwrite timeout/failure UI state; keep
the rest of each method unchanged (e.g., runOnUiThread in onSetWifiSuccess,
handleConfigurationSuccess(), handleConfigurationFailure(...)) so
waitingForWifiConfigResult is still set to false by those handlers when
appropriate.

---

Nitpick comments:
In `@app/proguard-rules.pro`:
- Line 20: The ProGuard rule "keep class library.** { *; }" is too broad and may
retain unintended classes; update the rule in proguard-rules.pro by either
removing this line if it's redundant with the inuker Bluetooth rule on the next
line, or replace "library.**" with the library's full package (e.g.,
com.vendor.library.**) so only the intended package is retained; ensure the rule
references the exact package used by the inuker Bluetooth dependency rather than
the generic "library.**".

In `@app/src/main/java/com/sunmi/printerconfig/BluetoothDeviceAdapter.java`:
- Around line 50-57: Replace the runtime concatenation of the hint bullet in
BluetoothDeviceAdapter with a formatted string resource: when
PrinterDeviceClassifier.isLikelySunmi(name) is true, call
holder.itemView.getContext().getString(R.string.device_name_with_hint, baseName,
holder.itemView.getContext().getString(R.string.likely_sunmi)) instead of
baseName + " • " + ...; add the suggested <string
name="device_name_with_hint">%1$s • %2$s</string> to strings.xml so localization
uses the formatted resource and remove the hard-coded " • " from the adapter.

In `@app/src/main/res/layout/activity_wifi_config.xml`:
- Around line 58-67: The TextView with id manualSsidLabel should be linked to
the EditText manualSsidInput for accessibility: add the attribute
android:labelFor="@id/manualSsidInput" to the manualSsidLabel element so screen
readers associate the label (manualSsidLabel) with the input field
(manualSsidInput).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3039117 and e551035.

📒 Files selected for processing (12)
  • .gitignore
  • app/build.gradle
  • app/libs/BluetoothBinding.aar
  • app/proguard-rules.pro
  • app/src/main/AndroidManifest.xml
  • app/src/main/java/com/sunmi/printerconfig/BluetoothDeviceAdapter.java
  • app/src/main/java/com/sunmi/printerconfig/MainActivity.java
  • app/src/main/java/com/sunmi/printerconfig/PrinterConfigHelper.java
  • app/src/main/java/com/sunmi/printerconfig/PrinterDeviceClassifier.java
  • app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java
  • app/src/main/res/layout/activity_wifi_config.xml
  • app/src/main/res/values/strings.xml
💤 Files with no reviewable changes (1)
  • app/src/main/java/com/sunmi/printerconfig/PrinterConfigHelper.java

Comment thread app/build.gradle
}

dependencies {
implementation files('libs/BluetoothBinding.aar')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Verify artifact exists
if [ -f app/libs/BluetoothBinding.aar ]; then
  echo "✓ File exists: app/libs/BluetoothBinding.aar"
  # 2) Produce deterministic digest to pin in CI/docs
  sha256sum app/libs/BluetoothBinding.aar
else
  echo "✗ File NOT found: app/libs/BluetoothBinding.aar"
fi

# 3) Confirm local AAR usage points
echo ""
echo "Searching for local AAR references in build files:"
rg -n "implementation\s+files\('libs/.*\.aar" --type gradle

Repository: Arieboomsma/connectprinter

Length of output: 181


🏁 Script executed:

# Check for CI configuration that might validate dependencies
echo "Checking for CI/CD configuration:"
find . -type f \( -name ".github" -o -name ".gitlab-ci.yml" -o -name "*.yml" -o -name "*.yaml" \) -o -path "*/.github/workflows/*" | head -20

# Look for any checksum or integrity validation docs
echo ""
echo "Searching for provenance/checksum documentation:"
rg -i "checksum|sha256|integrity|provenance|BluetoothBinding" --type md --type txt

Repository: Arieboomsma/connectprinter

Length of output: 153


🏁 Script executed:

# Check if there are any gradle dependency verification mechanisms
echo "Checking for gradle dependency verification:"
cat -n gradle/verification-metadata.xml 2>/dev/null || echo "No verification-metadata.xml found"

# Check build.gradle structure for other dependency management
echo ""
echo "Full app/build.gradle to understand context:"
cat -n app/build.gradle | head -80

Repository: Arieboomsma/connectprinter

Length of output: 2415


🏁 Script executed:

# Search for any documentation or context about BluetoothBinding
echo "Searching for BluetoothBinding references:"
rg -i "bluetooth" --type md --type txt --type java --type kt

# Check for README or documentation
echo ""
echo "Checking for README or documentation:"
find . -maxdepth 2 -type f \( -name "README*" -o -name "*.md" \)

Repository: Arieboomsma/connectprinter

Length of output: 268


🏁 Script executed:

# Check git history to understand when and why this was added
echo "Checking file existence and context:"
ls -lh app/libs/BluetoothBinding.aar 2>/dev/null || echo "File details unavailable"

# Look for any build documentation
echo ""
echo "Build/dependency documentation:"
find . -maxdepth 2 -type f -name "*build*" -o -name "*DEPEND*" -o -name "*.md"

Repository: Arieboomsma/connectprinter

Length of output: 336


🏁 Script executed:

# Check README for dependency context
echo "=== README.md ==="
cat README.md

echo ""
echo "=== QUICK_START.md ==="
cat QUICK_START.md

Repository: Arieboomsma/connectprinter

Length of output: 10807


🏁 Script executed:

# Check build.sh for any validation or checksum logic
echo "=== build.sh ==="
cat build.sh

# Check root build.gradle for dependency management
echo ""
echo "=== root build.gradle ==="
cat build.gradle

Repository: Arieboomsma/connectprinter

Length of output: 2008


Pin the BluetoothBinding.aar artifact hash in CI to verify supply-chain integrity.

The local BluetoothBinding.aar dependency bypasses Maven metadata and weakens supply-chain visibility. Add a SHA-256 verification step in your CI/CD pipeline to ensure the artifact hasn't been tampered with. If this is a vendor-supplied library, document its origin and source in the repository (CONTRIBUTING.md or build README).

No existing verification mechanisms (gradle verification-metadata.xml, CI checks) were found.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/build.gradle` at line 59, The dependency declaration implementation
files('libs/BluetoothBinding.aar') should be protected by pinning its SHA-256
and documenting its origin; update CI to compute and verify the artifact's
SHA-256 before build (reject if mismatch) and add the expected hex hash to the
CI job or a repository file, and also add vendor/source and download provenance
for BluetoothBinding.aar to CONTRIBUTING.md or the build README; alternatively,
generate/commit a gradle verification-metadata.xml entry for
BluetoothBinding.aar and have CI validate it prior to invoking the Gradle build.

<!-- Needed for Bluetooth discovery on Android 6-11 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and examine the AndroidManifest.xml file
find . -name "AndroidManifest.xml" -type f

Repository: Arieboomsma/connectprinter

Length of output: 104


🏁 Script executed:

# Check the content of the file around lines 16-23
if [ -f "app/src/main/AndroidManifest.xml" ]; then
  echo "=== Current AndroidManifest.xml (lines 1-35) ==="
  head -35 "app/src/main/AndroidManifest.xml" | cat -n
fi

Repository: Arieboomsma/connectprinter

Length of output: 2023


🏁 Script executed:

# Check git history for this file to see what changed
cd . && git log --oneline -10 -- "app/src/main/AndroidManifest.xml" 2>/dev/null || echo "Git history not available"

Repository: Arieboomsma/connectprinter

Length of output: 142


🏁 Script executed:

# Try to see the diff for the most recent change to this file
git diff HEAD~1 HEAD -- "app/src/main/AndroidManifest.xml" 2>/dev/null || echo "Cannot get git diff"

Repository: Arieboomsma/connectprinter

Length of output: 89


🏁 Script executed:

# Try to get the full git log with patch to see if maxSdkVersion was removed
git log -p --all -- "app/src/main/AndroidManifest.xml" 2>/dev/null | grep -A5 -B5 "ACCESS_FINE_LOCATION" | head -50 || echo "Cannot retrieve full history"

Repository: Arieboomsma/connectprinter

Length of output: 52


🏁 Script executed:

# Check if there are any recent commits that mention this change
git log --all --oneline -20 2>/dev/null || echo "Git not available"

Repository: Arieboomsma/connectprinter

Length of output: 599


🏁 Script executed:

# Search for any issues or comments in the code about location permissions
rg "ACCESS_FINE_LOCATION|maxSdkVersion.*30" --type xml -B2 -A2

Repository: Arieboomsma/connectprinter

Length of output: 1077


Scope ACCESS_FINE_LOCATION to Android 11 and earlier.

Line 16 declares precise location permission without API level constraints, but the comment on line 14 explicitly states this is needed only for "Bluetooth discovery on Android 6-11." The parallel permission on line 15 (ACCESS_COARSE_LOCATION) is correctly scoped to maxSdkVersion="30" for the same feature. On Android 12+, the app uses NEARBY_WIFI_DEVICES with neverForLocation flag, making ACCESS_FINE_LOCATION unnecessary. Leaving it unscoped unnecessarily broadens the privacy/compliance scope on modern Android versions.

🔧 Suggested fix
-    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission
+        android:name="android.permission.ACCESS_FINE_LOCATION"
+        android:maxSdkVersion="30" />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="30" />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/AndroidManifest.xml` at line 16, Scope the ACCESS_FINE_LOCATION
permission to Android 11 and earlier by adding maxSdkVersion="30" to the
uses-permission element named android.permission.ACCESS_FINE_LOCATION; locate
the uses-permission with android:name="android.permission.ACCESS_FINE_LOCATION"
and update it to mirror the ACCESS_COARSE_LOCATION entry (which uses
maxSdkVersion="30") so the precise location permission is not requested on
Android 12+ where NEARBY_WIFI_DEVICES with neverForLocation is used.

Comment on lines +188 to +220
private void onDeviceClick(BluetoothDevice device) {
if (checkBluetoothPermission() && bluetoothAdapter.isDiscovering()) {
if (!checkBluetoothPermission()) {
Toast.makeText(this, R.string.permissions_required, Toast.LENGTH_SHORT).show();
return;
}

if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}

pendingPrinterAddress = safeGetDeviceAddress(device);
pendingPrinterName = safeGetDeviceName(device);

if (pendingPrinterAddress.isEmpty()) {
Toast.makeText(this, R.string.printer_address_unavailable, Toast.LENGTH_LONG).show();
return;
}

waitingForPrinterConnection = true;
progressBar.setVisibility(View.VISIBLE);
scanButton.setEnabled(false);
statusText.setText(R.string.connecting_to_printer);

connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);
connectionTimeoutHandler.postDelayed(connectionTimeoutRunnable, PRINTER_CONNECTION_TIMEOUT_MS);

try {
// Match the known stable flow: establish BLE session before Wi-Fi config screen.
sunmiPrinterClient.getPrinterSn(pendingPrinterAddress);
} catch (Throwable t) {
handlePrinterConnectionFailure(getString(R.string.printer_connection_failed));
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Prevent overlapping connection attempts from repeated device taps.

Line 188 currently allows another click while a connection attempt is active, which can overwrite pendingPrinterAddress/pendingPrinterName and race requests.

🔒 Suggested guard
     private void onDeviceClick(BluetoothDevice device) {
+        if (waitingForPrinterConnection) {
+            return;
+        }
+
         if (!checkBluetoothPermission()) {
             Toast.makeText(this, R.string.permissions_required, Toast.LENGTH_SHORT).show();
             return;
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private void onDeviceClick(BluetoothDevice device) {
if (checkBluetoothPermission() && bluetoothAdapter.isDiscovering()) {
if (!checkBluetoothPermission()) {
Toast.makeText(this, R.string.permissions_required, Toast.LENGTH_SHORT).show();
return;
}
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
pendingPrinterAddress = safeGetDeviceAddress(device);
pendingPrinterName = safeGetDeviceName(device);
if (pendingPrinterAddress.isEmpty()) {
Toast.makeText(this, R.string.printer_address_unavailable, Toast.LENGTH_LONG).show();
return;
}
waitingForPrinterConnection = true;
progressBar.setVisibility(View.VISIBLE);
scanButton.setEnabled(false);
statusText.setText(R.string.connecting_to_printer);
connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);
connectionTimeoutHandler.postDelayed(connectionTimeoutRunnable, PRINTER_CONNECTION_TIMEOUT_MS);
try {
// Match the known stable flow: establish BLE session before Wi-Fi config screen.
sunmiPrinterClient.getPrinterSn(pendingPrinterAddress);
} catch (Throwable t) {
handlePrinterConnectionFailure(getString(R.string.printer_connection_failed));
}
}
private void onDeviceClick(BluetoothDevice device) {
if (waitingForPrinterConnection) {
return;
}
if (!checkBluetoothPermission()) {
Toast.makeText(this, R.string.permissions_required, Toast.LENGTH_SHORT).show();
return;
}
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
pendingPrinterAddress = safeGetDeviceAddress(device);
pendingPrinterName = safeGetDeviceName(device);
if (pendingPrinterAddress.isEmpty()) {
Toast.makeText(this, R.string.printer_address_unavailable, Toast.LENGTH_LONG).show();
return;
}
waitingForPrinterConnection = true;
progressBar.setVisibility(View.VISIBLE);
scanButton.setEnabled(false);
statusText.setText(R.string.connecting_to_printer);
connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);
connectionTimeoutHandler.postDelayed(connectionTimeoutRunnable, PRINTER_CONNECTION_TIMEOUT_MS);
try {
// Match the known stable flow: establish BLE session before Wi-Fi config screen.
sunmiPrinterClient.getPrinterSn(pendingPrinterAddress);
} catch (Throwable t) {
handlePrinterConnectionFailure(getString(R.string.printer_connection_failed));
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/sunmi/printerconfig/MainActivity.java` around lines 188
- 220, onDeviceClick currently allows multiple taps to start overlapping
connections; add an early guard that checks the waitingForPrinterConnection flag
(or set it atomically) at the start of onDeviceClick and if true show a brief
Toast (or ignore) and return to prevent overwriting
pendingPrinterAddress/pendingPrinterName and racing
sunmiPrinterClient.getPrinterSn; ensure the flag is set to true only once before
posting the connection timeout and cleared by all failure/success paths that
call handlePrinterConnectionFailure or the success handler so subsequent taps
are allowed.

Comment on lines +295 to +317
public void sendDataFail(int code, String msg) {
String failure = getString(R.string.wifi_push_error_with_code, code, msg == null ? "Unknown" : msg);
handlePrinterConnectionFailure(failure);
}

@Override
public void getSnRequestSuccess() {
// Wait for onSnReceived callback.
}

@Override
public void onSnReceived(String sn) {
waitingForPrinterConnection = false;
connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);

runOnUiThread(() -> {
progressBar.setVisibility(View.GONE);
scanButton.setEnabled(true);
scanButton.setText(R.string.scan_bluetooth);
statusText.setText("");
openWifiConfigScreen();
});
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "MainActivity.java" -path "*/sunmi/printerconfig/*" | head -5

Repository: Arieboomsma/connectprinter

Length of output: 131


🏁 Script executed:

wc -l ./app/src/main/java/com/sunmi/printerconfig/MainActivity.java

Repository: Arieboomsma/connectprinter

Length of output: 135


🏁 Script executed:

cat -n ./app/src/main/java/com/sunmi/printerconfig/MainActivity.java

Repository: Arieboomsma/connectprinter

Length of output: 15562


Guard callback handlers against stale invocations after connection attempt completes.

The methods sendDataFail() and onSnReceived() (lines 295-317) implement asynchronous callbacks from the SunmiPrinterClient layer. These callbacks can be queued in the BLE/network layer and may arrive after the connection attempt has already concluded (via timeout or a competing callback), causing them to overwrite previous state and unexpectedly reopen the Wi-Fi configuration screen or show duplicate error messages.

While connectionTimeoutRunnable itself guards against stale execution (line 55), the callback methods do not. Add early-return checks for waitingForPrinterConnection to prevent delayed callbacks from executing side effects after their associated connection attempt is no longer pending.

Suggested fix
    `@Override`
    public void sendDataFail(int code, String msg) {
+       if (!waitingForPrinterConnection) {
+           return;
+       }
        String failure = getString(R.string.wifi_push_error_with_code, code, msg == null ? "Unknown" : msg);
        handlePrinterConnectionFailure(failure);
    }

    `@Override`
    public void onSnReceived(String sn) {
+       if (!waitingForPrinterConnection) {
+           return;
+       }
        waitingForPrinterConnection = false;
        connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);

        runOnUiThread(() -> {
            progressBar.setVisibility(View.GONE);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/sunmi/printerconfig/MainActivity.java` around lines 295
- 317, Add an early guard in the asynchronous callback handlers so they no-op if
the connection attempt is already finished: at the start of sendDataFail(int
code, String msg) and onSnReceived(String sn) check the
waitingForPrinterConnection boolean and return immediately if it is false; this
prevents delayed callbacks from executing UI/state changes (like
handlePrinterConnectionFailure(...) or openWifiConfigScreen()) after a timeout
or competing result, while leaving existing cleanup calls (e.g.,
connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable)) intact
where appropriate.

Comment on lines +341 to +358
public void onSetWifiSuccess() {
runOnUiThread(() -> statusText.setText(R.string.configuring));
}

@Override
public void wifiConfigSuccess() {
handleConfigurationSuccess();
}

@Override
public void onWifiConfigFail() {
handleConfigurationFailure(getString(R.string.wifi_push_failed_try_24g));
}

@Override
public void sendDataFail(int code, String msg) {
String failureMessage = getString(R.string.wifi_push_error_with_code, code, msg == null ? "Unknown" : msg);
handleConfigurationFailure(failureMessage);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -t f WifiConfigActivity.java

Repository: Arieboomsma/connectprinter

Length of output: 135


🏁 Script executed:

wc -l app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java

Repository: Arieboomsma/connectprinter

Length of output: 139


🏁 Script executed:

cat -n app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java

Repository: Arieboomsma/connectprinter

Length of output: 15333


Add state guards to config callbacks to prevent late SDK callbacks from overwriting timeout/failure state.

The callback handlers at lines 341-358 can still execute after timeout (line 50-54) or explicit failure, overwriting the UI state with contradictory outcomes. Although handleConfigurationSuccess() and handleConfigurationFailure() both set waitingForWifiConfigResult = false, this happens after being called, so late callbacks proceed unchecked. Add waitingForWifiConfigResult guards to all four callback entry points as suggested.

Suggested fix
     `@Override`
     public void onSetWifiSuccess() {
+        if (!waitingForWifiConfigResult) {
+            return;
+        }
         runOnUiThread(() -> statusText.setText(R.string.configuring));
     }

     `@Override`
     public void wifiConfigSuccess() {
+        if (!waitingForWifiConfigResult) {
+            return;
+        }
         handleConfigurationSuccess();
     }

     `@Override`
     public void onWifiConfigFail() {
+        if (!waitingForWifiConfigResult) {
+            return;
+        }
         handleConfigurationFailure(getString(R.string.wifi_push_failed_try_24g));
     }

     `@Override`
     public void sendDataFail(int code, String msg) {
+        if (!waitingForWifiConfigResult) {
+            return;
+        }
         String failureMessage = getString(R.string.wifi_push_error_with_code, code, msg == null ? "Unknown" : msg);
         handleConfigurationFailure(failureMessage);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java` around
lines 341 - 358, Add an early guard that checks the boolean
waitingForWifiConfigResult at the start of each callback (onSetWifiSuccess,
wifiConfigSuccess, onWifiConfigFail, sendDataFail) and return immediately if
it's false so late SDK callbacks cannot overwrite timeout/failure UI state; keep
the rest of each method unchanged (e.g., runOnUiThread in onSetWifiSuccess,
handleConfigurationSuccess(), handleConfigurationFailure(...)) so
waitingForWifiConfigResult is still set to false by those handlers when
appropriate.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (3)
app/src/main/java/com/sunmi/printerconfig/MainActivity.java (2)

191-223: ⚠️ Potential issue | 🟠 Major

Prevent overlapping connection attempts from repeated taps.

onDeviceClick should return immediately when a connection attempt is already pending to avoid racing pendingPrinterAddress/pendingPrinterName.

Suggested fix
 private void onDeviceClick(BluetoothDevice device) {
+    if (waitingForPrinterConnection) {
+        return;
+    }
+
     if (!checkBluetoothPermission()) {
         Toast.makeText(this, R.string.permissions_required, Toast.LENGTH_SHORT).show();
         return;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/sunmi/printerconfig/MainActivity.java` around lines 191
- 223, The onDeviceClick method can start overlapping connections; add an early
guard that returns immediately when waitingForPrinterConnection is true to
prevent races updating pendingPrinterAddress/pendingPrinterName and duplicate
connection attempts. Locate the onDeviceClick(BluetoothDevice) method and at its
start check the waitingForPrinterConnection flag and return (optionally show a
Toast or ignore) if a connection is already pending, ensuring existing logic
that sets progressBar, scanButton, statusText, and posts
connectionTimeoutRunnable only runs when not already waiting.

297-320: ⚠️ Potential issue | 🟠 Major

Ignore stale printer callbacks after attempt completion.

sendDataFail and onSnReceived should guard on waitingForPrinterConnection so delayed callbacks can’t reopen flow or overwrite terminal state.

Suggested fix
 `@Override`
 public void sendDataFail(int code, String msg) {
+    if (!waitingForPrinterConnection) {
+        return;
+    }
     String failure = getString(R.string.wifi_push_error_with_code, code, msg == null ? "Unknown" : msg);
     handlePrinterConnectionFailure(failure);
 }

 `@Override`
 public void onSnReceived(String sn) {
+    if (!waitingForPrinterConnection) {
+        return;
+    }
     waitingForPrinterConnection = false;
     connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);

     runOnUiThread(() -> {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/sunmi/printerconfig/MainActivity.java` around lines 297
- 320, Both sendDataFail and onSnReceived should ignore stale callbacks by
checking waitingForPrinterConnection at the start and bailing out if it's false;
update sendDataFail to return immediately when waitingForPrinterConnection is
false before building failure string/handling, and update onSnReceived to return
immediately if waitingForPrinterConnection is false (otherwise keep the existing
logic that clears waitingForPrinterConnection, removes callbacks, updates UI and
calls openWifiConfigScreen). Reference the methods sendDataFail(...) and
onSnReceived(String) when making these guards.
app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java (1)

343-362: ⚠️ Potential issue | 🟠 Major

Guard Wi‑Fi config callbacks against stale invocations.

These async callbacks should no-op once the request is no longer active; otherwise late SDK events can overwrite timeout/failure UI state.

Suggested fix
 `@Override`
 public void onSetWifiSuccess() {
+    if (!waitingForWifiConfigResult) {
+        return;
+    }
     runOnUiThread(() -> statusText.setText(R.string.configuring));
 }

 `@Override`
 public void wifiConfigSuccess() {
+    if (!waitingForWifiConfigResult) {
+        return;
+    }
     handleConfigurationSuccess();
 }

 `@Override`
 public void onWifiConfigFail() {
+    if (!waitingForWifiConfigResult) {
+        return;
+    }
     handleConfigurationFailure(getString(R.string.wifi_push_failed_try_24g));
 }

 `@Override`
 public void sendDataFail(int code, String msg) {
+    if (!waitingForWifiConfigResult) {
+        return;
+    }
     String failureMessage = getString(R.string.wifi_push_error_with_code, code, msg == null ? "Unknown" : msg);
     handleConfigurationFailure(failureMessage);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java` around
lines 343 - 362, The Wi‑Fi callback handlers (onSetWifiSuccess,
wifiConfigSuccess, onWifiConfigFail, sendDataFail) must be guarded so they no‑op
if the original request is no longer active; add a check at the top of each
method that verifies a config-in-progress marker (e.g., a boolean like
isConfigActive or a currentRequestId match) and return early if the marker
indicates the request was cancelled/expired, and ensure the marker is set true
when starting configuration and cleared on timeout/success/failure so late SDK
events cannot overwrite UI state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@app/src/main/java/com/sunmi/printerconfig/MainActivity.java`:
- Around line 191-223: The onDeviceClick method can start overlapping
connections; add an early guard that returns immediately when
waitingForPrinterConnection is true to prevent races updating
pendingPrinterAddress/pendingPrinterName and duplicate connection attempts.
Locate the onDeviceClick(BluetoothDevice) method and at its start check the
waitingForPrinterConnection flag and return (optionally show a Toast or ignore)
if a connection is already pending, ensuring existing logic that sets
progressBar, scanButton, statusText, and posts connectionTimeoutRunnable only
runs when not already waiting.
- Around line 297-320: Both sendDataFail and onSnReceived should ignore stale
callbacks by checking waitingForPrinterConnection at the start and bailing out
if it's false; update sendDataFail to return immediately when
waitingForPrinterConnection is false before building failure string/handling,
and update onSnReceived to return immediately if waitingForPrinterConnection is
false (otherwise keep the existing logic that clears
waitingForPrinterConnection, removes callbacks, updates UI and calls
openWifiConfigScreen). Reference the methods sendDataFail(...) and
onSnReceived(String) when making these guards.

In `@app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java`:
- Around line 343-362: The Wi‑Fi callback handlers (onSetWifiSuccess,
wifiConfigSuccess, onWifiConfigFail, sendDataFail) must be guarded so they no‑op
if the original request is no longer active; add a check at the top of each
method that verifies a config-in-progress marker (e.g., a boolean like
isConfigActive or a currentRequestId match) and return early if the marker
indicates the request was cancelled/expired, and ensure the marker is set true
when starting configuration and cleared on timeout/success/failure so late SDK
events cannot overwrite UI state.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e551035 and 310a152.

📒 Files selected for processing (4)
  • app/build.gradle
  • app/src/main/java/com/sunmi/printerconfig/MainActivity.java
  • app/src/main/java/com/sunmi/printerconfig/ReceiverSafeContext.java
  • app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/build.gradle

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b492a564f3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

private Router buildManualRouter(String ssid) {
Router router = new Router();
router.setName(ssid);
router.setEssid(ssid.getBytes(StandardCharsets.UTF_8));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Pad manual SSID before sending Wi-Fi config

Manual SSID entry stores router.setEssid(ssid.getBytes(...)) as a variable-length byte array, but the Sunmi SDK Wi‑Fi command format expects the ESSID field in the fixed-size form used by scanned routers (64-byte payload). When users rely on manual entry (for hidden SSIDs or failed scans), this mismatch can produce malformed config payloads and cause provisioning to fail; encode/pad manual SSIDs to the SDK’s expected ESSID width before calling setPrinterWifi.

Useful? React with 👍 / 👎.

Comment on lines +349 to +350
public void wifiConfigSuccess() {
handleConfigurationSuccess();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore stale Wi-Fi config callbacks after timeout

This success callback always finalizes as success, even after wifiConfigTimeoutRunnable has already marked the request failed or a newer attempt has started. Since timeout handling does not cancel the in-flight SDK request, late wifiConfigSuccess (or fail) callbacks from an older attempt can still close the activity and overwrite current state; guard callbacks with active-request state/token checks before updating UI.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a2f1b23d77

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +321 to +323
progressBar.setVisibility(View.GONE);
configureButton.setEnabled(true);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate Wi-Fi list completion UI while config is in progress

onGetWifiListFinish always hides the progress indicator and re-enables the Configure button even if setPrinterWifi is already in flight (waitingForWifiConfigResult == true). Because manual submission is possible before list fetch completes, a late list-finish callback can overwrite the “sending” state and let users submit a second configuration request while the first is still pending, causing duplicated/competing writes and misleading status.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant