From fd0d86efabcef92415070cb48ace0f20ebf8d7ed Mon Sep 17 00:00:00 2001 From: isra el Date: Fri, 6 Feb 2026 10:07:30 +0300 Subject: [PATCH] ui(android): more app ui enhancement --- .../vernu/sms/activities/MainActivity.java | 74 +++++++++++++++---- .../main/res/color/button_background_tint.xml | 5 ++ .../src/main/res/color/button_text_color.xml | 5 ++ .../app/src/main/res/layout/activity_main.xml | 24 ++---- 4 files changed, 76 insertions(+), 32 deletions(-) create mode 100644 android/app/src/main/res/color/button_background_tint.xml create mode 100644 android/app/src/main/res/color/button_text_color.xml diff --git a/android/app/src/main/java/com/vernu/sms/activities/MainActivity.java b/android/app/src/main/java/com/vernu/sms/activities/MainActivity.java index a4fdd57..749d2d5 100644 --- a/android/app/src/main/java/com/vernu/sms/activities/MainActivity.java +++ b/android/app/src/main/java/com/vernu/sms/activities/MainActivity.java @@ -35,6 +35,9 @@ import com.vernu.sms.helpers.SharedPreferenceHelper; import com.vernu.sms.helpers.VersionTracker; import com.vernu.sms.helpers.HeartbeatManager; import com.google.firebase.crashlytics.FirebaseCrashlytics; +import com.google.gson.Gson; +import okhttp3.ResponseBody; +import java.io.IOException; import java.util.Arrays; import java.util.Objects; import retrofit2.Call; @@ -159,7 +162,7 @@ public class MainActivity extends AppCompatActivity { public void onResponse(Call call, Response response) { Log.d(TAG, response.toString()); if (!response.isSuccessful()) { - Snackbar.make(view, response.message().isEmpty() ? "An error occurred :( "+ response.code() : response.message(), Snackbar.LENGTH_LONG).show(); + Snackbar.make(view, extractErrorMessage(response), Snackbar.LENGTH_LONG).show(); compoundButton.setEnabled(true); return; } @@ -257,7 +260,8 @@ public class MainActivity extends AppCompatActivity { // Create radio buttons for each SIM with proper styling TextBeeUtils.getAvailableSimSlots(mContext).forEach(subscriptionInfo -> { - String simInfo = "SIM " + (subscriptionInfo.getSimSlotIndex() + 1) + " (" + subscriptionInfo.getDisplayName() + ")"; + String displayName = subscriptionInfo.getDisplayName() != null ? subscriptionInfo.getDisplayName().toString() : "Unknown"; + String simInfo = displayName + " (Subscription ID: " + subscriptionInfo.getSubscriptionId() + ")"; RadioButton radioButton = new RadioButton(mContext); radioButton.setText(simInfo); radioButton.setId(subscriptionInfo.getSubscriptionId()); @@ -292,6 +296,44 @@ public class MainActivity extends AppCompatActivity { } } + /** + * Extracts error message from API response, trying multiple sources: + * 1. Error message from response body (error field) + * 2. Response message from HTTP headers + * 3. Generic error with status code as fallback + */ + private String extractErrorMessage(Response response) { + // Try to parse error from response body + try { + ResponseBody errorBody = response.errorBody(); + if (errorBody != null) { + String errorBodyString = errorBody.string(); + if (errorBodyString != null && !errorBodyString.isEmpty()) { + try { + Gson gson = new Gson(); + RegisterDeviceResponseDTO errorResponse = gson.fromJson(errorBodyString, RegisterDeviceResponseDTO.class); + if (errorResponse != null && errorResponse.error != null && !errorResponse.error.isEmpty()) { + return errorResponse.error; + } + } catch (Exception e) { + // If JSON parsing fails, try to extract message from raw string + Log.d(TAG, "Could not parse error response as JSON: " + errorBodyString); + } + } + } + } catch (IOException e) { + Log.d(TAG, "Could not read error body: " + e.getMessage()); + } + + // Fall back to response message + if (response.message() != null && !response.message().isEmpty()) { + return response.message(); + } + + // Final fallback to generic error with status code + return "An error occurred :( " + response.code(); + } + /** * Apply the custom radio button style to a programmatically created radio button */ @@ -391,7 +433,7 @@ public class MainActivity extends AppCompatActivity { public void onResponse(Call call, Response response) { Log.d(TAG, response.toString()); if (!response.isSuccessful()) { - Snackbar.make(view, response.message().isEmpty() ? "An error occurred :( "+ response.code() : response.message(), Snackbar.LENGTH_LONG).show(); + Snackbar.make(view, extractErrorMessage(response), Snackbar.LENGTH_LONG).show(); registerDeviceBtn.setEnabled(true); registerDeviceBtn.setText("Update"); return; @@ -445,18 +487,18 @@ public class MainActivity extends AppCompatActivity { } Call apiCall = ApiManager.getApiService().registerDevice(newKey, registerDeviceInput); - apiCall.enqueue(new Callback() { - @Override - public void onResponse(Call call, Response response) { - Log.d(TAG, response.toString()); - if (!response.isSuccessful()) { - Snackbar.make(view, response.message().isEmpty() ? "An error occurred :( "+ response.code() : response.message(), Snackbar.LENGTH_LONG).show(); - registerDeviceBtn.setEnabled(true); - registerDeviceBtn.setText("Update"); - return; - } - SharedPreferenceHelper.setSharedPreferenceString(mContext, AppConstants.SHARED_PREFS_API_KEY_KEY, newKey); - Snackbar.make(view, "Device Registration Successful :)", Snackbar.LENGTH_LONG).show(); + apiCall.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + Log.d(TAG, response.toString()); + if (!response.isSuccessful()) { + Snackbar.make(view, extractErrorMessage(response), Snackbar.LENGTH_LONG).show(); + registerDeviceBtn.setEnabled(true); + registerDeviceBtn.setText("Update"); + return; + } + SharedPreferenceHelper.setSharedPreferenceString(mContext, AppConstants.SHARED_PREFS_API_KEY_KEY, newKey); + Snackbar.make(view, "Device Registration Successful :)", Snackbar.LENGTH_LONG).show(); if (response.body() != null && response.body().data != null && response.body().data.get("_id") != null) { deviceId = response.body().data.get("_id").toString(); @@ -544,7 +586,7 @@ public class MainActivity extends AppCompatActivity { public void onResponse(Call call, Response response) { Log.d(TAG, response.toString()); if (!response.isSuccessful()) { - Snackbar.make(view, response.message().isEmpty() ? "An error occurred :( "+ response.code() : response.message(), Snackbar.LENGTH_LONG).show(); + Snackbar.make(view, extractErrorMessage(response), Snackbar.LENGTH_LONG).show(); registerDeviceBtn.setEnabled(true); registerDeviceBtn.setText("Update"); return; diff --git a/android/app/src/main/res/color/button_background_tint.xml b/android/app/src/main/res/color/button_background_tint.xml new file mode 100644 index 0000000..b9bdc50 --- /dev/null +++ b/android/app/src/main/res/color/button_background_tint.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android/app/src/main/res/color/button_text_color.xml b/android/app/src/main/res/color/button_text_color.xml new file mode 100644 index 0000000..29aebc3 --- /dev/null +++ b/android/app/src/main/res/color/button_text_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index 18c1948..aa94ff7 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -256,11 +256,11 @@ android:id="@+id/registerDeviceBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:backgroundTint="?attr/colorPrimary" + android:backgroundTint="@color/button_background_tint" android:paddingHorizontal="28dp" android:paddingVertical="12dp" android:text="Connect" - android:textColor="@color/white" + android:textColor="@color/button_text_color" android:textSize="15sp" android:letterSpacing="0.01" style="@style/Widget.MaterialComponents.Button" @@ -334,24 +334,15 @@ android:textSize="16sp" android:textStyle="bold" /> - -