Compare commits
2 commits
2fcb6e1fae
...
ce21244517
Author | SHA1 | Date | |
---|---|---|---|
ce21244517 | |||
65276d4984 |
21 changed files with 103 additions and 26 deletions
|
@ -1,5 +1,9 @@
|
||||||
namespace Neighbourhood.omg.lol {
|
namespace Neighbourhood.omg.lol {
|
||||||
public partial class App : Application {
|
public partial class App : Application {
|
||||||
|
|
||||||
|
public static string Name { get; set; }
|
||||||
|
public static string Version { get; set; }
|
||||||
|
|
||||||
public App(NavigatorService navigatorService) {
|
public App(NavigatorService navigatorService) {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
if (!string.IsNullOrEmpty(Pic?.Id)) {
|
if (!string.IsNullOrEmpty(Pic?.Id)) {
|
||||||
await api.DeletePic(State.SelectedAddressName, Pic.Id);
|
await api.DeletePic(State.SelectedAddressName, Pic.Id);
|
||||||
await State.RefreshPics();
|
await State.RefreshPics();
|
||||||
|
State.SendRefresh();
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +93,7 @@
|
||||||
if(!string.IsNullOrEmpty(Pic?.Id)) {
|
if(!string.IsNullOrEmpty(Pic?.Id)) {
|
||||||
await api.PostPicDescription(State.SelectedAddressName, Pic.Id, Description);
|
await api.PostPicDescription(State.SelectedAddressName, Pic.Id, Description);
|
||||||
await State.RefreshPics();
|
await State.RefreshPics();
|
||||||
|
State.SendRefresh();
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,7 @@
|
||||||
if (!string.IsNullOrEmpty(Status?.Id)) {
|
if (!string.IsNullOrEmpty(Status?.Id)) {
|
||||||
await api.DeleteStatus(State.SelectedAddressName, Status.Id);
|
await api.DeleteStatus(State.SelectedAddressName, Status.Id);
|
||||||
await State.RefreshStatuses();
|
await State.RefreshStatuses();
|
||||||
|
State.SendRefresh();
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +113,7 @@
|
||||||
if (!string.IsNullOrEmpty(Status?.Id)) {
|
if (!string.IsNullOrEmpty(Status?.Id)) {
|
||||||
await api.PatchStatus(State.SelectedAddressName, Status.Id, Content, Emoji);
|
await api.PatchStatus(State.SelectedAddressName, Status.Id, Content, Emoji);
|
||||||
await State.RefreshStatuses();
|
await State.RefreshStatuses();
|
||||||
|
State.SendRefresh();
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Reload() {
|
public async Task Reload() {
|
||||||
if (Html == null){
|
// if (Html == null){
|
||||||
Html = await api.GetHtml(Url);
|
Html = await api.GetHtml(Url);
|
||||||
string? HtmlString = Html?.ToString();
|
string? HtmlString = Html?.ToString();
|
||||||
HtmlString = HtmlString?.Replace("</head>", "<base target='_blank'></head>");
|
HtmlString = HtmlString?.Replace("</head>", "<base target='_blank'></head>");
|
||||||
HtmlString = HtmlString?.Replace("</body>", "<script src='https://cdn.jsdelivr.net/npm/@iframe-resizer/child'></script></body>");
|
HtmlString = HtmlString?.Replace("</body>", "<script src='https://cdn.jsdelivr.net/npm/@iframe-resizer/child'></script></body>");
|
||||||
Html = (MarkupString)HtmlString;
|
Html = (MarkupString)HtmlString;
|
||||||
}
|
// }
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
@using System.Reflection
|
@inject CustomAuthenticationStateProvider AuthStateProvider;
|
||||||
@inject CustomAuthenticationStateProvider AuthStateProvider;
|
|
||||||
@inject State State;
|
@inject State State;
|
||||||
<AuthorizeView>
|
<AuthorizeView>
|
||||||
<Authorized>
|
<Authorized>
|
||||||
|
@ -45,7 +44,7 @@
|
||||||
</a>
|
</a>
|
||||||
<a class="row medium-opacity">
|
<a class="row medium-opacity">
|
||||||
<i class="fa-solid fa-circle-info tiny"></i>
|
<i class="fa-solid fa-circle-info tiny"></i>
|
||||||
<small>@assembly.Name - @assembly.Version?.ToString()</small>
|
<small>@App.Name - @App.Version</small>
|
||||||
</a>
|
</a>
|
||||||
</menu>
|
</menu>
|
||||||
</button>
|
</button>
|
||||||
|
@ -81,7 +80,6 @@
|
||||||
</AuthorizeView>
|
</AuthorizeView>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
AssemblyName assembly = Assembly.GetExecutingAssembly().GetName();
|
|
||||||
public void changeAddress(AddressResponseData address) {
|
public void changeAddress(AddressResponseData address) {
|
||||||
State.SelectedAddress = address;
|
State.SelectedAddress = address;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@
|
||||||
if(!string.IsNullOrEmpty(Description) && response != null && !string.IsNullOrEmpty(response.Id)) {
|
if(!string.IsNullOrEmpty(Description) && response != null && !string.IsNullOrEmpty(response.Id)) {
|
||||||
await api.PostPicDescription(State.SelectedAddressName, response.Id, Description);
|
await api.PostPicDescription(State.SelectedAddressName, response.Id, Description);
|
||||||
await State.RefreshPics();
|
await State.RefreshPics();
|
||||||
|
State.SendRefresh();
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,9 @@
|
||||||
var result = await api.StatusPost(State!.SelectedAddressName!, post);
|
var result = await api.StatusPost(State!.SelectedAddressName!, post);
|
||||||
if(result != null){
|
if(result != null){
|
||||||
await State.RefreshStatuses();
|
await State.RefreshStatuses();
|
||||||
|
State.SendRefresh();
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
navigationManager.NavigateTo("/statuslog/latest");
|
// navigationManager.NavigateTo("/statuslog/latest");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Active = false;
|
this.Active = false;
|
||||||
|
|
|
@ -65,9 +65,11 @@ else {
|
||||||
|
|
||||||
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
||||||
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
||||||
addresses = await State.GetDirectory(true);
|
using (State.GetRefreshToken()) {
|
||||||
GroupAddresses();
|
addresses = await State.GetDirectory(true);
|
||||||
State.IsRefreshing = false;
|
GroupAddresses();
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,10 @@
|
||||||
|
|
||||||
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
||||||
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
||||||
messages = await State.GetEphemeralMessages(true);
|
using (State.GetRefreshToken()) {
|
||||||
State.IsRefreshing = false;
|
messages = await State.GetEphemeralMessages(true);
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,10 @@
|
||||||
|
|
||||||
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
||||||
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
||||||
garden = await State.GetNowGarden(true);
|
using (State.GetRefreshToken()){
|
||||||
State.IsRefreshing = false;
|
garden = await State.GetNowGarden(true);
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,18 @@
|
||||||
if (fragment.EndsWith("now")) await ReloadNow();
|
if (fragment.EndsWith("now")) await ReloadNow();
|
||||||
else if (fragment.EndsWith("profile")) await ReloadProfile();
|
else if (fragment.EndsWith("profile")) await ReloadProfile();
|
||||||
bio = await State.GetBio(Address);
|
bio = await State.GetBio(Address);
|
||||||
|
State.PropertyChanged += StateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
||||||
|
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
||||||
|
using (State.GetRefreshToken()){
|
||||||
|
await ReloadNow();
|
||||||
|
await ReloadProfile();
|
||||||
|
bio = await State.GetBio(Address);
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ReloadNow() {
|
private async Task ReloadNow() {
|
||||||
|
|
|
@ -34,8 +34,10 @@
|
||||||
|
|
||||||
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
||||||
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
||||||
pics = await PicsFunc(true);
|
using (State.GetRefreshToken()){
|
||||||
State.IsRefreshing = false;
|
pics = await PicsFunc(true);
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
@inject State State
|
@inject State State
|
||||||
|
|
||||||
<button id="refreshButton" class="absolute transparent circle top right margin" @onclick="() => State.IsRefreshing = true">
|
<button id="refreshButton" class="absolute transparent circle top right margin" @onclick="() => State.SendRefresh()">
|
||||||
<i class="fa-solid fa-arrow-rotate-right @(State.IsRefreshing ? "fa-spin" : "")"></i>
|
<i class="fa-solid fa-arrow-rotate-right @(State.IsRefreshing ? "fa-spin" : "")"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
public bool Editable { get; set; } = false;
|
public bool Editable { get; set; } = false;
|
||||||
|
|
||||||
public EditStatusDialog? Dialog { get; set; }
|
public EditStatusDialog? Dialog { get; set; }
|
||||||
|
|
||||||
private List<Status>? statuses;
|
private List<Status>? statuses;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync() {
|
protected override async Task OnInitializedAsync() {
|
||||||
|
@ -33,8 +33,10 @@
|
||||||
|
|
||||||
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
private async void StateChanged(object? sender, PropertyChangedEventArgs e) {
|
||||||
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
if (e.PropertyName == nameof(State.IsRefreshing) && State.IsRefreshing) {
|
||||||
statuses = await StatusFunc(true);
|
using (State.GetRefreshToken()) {
|
||||||
State.IsRefreshing = false;
|
statuses = await StatusFunc(true);
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ public partial class LoginWebViewPage : ContentPage
|
||||||
if ( client_id != null
|
if ( client_id != null
|
||||||
&& client_secret != null
|
&& client_secret != null
|
||||||
&& redirect_uri != null) {
|
&& redirect_uri != null) {
|
||||||
|
//this.loginwebview.UserAgent = new System.Net.Http.Headers.ProductInfoHeaderValue(App.Name, App.Version).ToString();
|
||||||
this.loginwebview.Source = $"https://home.omg.lol/oauth/authorize?client_id={client_id}&scope=everything&redirect_uri={redirect_uri}&response_type=code";
|
this.loginwebview.Source = $"https://home.omg.lol/oauth/authorize?client_id={client_id}&scope=everything&redirect_uri={redirect_uri}&response_type=code";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Components.Authorization;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Neighbourhood.omg.lol.Models;
|
using Neighbourhood.omg.lol.Models;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Neighbourhood.omg.lol {
|
namespace Neighbourhood.omg.lol {
|
||||||
public static class MauiProgram {
|
public static class MauiProgram {
|
||||||
|
@ -22,8 +23,16 @@ namespace Neighbourhood.omg.lol {
|
||||||
builder.Services.AddSingleton<State>();
|
builder.Services.AddSingleton<State>();
|
||||||
builder.Services.AddSingleton<NavigatorService>();
|
builder.Services.AddSingleton<NavigatorService>();
|
||||||
|
|
||||||
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
|
//ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
|
||||||
builder.Services.AddSingleton<IConfiguration>(configurationBuilder.AddUserSecrets<App>().Build());
|
//builder.Services.AddSingleton<IConfiguration>(configurationBuilder.AddUserSecrets<App>().Build());
|
||||||
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
|
var details = assembly.GetName();
|
||||||
|
App.Name = details.Name!;
|
||||||
|
App.Version = details.Version!.ToString();
|
||||||
|
var appSettings = $"{App.Name}.appsettings.json";
|
||||||
|
using var stream = assembly.GetManifestResourceStream(appSettings);
|
||||||
|
var config = new ConfigurationBuilder().AddJsonStream(stream).Build();
|
||||||
|
builder.Configuration.AddConfiguration(config);
|
||||||
|
|
||||||
builder.Services.AddAuthorizationCore();
|
builder.Services.AddAuthorizationCore();
|
||||||
builder.Services.AddScoped<CustomAuthenticationStateProvider>();
|
builder.Services.AddScoped<CustomAuthenticationStateProvider>();
|
||||||
|
|
|
@ -70,12 +70,37 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
private bool _isRefreshing;
|
private bool _isRefreshing;
|
||||||
public bool IsRefreshing {
|
public bool IsRefreshing {
|
||||||
get => _isRefreshing;
|
get => _isRefreshing;
|
||||||
set {
|
private set {
|
||||||
_isRefreshing = value;
|
_isRefreshing = value;
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsRefreshing)));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsRefreshing)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendRefresh() => IsRefreshing = true;
|
||||||
|
|
||||||
|
private static int _refresherCount = 0;
|
||||||
|
private static Mutex mutex = new Mutex();
|
||||||
|
|
||||||
|
public class RefreshToken : IDisposable {
|
||||||
|
public event EventHandler? Disposed;
|
||||||
|
public void Dispose() => Disposed?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
public RefreshToken GetRefreshToken() {
|
||||||
|
mutex.WaitOne();
|
||||||
|
_refresherCount++;
|
||||||
|
mutex.ReleaseMutex();
|
||||||
|
RefreshToken token = new RefreshToken();
|
||||||
|
token.Disposed += RefreshToken_Disposed;
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshToken_Disposed(object? sender, EventArgs e) {
|
||||||
|
mutex.WaitOne();
|
||||||
|
_refresherCount--;
|
||||||
|
if (_refresherCount == 0) IsRefreshing = false;
|
||||||
|
mutex.ReleaseMutex();
|
||||||
|
}
|
||||||
|
|
||||||
private bool _canRefresh;
|
private bool _canRefresh;
|
||||||
public bool CanRefresh {
|
public bool CanRefresh {
|
||||||
get => _canRefresh;
|
get => _canRefresh;
|
||||||
|
|
|
@ -90,6 +90,10 @@
|
||||||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Remove="appsettings.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<MauiFont Remove="Resources\Fonts\fa-brands-400.ttf" />
|
<MauiFont Remove="Resources\Fonts\fa-brands-400.ttf" />
|
||||||
<MauiFont Remove="Resources\Fonts\fa-brands-400.woff2" />
|
<MauiFont Remove="Resources\Fonts\fa-brands-400.woff2" />
|
||||||
|
@ -195,6 +199,10 @@
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="appsettings.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
||||||
<PackageReference Include="Markdig" Version="0.37.0" />
|
<PackageReference Include="Markdig" Version="0.37.0" />
|
||||||
|
|
|
@ -19,8 +19,7 @@ namespace Neighbourhood.omg.lol {
|
||||||
public RestService(string? token = null) {
|
public RestService(string? token = null) {
|
||||||
_client = new HttpClient();
|
_client = new HttpClient();
|
||||||
_client.BaseAddress = new Uri(BaseUrl);
|
_client.BaseAddress = new Uri(BaseUrl);
|
||||||
AssemblyName name = Assembly.GetExecutingAssembly().GetName();
|
_client.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue(App.Name, App.Version));
|
||||||
_client.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue(name.Name ?? "Neighbourhood.omg.lol", name.Version?.ToString()));
|
|
||||||
_serializerOptions = new JsonSerializerOptions {
|
_serializerOptions = new JsonSerializerOptions {
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||||
WriteIndented = true
|
WriteIndented = true
|
||||||
|
|
5
appsettings.json
Normal file
5
appsettings.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"client_id": "08656a9ade42b8ff16b868c4bb33379e",
|
||||||
|
"client_secret": "529e47904ca8900a4fb187ecee2f6221",
|
||||||
|
"redirect_uri": "https://auth.neighbourhood.omg.lol/"
|
||||||
|
}
|
|
@ -461,7 +461,7 @@ article {
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav label {
|
nav label:is(.checkbox, .radio, .switch) {
|
||||||
white-space: break-spaces;
|
white-space: break-spaces;
|
||||||
flex: 1 1 100%;
|
flex: 1 1 100%;
|
||||||
}
|
}
|
Loading…
Reference in a new issue