Redesign push testing pages and store APNs .p8 keys in secret providers - #261
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved send validation, dirty-state, secret-readiness, metadata, and provider-synchronization issues block approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Redesigns APNs and FCM push-testing pages and adds managed APNs .p8 secret-provider support.
Changes:
- Adds shared previews, JSON editors, history, and project controls.
- Supports APNs key import, selection, metadata, and synchronization.
- Adds configurable secret-picker actions and operation cancellation.
File summaries
| File | Description |
|---|---|
src/MauiSherpa/wwwroot/index.html |
Loads shared push-testing styles. |
src/MauiSherpa/wwwroot/css/pushTesting.css |
Defines shared push UI styling. |
src/MauiSherpa/Pages/PushTesting.razor |
Redesigns APNs testing and secret handling. |
src/MauiSherpa/Pages/Modals/SecretPickerPage.cs |
Supports customizable picker titles and buttons. |
src/MauiSherpa/Pages/FirebasePush.razor |
Redesigns FCM testing and previews. |
src/MauiSherpa/Components/PushProjectBar.razor |
Adds redesigned project controls. |
src/MauiSherpa/Components/PushNotificationPreview.razor |
Adds device notification previews. |
src/MauiSherpa/Components/PushJsonEditor.razor |
Adds JSON validation and formatting. |
src/MauiSherpa/Components/PushHistoryList.razor |
Adds shared send-history rendering. |
src/MauiSherpa.Core/Interfaces.cs |
Adds cancellation API and APNs secret configuration. |
Review details
Suppressed comments (3)
src/MauiSherpa/Components/PushJsonEditor.razor:30
- This textarea has no associated label or
aria-label; the visible filename in the toolbar is not programmatically associated with it. Both push pages therefore expose an unnamed multiline editor to screen readers. Add an accessible label to the editor.
<textarea class="push-json-input" rows="@Rows" spellcheck="false" placeholder="@Placeholder"
value="@Value" @oninput="OnInput"></textarea>
src/MauiSherpa/Pages/PushTesting.razor:363
- In the new
secretmode this only checks the configured secret name and Key ID. A deleted or unreadable provider copy still marks the signing-key checklist as complete and enables Send;SendPushthen discovers the missing value inGetValueAsyncand fails only after the click. Track secret availability or make readiness asynchronous so the checklist and button reflect whether the key can actually be read.
bool HasSigningKey => authMode switch
{
"identity" => !string.IsNullOrWhiteSpace(selectedIdentityId),
"secret" => !string.IsNullOrWhiteSpace(p8SecretKey) && !string.IsNullOrWhiteSpace(p8KeyId),
_ => !string.IsNullOrWhiteSpace(p8FilePath) && !string.IsNullOrWhiteSpace(p8KeyId)
};
src/MauiSherpa/Pages/PushTesting.razor:644
- When the selected secret has neither APNs metadata nor an
AuthKey_...filename, these branches leave the previousp8KeyIdandteamIdunchanged. Switching from key A to such a secret can then pair the new key material with stale credentials, which APNs rejects. Clear each field when it cannot be derived so the checklist forces the user to supply matching values.
p8KeyId = storedKeyId;
else if (KeyIdFromFileName(selected.OriginalFileName ?? selected.Key) is { } parsedKeyId)
p8KeyId = parsedKeyId;
if (selected.Metadata?.TryGetValue(ApnsTeamIdMetadata, out var storedTeamId) == true && !string.IsNullOrWhiteSpace(storedTeamId))
teamId = storedTeamId;
- Files reviewed: 10/10 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+26
to
+30
| @if (IsDirty) | ||
| { | ||
| <span class="push-unsaved"><span class="push-unsaved-dot"></span> Unsaved</span> | ||
| } | ||
| <button class="btn btn-sm @(IsDirty ? "btn-primary" : "btn-secondary")" @onclick="HandleSave" title="Save project"> |
Comment on lines
+241
to
+244
| bool HasRawJson => !string.IsNullOrWhiteSpace(rawJson); | ||
|
|
||
| bool CanSend => hasCredentials && HasTarget && HasContent; | ||
| bool CanSendCurrent => rawJsonMode ? hasCredentials && HasRawJson : CanSend; |
| bool HasTeamId => !string.IsNullOrWhiteSpace(teamId); | ||
| bool HasBundleId => !string.IsNullOrWhiteSpace(bundleId); | ||
| bool HasDeviceToken => !string.IsNullOrWhiteSpace(deviceToken); | ||
| bool HasPayload => !string.IsNullOrWhiteSpace(jsonPayload); |
Comment on lines
+703
to
+707
| stored = await SecretsService.CreateAsync(secretKey, bytes, ManagedSecretType.File, description, fileName, metadata); | ||
| if (stored) | ||
| await SecretSyncCoordinator.SetDefaultProvidersAsync( | ||
| new SecretItemRef(SecretItemKind.ManagedSecret, secretKey, fileName)); | ||
| } |
Redth
force-pushed
the
aritchie/push-refresh
branch
from
September 21, 2026 12:38
0b0f783 to
51d1ac4
Compare
Restyle the APNs and Firebase push pages to match the rest of the app: Settings-style sections, segmented controls, a sticky notification preview and send checklist, a JSON editor with validation and payload size, and a shared send history list. Shared styles move to pushTesting.css. Add a "Secret provider" key source for APNs: import a .p8 as a managed File secret (synced to default providers), choose an existing one, or move a file-based key into providers. The key is read from providers at send time and the project stores its secret key in P8SecretKey. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LMQybcsC24APNz8Vfhbbhw
Redth
force-pushed
the
aritchie/push-refresh
branch
from
September 22, 2026 19:12
51d1ac4 to
efbe5d4
Compare
Redth
added this pull request to stack #268
September 22, 2026 20:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Redesigns the Apple (APNs) and Firebase (FCM) push testing pages to match the rest of the app, and adds the ability to store APNs
.p8auth keys in secret providers.Push testing redesign
<select>that rendered blank.wwwroot/css/pushTesting.css; new components:PushJsonEditor,PushNotificationPreview,PushHistoryList.APNs
.p8keys in secret providersapns/<file name>withapnsKeyId/apnsTeamIdmetadata; it goes to the active provider and is synced to default providers viaISecretSyncCoordinator, so it also appears on the Secrets page.SecretPickerPage(now takes an optional title/button text; defaults unchanged) filtered to.p8keys, and fills in Key ID/Team ID.SecretProviderPickerHostcontrols which providers hold the key.IManagedSecretsService.GetValueAsync, which checks every provider.ApnsPushProjectConfiggains a nullableP8SecretKey; existing projects load unchanged.Build fix
maindidn't compile:XcodeManagement.razor(from #247) callsIOperationModalService.RequestCancellation(), which only existed on the concrete service. The first commit adds it to the interface;OperationModalServiceis the only implementer.Testing
dotnet build src/MauiSherpa.MacOS -f net10.0-macossucceeds.dotnet test tests/MauiSherpa.Core.Tests: 592 passed, 0 failed.Not verified yet:
🤖 Generated with Claude Code
https://claude.ai/code/session_01LMQybcsC24APNz8Vfhbbhw