summaryrefslogtreecommitdiff
path: root/Pages/Component/LoadableContent.razor
blob: 570317ff4575e1bbc5bb368049fb54bbde4af46d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@attribute [CascadingTypeParameter(nameof(T))]
@typeparam T

<CascadingValue Value=this>
	@ChildContent
</CascadingValue>

@code {
	[Parameter]
	public RenderFragment? ChildContent { get; set; }

	[Parameter]
	public required Func<Task<T>> DataSource { private get; set; }

	public T Data { get; private set; }

	public ComponentState ComponentState { get; private set; } = ComponentState.Loading;

	public event EventHandler? OnStateChanged;

	private bool   reloadRequested = false;
	private Task?  loadTask        = null;
	private object loadLock        = new();

	protected override void OnInitialized() => Load();

	public void Load() {
		lock(loadLock) {
			reloadRequested = true;
			if(loadTask is null || loadTask.IsCompleted) {
				//loadTask = Task.Run(LoadInternalAsync);
				loadTask = LoadInternalAsync();
			}
		}
	}

	private async Task LoadInternalAsync() {
		while(true) {
			lock(loadLock) {
				if(!reloadRequested)
					break;
				reloadRequested = false;
			}

			//ComponentState = ComponentState.Loading;
			//await InvokeAsync(() => OnStateChanged?.Invoke(this, EventArgs.Empty));
			//await InvokeAsync(() => StateHasChanged());
			try {
				Data           = await DataSource.Invoke();
				ComponentState = ComponentState.Loaded;
			} catch {
				ComponentState = ComponentState.Error;
			}

			await InvokeAsync(() => OnStateChanged?.Invoke(this, EventArgs.Empty));
			await InvokeAsync(() => StateHasChanged());
		}
	}
}