Skip to content

Commit df1f6df

Browse files
runningcodeclaude
andcommitted
ref(feedback): Extend Dialog instead of AlertDialog in SentryUserFeedbackForm
The form never used AlertDialog's title, message, buttons or custom view; it replaces the content with its own layout in onCreate. Dialog falls back to dialogTheme for theme 0, while AlertDialog uses alertDialogTheme, so the form now resolves alertDialogTheme itself to keep the default look unchanged. The FLAG_ALT_FOCUSABLE_IM workaround goes away because only AlertDialog set that flag. Resolves JAVA-494 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 1f0e1e0 commit df1f6df

3 files changed

Lines changed: 35 additions & 10 deletions

File tree

‎sentry-android-core/api/sentry-android-core.api‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ public abstract interface class io/sentry/android/core/SentryShakeDetector$Liste
576576
public abstract fun onShake ()V
577577
}
578578

579-
public class io/sentry/android/core/SentryUserFeedbackForm : android/app/AlertDialog {
579+
public class io/sentry/android/core/SentryUserFeedbackForm : android/app/Dialog {
580580
protected fun onCreate (Landroid/os/Bundle;)V
581581
public fun onDetachedFromWindow ()V
582582
protected fun onStart ()V

‎sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackForm.java‎

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
package io.sentry.android.core;
22

33
import android.app.Activity;
4-
import android.app.AlertDialog;
54
import android.app.Application;
5+
import android.app.Dialog;
66
import android.content.ContentResolver;
77
import android.content.Context;
88
import android.content.ContextWrapper;
99
import android.database.Cursor;
1010
import android.net.Uri;
1111
import android.os.Bundle;
1212
import android.provider.OpenableColumns;
13+
import android.util.TypedValue;
1314
import android.view.View;
14-
import android.view.Window;
15-
import android.view.WindowManager;
1615
import android.webkit.MimeTypeMap;
1716
import android.widget.Button;
1817
import android.widget.EditText;
@@ -39,7 +38,7 @@
3938
import org.jetbrains.annotations.NotNull;
4039
import org.jetbrains.annotations.Nullable;
4140

42-
public class SentryUserFeedbackForm extends AlertDialog {
41+
public class SentryUserFeedbackForm extends Dialog {
4342

4443
private boolean isCancelable = false;
4544
private @Nullable SentryId currentReplayId;
@@ -60,7 +59,7 @@ public class SentryUserFeedbackForm extends AlertDialog {
6059
final @Nullable SentryId associatedEventId,
6160
final @Nullable OptionsConfiguration configuration,
6261
final @Nullable SentryFeedbackOptions.OptionsConfigurator configurator) {
63-
super(context, themeResId);
62+
super(context, resolveTheme(context, themeResId));
6463
this.associatedEventId = associatedEventId;
6564
final @NotNull SentryOptions options = Sentry.getCurrentScopes().getOptions();
6665
@NotNull
@@ -211,6 +210,19 @@ public void onActivitySaveInstanceState(
211210
final @NotNull Activity activity, final @NotNull Bundle outState) {}
212211
}
213212

213+
/**
214+
* {@link Dialog} falls back to {@link android.R.attr#dialogTheme} for {@code 0}, but the form has
215+
* always defaulted to {@link android.R.attr#alertDialogTheme}, as {@code AlertDialog} does.
216+
*/
217+
static int resolveTheme(final @NotNull Context context, final int themeResId) {
218+
if (themeResId != 0) {
219+
return themeResId;
220+
}
221+
final @NotNull TypedValue outValue = new TypedValue();
222+
context.getTheme().resolveAttribute(android.R.attr.alertDialogTheme, outValue, true);
223+
return outValue.resourceId;
224+
}
225+
214226
@Override
215227
public void setCancelable(boolean cancelable) {
216228
super.setCancelable(cancelable);
@@ -222,10 +234,6 @@ public void setCancelable(boolean cancelable) {
222234
protected void onCreate(Bundle savedInstanceState) {
223235
super.onCreate(savedInstanceState);
224236
setContentView(R.layout.sentry_dialog_user_feedback);
225-
final @Nullable Window window = getWindow();
226-
if (window != null) {
227-
window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
228-
}
229237
setCancelable(isCancelable);
230238

231239
final @NotNull SentryFeedbackOptions feedbackOptions = resolvedFeedbackOptions;

‎sentry-android-core/src/test/java/io/sentry/android/core/SentryUserFeedbackFormTest.kt‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import android.database.Cursor
1010
import android.net.Uri
1111
import android.os.Looper
1212
import android.provider.OpenableColumns
13+
import android.view.ContextThemeWrapper
1314
import android.view.View
1415
import android.view.WindowManager
1516
import android.widget.Button
@@ -244,6 +245,22 @@ class SentryUserFeedbackFormTest {
244245
assertEquals(0, flags and WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
245246
}
246247

248+
@Test
249+
fun `default theme resolves to the context's alert dialog theme`() {
250+
val context = ContextThemeWrapper(fixture.application, android.R.style.Theme_Material_Light)
251+
252+
assertThat(SentryUserFeedbackForm.resolveTheme(context, 0))
253+
.isEqualTo(android.R.style.Theme_Material_Light_Dialog_Alert)
254+
}
255+
256+
@Test
257+
fun `explicit theme is used as is`() {
258+
val context = ContextThemeWrapper(fixture.application, android.R.style.Theme_Material_Light)
259+
260+
assertThat(SentryUserFeedbackForm.resolveTheme(context, android.R.style.Theme_Material_Dialog))
261+
.isEqualTo(android.R.style.Theme_Material_Dialog)
262+
}
263+
247264
@Test
248265
fun `a crashing onFormClose callback does not crash the app when the dialog is closed`() {
249266
fixture.options.isEnabled = true

0 commit comments

Comments
 (0)