diff --git a/salesbook.Maui/Core/Interface/IFilePreviewService.cs b/salesbook.Maui/Core/Interface/IFilePreviewService.cs new file mode 100644 index 0000000..1bffb8f --- /dev/null +++ b/salesbook.Maui/Core/Interface/IFilePreviewService.cs @@ -0,0 +1,6 @@ +namespace salesbook.Maui.Core.Interface; + +public interface IFilePreviewService +{ + Task Preview(string fileName, string filePath); +} \ No newline at end of file diff --git a/salesbook.Maui/Core/Services/AttachedService.cs b/salesbook.Maui/Core/Services/AttachedService.cs index 48bce9c..77869c2 100644 --- a/salesbook.Maui/Core/Services/AttachedService.cs +++ b/salesbook.Maui/Core/Services/AttachedService.cs @@ -1,9 +1,10 @@ -using salesbook.Shared.Core.Dto; +using salesbook.Maui.Core.Interface; +using salesbook.Shared.Core.Dto; using salesbook.Shared.Core.Interface; namespace salesbook.Maui.Core.Services; -public class AttachedService : IAttachedService +public class AttachedService(IFilePreviewService filePreviewService) : IAttachedService { public async Task SelectImageFromCamera() { @@ -95,48 +96,34 @@ public class AttachedService : IAttachedService }; } - private static async Task SaveToTempStorage(Stream file, string fileName) + public async Task SaveToTempStorage(Stream file, string fileName, CancellationToken ct = default) { - var cacheDirectory = FileSystem.CacheDirectory; - var targetDirectory = Path.Combine(cacheDirectory, "file"); + ArgumentNullException.ThrowIfNull(file); - if (!Directory.Exists(targetDirectory)) Directory.CreateDirectory(targetDirectory); + if (file.CanSeek) + file.Position = 0; - var tempFilePath = Path.Combine(targetDirectory, fileName + ".temp"); - var filePath = Path.Combine(targetDirectory, fileName); + fileName = Path.GetFileName(fileName); - if (File.Exists(filePath)) return filePath; + var dir = FileSystem.CacheDirectory; + var filePath = Path.Combine(dir, fileName); - try - { - await using var fileStream = - new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None); - await file.CopyToAsync(fileStream); - - File.Move(tempFilePath, filePath); - } - catch (Exception e) - { - Console.WriteLine($"Errore durante il salvataggio dello stream: {e.Message}"); - SentrySdk.CaptureException(e); - return null; - } - finally - { - if (File.Exists(tempFilePath)) File.Delete(tempFilePath); - } + await using var fileStream = File.Create(filePath); + await file.CopyToAsync(fileStream, ct); return filePath; } - public async Task OpenFile(Stream file, string fileName) + public Task OpenFile(string fileName, string filePath) { - var filePath = await SaveToTempStorage(file, fileName); - - if (filePath is null) return; - await Launcher.OpenAsync(new OpenFileRequest +#if IOS + return filePreviewService.Preview(fileName, filePath); +#else + return Launcher.OpenAsync(new OpenFileRequest { + Title = "Apri file", File = new ReadOnlyFile(filePath) }); +#endif } } \ No newline at end of file diff --git a/salesbook.Maui/MauiProgram.cs b/salesbook.Maui/MauiProgram.cs index 7430936..c1f7a00 100644 --- a/salesbook.Maui/MauiProgram.cs +++ b/salesbook.Maui/MauiProgram.cs @@ -5,6 +5,8 @@ using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.Logging; using MudBlazor.Services; using MudExtensions.Services; +using salesbook.Maui.Core; +using salesbook.Maui.Core.Interface; using salesbook.Maui.Core.RestClient.IntegryApi; using salesbook.Maui.Core.Services; using salesbook.Maui.Core.System; @@ -106,6 +108,7 @@ namespace salesbook.Maui builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); _ = typeof(System.Runtime.InteropServices.SafeHandle); _ = typeof(System.IO.FileStream); diff --git a/salesbook.Maui/Platforms/Android/Core/FilePreviewService.cs b/salesbook.Maui/Platforms/Android/Core/FilePreviewService.cs new file mode 100644 index 0000000..748a709 --- /dev/null +++ b/salesbook.Maui/Platforms/Android/Core/FilePreviewService.cs @@ -0,0 +1,11 @@ +using salesbook.Maui.Core.Interface; + +namespace salesbook.Maui.Core; + +public class FilePreviewService :IFilePreviewService +{ + public Task Preview(string fileName, string filePath) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/salesbook.Maui/Platforms/iOS/Core/FilePreviewService.cs b/salesbook.Maui/Platforms/iOS/Core/FilePreviewService.cs new file mode 100644 index 0000000..fe8077f --- /dev/null +++ b/salesbook.Maui/Platforms/iOS/Core/FilePreviewService.cs @@ -0,0 +1,24 @@ +using QuickLook; +using salesbook.Maui.Core.Interface; +using salesbook.Maui.Helpers; +using UIKit; + +namespace salesbook.Maui.Core; + +public class FilePreviewService : IFilePreviewService +{ + public Task Preview(string fileName, string filePath) + { + var currentController = UIApplication.SharedApplication.KeyWindow?.RootViewController; + while (currentController?.PresentedViewController != null) + currentController = currentController.PresentedViewController; + + var currentView = currentController?.View; + var qLPreview = new QLPreviewController(); + var item = new QlPreviewItemBundle(fileName, filePath); + qLPreview.DataSource = new PreviewControllerDs(item); + currentController?.PresentViewController(qLPreview, true, null); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/salesbook.Maui/Platforms/iOS/Helpers/PreviewControllerDs.cs b/salesbook.Maui/Platforms/iOS/Helpers/PreviewControllerDs.cs new file mode 100644 index 0000000..f41746b --- /dev/null +++ b/salesbook.Maui/Platforms/iOS/Helpers/PreviewControllerDs.cs @@ -0,0 +1,16 @@ +using QuickLook; + +namespace salesbook.Maui.Helpers; + +public class PreviewControllerDs(QLPreviewItem item) : QLPreviewControllerDataSource +{ + public override nint PreviewItemCount(QLPreviewController controller) + { + return 1; + } + + public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index) + { + return item; + } +} \ No newline at end of file diff --git a/salesbook.Maui/Platforms/iOS/Helpers/QlPreviewItemBundle.cs b/salesbook.Maui/Platforms/iOS/Helpers/QlPreviewItemBundle.cs new file mode 100644 index 0000000..e9fd8b4 --- /dev/null +++ b/salesbook.Maui/Platforms/iOS/Helpers/QlPreviewItemBundle.cs @@ -0,0 +1,19 @@ +using Foundation; +using QuickLook; + +namespace salesbook.Maui.Helpers; + +public class QlPreviewItemBundle(string fileName, string filePath) : QLPreviewItem +{ + public override string PreviewItemTitle => fileName; + public override NSUrl PreviewItemUrl + { + get + { + var documents = NSBundle.MainBundle.BundlePath; + var lib = Path.Combine(documents, filePath); + var url = NSUrl.FromFilename(lib); + return url; + } + } +} \ No newline at end of file diff --git a/salesbook.Maui/Platforms/iOS/Helpers/QlPreviewItemFileSystem.cs b/salesbook.Maui/Platforms/iOS/Helpers/QlPreviewItemFileSystem.cs new file mode 100644 index 0000000..8cea0d5 --- /dev/null +++ b/salesbook.Maui/Platforms/iOS/Helpers/QlPreviewItemFileSystem.cs @@ -0,0 +1,12 @@ +using Foundation; +using QuickLook; + +namespace salesbook.Maui.Helpers; + +public class QlPreviewItemFileSystem(string fileName, string filePath) : QLPreviewItem +{ + public override string PreviewItemTitle => fileName; + + public override NSUrl PreviewItemUrl => NSUrl.FromString(filePath); + +} \ No newline at end of file diff --git a/salesbook.Maui/salesbook.Maui.csproj b/salesbook.Maui/salesbook.Maui.csproj index 1644777..2ffb8cb 100644 --- a/salesbook.Maui/salesbook.Maui.csproj +++ b/salesbook.Maui/salesbook.Maui.csproj @@ -156,7 +156,7 @@ - + diff --git a/salesbook.Shared/Components/Pages/Commessa.razor.css b/salesbook.Shared/Components/Pages/Commessa.razor.css index 820e906..7fda9e3 100644 --- a/salesbook.Shared/Components/Pages/Commessa.razor.css +++ b/salesbook.Shared/Components/Pages/Commessa.razor.css @@ -121,6 +121,7 @@ background: var(--light-card-background); border-radius: 16px; overflow: clip; + min-height: 45px; margin-bottom: 1rem; } diff --git a/salesbook.Shared/Components/Pages/User.razor b/salesbook.Shared/Components/Pages/User.razor index 9cb1386..3bb732c 100644 --- a/salesbook.Shared/Components/Pages/User.razor +++ b/salesbook.Shared/Components/Pages/User.razor @@ -274,9 +274,9 @@ else - - - + @* *@ + @* *@ + @* *@ } diff --git a/salesbook.Shared/Components/Pages/Users.razor b/salesbook.Shared/Components/Pages/Users.razor index 610d3c7..adc2a1f 100644 --- a/salesbook.Shared/Components/Pages/Users.razor +++ b/salesbook.Shared/Components/Pages/Users.razor @@ -170,6 +170,7 @@ var matchesText = (!string.IsNullOrEmpty(user.RagSoc) && user.RagSoc.Contains(filter, StringComparison.OrdinalIgnoreCase)) || + (!string.IsNullOrEmpty(user.CodContact) && user.CodContact.Contains(filter, StringComparison.OrdinalIgnoreCase)) || (!string.IsNullOrEmpty(user.Indirizzo) && user.Indirizzo.Contains(filter, StringComparison.OrdinalIgnoreCase)) || (!string.IsNullOrEmpty(user.Telefono) && user.Telefono.Contains(filter, StringComparison.OrdinalIgnoreCase)) || (!string.IsNullOrEmpty(user.EMail) && user.EMail.Contains(filter, StringComparison.OrdinalIgnoreCase)) || diff --git a/salesbook.Shared/Components/SingleElements/Card/AttachCard.razor b/salesbook.Shared/Components/SingleElements/Card/AttachCard.razor index 3d0d085..4b4a20b 100644 --- a/salesbook.Shared/Components/SingleElements/Card/AttachCard.razor +++ b/salesbook.Shared/Components/SingleElements/Card/AttachCard.razor @@ -1,3 +1,4 @@ +@using salesbook.Shared.Components.Layout.Spinner @using salesbook.Shared.Core.Dto @using salesbook.Shared.Core.Interface @using salesbook.Shared.Core.Interface.IntegryApi @@ -34,12 +35,24 @@ + + @code { [Parameter] public CRMAttachedResponseDTO Attached { get; set; } = new(); + + private bool VisibleOverlay { get; set; } private async Task OpenAttached() { - var bytes = await IntegryApiService.DownloadFileFromRefUuid(Attached.RefUuid, Attached.FileName); - await AttachedService.OpenFile(bytes, Attached.FileName); + VisibleOverlay = true; + StateHasChanged(); + + await using var file = await IntegryApiService.DownloadFileFromRefUuid(Attached.RefUuid, Attached.FileName); + var path = await AttachedService.SaveToTempStorage(file, Attached.FileName); + + VisibleOverlay = false; + StateHasChanged(); + + await AttachedService.OpenFile(Attached.FileName, path); } } \ No newline at end of file diff --git a/salesbook.Shared/Components/SingleElements/Modal/ActivityForm.razor b/salesbook.Shared/Components/SingleElements/Modal/ActivityForm.razor index 7811692..524e5c8 100644 --- a/salesbook.Shared/Components/SingleElements/Modal/ActivityForm.razor +++ b/salesbook.Shared/Components/SingleElements/Modal/ActivityForm.razor @@ -2,6 +2,7 @@ @using CommunityToolkit.Mvvm.Messaging @using salesbook.Shared.Components.Layout @using salesbook.Shared.Components.Layout.Overlay +@using salesbook.Shared.Components.Layout.Spinner @using salesbook.Shared.Components.SingleElements.BottomSheet @using salesbook.Shared.Core.Dto @using salesbook.Shared.Core.Dto.Activity @@ -235,7 +236,7 @@ { foreach (var file in ActivityFileList) { - @file.FileName @@ -304,6 +305,8 @@ + + @@ -332,8 +335,9 @@ private string? LabelSave { get; set; } - //Overlay for save + //Overlay private bool VisibleOverlay { get; set; } + private bool VisibleLoadingOverlay { get; set; } private bool SuccessAnimation { get; set; } private bool OpenEsito { get; set; } @@ -770,15 +774,29 @@ StateHasChanged(); } - private async Task OpenAttached(string idAttached, string fileName) + private async Task OpenAttached(string fileName) { try { - var bytes = await IntegryApiService.DownloadFile(ActivityModel.ActivityId!, fileName); - await AttachedService.OpenFile(bytes, fileName); + VisibleOverlay = true; + StateHasChanged(); + + await using var file = await IntegryApiService.DownloadFile(ActivityModel.ActivityId!, fileName); + var path = await AttachedService.SaveToTempStorage(file, fileName); + + VisibleOverlay = false; + StateHasChanged(); + + await AttachedService.OpenFile(fileName, path); } catch (Exception ex) { + if (VisibleOverlay) + { + VisibleOverlay = false; + StateHasChanged(); + } + Snackbar.Clear(); Snackbar.Add("Impossibile aprire il file", Severity.Error); Console.WriteLine($"Errore durante l'apertura del file: {ex.Message}"); @@ -789,7 +807,15 @@ { if (attached is { FileContent: not null, MimeType: not null }) { - await AttachedService.OpenFile(attached.FileContent!, attached.Name); + VisibleOverlay = true; + StateHasChanged(); + + var path = await AttachedService.SaveToTempStorage(attached.FileContent!, attached.Name); + + VisibleOverlay = false; + StateHasChanged(); + + await AttachedService.OpenFile(attached.Name, path); } else { diff --git a/salesbook.Shared/Core/Interface/IAttachedService.cs b/salesbook.Shared/Core/Interface/IAttachedService.cs index bc267bc..dde3438 100644 --- a/salesbook.Shared/Core/Interface/IAttachedService.cs +++ b/salesbook.Shared/Core/Interface/IAttachedService.cs @@ -8,5 +8,7 @@ public interface IAttachedService Task SelectImageFromGallery(); Task SelectFile(); Task SelectPosition(); - Task OpenFile(Stream file, string fileName); + + Task SaveToTempStorage(Stream file, string fileName, CancellationToken ct = default); + Task OpenFile(string fileName, string filePath); } \ No newline at end of file diff --git a/salesbook.Shared/salesbook.Shared.csproj b/salesbook.Shared/salesbook.Shared.csproj index 7c001bc..71281be 100644 --- a/salesbook.Shared/salesbook.Shared.csproj +++ b/salesbook.Shared/salesbook.Shared.csproj @@ -24,7 +24,7 @@ - + diff --git a/salesbook.Web/salesbook.Web.csproj b/salesbook.Web/salesbook.Web.csproj index d335db5..db45543 100644 --- a/salesbook.Web/salesbook.Web.csproj +++ b/salesbook.Web/salesbook.Web.csproj @@ -16,7 +16,7 @@ - +