Skip to content

Commit 43eabed

Browse files
committed
Extract local storage into own project
1 parent 8e510dd commit 43eabed

17 files changed

Lines changed: 194 additions & 169 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
using System.Reflection;
2+
using Blazored.LocalStorage;
3+
4+
namespace PocketDDD.BlazorClient.LocalStorage;
5+
6+
public abstract class LocalStorageContext
7+
{
8+
private readonly ILocalStorageService _localStorage;
9+
10+
protected LocalStorageContext(ILocalStorageService localStorage)
11+
{
12+
_localStorage = localStorage;
13+
14+
InitialiseKeys(typeof(KeyItem<>));
15+
InitialiseKeys(typeof(KeyListItem<>));
16+
InitialiseKeys(typeof(KeySyncItem<>));
17+
}
18+
19+
private void InitialiseKeys(Type keyType)
20+
{
21+
this.GetType()
22+
.GetProperties()
23+
.Where(p => p.PropertyType.IsGenericType &&
24+
p.PropertyType.GetGenericTypeDefinition() == keyType)
25+
.ToList()
26+
.ForEach(item =>
27+
{
28+
Type itemType = item.PropertyType.GetGenericArguments()[0];
29+
Type genericType = keyType.MakeGenericType(itemType);
30+
31+
ConstructorInfo? constructor = genericType.GetConstructor(new[] { typeof(ILocalStorageService), typeof(string) });
32+
object? instance = constructor?.Invoke(new object[] { _localStorage, item.Name });
33+
item.SetValue(this, instance);
34+
});
35+
}
36+
}
37+
38+
public class KeyItem<T>
39+
{
40+
private readonly ILocalStorageService _localStorage;
41+
private readonly string _key;
42+
43+
public KeyItem(ILocalStorageService localStorage, string key)
44+
{
45+
_localStorage = localStorage;
46+
_key = key;
47+
}
48+
49+
public ValueTask<T?> GetAsync() => _localStorage.GetItemAsync<T?>(_key);
50+
public async ValueTask<T> GetOrDefaultAsync(Func<T> defaultConstructor)
51+
{
52+
var val = await _localStorage.GetItemAsync<T?>(_key);
53+
return val ?? defaultConstructor();
54+
}
55+
56+
public ValueTask SetAsync(T item) => _localStorage.SetItemAsync(_key, item);
57+
58+
public void SubscribeToChanges(Action<T> callback)
59+
{
60+
_localStorage.Changed += (_, args) =>
61+
{
62+
if (args.Key == _key)
63+
callback((T)args.NewValue);
64+
};
65+
}
66+
}
67+
68+
public class KeyListItem<T>
69+
{
70+
private readonly ILocalStorageService _localStorage;
71+
private readonly string _key;
72+
73+
public KeyListItem(ILocalStorageService localStorage, string key)
74+
{
75+
_localStorage = localStorage;
76+
_key = key;
77+
}
78+
79+
public async ValueTask<List<T>> GetOrDefaultAsync() =>
80+
await _localStorage.GetItemAsync<List<T>>(_key) ?? new List<T>();
81+
82+
public ValueTask SetAsync(List<T> list) => _localStorage.SetItemAsync(_key, list);
83+
84+
public void SubscribeToChanges(Action<List<T>> callback)
85+
{
86+
_localStorage.Changed += (_, args) =>
87+
{
88+
if (args.Key == _key)
89+
callback((List<T>)args.NewValue);
90+
};
91+
}
92+
}
93+
94+
public class KeySyncItem<T>
95+
{
96+
private readonly ILocalStorageService _localStorage;
97+
private readonly string _keyPrefix;
98+
99+
public KeySyncItem(ILocalStorageService localStorage, string key)
100+
{
101+
_localStorage = localStorage;
102+
_keyPrefix = $"{key}_sync_";
103+
}
104+
private ValueTask<T> GetItemAsync(string key) => _localStorage.GetItemAsync<T>(key);
105+
public ValueTask<T?> GetSyncItemAsync(string clientId) => _localStorage.GetItemAsync<T?>(_keyPrefix + clientId);
106+
public async ValueTask<IList<T>> GetAllSyncItemsAsync()
107+
{
108+
var items = new List<T>();
109+
var keys = await _localStorage.KeysAsync();
110+
foreach (var key in keys)
111+
{
112+
if (key.StartsWith(_keyPrefix))
113+
items.Add((await GetItemAsync(key)));
114+
}
115+
return items;
116+
}
117+
118+
public ValueTask AddSyncItemAsync(T item, string clientId) =>
119+
_localStorage.SetItemAsync(_keyPrefix + clientId, item);
120+
121+
public ValueTask RemoveSyncItemAsync(string clientId) =>
122+
_localStorage.RemoveItemAsync(_keyPrefix + clientId);
123+
124+
public void SubscribeToChanges(Action<IList<T>> callback)
125+
{
126+
_localStorage.Changed += async (_, args) =>
127+
{
128+
if (args.Key.StartsWith(_keyPrefix))
129+
callback((await GetAllSyncItemsAsync()));
130+
};
131+
}
132+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Razor">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
10+
<ItemGroup>
11+
<SupportedPlatform Include="browser" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="Blazored.LocalStorage" Version="4.3.0" />
16+
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="6.0.16" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<Folder Include="wwwroot\" />
21+
</ItemGroup>
22+
23+
</Project>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@using Microsoft.AspNetCore.Components.Web

PocketDDD.BlazorClient/PocketDDD.BlazorClient.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PocketDDD.Server.Model", ".
1515
EndProject
1616
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PocketDDD.Server.DB", "..\PocketDDD.Server\PocketDDD.Server.DB\PocketDDD.Server.DB.csproj", "{48A20EF1-0384-4934-8632-5B7AE5B02C0F}"
1717
EndProject
18+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PocketDDD.BlazorClient.LocalStorage", "PocketDDD.BlazorClient.LocalStorage\PocketDDD.BlazorClient.LocalStorage.csproj", "{5CBDD65B-BAB5-4E97-A1A2-445511B3D6B3}"
19+
EndProject
1820
Global
1921
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2022
Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@ Global
4547
{48A20EF1-0384-4934-8632-5B7AE5B02C0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
4648
{48A20EF1-0384-4934-8632-5B7AE5B02C0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
4749
{48A20EF1-0384-4934-8632-5B7AE5B02C0F}.Release|Any CPU.Build.0 = Release|Any CPU
50+
{5CBDD65B-BAB5-4E97-A1A2-445511B3D6B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51+
{5CBDD65B-BAB5-4E97-A1A2-445511B3D6B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
52+
{5CBDD65B-BAB5-4E97-A1A2-445511B3D6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
53+
{5CBDD65B-BAB5-4E97-A1A2-445511B3D6B3}.Release|Any CPU.Build.0 = Release|Any CPU
4854
EndGlobalSection
4955
GlobalSection(SolutionProperties) = preSolution
5056
HideSolutionNode = FALSE

PocketDDD.BlazorClient/PocketDDD.BlazorClient/Features/EventFeedback/Store/EventFeedbackEffects.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ namespace PocketDDD.BlazorClient.Features.EventFeedback.Store;
88
public class EventFeedbackEffects
99
{
1010
private readonly IState<EventFeedbackState> _state;
11-
private readonly LocalStorageService _localStorage;
11+
private readonly LocalStorageContext _localStorage;
1212

13-
public EventFeedbackEffects(IState<EventFeedbackState> state, IDispatcher dispatcher, LocalStorageService localStorage)
13+
public EventFeedbackEffects(IState<EventFeedbackState> state, IDispatcher dispatcher, LocalStorageContext localStorage)
1414
{
1515
_state = state;
1616
_localStorage = localStorage;

PocketDDD.BlazorClient/PocketDDD.BlazorClient/Features/EventScore/Store/EventScoreEffects.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ namespace PocketDDD.BlazorClient.Features.EventScore.Store;
66

77
public class EventScoreEffects
88
{
9-
private readonly LocalStorageService _localStorage;
9+
private readonly LocalStorageContext _localStorage;
1010

11-
public EventScoreEffects(LocalStorageService localStorage)
11+
public EventScoreEffects(LocalStorageContext localStorage)
1212
{
1313
_localStorage = localStorage;
1414
}

PocketDDD.BlazorClient/PocketDDD.BlazorClient/Features/Home/Components/Home.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
@inject IState<HomeState> State
1313
@inject IDispatcher Dispatcher
1414
@inject IDialogService Dialog
15-
@inject LocalStorageService LocalStorage
15+
@inject LocalStorageContext LocalStorage
1616

1717
@WhenLoadingAndNotFailedShowAlert()
1818
@WhenLoadingFailedShowCard()

PocketDDD.BlazorClient/PocketDDD.BlazorClient/Features/Home/Store/HomeEffects.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,17 @@
55
using PocketDDD.BlazorClient.Services;
66
using PocketDDD.Shared.API.RequestDTOs;
77
using System.Collections.ObjectModel;
8-
using EventDataUpdatedAction = PocketDDD.BlazorClient.Services.EventDataUpdatedAction;
98

109
namespace PocketDDD.BlazorClient.Features.Home.Store;
1110

1211
public class HomeEffects
1312
{
1413
private readonly IState<HomeState> _state;
15-
private readonly LocalStorageService _localStorage;
14+
private readonly LocalStorageContext _localStorage;
1615
private readonly IPocketDDDApiService _pocketDDDAPI;
1716
private readonly IDialogService _dialog;
1817

19-
public HomeEffects(IState<HomeState> state, IDispatcher dispatcher, LocalStorageService localStorage,
18+
public HomeEffects(IState<HomeState> state, IDispatcher dispatcher, LocalStorageContext localStorage,
2019
IPocketDDDApiService pocketDDDAPI, IDialogService dialog)
2120
{
2221
_state = state;

PocketDDD.BlazorClient/PocketDDD.BlazorClient/Features/Security/Store/SecurityEffects.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ namespace PocketDDD.BlazorClient.Features.Security.Store;
1111
public class SecurityEffects
1212
{
1313
private readonly IState<SecurityState> _state;
14-
private readonly LocalStorageService _localStorage;
14+
private readonly LocalStorageContext _localStorage;
1515
private readonly IPocketDDDApiService _pocketDDDAPI;
1616
private readonly IDialogService _dialog;
1717

1818
private IDialogReference? currentDialogReference = null;
1919

20-
public SecurityEffects(IState<SecurityState> state, LocalStorageService localStorage, IPocketDDDApiService pocketDDDAPI, IDialogService dialog)
20+
public SecurityEffects(IState<SecurityState> state, LocalStorageContext localStorage, IPocketDDDApiService pocketDDDAPI, IDialogService dialog)
2121
{
2222
_state = state;
2323
_localStorage = localStorage;

PocketDDD.BlazorClient/PocketDDD.BlazorClient/Features/Session/Store/SessionEffects.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ namespace PocketDDD.BlazorClient.Features.Session.Store;
99
public class SessionEffects
1010
{
1111
private readonly IState<SessionState> _state;
12-
private readonly LocalStorageService _localStorage;
12+
private readonly LocalStorageContext _localStorage;
1313
private readonly IPocketDDDApiService _pocketDDDAPI;
1414
private readonly NavigationManager _navigation;
1515

16-
public SessionEffects(IState<SessionState> state, LocalStorageService localStorage, IPocketDDDApiService pocketDDDAPI, NavigationManager navigation)
16+
public SessionEffects(IState<SessionState> state, LocalStorageContext localStorage, IPocketDDDApiService pocketDDDAPI, NavigationManager navigation)
1717
{
1818
_state = state;
1919
_localStorage = localStorage;

0 commit comments

Comments
 (0)