| @@ -0,0 +1,9 @@ | |||
| @page "/doneimage" | |||
| <div class="text-center"> | |||
| <img src="./images/done.png" class="w-50" alt="Done!" /> | |||
| </div> | |||
| @code { | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| @page "/failureimage" | |||
| <div class="text-center"> | |||
| <img src="./images/failure.png" class="w-50" alt="Failure!" /> | |||
| </div> | |||
| @code { | |||
| } | |||
| @@ -0,0 +1,38 @@ | |||
| @using cwebplusApp.Shared.Services; | |||
| @implements IDisposable; | |||
| @inject OnlineStatusProvider OnlineStatusProvider; | |||
| <div class="row no-gutters w-100 justify-content-end" style="position: absolute;"> | |||
| @if (isOffline) { | |||
| <MatIcon Style="padding-right:0.5rem"> | |||
| <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> | |||
| <path d="M0 0h24v24H0V0z" fill="none" /> | |||
| <path d="M21 11l2-2c-3.73-3.73-8.87-5.15-13.7-4.31l2.58 2.58c3.3-.02 6.61 1.22 9.12 3.73zm-2 2c-1.08-1.08-2.36-1.85-3.72-2.33l3.02 3.02.7-.69zM9 17l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zM3.41 1.64L2 3.05 5.05 6.1C3.59 6.83 2.22 7.79 1 9l2 2c1.23-1.23 2.65-2.16 4.17-2.78l2.24 2.24C7.79 10.89 6.27 11.74 5 13l2 2c1.35-1.35 3.11-2.04 4.89-2.06l7.08 7.08 1.41-1.41L3.41 1.64z" /> | |||
| </svg> | |||
| </MatIcon> | |||
| } | |||
| </div> | |||
| @code { | |||
| private bool isOffline; | |||
| public void Dispose() { | |||
| OnlineStatusProvider.RemoveOnlineStatusChangeCallBack(OnOnlineStatusChanged); | |||
| } | |||
| protected override void OnInitialized() { | |||
| base.OnInitialized(); | |||
| OnlineStatusProvider.AddOnlineStatusChangeCallBack(OnOnlineStatusChanged); | |||
| OnOnlineStatusChanged(OnlineStatusProvider.Online); | |||
| } | |||
| private void OnOnlineStatusChanged(bool isOnline) { | |||
| this.isOffline = !isOnline; | |||
| StateHasChanged(); | |||
| } | |||
| } | |||
| @@ -2,12 +2,13 @@ | |||
| @using cwebplusApp.Shared.Services; | |||
| @using cwebplusApp.Shared.Models; | |||
| @using cwebplusApp.Components; | |||
| @inject NavigationManager NavigationManager; | |||
| @inject IStringLocalizer<Resources> i18n; | |||
| @inject PageHistoryManager PageHistoryManager; | |||
| @inject ReportDataProvider ReportDataProvider; | |||
| @inject ILFBicycleRest ILFBicycleRest; | |||
| @inject IBicycleRestService IBicycleRestService; | |||
| @inject Toaster Toaster; | |||
| @inject AppState AppState; | |||
| @@ -65,7 +66,7 @@ | |||
| base.OnInitialized(); | |||
| PageHistoryManager.AddPageToHistory(NavigationManager.Uri); | |||
| try { | |||
| response = await ILFBicycleRest.SendFoundReport(ReportDataProvider.Report); | |||
| response = await IBicycleRestService.SendFoundReport(ReportDataProvider.Report); | |||
| responseOk = System.Net.HttpStatusCode.OK == response.StatusCode ? true : false; | |||
| } catch (HttpRequestException ex) { | |||
| response = new(i18n.GetString("FoundBike"), new string[] { ex.Message }); | |||
| @@ -1,6 +1,7 @@ | |||
| @page "/fundvelo/keydata/Found" | |||
| @inherits CaritasServiceFundVeloKeyDataPageBase | |||
| @implements IDisposable; | |||
| @using cwebplusApp.Shared.Models; | |||
| @using cwebplusApp.Shared.Services; | |||
| @@ -15,6 +16,7 @@ | |||
| @inject Toaster Toaster | |||
| @inject IJSRuntime JS | |||
| @inject ReportDataProvider ReportDataProvider | |||
| @inject OnlineStatusProvider OnlineStatusProvider | |||
| <div class="row px-3 h-100"> | |||
| <div class="row no-gutters align-items-center justify-content-center w-100" style="padding-top:1em"> | |||
| @@ -68,23 +70,25 @@ | |||
| </MatCard> | |||
| </div> | |||
| </div> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-1 justify-content-center" style="text-align: center"> | |||
| <MatRipple class="inputfile-mat-ripple" Color="@MatRippleColor.Default" @onclick="InitializeMapPosition"> | |||
| <label> | |||
| <svg xmlns="http://www.w3.org/2000/svg" height="48px" width="48px" viewBox="0 0 24 24" fill="#000000"> | |||
| <path d="M0 0h24v24H0V0z" fill="none" /> | |||
| <path d="M13 3.06V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06c-.46-4.17-3.77-7.48-7.94-7.94zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z" /> | |||
| <circle cx="12" cy="12" opacity=".3" r="2" /> | |||
| <path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z" /> | |||
| </svg> | |||
| </label> | |||
| </MatRipple> | |||
| </div> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-3"> | |||
| <div class="w-100 fv-osm-tile map-wrapper"> | |||
| <Map @ref="mapRef" MapOptions="@mapOptions" AfterRender="AfterRenderMap"></Map> | |||
| @if (OnlineStatusProvider.Online) { | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-1 justify-content-center" style="text-align: center"> | |||
| <MatRipple class="inputfile-mat-ripple" Color="@MatRippleColor.Default" @onclick="InitializeMapPosition"> | |||
| <label> | |||
| <svg xmlns="http://www.w3.org/2000/svg" height="48px" width="48px" viewBox="0 0 24 24" fill="#000000"> | |||
| <path d="M0 0h24v24H0V0z" fill="none" /> | |||
| <path d="M13 3.06V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06c-.46-4.17-3.77-7.48-7.94-7.94zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z" /> | |||
| <circle cx="12" cy="12" opacity=".3" r="2" /> | |||
| <path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z" /> | |||
| </svg> | |||
| </label> | |||
| </MatRipple> | |||
| </div> | |||
| </div> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-3"> | |||
| <div class="w-100 fv-osm-tile map-wrapper"> | |||
| <Map @ref="mapRef" MapOptions="@mapOptions" AfterRender="AfterRenderMap"></Map> | |||
| </div> | |||
| </div> | |||
| } | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-8-tablet mat-layout-grid-cell-span-4-desktop"> | |||
| <div class="mat-layout-grid-inner"> | |||
| <div class="mat-layout-grid-cell mat-layout-grid-cell-span-4-phone mat-layout-grid-cell-span-4-tablet mat-layout-grid-cell-span-12-desktop"> | |||
| @@ -190,6 +194,10 @@ | |||
| private string remark; | |||
| private bool abholadresseIsNotContact; | |||
| public void Dispose() { | |||
| OnlineStatusProvider.RemoveOnlineStatusChangeCallBack(OnOnlineStatusChanged); | |||
| } | |||
| protected async override void OnInitialized() { | |||
| base.OnInitialized(); | |||
| await GetColors(); | |||
| @@ -197,6 +205,11 @@ | |||
| await GetBrands(); | |||
| refreshGUIFromDto(); | |||
| PageHistoryManager.AddPageToHistory(NavigationManager.Uri); | |||
| OnlineStatusProvider.AddOnlineStatusChangeCallBack(OnOnlineStatusChanged); | |||
| StateHasChanged(); | |||
| } | |||
| private void OnOnlineStatusChanged(bool isOnline) { | |||
| StateHasChanged(); | |||
| } | |||
| @@ -296,7 +309,7 @@ | |||
| bicycleGeoPosition.Longitude = report.GeographicInfo.Longitude; | |||
| imgUrl = report.FotoString; | |||
| selectedColor = Array.Find(Colors, color => color.Id == report.FarbeId); | |||
| selectedBrand = String.IsNullOrEmpty(report.NeueMarke) ? Array.Find(Brands, brand => brand.Id == report.MarkeId): new Brand(-999, report.NeueMarke); | |||
| selectedBrand = String.IsNullOrEmpty(report.NeueMarke) ? Array.Find(Brands, brand => brand.Id == report.MarkeId) : new Brand(-999, report.NeueMarke); | |||
| selectedBcType = Array.Find(BicycleTypes, bcType => bcType.Id == report.TypId); | |||
| frameNumber = report.RahmenNummer; | |||
| remark = report.Bemerkung; | |||
| @@ -2,12 +2,13 @@ | |||
| @using cwebplusApp.Shared.Services; | |||
| @using cwebplusApp.Shared.Models; | |||
| @using cwebplusApp.Components; | |||
| @inject NavigationManager NavigationManager; | |||
| @inject IStringLocalizer<Resources> i18n; | |||
| @inject PageHistoryManager PageHistoryManager; | |||
| @inject ReportDataProvider ReportDataProvider; | |||
| @inject ILFBicycleRest ILFBicycleRest; | |||
| @inject IBicycleRestService IBicycleRestService; | |||
| @inject Toaster Toaster; | |||
| @inject AppState AppState; | |||
| @@ -94,7 +95,7 @@ | |||
| base.OnInitialized(); | |||
| PageHistoryManager.AddPageToHistory(NavigationManager.Uri); | |||
| try { | |||
| response = await ILFBicycleRest.SendMissingReport(ReportDataProvider.Report); | |||
| response = await IBicycleRestService.SendMissingReport(ReportDataProvider.Report); | |||
| responseOk = System.Net.HttpStatusCode.OK == response.StatusCode ? true : false; | |||
| } catch (HttpRequestException ex) { | |||
| response = new(i18n.GetString("MissingBike"), new string[] { ex.Message }); | |||
| @@ -1,7 +1,6 @@ | |||
| @page "/" | |||
| @using cwebplusApp.Shared.Services; | |||
| @using System.Threading; | |||
| @using Microsoft.Extensions.Configuration; | |||
| @inject NavigationManager NavigationManager; | |||
| @@ -11,7 +10,7 @@ | |||
| @inject MasterDataService MasterDataService; | |||
| @inject Toaster Toaster; | |||
| @inject IConfiguration Configuration; | |||
| @inject ILFBicycleRest ILFBicycleRest; | |||
| @inject IBicycleRestService IBicycleRestService; | |||
| <div class="row h-100 justify-content-center"> | |||
| @@ -52,7 +51,7 @@ | |||
| showProgressCircle = true; | |||
| StateHasChanged(); | |||
| try { | |||
| ILFBicycleRest.Initialize(Configuration); | |||
| IBicycleRestService.Initialize(Configuration); | |||
| await MasterDataService.SynchronizeMasterdata(); | |||
| } catch (Exception) { | |||
| Toaster.ShowWarning(i18n.GetString("Warning.Masterdata.Title"), i18n.GetString("Warning.Masterdata.Msg")); | |||
| @@ -18,10 +18,11 @@ namespace CaritasPWA { | |||
| builder.Services.AddMatBlazor(); | |||
| builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); | |||
| builder.Services.AddSingleton<ILFBicycleRest, LFBicycleRest>(); | |||
| builder.Services.AddSingleton<IBicycleRestService, BicycleRestService>(); | |||
| builder.Services.AddSingleton<AppState>(); | |||
| builder.Services.AddSingleton<PageHistoryManager>(); | |||
| builder.Services.AddSingleton<ReportDataProvider>(); | |||
| builder.Services.AddSingleton<OnlineStatusProvider>(); | |||
| builder.Services.AddScoped<Toaster>(); | |||
| builder.Services.AddScoped<UserDataProvider>(); | |||
| builder.Services.AddScoped<MasterDataService>(); | |||
| @@ -1,4 +1,5 @@ | |||
| @using cwebplusApp.Shared.Services; | |||
| @using cwebplusApp.Components; | |||
| @inject AppState AppState; | |||
| @inject NavigationManager NavigationManager; | |||
| @@ -66,10 +67,10 @@ | |||
| </MatList> | |||
| </MatDrawer> | |||
| </MatDrawerContainer> | |||
| </MatAppBarContent> | |||
| </MatAppBarContainer> | |||
| </div> | |||
| <OnlineStatusIndicator /> | |||
| } | |||
| @@ -0,0 +1,104 @@ | |||
| using cwebplusApp.Shared.Models; | |||
| using Microsoft.AspNetCore.Components; | |||
| using Microsoft.Extensions.Configuration; | |||
| using Newtonsoft.Json; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Globalization; | |||
| using System.Net.Http; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace cwebplusApp.Shared.Services { | |||
| // REST interface responsible to submit lost or found reports and get the available master data. | |||
| public class BicycleRestService : IBicycleRestService { | |||
| private static readonly string VERSION = "v1"; | |||
| private HttpClient httpClient; | |||
| [Inject] | |||
| public IConfiguration Configuration { get; set; } | |||
| public void Initialize(IConfiguration configuration) { | |||
| this.Configuration = configuration; | |||
| string hostBaseUrl = Configuration.GetValue<string>("host_base_url"); | |||
| if (!String.IsNullOrEmpty(hostBaseUrl)) { | |||
| this.httpClient = new HttpClient { BaseAddress = new Uri(hostBaseUrl) }; | |||
| } | |||
| } | |||
| public async Task<List<ColorItem>> GetColors() { | |||
| if (httpClient != null) { | |||
| string subResourceUrl = Configuration.GetValue<string>("subresource_url_colors"); | |||
| if (!String.IsNullOrEmpty(subResourceUrl)) { | |||
| HttpResponseMessage httpResult = await httpClient.GetAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName)); | |||
| if (httpResult.StatusCode == System.Net.HttpStatusCode.OK) { | |||
| ColorItem[] colors = JsonConvert.DeserializeObject<ColorItem[]>(await httpResult.Content.ReadAsStringAsync()); | |||
| return new List<ColorItem>(colors); | |||
| } | |||
| throw new HttpRequestException("HTTP error " + httpResult.StatusCode); | |||
| } | |||
| } | |||
| throw new HttpRequestException("HTTP client not initialized!"); | |||
| } | |||
| public async Task<List<BicycleType>> GetBicycleTypes() { | |||
| if (httpClient != null) { | |||
| string subResourceUrl = Configuration.GetValue<string>("subresource_url_types"); | |||
| if (!String.IsNullOrEmpty(subResourceUrl)) { | |||
| HttpResponseMessage httpResult = await httpClient.GetAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName)); | |||
| if (httpResult.StatusCode == System.Net.HttpStatusCode.OK) { | |||
| BicycleType[] bicycleTypes = JsonConvert.DeserializeObject<BicycleType[]>(await httpResult.Content.ReadAsStringAsync()); | |||
| return new List<BicycleType>(bicycleTypes); | |||
| } | |||
| throw new HttpRequestException("HTTP error " + httpResult.StatusCode); | |||
| } | |||
| } | |||
| throw new HttpRequestException("HTTP client not initialized!"); | |||
| } | |||
| public async Task<List<Brand>> GetBrands() { | |||
| if (httpClient != null) { | |||
| string subResourceUrl = Configuration.GetValue<string>("subresource_url_brands"); | |||
| if (!String.IsNullOrEmpty(subResourceUrl)) { | |||
| HttpResponseMessage httpResult = await httpClient.GetAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName)); | |||
| if (httpResult.StatusCode == System.Net.HttpStatusCode.OK) { | |||
| Brand[] brands = JsonConvert.DeserializeObject<Brand[]>(await httpResult.Content.ReadAsStringAsync()); | |||
| return new List<Brand>(brands); | |||
| } | |||
| throw new HttpRequestException("HTTP error " + httpResult.StatusCode); | |||
| } | |||
| } | |||
| throw new HttpRequestException("HTTP client not initialized!"); | |||
| } | |||
| public async Task<ReportResponse> SendFoundReport(Report report) { | |||
| string subResourceUrl = Configuration.GetValue<string>("subresource_url_foundreport"); | |||
| return await SendReport(report, subResourceUrl); | |||
| } | |||
| public async Task<ReportResponse> SendMissingReport(Report report) { | |||
| string subResourceUrl = Configuration.GetValue<string>("subresource_url_missingreport"); | |||
| return await SendReport(report, subResourceUrl); | |||
| } | |||
| protected async Task<ReportResponse> SendReport(Report report, string subResourceUrl) { | |||
| if (httpClient != null) { | |||
| if (!String.IsNullOrEmpty(subResourceUrl)) { | |||
| string reportJson = JsonConvert.SerializeObject(report); | |||
| HttpContent content = new StringContent(reportJson, Encoding.UTF8, "application/json"); | |||
| HttpResponseMessage httpResult = await httpClient.PostAsync(string.Format(subResourceUrl, VERSION, CultureInfo.CurrentCulture.TwoLetterISOLanguageName), content); | |||
| string msg = await httpResult.Content.ReadAsStringAsync(); | |||
| ReportResponse response = JsonConvert.DeserializeObject<ReportResponse>(msg); | |||
| response.StatusCode = httpResult.StatusCode; | |||
| return response; | |||
| } | |||
| } | |||
| throw new HttpRequestException("HTTP client not initialized!"); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| using cwebplusApp.Shared.Models; | |||
| using Microsoft.Extensions.Configuration; | |||
| using System.Collections.Generic; | |||
| using System.Threading.Tasks; | |||
| namespace cwebplusApp.Shared.Services { | |||
| public interface IBicycleRestService { | |||
| void Initialize(IConfiguration configuration); | |||
| Task<List<ColorItem>> GetColors(); | |||
| Task<List<BicycleType>> GetBicycleTypes(); | |||
| Task<List<Brand>> GetBrands(); | |||
| Task<ReportResponse> SendFoundReport(Report report); | |||
| Task<ReportResponse> SendMissingReport(Report report); | |||
| } | |||
| } | |||
| @@ -10,13 +10,14 @@ using System.Threading.Tasks; | |||
| namespace cwebplusApp.Shared.Services { | |||
| public class MasterDataService { | |||
| private readonly ILFBicycleRest _lFBicycleRest; | |||
| private readonly IBicycleRestService _bicycleRestService; | |||
| private readonly IJSRuntime _jsRuntime; | |||
| private readonly IStringLocalizer<Resources> _i18n; | |||
| private readonly OnlineStatusProvider _onlineStatusProvider; | |||
| private const string KeyNameColors = "colors"; | |||
| private const string KeyNameBcTypes = "bicycleTypes"; | |||
| private const string KeyNameBrands = "brands"; | |||
| private readonly IJSRuntime _jsRuntime; | |||
| private readonly IStringLocalizer<Resources> _i18n; | |||
| private bool _initializedColors; | |||
| private bool _initializedBcTypes; | |||
| private bool _initializedBrands; | |||
| @@ -40,10 +41,11 @@ namespace cwebplusApp.Shared.Services { | |||
| public event EventHandler Changed; | |||
| public MasterDataService(IJSRuntime jsRuntime, ILFBicycleRest lFBicycleRest, IStringLocalizer<Resources> i18n) { | |||
| public MasterDataService(IJSRuntime jsRuntime, IBicycleRestService bicycleRestService, IStringLocalizer<Resources> i18n, OnlineStatusProvider onlineStatusProvider) { | |||
| _jsRuntime = jsRuntime; | |||
| _lFBicycleRest = lFBicycleRest; | |||
| _bicycleRestService = bicycleRestService; | |||
| _i18n = i18n; | |||
| _onlineStatusProvider = onlineStatusProvider; | |||
| _firstActivation = true; | |||
| _brands = Defaults.GetBrandDefaults(_i18n).ToArray(); | |||
| _colors = Defaults.GetColorDefaults(_i18n).ToArray(); | |||
| @@ -51,17 +53,21 @@ namespace cwebplusApp.Shared.Services { | |||
| } | |||
| public async Task SynchronizeMasterdata() { | |||
| try { | |||
| await SynchronizeColors(); | |||
| await SynchronizeBcTypes(); | |||
| await SynchronizeBrands(); | |||
| } finally { | |||
| _firstActivation = false; | |||
| if (_onlineStatusProvider.Online) { | |||
| try { | |||
| await SynchronizeColors(); | |||
| await SynchronizeBcTypes(); | |||
| await SynchronizeBrands(); | |||
| } finally { | |||
| _firstActivation = false; | |||
| } | |||
| } else { | |||
| throw new Exception("No internet connection available!"); | |||
| } | |||
| } | |||
| public async Task SynchronizeColors() { | |||
| ColorItem[] colors = (await _lFBicycleRest.GetColors()).ToArray(); | |||
| ColorItem[] colors = (await _bicycleRestService.GetColors()).ToArray(); | |||
| if (colors != null && colors.Length > 0) { | |||
| _colors = colors; | |||
| await SaveColorsToStorage(colors); | |||
| @@ -69,7 +75,7 @@ namespace cwebplusApp.Shared.Services { | |||
| } | |||
| public async Task SynchronizeBcTypes() { | |||
| BicycleType[] bicycleTypes = (await _lFBicycleRest.GetBicycleTypes()).ToArray(); | |||
| BicycleType[] bicycleTypes = (await _bicycleRestService.GetBicycleTypes()).ToArray(); | |||
| if (bicycleTypes != null && bicycleTypes.Length > 0) { | |||
| _bicycleTypes = bicycleTypes; | |||
| await SaveBcTypesToStorage(bicycleTypes); | |||
| @@ -77,7 +83,7 @@ namespace cwebplusApp.Shared.Services { | |||
| } | |||
| public async Task SynchronizeBrands() { | |||
| Brand[] brands = (await _lFBicycleRest.GetBrands()).ToArray(); | |||
| Brand[] brands = (await _bicycleRestService.GetBrands()).ToArray(); | |||
| if (brands != null && brands.Length > 0) { | |||
| _brands = brands; | |||
| await SaveBrandsToStorage(brands); | |||
| @@ -0,0 +1,39 @@ | |||
| using Microsoft.JSInterop; | |||
| using System.Collections.Generic; | |||
| namespace cwebplusApp.Shared.Services { | |||
| public class OnlineStatusProvider { | |||
| public bool Online { get => online; } | |||
| public delegate void OnlineStatusChangeCallBack(bool online); | |||
| public IJSRuntime JSRuntime { get; set; } | |||
| private bool online; | |||
| private HashSet<OnlineStatusChangeCallBack> OnlineStatusChangeCallBacks; | |||
| public OnlineStatusProvider(IJSRuntime jSRuntime) { | |||
| this.JSRuntime = jSRuntime; | |||
| OnlineStatusChangeCallBacks = new(); | |||
| var dotNetObjRef = DotNetObjectReference.Create(this); | |||
| JSRuntime.InvokeVoidAsync("registerOnlineStatusHandler", dotNetObjRef); | |||
| } | |||
| [JSInvokable] | |||
| public void SetOnlineStatus(bool isOnline) { | |||
| this.online = isOnline; | |||
| foreach (OnlineStatusChangeCallBack OnlineStatusCallBack in OnlineStatusChangeCallBacks) { | |||
| OnlineStatusCallBack?.Invoke(isOnline); | |||
| } | |||
| } | |||
| public void AddOnlineStatusChangeCallBack(OnlineStatusChangeCallBack listener) { | |||
| OnlineStatusChangeCallBacks.Add(listener); | |||
| } | |||
| public void RemoveOnlineStatusChangeCallBack(OnlineStatusChangeCallBack listener) { | |||
| OnlineStatusChangeCallBacks.Remove(listener); | |||
| } | |||
| } | |||
| } | |||
| @@ -54,6 +54,15 @@ | |||
| await component.invokeMethodAsync("OnStorageUpdated", e.key); | |||
| }); | |||
| } | |||
| function registerOnlineStatusHandler(dotNetObjRef) { | |||
| function onlineStatusHandler() { | |||
| dotNetObjRef.invokeMethodAsync("SetOnlineStatus", navigator.onLine); | |||
| }; | |||
| onlineStatusHandler(); | |||
| window.addEventListener("online", onlineStatusHandler); | |||
| window.addEventListener("offline", onlineStatusHandler); | |||
| } | |||
| </script> | |||
| <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" | |||
| @@ -92,7 +92,21 @@ self.addEventListener('fetch', event => { | |||
| cache.put(event.request, response.clone()); | |||
| return response; | |||
| }); | |||
| }); | |||
| }).catch(function () { | |||
| var cr; | |||
| console.log('catch network fetch failure 1'); | |||
| event.waitUntil( | |||
| caches.match(event.request).then(cacheRes => { | |||
| console.log('catch network fetch failure 2'); | |||
| console.log(cacheRes); | |||
| cr = cacheRes; | |||
| }) | |||
| ); | |||
| console.log('catch network fetch failure 3'); | |||
| console.log(cr); | |||
| return cr; | |||
| //fromCache(event.request); | |||
| }) | |||
| } else { | |||
| event.respondWith( | |||
| caches.match(event.request).then(cacheRes => { | |||
| @@ -100,4 +114,38 @@ self.addEventListener('fetch', event => { | |||
| }) | |||
| ); | |||
| } | |||
| }); | |||
| }); | |||
| //self.addEventListener('fetch', event => { | |||
| // if (event.request.url.endsWith(appsettings_url)) { | |||
| // networkOrCache(event.request); | |||
| // } else { | |||
| // event.respondWith( | |||
| // caches.match(event.request).then(cacheRes => { | |||
| // return cacheRes || fetch(event.request); | |||
| // }) | |||
| // ); | |||
| // } | |||
| //}); | |||
| //function networkOrCache(request) { | |||
| // return fetch(request).then(function (response) { | |||
| // caches.open(staticCacheName).then(function (cache) { | |||
| // console.log('update cache'); | |||
| // cache.put(request, response.clone()); | |||
| // }); | |||
| // return response.ok ? response : fromCache(request); | |||
| // //}).catch(function () { | |||
| // // return fromCache(request); | |||
| // }); | |||
| //} | |||
| //function fromCache(request) { | |||
| // return caches.open(staticCacheName).then(function (cache) { | |||
| // return cache.match(request).then(function (matching) { | |||
| // return matching || Promise.reject('request-not-in-cache'); | |||
| // }); | |||
| // }); | |||
| //} | |||