From 833a1e456f6972479ca14cfdddd5ceca4a3c1170 Mon Sep 17 00:00:00 2001 From: MarcoE Date: Mon, 25 Aug 2025 10:00:41 +0200 Subject: [PATCH] Iniziata implementazione notifiche firebase --- .../IntegryApi/Dto/RegisterDeviceDTO.cs | 10 +++++ .../IntegryApi/Dto/WtbUserDeviceTokenDTO.cs | 22 +++++++++++ .../IntegryNotificationRestClient.cs | 38 +++++++++++++++++++ .../Network}/NetworkService.cs | 2 +- .../FirebaseNotificationService.cs | 16 ++++++++ .../Push/PushNotificationDelegate.cs | 31 +++++++++++++++ salesbook.Maui/GoogleService-Info.plist | 30 +++++++++++++++ salesbook.Maui/MauiProgram.cs | 11 ++++++ .../Platforms/Android/AndroidManifest.xml | 11 +++++- .../Platforms/Android/MainActivity.cs | 6 +++ salesbook.Maui/Platforms/iOS/Info.plist | 4 ++ salesbook.Maui/google-services.json | 29 ++++++++++++++ salesbook.Maui/salesbook.Maui.csproj | 12 ++++++ salesbook.Shared/Components/Pages/Home.razor | 10 +++++ .../Interface/IFirebaseNotificationService.cs | 6 +++ .../IIntegryNotificationRestClient.cs | 8 ++++ 16 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 salesbook.Maui/Core/RestClient/IntegryApi/Dto/RegisterDeviceDTO.cs create mode 100644 salesbook.Maui/Core/RestClient/IntegryApi/Dto/WtbUserDeviceTokenDTO.cs create mode 100644 salesbook.Maui/Core/RestClient/IntegryApi/IntegryNotificationRestClient.cs rename salesbook.Maui/Core/{Services => System/Network}/NetworkService.cs (82%) create mode 100644 salesbook.Maui/Core/System/Notification/FirebaseNotificationService.cs create mode 100644 salesbook.Maui/Core/System/Notification/Push/PushNotificationDelegate.cs create mode 100644 salesbook.Maui/GoogleService-Info.plist create mode 100644 salesbook.Maui/google-services.json create mode 100644 salesbook.Shared/Core/Interface/IFirebaseNotificationService.cs create mode 100644 salesbook.Shared/Core/Interface/IIntegryNotificationRestClient.cs diff --git a/salesbook.Maui/Core/RestClient/IntegryApi/Dto/RegisterDeviceDTO.cs b/salesbook.Maui/Core/RestClient/IntegryApi/Dto/RegisterDeviceDTO.cs new file mode 100644 index 0000000..fc7c01d --- /dev/null +++ b/salesbook.Maui/Core/RestClient/IntegryApi/Dto/RegisterDeviceDTO.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; + +namespace salesbook.Maui.Core.RestClient.IntegryApi.Dto; + +public class RegisterDeviceDTO +{ + [JsonPropertyName("userDeviceToken")] + public WtbUserDeviceTokenDTO UserDeviceToken { get; set; } + +} \ No newline at end of file diff --git a/salesbook.Maui/Core/RestClient/IntegryApi/Dto/WtbUserDeviceTokenDTO.cs b/salesbook.Maui/Core/RestClient/IntegryApi/Dto/WtbUserDeviceTokenDTO.cs new file mode 100644 index 0000000..136bd4e --- /dev/null +++ b/salesbook.Maui/Core/RestClient/IntegryApi/Dto/WtbUserDeviceTokenDTO.cs @@ -0,0 +1,22 @@ +using System.Text.Json.Serialization; + +namespace salesbook.Maui.Core.RestClient.IntegryApi.Dto; + +public class WtbUserDeviceTokenDTO +{ + [JsonPropertyName("type")] + public string Type => "wtb_user_device_tokens"; + + [JsonPropertyName("deviceToken")] + public string DeviceToken { get; set; } + + [JsonPropertyName("userName")] + public string Username { get; set; } + + [JsonPropertyName("appName")] + public int AppName => 7; //salesbook + + [JsonPropertyName("platform")] + public string Platform { get; set; } + +} \ No newline at end of file diff --git a/salesbook.Maui/Core/RestClient/IntegryApi/IntegryNotificationRestClient.cs b/salesbook.Maui/Core/RestClient/IntegryApi/IntegryNotificationRestClient.cs new file mode 100644 index 0000000..d18ff4c --- /dev/null +++ b/salesbook.Maui/Core/RestClient/IntegryApi/IntegryNotificationRestClient.cs @@ -0,0 +1,38 @@ +using IntegryApiClient.Core.Domain.Abstraction.Contracts.Account; +using IntegryApiClient.Core.Domain.RestClient.Contacts; +using Microsoft.Extensions.Logging; +using salesbook.Maui.Core.RestClient.IntegryApi.Dto; +using salesbook.Shared.Core.Interface; + +namespace salesbook.Maui.Core.RestClient.IntegryApi; + +public class IntegryNotificationRestClient( + ILogger logger, + IUserSession userSession, + IIntegryApiRestClient integryApiRestClient +) : IIntegryNotificationRestClient +{ + public async Task Register(string fcmToken, ILogger? logger1 = null) + { + logger1 ??= logger; + + var userDeviceToken = new RegisterDeviceDTO() + { + UserDeviceToken = new WtbUserDeviceTokenDTO() + { + DeviceToken = fcmToken, + Platform = OperatingSystem.IsAndroid() ? "Android" : "iOS", + Username = userSession.User.Username + } + }; + try + { + await integryApiRestClient.AuthorizedPost($"device_tokens/insert", userDeviceToken, + logger: logger1); + } + catch (Exception ex) + { + SentrySdk.CaptureException(ex); + } + } +} \ No newline at end of file diff --git a/salesbook.Maui/Core/Services/NetworkService.cs b/salesbook.Maui/Core/System/Network/NetworkService.cs similarity index 82% rename from salesbook.Maui/Core/Services/NetworkService.cs rename to salesbook.Maui/Core/System/Network/NetworkService.cs index 31a45b0..7fb8b96 100644 --- a/salesbook.Maui/Core/Services/NetworkService.cs +++ b/salesbook.Maui/Core/System/Network/NetworkService.cs @@ -1,6 +1,6 @@ using salesbook.Shared.Core.Interface; -namespace salesbook.Maui.Core.Services; +namespace salesbook.Maui.Core.System.Network; public class NetworkService : INetworkService { diff --git a/salesbook.Maui/Core/System/Notification/FirebaseNotificationService.cs b/salesbook.Maui/Core/System/Notification/FirebaseNotificationService.cs new file mode 100644 index 0000000..e0b7c28 --- /dev/null +++ b/salesbook.Maui/Core/System/Notification/FirebaseNotificationService.cs @@ -0,0 +1,16 @@ +using salesbook.Shared.Core.Interface; +using Shiny; +using Shiny.Push; + +namespace salesbook.Maui.Core.System.Notification; + +public class FirebaseNotificationService(IPushManager pushManager, IIntegryNotificationRestClient integryNotificationRestClient) : IFirebaseNotificationService +{ + public async Task InitFirebase() + { + var (accessState, token) = await pushManager.RequestAccess(); + + if (accessState == AccessState.Denied || token is null) return; + await integryNotificationRestClient.Register(token); + } +} \ No newline at end of file diff --git a/salesbook.Maui/Core/System/Notification/Push/PushNotificationDelegate.cs b/salesbook.Maui/Core/System/Notification/Push/PushNotificationDelegate.cs new file mode 100644 index 0000000..14cf03d --- /dev/null +++ b/salesbook.Maui/Core/System/Notification/Push/PushNotificationDelegate.cs @@ -0,0 +1,31 @@ +using Shiny.Push; + +namespace salesbook.Maui.Core.System.Notification.Push; + +public class PushNotificationDelegate : IPushDelegate +{ + public Task OnEntry(PushNotification notification) + { + // fires when the user taps on a push notification + return Task.CompletedTask; + } + + public Task OnReceived(PushNotification notification) + { + // fires when a push notification is received (silient or notification) + //notification.Data["content-available"] = "1"; + return Task.CompletedTask; + } + + public Task OnNewToken(string token) + { + // fires when a push notification change is set by the operating system or provider + return Task.CompletedTask; + } + + public Task OnUnRegistered(string token) + { + // fires when a push notification change is set by the operating system or provider + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/salesbook.Maui/GoogleService-Info.plist b/salesbook.Maui/GoogleService-Info.plist new file mode 100644 index 0000000..4ed039f --- /dev/null +++ b/salesbook.Maui/GoogleService-Info.plist @@ -0,0 +1,30 @@ + + + + + API_KEY + AIzaSyC_QtQpsVortjzgl-B7__IQZ-85lOct55E + GCM_SENDER_ID + 830771692001 + PLIST_VERSION + 1 + BUNDLE_ID + it.integry.salesbook + PROJECT_ID + salesbook-smetar + STORAGE_BUCKET + salesbook-smetar.firebasestorage.app + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:830771692001:ios:59d8b1d8570ac81f3752a0 + + \ No newline at end of file diff --git a/salesbook.Maui/MauiProgram.cs b/salesbook.Maui/MauiProgram.cs index 2b3aa2a..c4d0361 100644 --- a/salesbook.Maui/MauiProgram.cs +++ b/salesbook.Maui/MauiProgram.cs @@ -6,7 +6,11 @@ using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.Logging; using MudBlazor.Services; using MudExtensions.Services; +using salesbook.Maui.Core.RestClient.IntegryApi; using salesbook.Maui.Core.Services; +using salesbook.Maui.Core.System.Network; +using salesbook.Maui.Core.System.Notification; +using salesbook.Maui.Core.System.Notification.Push; using salesbook.Shared; using salesbook.Shared.Core.Dto; using salesbook.Shared.Core.Helpers; @@ -16,6 +20,7 @@ using salesbook.Shared.Core.Messages.Activity.New; using salesbook.Shared.Core.Messages.Back; using salesbook.Shared.Core.Messages.Contact; using salesbook.Shared.Core.Services; +using Shiny; namespace salesbook.Maui { @@ -64,6 +69,12 @@ namespace salesbook.Maui builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + + //Notification + builder.Services.AddNotifications(); + builder.Services.AddPush(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); #if DEBUG builder.Services.AddBlazorWebViewDeveloperTools(); diff --git a/salesbook.Maui/Platforms/Android/AndroidManifest.xml b/salesbook.Maui/Platforms/Android/AndroidManifest.xml index ddb278b..a8b23a0 100644 --- a/salesbook.Maui/Platforms/Android/AndroidManifest.xml +++ b/salesbook.Maui/Platforms/Android/AndroidManifest.xml @@ -1,6 +1,15 @@  - + + + + + + + + + + diff --git a/salesbook.Maui/Platforms/Android/MainActivity.cs b/salesbook.Maui/Platforms/Android/MainActivity.cs index 1c93fe9..75ed53c 100644 --- a/salesbook.Maui/Platforms/Android/MainActivity.cs +++ b/salesbook.Maui/Platforms/Android/MainActivity.cs @@ -7,6 +7,12 @@ namespace salesbook.Maui MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] + [IntentFilter([Shiny.ShinyPushIntents.NotificationClickAction], + Categories = new[] + { + "android.intent.category.DEFAULT" + } + )] public class MainActivity : MauiAppCompatActivity { } diff --git a/salesbook.Maui/Platforms/iOS/Info.plist b/salesbook.Maui/Platforms/iOS/Info.plist index a094b3e..0c883a2 100644 --- a/salesbook.Maui/Platforms/iOS/Info.plist +++ b/salesbook.Maui/Platforms/iOS/Info.plist @@ -45,5 +45,9 @@ NSPhotoLibraryAddUsageDescription Permette all'app di salvare file o immagini nella tua libreria fotografica se necessario. + UIBackgroundModes + + remote-notification + diff --git a/salesbook.Maui/google-services.json b/salesbook.Maui/google-services.json new file mode 100644 index 0000000..ef98865 --- /dev/null +++ b/salesbook.Maui/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "830771692001", + "project_id": "salesbook-smetar", + "storage_bucket": "salesbook-smetar.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:830771692001:android:06bc5a9706bc9bef3752a0", + "android_client_info": { + "package_name": "it.integry.salesbook" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyB43ai_Ph0phO_OkBC1wAOazKZUV9KsLaM" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/salesbook.Maui/salesbook.Maui.csproj b/salesbook.Maui/salesbook.Maui.csproj index 4c87907..3120900 100644 --- a/salesbook.Maui/salesbook.Maui.csproj +++ b/salesbook.Maui/salesbook.Maui.csproj @@ -93,6 +93,16 @@ --> + + + PreserveNewest + + + + + + + @@ -128,6 +138,8 @@ + + diff --git a/salesbook.Shared/Components/Pages/Home.razor b/salesbook.Shared/Components/Pages/Home.razor index 6e62825..190c941 100644 --- a/salesbook.Shared/Components/Pages/Home.razor +++ b/salesbook.Shared/Components/Pages/Home.razor @@ -4,6 +4,7 @@ @using salesbook.Shared.Components.Layout.Spinner @inject IFormFactor FormFactor @inject INetworkService NetworkService +@inject IFirebaseNotificationService FirebaseNotificationService @@ -11,6 +12,15 @@ { protected override async Task OnInitializedAsync() { + try + { + await FirebaseNotificationService.InitFirebase(); + } + catch (Exception e) + { + Console.WriteLine($"Firebase init: {e.Message}"); + } + var lastSyncDate = LocalStorage.Get("last-sync"); if (!FormFactor.IsWeb() && NetworkService.IsNetworkAvailable() && lastSyncDate.Equals(DateTime.MinValue)) diff --git a/salesbook.Shared/Core/Interface/IFirebaseNotificationService.cs b/salesbook.Shared/Core/Interface/IFirebaseNotificationService.cs new file mode 100644 index 0000000..47c6707 --- /dev/null +++ b/salesbook.Shared/Core/Interface/IFirebaseNotificationService.cs @@ -0,0 +1,6 @@ +namespace salesbook.Shared.Core.Interface; + +public interface IFirebaseNotificationService +{ + Task InitFirebase(); +} \ No newline at end of file diff --git a/salesbook.Shared/Core/Interface/IIntegryNotificationRestClient.cs b/salesbook.Shared/Core/Interface/IIntegryNotificationRestClient.cs new file mode 100644 index 0000000..7eef3df --- /dev/null +++ b/salesbook.Shared/Core/Interface/IIntegryNotificationRestClient.cs @@ -0,0 +1,8 @@ +using Microsoft.Extensions.Logging; + +namespace salesbook.Shared.Core.Interface; + +public interface IIntegryNotificationRestClient +{ + Task Register(string fcmToken, ILogger? logger1 = null); +} \ No newline at end of file