feat: implement version check and update dialog; add browser cache clearing functionality
Build and Deploy / build (push) Successful in 1m40s
Build and Deploy / build (push) Successful in 1m40s
This commit is contained in:
@@ -1,8 +1,50 @@
|
||||
using FrontOffice.BFF.Configuration.Protobuf.Protos.AppVersion;
|
||||
using Blazored.LocalStorage;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace FrontOffice.Main.Utilities;
|
||||
|
||||
/// <summary>
|
||||
/// نتیجه بررسی نسخه اپلیکیشن
|
||||
/// </summary>
|
||||
public class VersionCheckResult
|
||||
{
|
||||
/// <summary>
|
||||
/// آیا نسخه جدیدی وجود دارد
|
||||
/// </summary>
|
||||
public bool HasNewVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آیا آپدیت اجباری است (force update)
|
||||
/// </summary>
|
||||
public bool IsForceUpdate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نسخه فعلی (local)
|
||||
/// </summary>
|
||||
public string? OldVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// نسخه جدید (server)
|
||||
/// </summary>
|
||||
public string? NewVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// یادداشتهای انتشار
|
||||
/// </summary>
|
||||
public string? ReleaseNotes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// پیام آپدیت
|
||||
/// </summary>
|
||||
public string? UpdateMessage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// آیا کش باید پاک شود
|
||||
/// </summary>
|
||||
public bool RequiresCacheClear { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// سرویس مدیریت نسخه اپلیکیشن و کش
|
||||
/// وقتی نسخه جدید منتشر بشه، این سرویس متوجه میشه و کش رو پاک میکنه
|
||||
@@ -11,31 +53,44 @@ public class AppVersionService
|
||||
{
|
||||
private readonly AppVersionContract.AppVersionContractClient _client;
|
||||
private readonly ILocalStorageService _localStorage;
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
private readonly ILogger<AppVersionService> _logger;
|
||||
|
||||
private const string APP_NAME = "FrontOffice";
|
||||
private const string APP_NAME = "KaraBazarApp";
|
||||
private const string LOCAL_VERSION_KEY = "app_version";
|
||||
private const string LAST_CHECK_KEY = "app_version_last_check";
|
||||
private const string SKIPPED_VERSION_KEY = "app_version_skipped";
|
||||
private const string LAST_DIALOG_SHOWN_KEY = "app_version_last_dialog_shown";
|
||||
|
||||
public AppVersionService(
|
||||
AppVersionContract.AppVersionContractClient client,
|
||||
ILocalStorageService localStorage,
|
||||
IJSRuntime jsRuntime,
|
||||
ILogger<AppVersionService> logger)
|
||||
{
|
||||
_client = client;
|
||||
_localStorage = localStorage;
|
||||
_jsRuntime = jsRuntime;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// بررسی نسخه اپلیکیشن و پاک کردن کش در صورت نیاز
|
||||
/// بررسی نسخه اپلیکیشن و برگرداندن نتیجه
|
||||
/// </summary>
|
||||
public async Task CheckVersionAndClearCacheIfNeededAsync()
|
||||
/// <param name="ignoreSkipped">اگر true باشه، نسخههای skip شده هم نشون داده میشن (برای آیکون منو)</param>
|
||||
/// <param name="forDialog">اگر true باشه، چک میکنه که یک روز از آخرین نمایش گذشته (برای popup)</param>
|
||||
public async Task<VersionCheckResult> CheckVersionAsync(bool ignoreSkipped = false, bool forDialog = false)
|
||||
{
|
||||
var result = new VersionCheckResult();
|
||||
|
||||
try
|
||||
{
|
||||
// دریافت نسخه فعلی از localStorage
|
||||
var localVersion = await _localStorage.GetItemAsStringAsync(LOCAL_VERSION_KEY);
|
||||
var skippedVersion = await _localStorage.GetItemAsStringAsync(SKIPPED_VERSION_KEY);
|
||||
var lastDialogShown = await _localStorage.GetItemAsStringAsync(LAST_DIALOG_SHOWN_KEY);
|
||||
|
||||
result.OldVersion = localVersion;
|
||||
|
||||
// بررسی نسخه از سرور
|
||||
var response = await _client.GetAppVersionAsync(new GetAppVersionRequest
|
||||
@@ -47,32 +102,119 @@ public class AppVersionService
|
||||
if (!response.Found)
|
||||
{
|
||||
_logger.LogWarning("App version not found on server for {AppName}", APP_NAME);
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
var serverVersion = response.CurrentVersion;
|
||||
result.NewVersion = serverVersion;
|
||||
result.ReleaseNotes = response.ReleaseNotes;
|
||||
result.UpdateMessage = response.UpdateMessage;
|
||||
result.RequiresCacheClear = response.RequiresFullCacheClear;
|
||||
result.IsForceUpdate = response.RequiresUpdate; // اگر نسخه کمتر از حداقل باشه
|
||||
|
||||
// اگر نسخه جدید باشه یا پاک کردن کش لازم باشه
|
||||
if (localVersion != serverVersion || response.RequiresFullCacheClear)
|
||||
// آیا نسخه جدید داریم؟
|
||||
if (localVersion != serverVersion)
|
||||
{
|
||||
result.HasNewVersion = true;
|
||||
|
||||
// اگر این نسخه رو قبلاً skip کرده و force نیست
|
||||
if (!result.IsForceUpdate && skippedVersion == serverVersion && !ignoreSkipped)
|
||||
{
|
||||
// برای popup: چک کن یک روز گذشته یا نه
|
||||
if (forDialog)
|
||||
{
|
||||
var oneDayPassed = await HasOneDayPassedSinceLastDialogAsync(lastDialogShown);
|
||||
if (!oneDayPassed)
|
||||
{
|
||||
result.HasNewVersion = false;
|
||||
}
|
||||
// اگه یک روز گذشته، HasNewVersion = true میمونه
|
||||
}
|
||||
else
|
||||
{
|
||||
result.HasNewVersion = false;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"New version detected: {OldVersion} -> {NewVersion}, CacheClear: {CacheClear}",
|
||||
localVersion ?? "null", serverVersion, response.RequiresFullCacheClear);
|
||||
|
||||
// پاک کردن کش
|
||||
await ClearAllCacheAsync();
|
||||
|
||||
// ذخیره نسخه جدید
|
||||
await _localStorage.SetItemAsStringAsync(LOCAL_VERSION_KEY, serverVersion);
|
||||
await _localStorage.SetItemAsStringAsync(LAST_CHECK_KEY, DateTime.UtcNow.ToString("O"));
|
||||
|
||||
_logger.LogInformation("Cache cleared and version updated to {Version}", serverVersion);
|
||||
"Version check: {OldVersion} -> {NewVersion}, Force: {Force}, Skipped: {Skipped}",
|
||||
localVersion ?? "null", serverVersion, result.IsForceUpdate, skippedVersion);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error checking app version");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// چک کردن اینکه یک روز از آخرین نمایش دیالوگ گذشته یا نه
|
||||
/// </summary>
|
||||
private async Task<bool> HasOneDayPassedSinceLastDialogAsync(string? lastDialogShown)
|
||||
{
|
||||
if (string.IsNullOrEmpty(lastDialogShown))
|
||||
return true; // اگه هیچوقت نشون نداده، نشون بده
|
||||
|
||||
if (DateTime.TryParse(lastDialogShown, out var lastShown))
|
||||
{
|
||||
return DateTime.UtcNow.Subtract(lastShown).TotalDays >= 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ثبت زمان نمایش دیالوگ
|
||||
/// </summary>
|
||||
public async Task RecordDialogShownAsync()
|
||||
{
|
||||
await _localStorage.SetItemAsStringAsync(LAST_DIALOG_SHOWN_KEY, DateTime.UtcNow.ToString("O"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// اعمال آپدیت - پاک کردن کش و ذخیره نسخه جدید
|
||||
/// </summary>
|
||||
public async Task ApplyUpdateAsync(string newVersion)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Applying update to version {Version}", newVersion);
|
||||
|
||||
// پاک کردن کش
|
||||
await ClearAllCacheAsync();
|
||||
|
||||
// ذخیره نسخه جدید
|
||||
await _localStorage.SetItemAsStringAsync(LOCAL_VERSION_KEY, newVersion);
|
||||
await _localStorage.SetItemAsStringAsync(LAST_CHECK_KEY, DateTime.UtcNow.ToString("O"));
|
||||
|
||||
// پاک کردن نسخه skip شده
|
||||
await _localStorage.RemoveItemAsync(SKIPPED_VERSION_KEY);
|
||||
|
||||
_logger.LogInformation("Update applied successfully to {Version}", newVersion);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error applying update");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skip کردن این نسخه (بعداً)
|
||||
/// </summary>
|
||||
public async Task SkipVersionAsync(string version)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _localStorage.SetItemAsStringAsync(SKIPPED_VERSION_KEY, version);
|
||||
_logger.LogInformation("Version {Version} skipped by user", version);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error skipping version");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -82,33 +224,14 @@ public class AppVersionService
|
||||
{
|
||||
try
|
||||
{
|
||||
// لیست کلیدهایی که باید حفظ بشن (مثل توکن و اطلاعات کاربر)
|
||||
var keysToKeep = new HashSet<string>
|
||||
{
|
||||
"access_token",
|
||||
"refresh_token",
|
||||
"user_info",
|
||||
"user_roles"
|
||||
};
|
||||
// پاک کردن کش مرورگر (Cache Storage و Service Worker)
|
||||
await _jsRuntime.InvokeVoidAsync("clearBrowserCache");
|
||||
|
||||
// دریافت همه کلیدها
|
||||
var allKeys = await _localStorage.KeysAsync();
|
||||
|
||||
// پاک کردن کلیدهایی که در لیست حفظ نیستن
|
||||
foreach (var key in allKeys)
|
||||
{
|
||||
if (!keysToKeep.Contains(key) && key != LOCAL_VERSION_KEY)
|
||||
{
|
||||
await _localStorage.RemoveItemAsync(key);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("Local storage cache cleared, {Count} keys removed",
|
||||
allKeys.Count() - keysToKeep.Count);
|
||||
_logger.LogInformation("Browser cache cleared successfully");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error clearing cache");
|
||||
_logger.LogError(ex, "Error clearing browser cache");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user