15 Commits
Author SHA1 Message Date
MarcoE c57df2cbb7 Finish v1.2.5(11) 2026-11-04 15:53:55 +01:00
MarcoE e5cf4215f6 -> v1.2.5 (11) 2026-11-04 15:53:51 +01:00
MarcoEandClaude Opus 5.5 c4c624667d Permette di eliminare le foto di una scheda anche dopo il salvataggio
Finora la foto si poteva togliere solo prima di salvare la scheda.

- La X compare su tutte le foto (non in sola lettura, non mentre la foto e'
  ancora in elaborazione). L'eliminazione avviene al salvataggio: uscendo
  senza salvare le foto restano.
- Una foto gia' inviata si toglie prima dal server (nuovo endpoint
  steup/removeAttachment), poi dal dispositivo e da Scheda.ImageNames. Senza
  rete la X avvisa e non la toglie; se il server non conferma al salvataggio
  la foto resta ovunque e compare un avviso.
- Una foto salvata ma non ancora inviata si elimina dal dispositivo (con la
  rete si prova anche a toglierla dal server, senza bloccare).
- Togliere una foto salvata non la cancellava mai: il flag ToRemove finiva
  su un elemento appena rimosso dall'elenco. Ora le foto tolte stanno in una
  lista a parte fino al salvataggio; ToRemove e' stato eliminato.
- FileManager.GetInspectionFiles: le foto in /toUpload si filtravano per
  nome, ma ImageNames contiene il percorso completo, quindi quelle salvate
  senza rete non ricomparivano mai riaprendo la scheda. Ora si accetta sia il
  percorso sia il nome, e il DTO porta anche i byte del file per l'invio.

Richiede i Servizi con steup/removeAttachment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 13:39:31 +01:00
MarcoE df827216c3 Finish v1.2.4(10) 2026-10-29 15:48:01 +01:00
MarcoE b2db0f2479 Finish v1.2.4(10) 2026-10-29 15:48:01 +01:00
MarcoE 817cd606b6 -> 1.2.4 (10) 2026-10-29 15:48:01 +01:00
MarcoEandClaude Opus 5.5 495f335b72 Evita articoli persi o doppi con griglia e scanner insieme
Nella scheda, scegliendo alcuni articoli dalla griglia e sparandone altri,
non tutti i barcode arrivavano al salvataggio.

- La selezione dalla griglia modificava Scheda.Articoli da un thread del
  pool, mentre le scansioni lo fanno sul thread della UI: le due modifiche
  potevano sovrapporsi e far perdere articoli. Ora passa da InvokeAsync.
- La griglia non scartava i barcode gia' sparati, e lo scanner controllava
  solo il codice letto, non quello restituito dal server (che puo' essere
  il barcode principale, lo stesso della griglia). Un doppione rompe il
  @key della lista e il salvataggio locale (indice unico SchedaId+Barcode).
  Ora entrambi i percorsi aggiungono solo barcode non ancora presenti.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 15:40:20 +01:00
MarcoEandClaude Opus 5.5 ed7c28feac Aggiorna IntegryApiClient alla 2.6.0
Con la 2.0.1 il login poteva fallire con WrongAccessTokenJsonException:
il token del server non contiene piu' la proprieta' 'web' che la vecchia
versione considerava obbligatoria.

- IntegryApiClient.Core, .MAUI e .Blazor: 2.0.1 -> 2.6.0.
- La 2.6.0 richiede dipendenze piu' recenti, che il restore segnalava come
  downgrade (NU1605): System.IdentityModel.Tokens.Jwt 8.17.0 -> 8.18.0,
  Microsoft.Extensions.Logging e .Logging.Debug 10.0.7 -> 10.0.8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 15:40:20 +01:00
MarcoE 42e2403362 Finish v1.2.3(9) 2026-10-21 08:51:50 +02:00
MarcoE f59c8d3aaf Finish v1.2.3(9) 2026-10-21 08:51:50 +02:00
MarcoE 249b301920 -> 1.2.3 (9) 2026-10-21 08:51:43 +02:00
MarcoEandClaude Opus 5.5 885b3cc6b6 Avvisa quando manca il permesso della fotocamera
Con il permesso negato "Aggiungi una foto" non faceva nulla: il servizio
restituiva null come per un annullamento. Dopo un rifiuto definitivo
Android non ripropone la richiesta, quindi il rilevatore restava bloccato
senza capire perche'.

- AttachedService: la richiesta dei permessi diventa RequestCameraPermissions,
  usata anche da SelectImageFromCamera; OpenAppSettings apre le impostazioni
  dell'app.
- ModalFormScheda e ModalAddAttached: chiedono i permessi prima di scattare
  e, se negati, mostrano un avviso con l'azione "Impostazioni".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 08:49:34 +02:00
MarcoEandClaude Opus 5.5 7e1492d118 Avvisa quando la fotocamera non si apre e passa alla galleria
Se lo scatto falliva, AttachedService restituiva null come per un
annullamento: il rilevatore toccava "Aggiungi una foto" e non succedeva
nulla.

- AttachedService: espone IsCameraAvailable (IsCaptureSupported) e, dopo
  aver registrato l'errore e averlo inviato a Sentry, lo rilancia invece di
  restituire null.
- ModalFormScheda: dalla scheda il pulsante apre solo la fotocamera, quindi
  senza fotocamera non c'era alternativa. Ora avvisa e apre la galleria;
  se lo scatto fallisce mostra un errore.
- ModalAddAttached: stessa gestione dell'errore di scatto.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 08:45:57 +02:00
MarcoEandClaude Opus 5.5 fd0c218ab5 Dichiara la fotocamera di sistema nelle queries del manifest
Da Android 11 un'app vede le altre app installate solo se le dichiara in
<queries>. Senza l'intent IMAGE_CAPTURE, MediaPicker.CapturePhotoAsync non
trovava la fotocamera di sistema e falliva con "Either there was no camera
on the device or 'android.media.action.IMAGE_CAPTURE' was not added to the
<queries> element" (segnalato su Sentry).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 08:45:57 +02:00
MarcoE e1ca03f646 Finish v1.2.2 2026-09-29 10:34:45 +02:00
12 changed files with 273 additions and 63 deletions

No files matched your search

+15 -3
View File
@@ -8,12 +8,21 @@ namespace SteUp.Maui.Core.Services;
public class AttachedService(ILogger<FileManager> logger) : IAttachedService
{
public async Task<AttachedDto?> SelectImageFromCamera()
public bool IsCameraAvailable => MediaPicker.Default.IsCaptureSupported;
public async Task<bool> RequestCameraPermissions()
{
var cameraPerm = await Permissions.RequestAsync<Permissions.Camera>();
var storagePerm = await Permissions.RequestAsync<Permissions.StorageWrite>();
if (cameraPerm != PermissionStatus.Granted || storagePerm != PermissionStatus.Granted)
return cameraPerm == PermissionStatus.Granted && storagePerm == PermissionStatus.Granted;
}
public void OpenAppSettings() => AppInfo.Current.ShowSettingsUI();
public async Task<AttachedDto?> SelectImageFromCamera()
{
if (!await RequestCameraPermissions())
return null;
FileResult? result;
@@ -28,7 +37,10 @@ public class AttachedService(ILogger<FileManager> logger) : IAttachedService
logger.LogError(ex, ex.Message);
Console.WriteLine($"Errore cattura foto: {ex.Message}");
SentrySdk.CaptureException(ex);
return null;
// Rilancia: restituire null qui era indistinguibile da un annullamento,
// e il rilevatore toccava "Aggiungi una foto" senza vedere nulla.
throw;
}
return result is null ? null : await UtilityFile.ConvertToDto(result, AttachedDto.TypeAttached.Image);
+7 -5
View File
@@ -16,15 +16,15 @@ public class FileManager(
private async Task<AttachedDto> ConvertToDto(FileInfo file, AttachedDto.TypeAttached type, bool isFromToUpload)
{
var (origUrl, thumbUrl) = await SaveAndCreateThumbAsync(
await File.ReadAllBytesAsync(file.FullName),
file.Name
);
var bytes = await File.ReadAllBytesAsync(file.FullName);
var (origUrl, thumbUrl) = await SaveAndCreateThumbAsync(bytes, file.Name);
return new AttachedDto
{
Name = file.Name,
Path = file.FullName,
// Servono per inviare le foto rimaste in /toUpload (salvate senza rete).
FileBytes = bytes,
TempPath = origUrl,
ThumbPath = thumbUrl,
Type = type,
@@ -101,7 +101,9 @@ public class FileManager(
foreach (var file in toUploadFiles)
{
if (!fileNameFilter.Contains(file.Name))
// Scheda.ImageNames contiene il percorso completo restituito da SaveInspectionFile:
// confrontando solo il nome le foto salvate e non ancora inviate non comparivano mai.
if (!fileNameFilter.Contains(file.FullName) && !fileNameFilter.Contains(file.Name))
continue;
ct.ThrowIfCancellationRequested();
@@ -25,4 +25,11 @@
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<!-- Android 11+: rende visibile l'app fotocamera di sistema a MediaPicker -->
<queries>
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
</queries>
</manifest>
+5 -5
View File
@@ -30,8 +30,8 @@
<ApplicationId>it.integry.SteUp</ApplicationId>
<!-- Versions -->
<ApplicationDisplayVersion>1.2.2</ApplicationDisplayVersion>
<ApplicationVersion>8</ApplicationVersion>
<ApplicationDisplayVersion>1.2.5</ApplicationDisplayVersion>
<ApplicationVersion>11</ApplicationVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
<!-- <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">-->
@@ -116,12 +116,12 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.Maui" Version="14.1.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageReference Include="IntegryApiClient.MAUI" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.7" />
<PackageReference Include="IntegryApiClient.MAUI" Version="2.6.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.8" />
<PackageReference Include="Microsoft.Maui.Controls" Version="10.0.51" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="10.0.51" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="10.0.51" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="10.0.7" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="10.0.8" />
<PackageReference Include="Sentry.Maui" Version="6.4.1" />
<PackageReference Include="SkiaSharp" Version="3.119.2" />
</ItemGroup>
@@ -40,7 +40,32 @@
private async Task OnCamera()
{
var selectImageFromCamera = await AttachedService.SelectImageFromCamera();
if (!await AttachedService.RequestCameraPermissions())
{
Snackbar.Clear();
Snackbar.Add("Per scattare le foto serve il permesso della fotocamera", Severity.Warning, config =>
{
config.Action = "Impostazioni";
config.OnClick = _ =>
{
AttachedService.OpenAppSettings();
return Task.CompletedTask;
};
});
return;
}
AttachedDto? selectImageFromCamera;
try
{
selectImageFromCamera = await AttachedService.SelectImageFromCamera();
}
catch (Exception)
{
Snackbar.Clear();
Snackbar.Add("Non è stato possibile scattare la foto, riprova", Severity.Error);
return;
}
if (selectImageFromCamera != null)
{
@@ -171,7 +171,10 @@
</div>
}
@if (item.p.ToUpload && !ReadOnly)
@* Rimovibile anche se gia' salvata o inviata. Non mentre e'
in elaborazione: l'indice della foto serve ancora al
caricamento in background. *@
@if (!ReadOnly && !item.p.ThumbPath.IsNullOrEmpty())
{
<button type="button" class="attach-item__remove"
aria-label="@($"Rimuovi la foto {item.p.Name}")"
@@ -336,6 +339,9 @@
// Gli allegati vivono in AttachedList finche' non si salva: li tracciamo con un flag.
private bool _attachmentsDirty;
private List<AttachedDto>? AttachedList { get; set; }
// Foto gia' salvate tolte dal rilevatore: si eliminano davvero solo al salvataggio,
// cosi' uscendo senza salvare restano dove sono.
private readonly List<AttachedDto> _removedAttachments = [];
private IDisposable? _backRegistration;
// Il tasto indietro puo' arrivare mentre il prompt di uscita e' gia' a video.
@@ -506,31 +512,30 @@
private async Task Update(SaveSchedaResponseDto? apiResponse, bool preserveActivityId = false)
{
var ispezione = new Ispezione
{
CodMdep = CodMdep,
Data = Data,
Rilevatore = UserSession.User.Username
};
// Prima di toccare l'ActivityId: le foto gia' inviate vanno tolte dall'attivita'
// su cui sono state caricate.
await RemoveDeletedAttachments(ispezione);
if (!AttachedList.IsNullOrEmpty())
{
foreach (var attached in AttachedList!.Where(x => !x.SavedOnAppData))
{
var ispezione = new Ispezione
{
CodMdep = CodMdep,
Data = Data,
Rilevatore = UserSession.User.Username
};
var fileNameAdded = await FileManager.SaveInspectionFile(
ispezione,
attached.FileBytes!,
attached.Name!
);
if (!attached.ToRemove)
{
var fileNameAdded = await FileManager.SaveInspectionFile(
ispezione,
attached.FileBytes!,
attached.Name!
);
Scheda.ImageNames ??= [];
if (fileNameAdded != null)
Scheda.ImageNames.Add(fileNameAdded);
}
else
_ = FileManager.RemoveInspectionFile(ispezione, attached.Name!);
Scheda.ImageNames ??= [];
if (fileNameAdded != null)
Scheda.ImageNames.Add(fileNameAdded);
}
}
@@ -549,6 +554,70 @@
}
}
/// <summary>
/// Elimina le foto salvate che il rilevatore ha tolto dalla scheda: dal server se
/// erano gia' state inviate, poi dal dispositivo e dall'elenco della scheda.
/// Se il server non conferma, la foto resta (sul server e sul dispositivo) invece
/// di sparire solo da qui.
/// </summary>
private async Task RemoveDeletedAttachments(Ispezione ispezione)
{
if (_removedAttachments.Count == 0) return;
var nonEliminate = 0;
foreach (var attached in _removedAttachments)
{
if (attached.Name.IsNullOrEmpty()) continue;
var giaInviata = !attached.ToUpload;
// Una foto ancora "da inviare" di norma non e' sul server, ma l'invio dalla
// card o dalla chiusura ispezione non la sposta fra le inviate: con la rete
// si prova comunque a toglierla, senza bloccare l'eliminazione se non c'e'.
if (Scheda.ActivityId.IsValorized() && (giaInviata || NetworkService.ConnectionAvailable))
{
try
{
await IntegrySteupService.RemoveFile(Scheda.ActivityId!, attached.Name!);
}
catch (Exception e)
{
if (giaInviata)
{
Logger.LogError(e, "Eliminazione della foto {FileName} dal server non riuscita", attached.Name);
nonEliminate++;
continue;
}
Logger.LogWarning(e, "Foto {FileName} non trovata sul server", attached.Name);
}
}
try
{
FileManager.RemoveInspectionFile(ispezione, attached.Name!);
}
catch (Exception e)
{
// Il file orfano non fa danni: conta che la foto esca dalla scheda.
Logger.LogError(e, "Eliminazione del file {FileName} non riuscita", attached.Name);
}
Scheda.ImageNames?.RemoveAll(x => System.IO.Path.GetFileName(x) == attached.Name);
}
_removedAttachments.Clear();
if (nonEliminate > 0)
{
Snackbar.Add(nonEliminate == 1
? "Una foto già inviata non è stata eliminata: riprova con la connessione"
: $"{nonEliminate} foto già inviate non sono state eliminate: riprova con la connessione",
Severity.Warning);
}
}
private async Task UploadFile(Scheda scheda)
{
if (AttachedList.IsNullOrEmpty()) return;
@@ -703,7 +772,8 @@
/// <summary>
/// Salva il lavoro in corso solo sul dispositivo, marcato come da completare.
/// Niente chiamate al server e niente validazione: una bozza può essere incompleta.
/// Niente salvataggio sul server e niente validazione: una bozza può essere incompleta.
/// Unica eccezione: le foto già inviate tolte dal rilevatore si eliminano anche dal server.
/// </summary>
private async Task SaveDraft()
{
@@ -754,12 +824,60 @@
#region File
// Dopo un rifiuto definitivo Android non ripropone la richiesta: il
// permesso si riattiva solo dalle impostazioni, quindi le apriamo noi.
private void ShowCameraPermissionDenied()
{
Snackbar.Clear();
Snackbar.Add("Per scattare le foto serve il permesso della fotocamera", Severity.Warning, config =>
{
config.Action = "Impostazioni";
config.OnClick = _ =>
{
AttachedService.OpenAppSettings();
return Task.CompletedTask;
};
});
}
private async Task OpenAddAttached()
{
var selectImageFromCamera = await AttachedService.SelectImageFromCamera();
if (selectImageFromCamera == null) return;
var attachedList = new List<AttachedDto> { selectImageFromCamera };
List<AttachedDto>? attachedList;
if (AttachedService.IsCameraAvailable)
{
if (!await AttachedService.RequestCameraPermissions())
{
ShowCameraPermissionDenied();
return;
}
AttachedDto? selectImageFromCamera;
try
{
selectImageFromCamera = await AttachedService.SelectImageFromCamera();
}
catch (Exception)
{
// Gia' registrato e inviato a Sentry dal servizio
Snackbar.Clear();
Snackbar.Add("Non è stato possibile scattare la foto, riprova", Severity.Error);
return;
}
if (selectImageFromCamera == null) return;
attachedList = [selectImageFromCamera];
}
else
{
// Senza fotocamera "Aggiungi una foto" non avrebbe altra strada:
// si passa alla galleria invece di lasciare il rilevatore fermo.
Snackbar.Clear();
Snackbar.Add("Fotocamera non disponibile: scegli la foto dalla galleria", Severity.Warning);
attachedList = await AttachedService.SelectImageFromGallery();
if (attachedList is null || attachedList.Count == 0) return;
}
OnLoading = true;
await InvokeAsync(StateHasChanged);
@@ -848,29 +966,32 @@
var modal = await WithChildDialog(() => Dialog.OpenSelectArt(articoli));
// Gli articoli si aggiungono sul thread della UI, come fanno le scansioni:
// toccare Scheda.Articoli da qui mentre arriva una lettura (o mentre la
// lista viene disegnata) puo' far perdere articoli.
await InvokeAsync(() =>
{
OnLoading = false;
TextLoading = null;
if (modal is { Canceled: false, Data: List<ArticoliInGrigliaDto> articoliSelezionati })
{
// Quelli gia' sparati non si aggiungono di nuovo.
Scheda.Articoli.InsertRange(0, articoliSelezionati
.DistinctBy(x => x.Barcode)
.Where(x => !ContainsBarcode(x.Barcode))
.Select(x => new SchedaArticolo
{
Barcode = x.Barcode,
Descrizione = x.Descrizione
})
);
RecalcDirty();
}
StateHasChanged();
});
if (modal is { Canceled: false, Data: List<ArticoliInGrigliaDto> articoliSelezionati })
{
Scheda.Articoli.InsertRange(0, articoliSelezionati.ConvertAll(x => new SchedaArticolo
{
Barcode = x.Barcode,
Descrizione = x.Descrizione
})
);
await InvokeAsync(() =>
{
RecalcDirty();
StateHasChanged();
});
}
});
}
@@ -878,8 +999,22 @@
{
if (AttachedList is null || index < 0 || index >= AttachedList.Count) return;
if (AttachedList[index].SavedOnAppData)
AttachedList[index].ToRemove = true;
var attached = AttachedList[index];
// Le foto appena scattate stanno solo in memoria: basta toglierle dall'elenco.
if (attached.SavedOnAppData)
{
// Una foto gia' inviata va tolta anche dal server: senza rete resterebbe
// nella scheda inviata pur sparendo dal dispositivo.
if (!attached.ToUpload && !NetworkService.ConnectionAvailable)
{
Snackbar.Clear();
Snackbar.Add("Per eliminare una foto già inviata serve la connessione", Severity.Warning);
return;
}
_removedAttachments.Add(attached);
}
AttachedList.RemoveAt(index);
_attachmentsDirty = true;
@@ -936,7 +1071,7 @@
try
{
if (value is null) return;
if (Scheda.Articoli.Any(x => x.Barcode.Equals(value))) return;
if (ContainsBarcode(value)) return;
await InvokeAsync(() =>
{
@@ -951,6 +1086,11 @@
OnLoading = false;
StateHasChanged();
// Il controllo va ripetuto sul barcode restituito: il server puo' rispondere
// con un barcode diverso da quello letto (lo stesso gia' scelto dalla griglia),
// e due letture ravvicinate superano entrambe il controllo iniziale.
if (art != null && ContainsBarcode(art.Barcode)) return;
if (art != null)
{
Scheda.Articoli.Insert(0, new SchedaArticolo
@@ -984,6 +1124,8 @@
private void OnErrorScan(string? value) => OnError(new Exception(value), value);
private bool ContainsBarcode(string barcode) => Scheda.Articoli.Any(x => x.Barcode.Equals(barcode));
#endregion
private void OnError(Exception? e, string? errorMessage)
-1
View File
@@ -15,7 +15,6 @@ public class AttachedDto
public string? ThumbPath { get; set; }
public bool SavedOnAppData { get; set; }
public bool ToRemove { get; set; }
public bool ToUpload { get; set; }
public Stream? FileContent =>
@@ -17,6 +17,7 @@ public interface IIntegrySteupService
Task<SaveSchedaResponseDto?> SaveMultipleSchede(List<SaveRequestDto> request);
Task CompleteInspection(string activityId);
Task UploadFile(string activityId, byte[] file, string fileName);
Task RemoveFile(string activityId, string fileName);
Task DeleteScheda(string activityId);
}
@@ -4,6 +4,14 @@ namespace SteUp.Shared.Core.Interface.System;
public interface IAttachedService
{
bool IsCameraAvailable { get; }
/// <summary>Chiede i permessi per scattare; false se negati.</summary>
Task<bool> RequestCameraPermissions();
void OpenAppSettings();
/// <summary>Null se l'utente annulla; lancia se lo scatto fallisce.</summary>
Task<AttachedDto?> SelectImageFromCamera();
Task<List<AttachedDto>?> SelectImageFromGallery();
}
@@ -70,6 +70,20 @@ public class IntegrySteupService(IIntegryApiRestClient integryApiRestClient) : I
content.Dispose();
}
/// <summary>
/// Toglie un allegato dalla scheda. Il server lo riconosce dal nome con cui
/// è stato caricato da <see cref="UploadFile"/>.
/// </summary>
public Task RemoveFile(string activityId, string fileName) =>
integryApiRestClient.AuthorizedGet<object>(
$"{BaseRequest}/removeAttachment",
new Dictionary<string, object?>
{
{ "activityId", activityId },
{ "fileName", fileName }
}
);
public Task DeleteScheda(string activityId) =>
integryApiRestClient.AuthorizedGet<object>(
$"{BaseRequest}/deleteScheda",
+2 -2
View File
@@ -11,13 +11,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="IntegryApiClient.Core" Version="2.0.1" />
<PackageReference Include="IntegryApiClient.Core" Version="2.6.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="10.0.7" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageReference Include="MudBlazor" Version="9.0.0" />
<PackageReference Include="CodeBeam.MudBlazor.Extensions" Version="9.0.1" />
<PackageReference Include="Sentry" Version="6.4.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.17.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.18.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.7" />
<PackageReference Include="Microsoft.Maui.Essentials" Version="10.0.51" />
</ItemGroup>
+1 -1
View File
@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IntegryApiClient.Blazor" Version="2.0.1" />
<PackageReference Include="IntegryApiClient.Blazor" Version="2.6.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.7" />