feat: send silent settings_changed FCM push on assignedSite update - #1689
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ssignedSite Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds a silent (data-only) FCM push ({ type: settings_changed }) when an assigned site is updated, so the Flutter time app can auto-refresh personal-mode settings without a visible notification.
Changes:
- Injects
IPushNotificationServiceintoTimeSettingServiceand triggers asettings_changedpush duringUpdateAssignedSite. - Adds
PushNotificationService.BuildMessage(...)to support data-only pushes (noNotificationpayload, sets iOScontent-available). - Extends test coverage for the new silent-push behavior and ensures settings updates still succeed if push sending fails.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| eFormAPI/Plugins/TimePlanning.Pn/TimePlanning.Pn/Services/TimePlanningSettingService/TimeSettingService.cs | Sends a settings_changed silent push during assigned-site updates. |
| eFormAPI/Plugins/TimePlanning.Pn/TimePlanning.Pn/Services/PushNotificationService/PushNotificationService.cs | Adds message builder supporting data-only (silent) FCM sends and uses it from SendToSiteAsync. |
| eFormAPI/Plugins/TimePlanning.Pn/TimePlanning.Pn.Test/SettingsServiceTests.cs | Adds push-service substitution and a test ensuring update succeeds even if the push task faults. |
| eFormAPI/Plugins/TimePlanning.Pn/TimePlanning.Pn.Test/SettingsServicePhoneNumberTests.cs | Updates TimeSettingService construction to provide IPushNotificationService. |
| eFormAPI/Plugins/TimePlanning.Pn/TimePlanning.Pn.Test/SettingsServiceExtendedTests.cs | Updates TimeSettingService construction to provide IPushNotificationService. |
| eFormAPI/Plugins/TimePlanning.Pn/TimePlanning.Pn.Test/PushNotificationServiceTests.cs | Adds unit tests validating silent vs visible message construction. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+1082
to
+1092
| // Fire-and-forget: tell the worker's device(s) that their assigned-site | ||
| // settings changed so personal mode can auto-refresh. Sent AFTER the row | ||
| // is committed; a push failure must NEVER fail the settings update. | ||
| try | ||
| { | ||
| await pushNotificationService.SendToSiteAsync( | ||
| dbAssignedSite.SiteId, | ||
| title: "", | ||
| body: "", | ||
| data: new Dictionary<string, string> { { "type", "settings_changed" } }); | ||
| } |
Bump Microting.TimePlanningBase 10.0.57 -> 10.0.58 (adds the AppBuildNumber column to DeviceToken). Repurpose device_token.proto field 3 from the long-ignored sdk_site_id to int32 build_number, matching the flutter-time client so the wire stays identical. The C# gRPC stub regenerates at build via the existing <Protobuf> item. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Thread the client-reported build number from the gRPC handler through RegisterForCallerAsync/RegisterAsync and set deviceToken.AppBuildNumber on BOTH the create and the update (re-register) branches, so a re-register refreshes the stored build number. The param defaults to 0 (old/unknown client). Tests: persists build number on create, refreshes it on re-register, and stores 0 when the client omits it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add an optional minBuild param to SendToSiteAsync (interface + impl) and filter DeviceTokens by AppBuildNumber >= minBuild. Default 0 includes every device, so existing callers (absence-request / content-handover notification pushes) are unaffected. UpdateAssignedSite now passes minBuild: MinSettingsChangedPushBuild (31221) — the first flutter-time build that both sends build_number and handles the settings_changed silent push. Older installs report 0 and are excluded to avoid a stray notification. The token-selection query is extracted to an internal ResolveTargetTokensAsync seam so the filter is unit-testable (Firebase is not configured in tests, so SendToSiteAsync itself short-circuits). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the fully-qualified DeviceToken return type on ResolveTargetTokensAsync with a using alias (the plain namespace import clashes with FirebaseAdmin.Messaging.Message), and factor the repeated PushNotificationService construction in the tests into a CreateService helper. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
On
UpdateAssignedSite, fire a fire-and-forget data-only FCM message{type: settings_changed}to the site's devices so the flutter-time app auto-refreshes its personal-mode settings.SendToSiteAsyncgains data-only (silent) support: it omits the Notification payload and sets iOScontent-availableso the message is delivered silently.Notes:
Pairs with the flutter-time client PR.