Added refresh (no pull-to-refresh, yet)

This commit is contained in:
Gordon Pedersen 2024-06-18 11:44:18 +10:00
parent 996e1286cb
commit 413051ad4c
10 changed files with 124 additions and 14 deletions

View file

@ -1,6 +1,10 @@
@page "/ephemeral" @page "/ephemeral"
@implements IDisposable
@inject IJSRuntime JS @inject IJSRuntime JS
@inject State State @inject State State
<RefreshButton></RefreshButton>
<PageHeading title="Eph.emer.al" icon="fa-light fa-comment-dots"> <PageHeading title="Eph.emer.al" icon="fa-light fa-comment-dots">
<Description><a href="https://eph.emer.al">Eph.emer.al</a> is a place for fleeting thoughts. Everything on this page will disappear after a while.</Description> <Description><a href="https://eph.emer.al">Eph.emer.al</a> is a place for fleeting thoughts. Everything on this page will disappear after a while.</Description>
</PageHeading> </PageHeading>
@ -24,7 +28,21 @@
protected override async Task OnInitializedAsync() { protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync(); await base.OnInitializedAsync();
if (messages == null || messages.Count == 0) messages = await State.GetEphemeralMessages(); if (messages == null || messages.Count == 0) messages = await State.GetEphemeralMessages();
State.PropertyChanged += StateChanged;
State.CanRefresh = true;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
await JS.InvokeVoidAsync("removeElementById", "ephemeral-loading"); await JS.InvokeVoidAsync("removeElementById", "ephemeral-loading");
} }
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
messages = await State.GetEphemeralMessages(true);
State.IsRefreshing = false;
}
}
public void Dispose() {
State.PropertyChanged -= StateChanged;
State.CanRefresh = false;
}
} }

View file

@ -1,6 +1,10 @@
@page "/now" @page "/now"
@implements IDisposable
@inject IJSRuntime JS @inject IJSRuntime JS
@inject State State @inject State State
<RefreshButton></RefreshButton>
<PageHeading title="Now.garden" icon="fa-duotone fa-seedling"> <PageHeading title="Now.garden" icon="fa-duotone fa-seedling">
<Description>Feel free to stroll through the <a href="now.garden">now.garden</a> and take a look at what people are up to.</Description> <Description>Feel free to stroll through the <a href="now.garden">now.garden</a> and take a look at what people are up to.</Description>
</PageHeading> </PageHeading>
@ -31,7 +35,21 @@
protected override async Task OnInitializedAsync() { protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync(); await base.OnInitializedAsync();
if (garden == null || garden.Count == 0) garden = await State.GetNowGarden(); if (garden == null || garden.Count == 0) garden = await State.GetNowGarden();
State.PropertyChanged += StateChanged;
State.CanRefresh = true;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
await JS.InvokeVoidAsync("removeElementById", "now-loading"); await JS.InvokeVoidAsync("removeElementById", "now-loading");
} }
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
garden = await State.GetNowGarden(true);
State.IsRefreshing = false;
}
}
public void Dispose() {
State.PropertyChanged -= StateChanged;
State.CanRefresh = false;
}
} }

View file

@ -3,6 +3,8 @@
@inject IJSRuntime JS @inject IJSRuntime JS
@inject NavigationManager Nav @inject NavigationManager Nav
<RefreshButton></RefreshButton>
<div class="row center-align"> <div class="row center-align">
<h3 class="page-heading"><i class="fa-solid fa-fw fa-at"></i>@Address</h3> <h3 class="page-heading"><i class="fa-solid fa-fw fa-at"></i>@Address</h3>
@ -51,7 +53,7 @@
} }
</article> </article>
</div> </div>
<StatusList @ref="StatusList" StatusFunc="@(async() => await State.GetStatuses(Address))" Editable="@Editable"></StatusList> <StatusList @ref="StatusList" StatusFunc="@(async(refresh) => await State.GetStatuses(Address, refresh))" Editable="@Editable"></StatusList>
@if(Address == State.SelectedAddressName) { @if(Address == State.SelectedAddressName) {
<button class="fab circle extra large-elevate" data-ui="#post-modal"> <button class="fab circle extra large-elevate" data-ui="#post-modal">
<i class="fa-solid fa-pen-to-square"></i> <i class="fa-solid fa-pen-to-square"></i>
@ -61,7 +63,7 @@
</div> </div>
<div id="pics" class="page padding"> <div id="pics" class="page padding">
<PicList @ref="PicList" PicsFunc="@(async() => await State.GetPics(Address))" Editable="@Editable"></PicList> <PicList @ref="PicList" PicsFunc="@(async(refresh) => await State.GetPics(Address, refresh))" Editable="@Editable"></PicList>
@if (Address == State.SelectedAddressName) { @if (Address == State.SelectedAddressName) {
<button class="fab circle extra large-elevate" data-ui="#post-modal"> <button class="fab circle extra large-elevate" data-ui="#post-modal">
<i class="fa-solid fa-camera-retro"></i> <i class="fa-solid fa-camera-retro"></i>
@ -84,8 +86,8 @@
get => _address; get => _address;
set { set {
_address = value; _address = value;
if(StatusList != null) StatusList.StatusFunc = async () => await State.GetStatuses(_address); if (StatusList != null) StatusList.StatusFunc = async (refresh) => await State.GetStatuses(_address, refresh);
if(PicList != null) PicList.PicsFunc = async () => await State.GetPics(_address); if (PicList != null) PicList.PicsFunc = async (refresh) => await State.GetPics(_address, refresh);
} }
} }
public string ProfileUrl { public string ProfileUrl {

View file

@ -1,6 +1,8 @@
@page "/pics" @page "/pics"
@inject State State @inject State State
<RefreshButton></RefreshButton>
<PageHeading title="Some.pics" icon="fa-solid fa-images"> <PageHeading title="Some.pics" icon="fa-solid fa-images">
<Description>Sit back, relax, and look at <a href="https://some.pics/">some.pics</a></Description> <Description>Sit back, relax, and look at <a href="https://some.pics/">some.pics</a></Description>
</PageHeading> </PageHeading>
@ -15,7 +17,7 @@
</AuthorizeView> </AuthorizeView>
<div id="pics" class="responsive card-grid"> <div id="pics" class="responsive card-grid">
<PicList PicsFunc="@(async() => await State.GetPics())"></PicList> <PicList PicsFunc="@(async(refresh) => await State.GetPics(refresh))"></PicList>
</div> </div>
@code { @code {

View file

@ -2,6 +2,8 @@
@page "/statuslog/latest" @page "/statuslog/latest"
@inject State State @inject State State
<RefreshButton></RefreshButton>
<PageHeading title="Status.lol" icon="fa-solid fa-message-smile"> <PageHeading title="Status.lol" icon="fa-solid fa-message-smile">
<Description>The latest posts from everyone at <a href="https://status.lol">status.lol</a></Description> <Description>The latest posts from everyone at <a href="https://status.lol">status.lol</a></Description>
</PageHeading> </PageHeading>
@ -16,7 +18,7 @@
</AuthorizeView> </AuthorizeView>
<div id="statuses" class="responsive"> <div id="statuses" class="responsive">
<StatusList StatusFunc="@(async() => await State.GetStatuses())"></StatusList> <StatusList StatusFunc="@(async(refresh) => await State.GetStatuses(refresh))"></StatusList>
</div> </div>
@code { @code {

View file

@ -1,4 +1,5 @@
@inject IJSRuntime JS @implements IDisposable
@inject IJSRuntime JS
@inject State State @inject State State
@if (Editable) { @if (Editable) {
@ -13,7 +14,7 @@
@code { @code {
[Parameter] [Parameter]
public Func<Task<List<Pic>?>> PicsFunc { get; set; } public Func<bool, Task<List<Pic>?>> PicsFunc { get; set; }
[Parameter] [Parameter]
public bool Editable { get; set; } = false; public bool Editable { get; set; } = false;
@ -24,8 +25,22 @@
// TODO: There is a noticable rendering delay between the pics loading and the page rendering // TODO: There is a noticable rendering delay between the pics loading and the page rendering
protected override async Task OnInitializedAsync() { protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync(); await base.OnInitializedAsync();
if (pics == null || pics.Count == 0) pics = await PicsFunc(); if (pics == null || pics.Count == 0) pics = await PicsFunc(false);
State.PropertyChanged += StateChanged;
State.CanRefresh = true;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
await JS.InvokeVoidAsync("removeElementById", "pics-loading"); await JS.InvokeVoidAsync("removeElementById", "pics-loading");
} }
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
pics = await PicsFunc(true);
State.IsRefreshing = false;
}
}
public void Dispose() {
State.PropertyChanged -= StateChanged;
State.CanRefresh = false;
}
} }

View file

@ -0,0 +1,18 @@
@inject State State
<button id="refreshButton" class="absolute transparent circle top right margin" @onclick="() => State.IsRefreshing = true">
<i class="fa-solid fa-arrow-rotate-right @(State.IsRefreshing ? "fa-spin" : "")"></i>
</button>
@code {
protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync();
State.PropertyChanged += StateChanged;
}
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
if (e.PropertyName == nameof(State.IsRefreshing)) {
await InvokeAsync(StateHasChanged);
}
}
}

View file

@ -1,4 +1,5 @@
@inject IJSRuntime JS @implements IDisposable
@inject IJSRuntime JS
@inject State State @inject State State
@if (Editable) { @if (Editable) {
@ -13,7 +14,7 @@
@code { @code {
[Parameter] [Parameter]
public Func<Task<List<Status>?>> StatusFunc { get; set; } public Func<bool, Task<List<Status>?>> StatusFunc { get; set; }
[Parameter] [Parameter]
public bool Editable { get; set; } = false; public bool Editable { get; set; } = false;
@ -23,8 +24,22 @@
protected override async Task OnInitializedAsync() { protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync(); await base.OnInitializedAsync();
if (statuses == null || statuses.Count == 0) statuses = await StatusFunc(); if (statuses == null || statuses.Count == 0) statuses = await StatusFunc(false);
State.PropertyChanged += StateChanged;
State.CanRefresh = true;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
await JS.InvokeVoidAsync("removeElementById", "statusLoading"); await JS.InvokeVoidAsync("removeElementById", "statusLoading");
} }
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
statuses = await StatusFunc(true);
State.IsRefreshing = false;
}
}
public void Dispose() {
State.PropertyChanged -= StateChanged;
State.CanRefresh = false;
}
} }

View file

@ -1,4 +1,5 @@
@using System.Net.Http @using System.ComponentModel
@using System.Net.Http
@using System.Net.Http.Json @using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Routing

View file

@ -1,8 +1,9 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using System.ComponentModel;
using System.Text.Json; using System.Text.Json;
namespace Neighbourhood.omg.lol.Models { namespace Neighbourhood.omg.lol.Models {
public class State { public class State : INotifyPropertyChanged {
// Main data lists // Main data lists
public List<Status>? Statuses { get; set; } public List<Status>? Statuses { get; set; }
public List<Pic>? Pics { get; set; } public List<Pic>? Pics { get; set; }
@ -57,7 +58,25 @@ namespace Neighbourhood.omg.lol.Models {
} }
} }
// refreshing
public event PropertyChangedEventHandler? PropertyChanged;
private bool _isRefreshing;
public bool IsRefreshing {
get => _isRefreshing;
set {
_isRefreshing = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsRefreshing)));
}
}
private bool _canRefresh;
public bool CanRefresh {
get => _canRefresh;
set {
_canRefresh = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CanRefresh)));
}
}
// api service // api service
private RestService api { get; set; } private RestService api { get; set; }