Now, now garden and profile pages
This commit is contained in:
parent
0e1f734f9f
commit
3f1531a934
17 changed files with 320 additions and 31 deletions
33
Components/ExternalPageComponent.razor
Normal file
33
Components/ExternalPageComponent.razor
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
@inject IJSRuntime JS
|
||||||
|
@if(Html != null) {
|
||||||
|
<iframe id="@id" frameborder="0" scrolling="no" srcdoc="@Html" onload="() => iframeResize({ license: 'GPLv3' })"></iframe>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter]
|
||||||
|
public string Url { get; set; }
|
||||||
|
[Parameter]
|
||||||
|
public string id { get; set; }
|
||||||
|
public MarkupString? Html { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender) {
|
||||||
|
if(firstRender){
|
||||||
|
await Reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Reload() {
|
||||||
|
if (Html == null){
|
||||||
|
RestService api = new RestService();
|
||||||
|
Html = await api.GetHtml(Url);
|
||||||
|
string? HtmlString = Html?.ToString();
|
||||||
|
HtmlString = HtmlString?.Replace("</head>", "<base target='_blank'></head>");
|
||||||
|
HtmlString = HtmlString?.Replace("</body>", "<script src='https://cdn.jsdelivr.net/npm/@iframe-resizer/child'></script></body>");
|
||||||
|
Html = (MarkupString)HtmlString;
|
||||||
|
}
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,10 @@
|
||||||
<i class="fa-light fa-comment-dots"></i>
|
<i class="fa-light fa-comment-dots"></i>
|
||||||
<div>Eph.emer.al</div>
|
<div>Eph.emer.al</div>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
<NavLink class="row nav-link" href="/now">
|
||||||
|
<i class="fa-duotone fa-seedling"></i>
|
||||||
|
<div>Now.garden</div>
|
||||||
|
</NavLink>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<nav class="left m">
|
<nav class="left m">
|
||||||
|
@ -110,6 +114,10 @@
|
||||||
<i class="fa-light fa-comment-dots"></i>
|
<i class="fa-light fa-comment-dots"></i>
|
||||||
<small>Eph.emer.al</small>
|
<small>Eph.emer.al</small>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
<NavLink class="nav-link" href="/now">
|
||||||
|
<i class="fa-duotone fa-seedling"></i>
|
||||||
|
<small>Now.garden</small>
|
||||||
|
</NavLink>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<nav class="bottom s">
|
<nav class="bottom s">
|
||||||
|
@ -125,6 +133,10 @@
|
||||||
<i class="fa-light fa-comment-dots"></i>
|
<i class="fa-light fa-comment-dots"></i>
|
||||||
<small>Eph.emer.al</small>
|
<small>Eph.emer.al</small>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
<NavLink class="nav-link" href="/now">
|
||||||
|
<i class="fa-duotone fa-seedling"></i>
|
||||||
|
<small>Now.garden</small>
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
<AuthorizeView>
|
<AuthorizeView>
|
||||||
<Authorized>
|
<Authorized>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<div class="row center-align">
|
<div class="row center-align">
|
||||||
<h3>
|
<h3>
|
||||||
Ephemeral
|
<i class="fa-light fa-comment-dots"></i> Ephemeral
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="row center-align">
|
<div class="row center-align">
|
||||||
|
|
34
Components/Pages/Now.razor
Normal file
34
Components/Pages/Now.razor
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
@page "/now"
|
||||||
|
@inject State State
|
||||||
|
<div class="row center-align">
|
||||||
|
<h3>
|
||||||
|
<i class="fa-duotone fa-seedling"></i> Now.garden
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="row center-align">
|
||||||
|
<p>Feel free to stroll through the <a href="now.garden">now.garden</a> and take a look at what people are up to.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="now-garden" class="responsive card-grid">
|
||||||
|
<Virtualize ItemsProvider="State.VirtualNowGarden" Context="now" ItemSize="180">
|
||||||
|
<ItemContent>
|
||||||
|
<article class="now">
|
||||||
|
<nav>
|
||||||
|
<a class="author" href="/person/@now.Address#now">
|
||||||
|
<i class="fa-duotone fa-seedling"></i> @now.Address
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
<nav>
|
||||||
|
<small>@now.UpdatedRelative</small>
|
||||||
|
</nav>
|
||||||
|
</article>
|
||||||
|
</ItemContent>
|
||||||
|
<Placeholder>
|
||||||
|
<StatusCardSkeleton></StatusCardSkeleton>
|
||||||
|
</Placeholder>
|
||||||
|
</Virtualize>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
@page "/person/{Address}"
|
@page "/person/{Address}"
|
||||||
@inject State State
|
@inject State State
|
||||||
|
@inject IJSRuntime JS
|
||||||
|
|
||||||
|
|
||||||
<div class="row center-align">
|
<div class="row center-align">
|
||||||
<h3><i class="fa-solid fa-fw fa-at"></i>@Address</h3>
|
<h3><i class="fa-solid fa-fw fa-at"></i>@Address</h3>
|
||||||
|
@ -20,6 +22,10 @@
|
||||||
|
|
||||||
<div class="responsive">
|
<div class="responsive">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
|
<a data-ui="#profile" @onclick="ReloadProfile">
|
||||||
|
<i class="fa-solid fa-id-card"></i>
|
||||||
|
<span>@(Address).omg.lol</span>
|
||||||
|
</a>
|
||||||
<a data-ui="#statuses" class="active">
|
<a data-ui="#statuses" class="active">
|
||||||
<i class="fa-solid fa-message-smile"></i>
|
<i class="fa-solid fa-message-smile"></i>
|
||||||
<span>Status.lol</span>
|
<span>Status.lol</span>
|
||||||
|
@ -28,7 +34,20 @@
|
||||||
<i class="fa-solid fa-images"></i>
|
<i class="fa-solid fa-images"></i>
|
||||||
<span>Some.pics</span>
|
<span>Some.pics</span>
|
||||||
</a>
|
</a>
|
||||||
|
@if(now != null){
|
||||||
|
<a data-ui="#now" @onclick="ReloadNow">
|
||||||
|
<i class="fa-duotone fa-seedling"></i>
|
||||||
|
<span>/Now</span>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="responsive page-container">
|
||||||
|
<div id="profile" class="page no-padding">
|
||||||
|
<a href="@ProfileUrl" target="_blank" class="hover absolute top right chip fill large-elevate">Open in browser <i class="fa-solid fa-arrow-up-right-from-square tiny"></i></a>
|
||||||
|
<ExternalPageComponent id="profile_page" @ref="ProfilePage" Url="@ProfileUrl"></ExternalPageComponent>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="statuses" class="page padding active">
|
<div id="statuses" class="page padding active">
|
||||||
<StatusList StatusFunc="@State.VirtualStatusesFunc(Address)"></StatusList>
|
<StatusList StatusFunc="@State.VirtualStatusesFunc(Address)"></StatusList>
|
||||||
</div>
|
</div>
|
||||||
|
@ -39,13 +58,24 @@
|
||||||
}
|
}
|
||||||
<PicList PicsFunc="@State.VirtualPicsFunc(Address)" Editable="@Editable" Dialog="@editPicDialog"></PicList>
|
<PicList PicsFunc="@State.VirtualPicsFunc(Address)" Editable="@Editable" Dialog="@editPicDialog"></PicList>
|
||||||
</div>
|
</div>
|
||||||
|
@if(now != null){
|
||||||
|
<div id="now" class="page no-padding">
|
||||||
|
<a href="@now.Url" target="_blank" class="hover absolute top right chip fill large-elevate">Open in browser <i class="fa-solid fa-arrow-up-right-from-square tiny"></i></a>
|
||||||
|
<ExternalPageComponent id="now_page" @ref="NowPage" Url="@now.Url"></ExternalPageComponent>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Address { get; set; }
|
public string Address { get; set; }
|
||||||
|
public string ProfileUrl {
|
||||||
|
get => $"https://{Address}.omg.lol/";
|
||||||
|
}
|
||||||
|
|
||||||
private EditPicDialog? editPicDialog { get; set; }
|
private EditPicDialog? editPicDialog { get; set; }
|
||||||
|
public ExternalPageComponent? NowPage { get; set; }
|
||||||
|
public ExternalPageComponent? ProfilePage { get; set; }
|
||||||
|
|
||||||
private bool Editable {
|
private bool Editable {
|
||||||
get => Address == State.SelectedAddressName;
|
get => Address == State.SelectedAddressName;
|
||||||
|
@ -53,7 +83,29 @@
|
||||||
|
|
||||||
private MarkupString? bio;
|
private MarkupString? bio;
|
||||||
|
|
||||||
|
private NowData? now;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync() {
|
protected override async Task OnInitializedAsync() {
|
||||||
bio = await State.GetBio(Address);
|
bio = await State.GetBio(Address);
|
||||||
|
List<NowData> garden = await State.GetNowGarden();
|
||||||
|
now = garden.FirstOrDefault(n => n.Address == Address);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ReloadNow() {
|
||||||
|
if(NowPage != null) {
|
||||||
|
await NowPage.Reload();
|
||||||
|
await ResizeIframes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ReloadProfile() {
|
||||||
|
if (ProfilePage != null) {
|
||||||
|
await ProfilePage.Reload();
|
||||||
|
await ResizeIframes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ResizeIframes() {
|
||||||
|
await JS.InvokeVoidAsync("iframeResize", new { license = "GPLv3" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
<div class="row center-align">
|
<div class="row center-align">
|
||||||
<h3>
|
<h3>
|
||||||
Some.pics
|
<i class="fa-solid fa-images"></i> Some.pics
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="row center-align">
|
<div class="row center-align">
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
|
|
||||||
<div class="row center-align">
|
<div class="row center-align">
|
||||||
<h3>
|
<h3>
|
||||||
<i><svg style="width: 1em; height: 1em; margin-right: 1em;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><path fill="#4dabf7" d="M250 450c-38.388 0-76.775-14.646-106.066-43.934l-100-100c-58.579-58.58-58.579-153.553 0-212.132C100.534 37.336 191.105 35.421 250 88.191c58.898-52.768 149.47-50.853 206.066 5.743 58.58 58.58 58.58 153.553 0 212.132l-100 100C326.778 435.354 288.39 450 250 450" /><path fill="#228be6" d="M220.52 176.634a11.792 11.792 0 1 1-23.586 0 11.792 11.792 0 0 1 23.585 0" /><path fill="#1864ab" stroke="#1864ab" stroke-miterlimit="10" stroke-width="11.32074" d="M220.52 176.634a11.792 11.792 0 1 1-23.586 0 11.792 11.792 0 0 1 23.585 0Z" /><path fill="#228be6" d="M303.066 176.634a11.792 11.792 0 1 1-23.585 0 11.792 11.792 0 0 1 23.585 0" /><path fill="#1864ab" stroke="#1864ab" stroke-miterlimit="10" stroke-width="11.32074" d="M303.066 176.634a11.792 11.792 0 1 1-23.585 0 11.792 11.792 0 0 1 23.585 0Z" /><path fill="#228be6" stroke="#461036" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="18.8679" d="M208.75 223.817c18.875 30.802 63.626 30.802 82.501 0" /><path fill="#1971c2" d="M438.68 212.011c0-32.564-26.399-58.962-58.963-58.962s-58.962 26.398-58.962 58.962 26.398 58.963 58.962 58.963 58.962-26.399 58.962-58.963m-259.433 0c0-32.564-26.398-58.962-58.962-58.962S61.32 179.447 61.32 212.011s26.398 58.963 58.963 58.963 58.962-26.399 58.962-58.963" /><path fill="#4dabf7" stroke="#1864ab" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="18.8679" d="M208.75 223.817c18.875 30.802 63.626 30.802 82.501 0" /></svg></i>
|
<i class="fa-solid fa-message-smile"></i> Statuslog
|
||||||
Statuslog
|
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="row center-align">
|
<div class="row center-align">
|
||||||
|
@ -27,20 +26,5 @@
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|
||||||
private List<Status> statuses;
|
|
||||||
private string statusContent = string.Empty;
|
|
||||||
private string? statusEmoji = null;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask<ItemsProviderResult<Status>> GetStatuses(ItemsProviderRequest request)
|
|
||||||
{
|
|
||||||
// TODO: request.cancellationToken
|
|
||||||
statuses = (await State.GetStatuses()) ?? new List<Status>();
|
|
||||||
var numStatuses = Math.Min(request.Count, statuses.Count - request.StartIndex);
|
|
||||||
return new ItemsProviderResult<Status>(statuses.Skip(request.StartIndex).Take(numStatuses), statuses.Count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,6 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
public ExpirationData Expiration { get; set; }
|
public ExpirationData Expiration { get; set; }
|
||||||
public PreferenceData? Preferences { get; set; }
|
public PreferenceData? Preferences { get; set; }
|
||||||
|
|
||||||
public class TimeData {
|
|
||||||
public long? UnixEpochTime { get; set; }
|
|
||||||
public string? Iso8601Time { get; set; }
|
|
||||||
public string? Rfc2822Time { get; set; }
|
|
||||||
public string? RelativeTime { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RegistrationData : TimeData {
|
public class RegistrationData : TimeData {
|
||||||
public string? Message { get; set; }
|
public string? Message { get; set; }
|
||||||
}
|
}
|
||||||
|
|
17
Models/NowData.cs
Normal file
17
Models/NowData.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Neighbourhood.omg.lol.Models {
|
||||||
|
public class NowData {
|
||||||
|
public string Address { get; set; }
|
||||||
|
public string Url { get; set; }
|
||||||
|
public TimeData Updated { get; set; }
|
||||||
|
|
||||||
|
public string UpdatedRelative {
|
||||||
|
get => State.RelativeTimeFromUnix(Convert.ToInt64(Updated.UnixEpochTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
Models/NowResponseData.cs
Normal file
13
Models/NowResponseData.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Neighbourhood.omg.lol.Models {
|
||||||
|
public class NowResponseData : IOmgLolResponseData {
|
||||||
|
public string Message { get; set; }
|
||||||
|
public long Count { get; set; }
|
||||||
|
public List<NowData> Garden { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
|
|
||||||
public List<Status>? Statuses { get; set; }
|
public List<Status>? Statuses { get; set; }
|
||||||
public List<Pic>? Pics { get; set; }
|
public List<Pic>? Pics { get; set; }
|
||||||
|
public List<NowData>? NowGarden { get; set; }
|
||||||
|
|
||||||
public List<Status>? CachedAddressStatuses { get; set; }
|
public List<Status>? CachedAddressStatuses { get; set; }
|
||||||
public List<Pic>? CachedAddressPics { get; set; }
|
public List<Pic>? CachedAddressPics { get; set; }
|
||||||
|
@ -116,6 +117,24 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<NowData>?> GetNowGarden(bool forceRefresh = false) {
|
||||||
|
RestService api = new RestService();
|
||||||
|
if (forceRefresh || this.NowGarden == null || this.NowGarden.Count == 0) {
|
||||||
|
this.NowGarden = await api.NowGarden();
|
||||||
|
}
|
||||||
|
return this.NowGarden;
|
||||||
|
}
|
||||||
|
public async ValueTask<ItemsProviderResult<NowData>> VirtualNowGarden(ItemsProviderRequest request) {
|
||||||
|
// TODO: request.cancellationToken
|
||||||
|
var garden = (await this.GetNowGarden()) ?? new List<NowData>();
|
||||||
|
var numSeedlings = Math.Min(request.Count, garden.Count - request.StartIndex);
|
||||||
|
return new ItemsProviderResult<NowData>(garden.Skip(request.StartIndex).Take(numSeedlings), garden.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Func<ItemsProviderRequest, ValueTask<ItemsProviderResult<NowData>>> VirtualNowGardenFunc() {
|
||||||
|
return VirtualNowGarden;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<List<Pic>?> GetPics(bool forceRefresh = false) {
|
public async Task<List<Pic>?> GetPics(bool forceRefresh = false) {
|
||||||
if(forceRefresh || this.Pics == null || this.Pics.Count == 0) {
|
if(forceRefresh || this.Pics == null || this.Pics.Count == 0) {
|
||||||
RestService api = new RestService();
|
RestService api = new RestService();
|
||||||
|
@ -162,5 +181,19 @@ namespace Neighbourhood.omg.lol.Models {
|
||||||
|
|
||||||
public async Task RefreshStatuses() => await GetStatuses(forceRefresh: true);
|
public async Task RefreshStatuses() => await GetStatuses(forceRefresh: true);
|
||||||
public async Task RefreshPics() => await GetPics(forceRefresh: true);
|
public async Task RefreshPics() => await GetPics(forceRefresh: true);
|
||||||
|
public async Task RefreshNow() => await GetNowGarden(forceRefresh: true);
|
||||||
|
|
||||||
|
public static string RelativeTimeFromUnix(long unix) {
|
||||||
|
DateTimeOffset createdTime = DateTimeOffset.UnixEpoch.AddSeconds(unix);
|
||||||
|
TimeSpan offset = DateTimeOffset.UtcNow - createdTime;
|
||||||
|
|
||||||
|
var offsetString = string.Empty;
|
||||||
|
if (offset.TotalDays >= 1) offsetString = $"{Math.Floor(offset.TotalDays)} days ago";
|
||||||
|
else if (offset.TotalHours >= 1) offsetString = $"{Math.Floor(offset.TotalHours)} hours, {offset.Minutes} minutes ago";
|
||||||
|
else if (offset.TotalMinutes >= 1) offsetString = $"{Math.Floor(offset.TotalMinutes)} minutes ago";
|
||||||
|
else offsetString = $"{Math.Floor(offset.TotalSeconds)} seconds ago";
|
||||||
|
|
||||||
|
return offsetString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
Models/TimeData.cs
Normal file
14
Models/TimeData.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Neighbourhood.omg.lol.Models {
|
||||||
|
public class TimeData {
|
||||||
|
public long? UnixEpochTime { get; set; }
|
||||||
|
public string? Iso8601Time { get; set; }
|
||||||
|
public string? Rfc2822Time { get; set; }
|
||||||
|
public string? RelativeTime { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ namespace Neighbourhood.omg.lol {
|
||||||
if (token != null) _client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
if (token != null) _client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<T?> Get<T>(string uri, CancellationToken cancellationToken = default) where T:IOmgLolResponseData {
|
private async Task<T?> Get<T>(string uri, CancellationToken cancellationToken = default) where T : IOmgLolResponseData {
|
||||||
T? responseData = default(T);
|
T? responseData = default(T);
|
||||||
try {
|
try {
|
||||||
HttpResponseMessage response = await _client.GetAsync(uri, cancellationToken: cancellationToken);
|
HttpResponseMessage response = await _client.GetAsync(uri, cancellationToken: cancellationToken);
|
||||||
|
@ -148,6 +148,9 @@ namespace Neighbourhood.omg.lol {
|
||||||
public async Task<PutPicResponseData?> PostPicDescription(string address, string id, string description) =>
|
public async Task<PutPicResponseData?> PostPicDescription(string address, string id, string description) =>
|
||||||
(await Post<PutPicResponseData, PostPic>($"/address/{address}/pics/{id}", new PostPic { Description = description }));
|
(await Post<PutPicResponseData, PostPic>($"/address/{address}/pics/{id}", new PostPic { Description = description }));
|
||||||
|
|
||||||
|
public async Task<List<NowData>?> NowGarden() =>
|
||||||
|
(await Get<NowResponseData>($"/now/garden"))?.Garden ?? new List<NowData>();
|
||||||
|
|
||||||
public async Task<List<string>> Ephemeral() {
|
public async Task<List<string>> Ephemeral() {
|
||||||
List<string> notes = new List<string>();
|
List<string> notes = new List<string>();
|
||||||
Uri Uri = new Uri($"https://eph.emer.al/");
|
Uri Uri = new Uri($"https://eph.emer.al/");
|
||||||
|
@ -157,7 +160,7 @@ namespace Neighbourhood.omg.lol {
|
||||||
string pattern = @"<p class=""post"">(.*?)<\/p>";
|
string pattern = @"<p class=""post"">(.*?)<\/p>";
|
||||||
var matches = Regex.Matches(str, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
|
var matches = Regex.Matches(str, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
|
||||||
foreach (Match match in matches) {
|
foreach (Match match in matches) {
|
||||||
notes.Add(match.Groups[1].Value);
|
notes.Add(match.Groups[1].Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
@ -183,5 +186,19 @@ namespace Neighbourhood.omg.lol {
|
||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<MarkupString?> GetHtml(string url) {
|
||||||
|
string? raw = null;
|
||||||
|
try {
|
||||||
|
HttpResponseMessage response = await _client.GetAsync(url);
|
||||||
|
if (response.IsSuccessStatusCode) {
|
||||||
|
raw = await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Debug.WriteLine(@"\tERROR {0}", ex.Message);
|
||||||
|
}
|
||||||
|
return string.IsNullOrEmpty(raw) ? null : (MarkupString)raw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,11 +199,12 @@ article.ephemeral {
|
||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-grid{
|
.card-grid {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction:row;
|
flex-direction: row;
|
||||||
flex-wrap:wrap;
|
flex-wrap: wrap;
|
||||||
gap: .5rem;
|
gap: .5rem;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pics article {
|
#pics article {
|
||||||
|
@ -230,4 +231,41 @@ article.ephemeral {
|
||||||
|
|
||||||
#pics article > img:first-child {
|
#pics article > img:first-child {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#now-garden > :not(.now) {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-grid > * {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-container > .page {
|
||||||
|
display:flex;
|
||||||
|
flex-direction:column;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
#now.page > iframe {
|
||||||
|
width:100%;
|
||||||
|
flex-grow: 1;
|
||||||
|
border: none;
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
main, .page-container {
|
||||||
|
flex-grow:1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover {
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
|
@ -12,6 +12,7 @@
|
||||||
<link rel="stylesheet" href="Neighbourhood.omg.lol.styles.css" />
|
<link rel="stylesheet" href="Neighbourhood.omg.lol.styles.css" />
|
||||||
<script type="module" src="vendor/beer.min.js"></script>
|
<script type="module" src="vendor/beer.min.js"></script>
|
||||||
<script type="module" src="vendor/material-dynamic-colors.min.js"></script>
|
<script type="module" src="vendor/material-dynamic-colors.min.js"></script>
|
||||||
|
<script src="vendor/iframe-resizer/parent.js"></script>
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
24
wwwroot/vendor/iframe-resizer/child.js
vendored
Normal file
24
wwwroot/vendor/iframe-resizer/child.js
vendored
Normal file
File diff suppressed because one or more lines are too long
24
wwwroot/vendor/iframe-resizer/parent.js
vendored
Normal file
24
wwwroot/vendor/iframe-resizer/parent.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue