Skip to content

support viewing paired auditees#318

Open
master-hax wants to merge 24 commits intoGrapheneOS:mainfrom
master-hax:inspect_auditees
Open

support viewing paired auditees#318
master-hax wants to merge 24 commits intoGrapheneOS:mainfrom
master-hax:inspect_auditees

Conversation

@master-hax
Copy link
Copy Markdown
Contributor

@master-hax master-hax commented Feb 20, 2026

background

the web app (https://attestation.app) allows users to view all the paired auditees - this PR adds the same functionality to the mobile app

this is a prerequisite for fixing #51 as the pairings need to be identifiable & enumerable before they can be individually deleted or renamed.

changes

  • add a new activity InspectAuditeeActivity that allows a paired auditee to be viewed in detail (with selectable TextViews)
  • update AttestationProtocol.java to allow retrieving information about paired auditees
  • update AttestationActivity to include a list of fingerprints below the buttons
  • add new content layouts for auditee summary fields & the fingerprint list entities

screenshots

  • paired auditee list: Screenshot_20260220_015743_Auditor
  • inspecting a single auditee pairing: Screenshot_20260224_024918_Auditor.png
  • no paired auditees Screenshot_20260220_021729_Auditor.png
  • horizontal layout (I have a camera cutout) Screenshot_20260224_220926_Auditor.png
  • horizontal layout light mode Screenshot_20260224_220947_Auditor.png
  • horizontal layout with navigation bar Screenshot_20260224_221301_Auditor.png

cc @muhomorr @inthewaves

@thestinger
Copy link
Copy Markdown
Member

Can you rebase this?

@master-hax
Copy link
Copy Markdown
Contributor Author

master-hax commented Feb 23, 2026

Can you rebase this?

done, thanks for taking a look. looks to be passing the build now.

@master-hax
Copy link
Copy Markdown
Contributor Author

master-hax commented Feb 23, 2026

the paired auditee list is not explicitly refreshed when a new auditee is added, but onCreate does seem to be called and refresh the list correctly in my testing.

also, my screenshot just shows the same fingerprint multiple times because i only have one auditable device for testing.

Comment on lines +335 to +341
final TextView auditeeListLabel = findViewById(R.id.auditee_list_label);
final LinearLayout auditeesContainer = findViewById(R.id.auditee_list_values);
if (auditees.isEmpty()) {
auditeeListLabel.setText(R.string.paired_auditees_list_empty);
auditeesContainer.removeAllViews();
return;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it's better to use a RecyclerView here, since the app doesn't have a limit on the number of auditees

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 24, 2026

Choose a reason for hiding this comment

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

updated in 734502c - used androidx.core.widget.NestedScrollView to make the whole page scroll correctly.

i didn't implement this initially because i incorrectly thought this wouldn't provide value without the asynchronous file iterator - though i now realize we still get value from the recycled views.

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 24, 2026

Choose a reason for hiding this comment

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

though now, i'm realizing that the nested scroll view might negate the benefits of the recycler view...i think i may have to make the existing attestation content a header within the recycler view.

}

static List<String> getAuditorFingerprints(final Context context) {
final File dir = new File(context.getFilesDir().getParent() + "/shared_prefs/");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

might be better to use the same way how AOSP gets the preference directory:

https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/app/ContextImpl.java;l=764

Suggested change
final File dir = new File(context.getFilesDir().getParent() + "/shared_prefs/");
final File dir = new File(context.getDataDir(), "shared_prefs");

but I did notice this was the code used elsewhere in the app already

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

given that this PR already has some significant changes, i think it would be good to limit the blast radius to make debugging / bisecting easier - could we make this change in a future PR?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

though, i guess we may have to change this anyway to achieve the ask in #318 (comment)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sure, I think issues like this could be handled later

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

are TODO comments acceptable? or shall i open an issue?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we should just open an issue for SharedPreference usage in general, and maybe make a TODO note that links to the issue

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

opened #321

}
});

final List<String> auditees = AttestationProtocol.getAuditorFingerprints(this);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems to do file system operations (listing files in a directory) on the main thread

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 24, 2026

Choose a reason for hiding this comment

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

good callout - fixed in 9396ebf, included an initial "loading paired auditees..." text for the label, & tested with a Thread.sleep(5000).

static List<String> getAuditorFingerprints(final Context context) {
final File dir = new File(context.getFilesDir().getParent() + "/shared_prefs/");
ArrayList<String> auditees = new ArrayList<>();
final String[] sharedPreferenceFiles = dir.list();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Using a directory stream might be more efficient here, since all we need here is iteration over the files. Doc comments for java.io.File#list says:

Note that the java.nio.file.Files class defines the newDirectoryStream method to open a directory and iterate over the names of the files in the directory. This may use less resources when working with very large directories, and may be more responsive when working with remote directories.

Though again, I did notice this was how the app was doing this initially

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 24, 2026

Choose a reason for hiding this comment

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

this was my initial thought - to return an iterator from AttestationProtocol rather than a list. There were a few reasons why I didn't implement this initially:

  1. keep in line with the existing code, reduce blast radius of this PR

  2. inconsistent ordering of auditee pairings - currently I have the auditee list sorted consistently based on lexicographic comparison of hex representation of their fingerprints. however by using the iterator, the list ordering is not guaranteed to be the same every time the list is loaded - it is unclear what ordering the OS will use and whether it will be the same when called twice.

  3. using an iterator does not provide random access to the filenames - e.g. if someone scrolls up, we can't go back to ask the iterator "hey could you remind me what the 5th filename was?" - meaning we will have to keep the entire list in memory as it loads. the iterator is still an efficiency win, but consumes the same amount of memory in the worst case scenario (when someone scrolls to the bottom of the list)

  4. we are loading only a very small amount of data per pairing - each fingerprint string takes up only ~64 bytes iiuc (+ a pointer or whatever java does internally)

so i think using the iterator definitely does provide greater efficiency, but might not be worth these drawbacks + increased complexity. what do you think? i'm happy to implement this either way.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see the reasoning and I agree, this should be fine then

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 24, 2026

Choose a reason for hiding this comment

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

re: the discussion on matrix - using sqlite solves problems 2 & 3 + also allows fancier ordering (like ordering by first or last verified time)

Comment on lines +1754 to +1758
final String deviceName = decapitatedFilename.substring(0, decapitatedFilename.length() - ".xml".length());
if (deviceName.isBlank()) {
continue;
}
auditees.add(deviceName);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

deviceName variable seems to be a fingerprint

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

updated in 04c9314

Comment on lines +13 to +16
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the toolbar in the new activity should show a back button, and the title in the toolbar should be something descriptive like "Viewing auditee"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added back button in 13975e1 - will update screenshots after other changes are done

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added title in 3c92624

Comment on lines +35 to +38
if (fingerprint_hex == null || fingerprint_hex.isBlank()) {
Log.e(TAG, "auditee fingerprint not provided");
return;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Activity should finish and/or show some error message

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

given that we don't expect this case to happen regularly (if at all) - i think using the snackbar might be overkill - do you think a toast is reasonable?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Toast seems fine, and yeah, I think this would only happen through programming error anyway

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 24, 2026

Choose a reason for hiding this comment

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

there is a different issue, where any random string can be passed as the fingerprint, which will cause the activity to display default values.

i think it is technically possible for a user to click the "clear auditor pairings" menu button, then click on an auditee before the clearing code is completely run.

we could temporarily disable the auditees list or do some locking to prevent this - but someone using adb or system settings to clear the app data while the app is running could still cause this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added toast & activity finishing behavior in f5a9eca

Comment on lines +43 to +53
addSummaryField("fingerprint", fingerprint_hex);
addSummaryField("first verified", new Date(summary.verifiedTimeFirst()).toString());
addSummaryField("last verified", new Date(summary.verifiedTimeLast()).toString());
addSummaryField("verified boot key", summary.verifiedBootKey());
addSummaryField("pinned OS version", String.valueOf(summary.pinnedOsVersion()));
addSummaryField("pinned OS patch level", String.valueOf(summary.pinnedOsPatchLevel()));
addSummaryField("pinned vendor patch level", String.valueOf(summary.pinnedVendorPatchLevel()));
addSummaryField("pinned boot patch level", String.valueOf(summary.pinnedBootPatchLevel()));
addSummaryField("pinned app version", String.valueOf(summary.pinnedAppVersion()));
addSummaryField("pinned app variant", String.valueOf(summary.pinnedAppVariant()));
addSummaryField("pinned security level", String.valueOf(summary.pinnedSecurityLevel()));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  1. I think we should use the strings for these labels in res/values/strings.xml, though they might need to be adapted here, since they have new line chars in them
  2. The "Information provided by the verified OS" section should probably be here, but I don't think the app is currently storing that info (unlike the server), so we can leave that for now
  3. For consistency, I think we should have sections here like the web app. The "first verified" and "last verified" should be under an "Attestation history" section, and the other fields should be under a "Hardware verified information" section.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

for 1, the existing strings in strings.xml have control characters + format placeholders in them, so i don't think it is viable to use them. i can add these to strings.xml though.

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 24, 2026

Choose a reason for hiding this comment

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

fixed 2 & 3 in 4aac0f3 based on the web app + updated the screenshot in the PR description

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed 1 in 3d4d301

@master-hax
Copy link
Copy Markdown
Contributor Author

the paired auditee list is not explicitly refreshed when a new auditee is added, but onCreate does seem to be called and refresh the list correctly in my testing.

also, my screenshot just shows the same fingerprint multiple times because i only have one auditable device for testing.

realized this was from the recreate() call when the back button is pressed. might need to be updated when delete or rename functionality is added.

Copy link
Copy Markdown
Member

@inthewaves inthewaves left a comment

Choose a reason for hiding this comment

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

Just some UI changes

Comment on lines +79 to +86
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/auditee_list_recycler"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clipToPadding="false"
android:scrollbars="vertical"
android:nestedScrollingEnabled="true"/>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

After thinking about it, I believe we should apply the same left and right margins as everything else (buttons, auditee_list_label, introduction text, etc.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

updated in 5f75e68

Comment on lines +123 to +139
<string name="inspect_auditee_title">inspect auditee</string>
<string name="inspect_auditee_os_provided_info">information from the verified OS</string>
<string name="inspect_auditee_hardware_verified">hardware verified information</string>
<string name="inspect_auditee_attestation_history">attestation history</string>
<string name="inspect_auditee_error_message_missing_fingerprint">auditee fingerprint was not provided</string>

<string name="inspect_auditee_field_name_fingerprint">fingerprint</string>
<string name="inspect_auditee_field_name_pinned_security_level">security level</string>
<string name="inspect_auditee_field_name_pinned_os_version">OS version</string>
<string name="inspect_auditee_field_name_pinned_os_patch_level">OS patch level</string>
<string name="inspect_auditee_field_name_pinned_vendor_patch_level">vendor patch level</string>
<string name="inspect_auditee_field_name_pinned_boot_patch_level">boot patch level</string>
<string name="inspect_auditee_field_name_verified_boot_key">verified boot key</string>
<string name="inspect_auditee_field_name_pinned_app_version">app version</string>
<string name="inspect_auditee_field_name_pinned_app_variant">app variant</string>
<string name="inspect_auditee_field_name_first_verified">first verified</string>
<string name="inspect_auditee_field_name_last_verified">last verified</string>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Think we should capitalize the first words for consistency

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 25, 2026

Choose a reason for hiding this comment

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

do you mean consistency with the web app or the rest of this app?

i personally feel that non-capitalized strings look better in the UI, especially in a table - are there project wide design guidelines for this kind of thing? happy to update it either way.

Copy link
Copy Markdown
Member

@inthewaves inthewaves Feb 25, 2026

Choose a reason for hiding this comment

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

I don't personally have an issue with non-capitalized strings, but I'd say we want to have consistency with the web app/rest of the app

I don't think we have explicit guidelines for design (we do loosely follow Material Design when possible), but the rest of our standalone apps also keep things capitalized. e.g., PdfViewer also has a "table" (constrained by dialog window) of properties:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

updated in b5cdf9b

Comment on lines +53 to +58
runOnUiThread(() -> {
Toast.makeText(
this,
R.string.inspect_auditee_error_message_missing_fingerprint,
Toast.LENGTH_SHORT
).show();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I believe this should be unnecessary; onCreate already runs on the UI/main thread

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed in bdd0634

Comment on lines +68 to +80
addSummaryFieldToTable(R.id.summary_hardware, R.string.inspect_auditee_field_name_fingerprint, fingerprint_hex);
addSummaryFieldToTable(R.id.summary_hardware, R.string.inspect_auditee_field_name_pinned_security_level, String.valueOf(summary.pinnedSecurityLevel()));
addSummaryFieldToTable(R.id.summary_hardware, R.string.inspect_auditee_field_name_pinned_os_version, String.valueOf(summary.pinnedOsVersion()));
addSummaryFieldToTable(R.id.summary_hardware, R.string.inspect_auditee_field_name_pinned_os_patch_level, String.valueOf(summary.pinnedOsPatchLevel()));
addSummaryFieldToTable(R.id.summary_hardware, R.string.inspect_auditee_field_name_pinned_vendor_patch_level, String.valueOf(summary.pinnedVendorPatchLevel()));
addSummaryFieldToTable(R.id.summary_hardware, R.string.inspect_auditee_field_name_pinned_boot_patch_level, String.valueOf(summary.pinnedBootPatchLevel()));
addSummaryFieldToTable(R.id.summary_hardware, R.string.inspect_auditee_field_name_verified_boot_key, summary.verifiedBootKey());

addSummaryFieldToTable(R.id.summary_os, R.string.inspect_auditee_field_name_pinned_app_version, String.valueOf(summary.pinnedAppVersion()));
addSummaryFieldToTable(R.id.summary_os, R.string.inspect_auditee_field_name_pinned_app_variant, String.valueOf(summary.pinnedAppVariant()));

addSummaryFieldToTable(R.id.summary_history, R.string.inspect_auditee_field_name_first_verified, new Date(summary.verifiedTimeFirst()).toString());
addSummaryFieldToTable(R.id.summary_history, R.string.inspect_auditee_field_name_last_verified, new Date(summary.verifiedTimeLast()).toString());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think these fields should have user-readable strings where possible, e.g. security level has various strings handled at appendVerifiedInformation (

private static void appendVerifiedInformation(final Context context,
final StringBuilder builder, final Verified verified, final String fingerprint,
final boolean attestKeyMigration) {
final StringBuilder splitFingerprint = new StringBuilder();
for (int i = 0; i < fingerprint.length(); i += FINGERPRINT_SPLIT_INTERVAL) {
splitFingerprint.append(fingerprint.substring(i,
Math.min(fingerprint.length(), i + FINGERPRINT_SPLIT_INTERVAL)));
if (i + FINGERPRINT_SPLIT_INTERVAL < fingerprint.length()) {
splitFingerprint.append("-");
}
}
builder.append(context.getString(R.string.identity, splitFingerprint.toString()));
final String securityLevel;
if (verified.securityLevel == ParsedAttestationRecord.securityLevelToInt(ParsedAttestationRecord.SecurityLevel.STRONG_BOX)) {
if (verified.attestKey && !attestKeyMigration) {
securityLevel = context.getString(R.string.security_level_strongbox_attest_key);
} else {
securityLevel = context.getString(R.string.security_level_strongbox);
}
} else {
if (verified.attestKey && !attestKeyMigration) {
securityLevel = context.getString(R.string.security_level_tee_attest_key);
} else {
securityLevel = context.getString(R.string.security_level_tee);
}
}
builder.append(context.getString(R.string.security_level, securityLevel));
builder.append(context.getString(R.string.device, context.getString(verified.device)));
builder.append(context.getString(R.string.os, context.getString(verified.osName)));
final String osVersion = String.format(Locale.US, "%06d", verified.osVersion);
builder.append(context.getString(R.string.os_version,
Integer.parseInt(osVersion.substring(0, 2)) + "." +
Integer.parseInt(osVersion.substring(2, 4)) + "." +
Integer.parseInt(osVersion.substring(4, 6))));
builder.append(context.getString(R.string.os_patch_level, formatPatchLevel(verified.osPatchLevel)));
if (verified.vendorPatchLevel != 0) {
builder.append(context.getString(R.string.vendor_patch_level, formatPatchLevel(verified.vendorPatchLevel)));
}
if (verified.bootPatchLevel != 0) {
builder.append(context.getString(R.string.boot_patch_level, formatPatchLevel(verified.bootPatchLevel)));
}
builder.append(context.getString(R.string.verified_boot_key_hash,
verified.verifiedBootKey));
if (verified.verifiedBootHash != null) {
builder.append(context.getString(R.string.verified_boot_hash,
BaseEncoding.base16().encode(verified.verifiedBootHash)));
}
}
), variant is converted to strings at https://github.com/GrapheneOS/Auditor/blob/main/app/src/main/java/app/attestation/auditor/AttestationProtocol.java#L1072-L1115, formatPatchLevel, etc.

Some of these methods for user-readable strings fortunately have static methods for use, but others are embedded in the AttestationProtocol methods and could be refactored for use here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

agree that it is ideal to show the human readable strings - however given that:

  1. we have many other existing display differences with the web app (different fingerprint display format, missing fields not stored in mobile, display of certificate info, etc.)
  2. the current numbers are still useful despite not being fully human readable
  3. we have to fix the history strings to remove the control characters & format specifiers before they can be easily repurposed

is this something we can implement in a future PR? happy to implement it either way.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I agree that cleaning up the rest of the UI code to make it reusable elsewhere/making it consistent can be done in a future PR

Comment on lines +50 to +51
final String fingerprint_hex = getIntent().getStringExtra(INTENT_KEY_FINGERPRINT);
if (fingerprint_hex == null || fingerprint_hex.isBlank()) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: let's use camelCase

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed in e8739cd

Comment on lines +34 to +36
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inspectauditee);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some issues with this activity:

  • Navigation bar can display over the contents
  • Status bar text such as clock, notification icons are not visible in light theme

AttestationActivity should have code that handles this, as this doesn't occur on AttestationActivity

Image

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 25, 2026

Choose a reason for hiding this comment

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

Interesting - good catch. I'm able to reproduce the color issue but not able to reproduce the layout issue on my SM-S928U1 - see screenshots. I think you're right, I missed some compatibility code from AttestationActivity.

EDIT: nm it does avoid my camera cutout & navigation bar after the fix

Screenshot_20260224_210101_Auditor.png

Screenshot_20260224_210421_Auditor.png

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 25, 2026

Choose a reason for hiding this comment

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

color issue is fixed with EdgeToEdge.enable(this); in d33414d

Screenshot_20260224_210738_Auditor.png

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 25, 2026

Choose a reason for hiding this comment

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

fixed insets in 9cb9a12 & e219aaa - it did stop the text from overlaying the camera cutout + buttons simultaneously (when i turned off gestures) do you mind verifying the fix on your side?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

umm for some reason my phone fails to take a screenshot in landscape mode now...

Copy link
Copy Markdown
Contributor Author

@master-hax master-hax Feb 25, 2026

Choose a reason for hiding this comment

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

the auto inset fix method in general seems a little hacky but is probably unavoidable to get good backwards compatibility i guess. i can't deny that it works effectively.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

updated the screenshots in the PR description

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do you mind verifying the fix on your side?

Looks good now

@master-hax
Copy link
Copy Markdown
Contributor Author

cc @inthewaves can we merge this?

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.

3 participants