From f24ef392f7527c604fcd1cc71c8b72cbb99767ac Mon Sep 17 00:00:00 2001 From: Gordon Pedersen Date: Thu, 11 Jul 2024 15:57:53 +1000 Subject: [PATCH] Edit profile / profile pic --- Classes/RestService.cs | 117 ++++++++++++++---- Classes/State.cs | 9 ++ Components/EditProfilePicDialog.razor | 117 ++++++++++++++++++ Components/ExternalPageComponent.razor | 17 ++- Components/NewPicDialog.razor | 6 - Components/Pages/EditNow.razor | 43 +++++-- Components/Pages/EditProfile.razor | 112 +++++++++++------- Components/Pages/Person.razor | 12 +- Components/Pages/ShareText.razor | 2 +- Components/Pages/StatuslogLatest.razor | 2 +- Components/ThemeCard.razor | 11 ++ Components/ThemeDialog.razor | 82 +++++++++++++ Models/API/AddressResponseData.cs | 8 +- Models/API/AddressResponseList.cs | 8 +- Models/API/BasicResponseData.cs | 8 +- Models/API/DirectoryResponseData.cs | 8 +- Models/API/EphemeralData.cs | 8 +- Models/API/EphemeralResponseData.cs | 8 +- Models/API/IOmgLolResponseList.cs | 8 +- Models/API/NowContentData.cs | 8 +- Models/API/NowPageResponseData.cs | 8 +- Models/API/NowResponseData.cs | 8 +- Models/API/PatchStatus.cs | 8 +- Models/API/PatchStatusResponseData.cs | 8 +- Models/API/PostPic.cs | 8 +- Models/API/PostProfile.cs | 9 +- Models/API/PreviewCssData.cs | 8 ++ Models/API/ProfileResponseData.cs | 15 +-- Models/API/PutPic.cs | 8 +- Models/API/PutPicResponseData.cs | 8 +- Models/API/SomePicsResponseData.cs | 8 +- Models/API/StatusBioResponseData.cs | 8 +- Models/API/StatusPost.cs | 8 +- Models/API/StatusPostResponseData.cs | 8 +- Models/API/StatusResponseData.cs | 8 +- Models/API/ThemePreviewResponseData.cs | 6 + Models/API/ThemeResponseData.cs | 6 + Models/StatusOrPic.cs | 8 +- Models/Theme.cs | 19 +++ Models/TimeData.cs | 8 +- Neighbourhood.omg.lol.csproj | 157 ++++++++++++------------- wwwroot/css/style.css | 7 +- wwwroot/js/csharp.js | 16 +++ 43 files changed, 611 insertions(+), 338 deletions(-) create mode 100644 Components/EditProfilePicDialog.razor create mode 100644 Components/ThemeCard.razor create mode 100644 Components/ThemeDialog.razor create mode 100644 Models/API/PreviewCssData.cs create mode 100644 Models/API/ThemePreviewResponseData.cs create mode 100644 Models/API/ThemeResponseData.cs create mode 100644 Models/Theme.cs diff --git a/Classes/RestService.cs b/Classes/RestService.cs index 4693d00..9a372f7 100644 --- a/Classes/RestService.cs +++ b/Classes/RestService.cs @@ -9,7 +9,7 @@ using System.Text.RegularExpressions; namespace Neighbourhood.omg.lol { - public class RestService { + public class RestService { HttpClient _client; JsonSerializerOptions _serializerOptions; public const string BaseUrl = "https://api.omg.lol"; @@ -25,6 +25,18 @@ namespace Neighbourhood.omg.lol AddToken(token); } + public T? Deserialize(string str) { + T? responseObj = default(T); + try { + responseObj = JsonSerializer.Deserialize(str, _serializerOptions); + } + catch (JsonException ex) { + Debug.WriteLine(@"\tERROR {0}", ex.Message); + Debug.WriteLine(str); + } + return responseObj; + } + public void AddToken(string? token = null) { if (token == null) token = Task.Run(() => SecureStorage.GetAsync("accounttoken")).GetAwaiter().GetResult(); if (token != null) _client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); @@ -42,8 +54,8 @@ namespace Neighbourhood.omg.lol string str = await response.Content.ReadAsStringAsync(); try { OmgLolResponse? responseObj = await response.Content.ReadFromJsonAsync>(_serializerOptions, cancellationToken: cancellationToken); - if (responseObj?.Request?.Success ?? false) { - responseData = responseObj.Response; + if (responseObj?.Request == null || (responseObj?.Request?.Success ?? false)) { + responseData = responseObj!.Response; } } catch (JsonException ex) { @@ -78,6 +90,81 @@ namespace Neighbourhood.omg.lol return responseData; } + private async Task PostBinary(string uri, FileResult? fileResult = null, CancellationToken cancellationToken = default) where TResponse : IOmgLolResponseData { + TResponse? responseData = default(TResponse); + try { + if (fileResult != null) using (var fileStream = await fileResult.OpenReadAsync()) { + Uri url = new Uri(_client.BaseAddress?.AbsoluteUri + uri); + if (string.IsNullOrEmpty(url.Query)) uri += "?binary"; + else if (!url.Query.Contains("binary")) uri += "&binary"; + + HttpContent fileStreamContent = new StreamContent(fileStream); + fileStreamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(fileResult.ContentType ?? "application/octet-stream"); + fileStreamContent.Headers.ContentLength = fileStream.Length; + HttpResponseMessage response = await _client.PostAsync(uri, fileStreamContent, cancellationToken: cancellationToken); + string str = await response.Content.ReadAsStringAsync(); + if (response.IsSuccessStatusCode) { + OmgLolResponse? responseObj = await response.Content.ReadFromJsonAsync>(_serializerOptions, cancellationToken: cancellationToken); + if (responseObj?.Request?.Success ?? false) { + responseData = responseObj.Response; + } + } + } + } + catch (Exception ex) { + Debug.WriteLine(@"\tERROR {0}", ex.Message); + } + + return responseData; + } + + private async Task PostMultipart(string uri, TData? data = null, FileResult? fileResult = null, CancellationToken cancellationToken = default) + where TResponse : IOmgLolResponseData where TData : class + { + if(fileResult != null) { + using (var fileStream = await fileResult.OpenReadAsync()) + return await PostMultipart(uri, data: data, fileStream: fileStream, fileName: fileResult.FileName, contentType: fileResult.ContentType); + } + else return await PostMultipart(uri, data, fileStream: null); + } + + private async Task PostMultipart(string uri, TData? data = null, Stream? fileStream = null, string? fileName = null, string? contentType = null, CancellationToken cancellationToken = default) + where TResponse : IOmgLolResponseData where TData : class + { + TResponse? responseData = default; + try { + using (MultipartFormDataContent formData = new MultipartFormDataContent()) { + if(fileStream != null) { + HttpContent fileStreamContent = new StreamContent(fileStream); + fileStreamContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") { + Name = "\"file\"", + FileName = $"\"{fileName}\"" ?? "\"unknown\"" + }; + fileStreamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType ?? "application/octet-stream"); + formData.Add(fileStreamContent); + } + if (data != null) { + HttpContent jsonContent = JsonContent.Create(data, options: _serializerOptions); + formData.Add(jsonContent); + } + + HttpResponseMessage response = await _client.PostAsync(uri, formData, cancellationToken: cancellationToken); + string str = await response.Content.ReadAsStringAsync(); + if (response.IsSuccessStatusCode) { + OmgLolResponse? responseObj = await response.Content.ReadFromJsonAsync>(_serializerOptions, cancellationToken: cancellationToken); + if (responseObj?.Request?.Success ?? false) { + responseData = responseObj.Response; + } + } + } + } + catch (Exception ex) { + Debug.WriteLine(@"\tERROR {0}", ex.Message); + } + + return responseData; + } + private async Task Put(string uri, TData data, CancellationToken cancellationToken = default) where TResponse : IOmgLolResponseData { TResponse? responseData = default(TResponse); try { @@ -231,24 +318,14 @@ namespace Neighbourhood.omg.lol public async Task PostProfile(string address, PostProfile data) => await Post($"/address/{address}/web", data); + public async Task?> GetThemes() => + (await Get($"/theme/list"))?.Themes; - public async Task> EphemeralScrape() { - List notes = new List(); - Uri Uri = new Uri($"https://eph.emer.al/"); - try { - var response = await _client.GetAsync(Uri); - var str = await response.Content.ReadAsStringAsync(); - string pattern = @"

(.*?)<\/p>"; - var matches = Regex.Matches(str, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); - foreach (Match match in matches) { - notes.Add(match.Groups[1].Value); - } - } - catch (Exception ex) { - Debug.WriteLine(ex); - } - return notes.Select(s => (MarkupString)s).ToList(); - } + public async Task GetThemePreview(string theme) => + (MarkupString)((await Get($"/theme/{theme}/preview"))?.Html ?? string.Empty); + + public async Task PostProfilePic(string address, FileResult image) => + await PostBinary($"/address/{address}/pfp", fileResult: image); public async Task OAuth(string code, string client_id, string client_secret, string redirect_uri) { string? token = null; diff --git a/Classes/State.cs b/Classes/State.cs index 5f8d13a..13eee09 100644 --- a/Classes/State.cs +++ b/Classes/State.cs @@ -26,6 +26,8 @@ namespace Neighbourhood.omg.lol { public List? Feed { get; set; } + public Dictionary? Themes { get; set; } + // Account data private AccountResponseData? _accountInfo; public AccountResponseData? AccountInfo { @@ -305,5 +307,12 @@ namespace Neighbourhood.omg.lol { return Feed.OrderByDescending(s => s.CreatedTime); } + public async Task?> GetThemes(bool forceRefresh = false) { + if (forceRefresh || this.Themes == null || this.Themes.Count == 0) { + this.Themes = await api.GetThemes(); + } + return this.Themes; + } + } } diff --git a/Components/EditProfilePicDialog.razor b/Components/EditProfilePicDialog.razor new file mode 100644 index 0000000..c463cda --- /dev/null +++ b/Components/EditProfilePicDialog.razor @@ -0,0 +1,117 @@ +@inject IJSRuntime JS +@inject State State +@inject RestService api +@inject NavigationManager navigationManager + +

+ +
Update your profile picture
+
+ +
+
+ + +
+ +
+ +@code { + [Parameter] + public string? Address { get; set; } + public string ExistingUrl { get => $"https://profiles.cache.lol/{Address ?? ""}/picture"; } + // private IBrowserFile? File { get; set; } + [Parameter] + public string? Base64File { get; set; } + [Parameter] + public long? FileSize { get; set; } + [Parameter] + public string? FileContentType { get; set; } + [Parameter] + public string? id { get; set; } + [Parameter] + public bool Active { get; set; } + + private bool loading = false; + + private FileResult? File { get; set; } + private string? Base64Url { + get { + if (FileContentType == null || Base64File == null) return null; + + return $"data:{FileContentType};base64,{Base64File}"; + } + } + + public async Task PostPic() { + loading = true; + await InvokeAsync(StateHasChanged); + + //TODO: upload the profile pic + //PutPicResponseData? response = await api.PutPic(State.SelectedAddressName!, Base64File!); + if (Base64File != null && File != null) + { + // using var fileStream = await File.OpenReadAsync(); + BasicResponseData? response = await api.PostProfilePic(Address!, File); + if (response != null) + { + await JS.InvokeVoidAsync("ui", "#" + id); + // clear input + File = null; + Base64File = null; + FileSize = null; + FileContentType = null; + await JS.InvokeVoidAsync("cacheBust", ExistingUrl); + } + loading = false; + await InvokeAsync(StateHasChanged); + } + } + + private string formatSizeUnits(long? bytes) { + if (bytes == null) return "?? bytes"; + string formatted = "0 bytes"; + if (bytes >= 1073741824) { formatted = $"{(bytes / 1073741824):.##} GB"; } + else if (bytes >= 1048576) { formatted = $"{(bytes / 1048576):.##} MB"; } + else if (bytes >= 1024) { formatted = $"{(bytes / 1024):.##} KB"; } + else if (bytes > 1) { formatted = $"{bytes} bytes"; } + else if (bytes == 1) { formatted = $"{bytes} byte"; } + + return formatted; + } + + + + private async Task PicFromMedia(EventArgs e) { + File = await MediaPicker.Default.PickPhotoAsync(); + await PopulateFileDetails(); + } + + private async Task PicFromPhoto(EventArgs e) { + File = await MediaPicker.Default.CapturePhotoAsync(); + await PopulateFileDetails(); + } + + private async Task PopulateFileDetails() { + if (File == null) { + FileContentType = null; + FileSize = null; + Base64File = null; + } + else { + FileContentType = File.ContentType; + FileSize = await Utilities.FileSize(File); + Base64File = await Utilities.Base64FromFile(File); + } + } +} diff --git a/Components/ExternalPageComponent.razor b/Components/ExternalPageComponent.razor index a0c3435..1bb9b6f 100644 --- a/Components/ExternalPageComponent.razor +++ b/Components/ExternalPageComponent.razor @@ -10,6 +10,8 @@ public string? Url { get; set; } [Parameter] public string? id { get; set; } + [Parameter] + public string? SrcString { get; set; } public MarkupString? Html { get; set; } protected override async Task OnAfterRenderAsync(bool firstRender) { @@ -21,11 +23,18 @@ public async Task Reload() { if (Url != null){ Html = await api.GetHtml(Url); - string? HtmlString = Html?.ToString(); - HtmlString = HtmlString?.Replace("", ""); - HtmlString = HtmlString?.Replace("", ""); - Html = (MarkupString)(HtmlString ?? string.Empty); + SrcString = Html?.ToString(); + } + if(SrcString != null) { + SrcString = SrcString?.Replace("", ""); + SrcString = SrcString?.Replace("", ""); + Html = (MarkupString)(SrcString ?? string.Empty); } await InvokeAsync(StateHasChanged); + await IframeResize(); + } + + public async Task IframeResize() { + await JS.InvokeVoidAsync("iframeResize", new { license = "GPLv3" }); } } diff --git a/Components/NewPicDialog.razor b/Components/NewPicDialog.razor index e1b23fd..3c4433d 100644 --- a/Components/NewPicDialog.razor +++ b/Components/NewPicDialog.razor @@ -9,12 +9,6 @@
- @*
- - - - -
*@
@if(Base64File != null && FileSize != null){ diff --git a/Components/Pages/EditNow.razor b/Components/Pages/EditNow.razor index 03e704e..8a92d7b 100644 --- a/Components/Pages/EditNow.razor +++ b/Components/Pages/EditNow.razor @@ -2,14 +2,32 @@ @inject NavigationManager Nav @inject RestService api @inject State State - +@inject IJSRuntime JS
- + @if (markdownValue != null) + { + + + + + + + + + + + + + + + + + }
- @Address +
+ @if (IsMe) { + + + } + @Address +
@if (FeatureFlags.Following) {
@@ -76,7 +82,7 @@ @if(IsMe) { } @@ -131,7 +137,7 @@ private PicList? PicList { get; set; } private bool IsMe { - get => Address == State.SelectedAddressName; + get => State.AddressList?.Any(a => a.Address == Address) ?? false; } private MarkupString? bio; diff --git a/Components/Pages/ShareText.razor b/Components/Pages/ShareText.razor index bf73415..861e21d 100644 --- a/Components/Pages/ShareText.razor +++ b/Components/Pages/ShareText.razor @@ -10,7 +10,7 @@ diff --git a/Components/Pages/StatuslogLatest.razor b/Components/Pages/StatuslogLatest.razor index 2ba0674..9b60c5a 100644 --- a/Components/Pages/StatuslogLatest.razor +++ b/Components/Pages/StatuslogLatest.razor @@ -11,7 +11,7 @@ diff --git a/Components/ThemeCard.razor b/Components/ThemeCard.razor new file mode 100644 index 0000000..885ce67 --- /dev/null +++ b/Components/ThemeCard.razor @@ -0,0 +1,11 @@ +
+
@theme?.Name
+

+ by @theme?.Author +

+
+ +@code { + [Parameter] + public Theme? theme { get; set; } +} diff --git a/Components/ThemeDialog.razor b/Components/ThemeDialog.razor new file mode 100644 index 0000000..d0c597b --- /dev/null +++ b/Components/ThemeDialog.razor @@ -0,0 +1,82 @@ +@inject IJSRuntime JS +@inject State State +@inject RestService api +@inject NavigationManager navigationManager + +
+ +
Choose a theme
+ + +
+ +
+ +
@activeTheme?.Name
+
+

@((MarkupString)(activeTheme?.Description ?? string.Empty)) A theme by @activeTheme?.Author.

+ @if(themePreview != null) { + + } +
+ +
+ +@code { + private Dictionary? themes; + [Parameter] + public string? id { get; set; } + private string? previewId { get => $"{id}-preview"; } + [Parameter] + public bool Active { get; set; } + [Parameter] + public Action? onthemechanged { get; set; } + + private Theme? activeTheme { get; set; } + private MarkupString? themePreview { get; set; } + private ExternalPageComponent iframe { get; set; } + + protected override async Task OnInitializedAsync() { + await base.OnInitializedAsync(); + activeTheme = null; + themes = await State.GetThemes(); + await InvokeAsync(StateHasChanged); + } + + public async Task ClickTheme(Theme theme) { + activeTheme = theme; + await InvokeAsync(StateHasChanged); + await JS.InvokeVoidAsync("ui", "#" + id); + await JS.InvokeVoidAsync("ui", "#" + previewId); + themePreview = await api.GetThemePreview(theme.Id); + await InvokeAsync(StateHasChanged); + @* iframe.SrcString = themePreview.ToString(); *@ + await iframe.Reload(); + } + + public async Task CancelPreview() { + activeTheme = null; + await InvokeAsync(StateHasChanged); + await JS.InvokeVoidAsync("ui", "#" + previewId); + await JS.InvokeVoidAsync("ui", "#" + id); + } + + public async Task UseTheme() { + // todo: update theme + onthemechanged?.Invoke(activeTheme); + activeTheme = null; + await InvokeAsync(StateHasChanged); + await JS.InvokeVoidAsync("ui", "#" + previewId); + } +} diff --git a/Models/API/AddressResponseData.cs b/Models/API/AddressResponseData.cs index 26b78be..06c0f19 100644 --- a/Models/API/AddressResponseData.cs +++ b/Models/API/AddressResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class AddressResponseData : IOmgLolResponseData { public string Address { get; set; } = string.Empty; public string Message { get; set; } = string.Empty; diff --git a/Models/API/AddressResponseList.cs b/Models/API/AddressResponseList.cs index a0f9f8e..ab787b3 100644 --- a/Models/API/AddressResponseList.cs +++ b/Models/API/AddressResponseList.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class AddressResponseList : List, IOmgLolResponseList { } } diff --git a/Models/API/BasicResponseData.cs b/Models/API/BasicResponseData.cs index 6c89cd8..a79145f 100644 --- a/Models/API/BasicResponseData.cs +++ b/Models/API/BasicResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class BasicResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; } diff --git a/Models/API/DirectoryResponseData.cs b/Models/API/DirectoryResponseData.cs index 34486c0..1d52e8f 100644 --- a/Models/API/DirectoryResponseData.cs +++ b/Models/API/DirectoryResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class DirectoryResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; public string Url { get; set; } = string.Empty; diff --git a/Models/API/EphemeralData.cs b/Models/API/EphemeralData.cs index df884d1..b41f398 100644 --- a/Models/API/EphemeralData.cs +++ b/Models/API/EphemeralData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class EphemeralData { public string Content { get; set; } = string.Empty; } diff --git a/Models/API/EphemeralResponseData.cs b/Models/API/EphemeralResponseData.cs index 46a3c5c..9bcb52f 100644 --- a/Models/API/EphemeralResponseData.cs +++ b/Models/API/EphemeralResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class EphemeralResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; public List Content { get; set; } = new List(); diff --git a/Models/API/IOmgLolResponseList.cs b/Models/API/IOmgLolResponseList.cs index 66c01e9..513f52c 100644 --- a/Models/API/IOmgLolResponseList.cs +++ b/Models/API/IOmgLolResponseList.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public interface IOmgLolResponseList : IList, IOmgLolResponseData where T : IOmgLolResponseData { } } diff --git a/Models/API/NowContentData.cs b/Models/API/NowContentData.cs index 52c21a9..c9cf481 100644 --- a/Models/API/NowContentData.cs +++ b/Models/API/NowContentData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class NowContentData { public string? Content { get; set; } public long? Updated { get; set; } diff --git a/Models/API/NowPageResponseData.cs b/Models/API/NowPageResponseData.cs index 3bfb50a..fc89e90 100644 --- a/Models/API/NowPageResponseData.cs +++ b/Models/API/NowPageResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class NowPageResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; public NowContentData? Now { get; set; } diff --git a/Models/API/NowResponseData.cs b/Models/API/NowResponseData.cs index 2805eaf..3b17029 100644 --- a/Models/API/NowResponseData.cs +++ b/Models/API/NowResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class NowResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; public long Count { get; set; } diff --git a/Models/API/PatchStatus.cs b/Models/API/PatchStatus.cs index 5f1a716..7b51456 100644 --- a/Models/API/PatchStatus.cs +++ b/Models/API/PatchStatus.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class PatchStatus { public string Id { get; set; } = string.Empty; public string Content { get; set; } = string.Empty; diff --git a/Models/API/PatchStatusResponseData.cs b/Models/API/PatchStatusResponseData.cs index f80b0a9..1070cc7 100644 --- a/Models/API/PatchStatusResponseData.cs +++ b/Models/API/PatchStatusResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class PatchStatusResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; public string Id { get; set; } = string.Empty; diff --git a/Models/API/PostPic.cs b/Models/API/PostPic.cs index 440b8fa..ab284a4 100644 --- a/Models/API/PostPic.cs +++ b/Models/API/PostPic.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class PostPic { public string? Description { get; set; } } diff --git a/Models/API/PostProfile.cs b/Models/API/PostProfile.cs index 7d3da00..78f5c73 100644 --- a/Models/API/PostProfile.cs +++ b/Models/API/PostProfile.cs @@ -1,13 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class PostProfile { public string Content { get; set; } = string.Empty; public bool Publish { get; set; } = true; + public string? Theme { get; set; } public string? Css { get; set; } public string? Head { get; set; } } diff --git a/Models/API/PreviewCssData.cs b/Models/API/PreviewCssData.cs new file mode 100644 index 0000000..7d93d0b --- /dev/null +++ b/Models/API/PreviewCssData.cs @@ -0,0 +1,8 @@ +namespace Neighbourhood.omg.lol.Models { + public class PreviewCssData { + public string BackgroundCss { get; set; } = string.Empty; + public string TextCss { get; set; } = string.Empty; + public string LinkCss { get; set; } = string.Empty; + public string IconCss { get; set; } = string.Empty; + } +} diff --git a/Models/API/ProfileResponseData.cs b/Models/API/ProfileResponseData.cs index 988e1e5..af83100 100644 --- a/Models/API/ProfileResponseData.cs +++ b/Models/API/ProfileResponseData.cs @@ -1,21 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class ProfileResponseData: IOmgLolResponseData { public string Message { get; set; } = string.Empty; public string Content { get; set; } = string.Empty; public string Type { get; set; } = string.Empty; public string Theme { get; set; } = string.Empty; - public string Css { get; set; } = string.Empty; - public string Head { get; set; } = string.Empty; - public string Verified { get; set; } = string.Empty; + public string? Css { get; set; } + public string? Head { get; set; } + public short Verified { get; set; } public string Pfp { get; set; } = string.Empty; public string Metadata { get; set; } = string.Empty; public string Branding { get; set; } = string.Empty; + public string? Modified { get; set; } } } diff --git a/Models/API/PutPic.cs b/Models/API/PutPic.cs index d297ec4..8edaf8a 100644 --- a/Models/API/PutPic.cs +++ b/Models/API/PutPic.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class PutPic { public string Pic { get; set; } = string.Empty; } diff --git a/Models/API/PutPicResponseData.cs b/Models/API/PutPicResponseData.cs index 8f5b9b2..adb10d9 100644 --- a/Models/API/PutPicResponseData.cs +++ b/Models/API/PutPicResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class PutPicResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; public string Id { get; set; } = string.Empty; diff --git a/Models/API/SomePicsResponseData.cs b/Models/API/SomePicsResponseData.cs index 49415df..c53d538 100644 --- a/Models/API/SomePicsResponseData.cs +++ b/Models/API/SomePicsResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class SomePicsResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; public List? Pics { get; set; } diff --git a/Models/API/StatusBioResponseData.cs b/Models/API/StatusBioResponseData.cs index 3d07f48..a57f691 100644 --- a/Models/API/StatusBioResponseData.cs +++ b/Models/API/StatusBioResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class StatusBioResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; public string Bio { get; set; } = string.Empty; diff --git a/Models/API/StatusPost.cs b/Models/API/StatusPost.cs index b9c402b..47e1bfe 100644 --- a/Models/API/StatusPost.cs +++ b/Models/API/StatusPost.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class StatusPost { public string? Emoji { get; set; } public string? Content { get; set; } diff --git a/Models/API/StatusPostResponseData.cs b/Models/API/StatusPostResponseData.cs index 18431cc..05f34da 100644 --- a/Models/API/StatusPostResponseData.cs +++ b/Models/API/StatusPostResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class StatusPostResponseData : IOmgLolResponseData { public string? Message { get; set; } public string? Id { get; set; } diff --git a/Models/API/StatusResponseData.cs b/Models/API/StatusResponseData.cs index 241ebe1..c7ab14d 100644 --- a/Models/API/StatusResponseData.cs +++ b/Models/API/StatusResponseData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class StatusResponseData : IOmgLolResponseData { public string Message { get; set; } = string.Empty; public List Statuses { get; set; } = new List(); diff --git a/Models/API/ThemePreviewResponseData.cs b/Models/API/ThemePreviewResponseData.cs new file mode 100644 index 0000000..2962486 --- /dev/null +++ b/Models/API/ThemePreviewResponseData.cs @@ -0,0 +1,6 @@ +namespace Neighbourhood.omg.lol.Models { + public class ThemePreviewResponseData : IOmgLolResponseData { + public string Message { get; set; } = string.Empty; + public string Html { get; set; } = string.Empty; + } +} diff --git a/Models/API/ThemeResponseData.cs b/Models/API/ThemeResponseData.cs new file mode 100644 index 0000000..cc7790513 --- /dev/null +++ b/Models/API/ThemeResponseData.cs @@ -0,0 +1,6 @@ +namespace Neighbourhood.omg.lol.Models { + public class ThemeResponseData : IOmgLolResponseData { + public string Message { get; set; } = string.Empty; + public Dictionary Themes { get; set; } = new Dictionary(); + } +} diff --git a/Models/StatusOrPic.cs b/Models/StatusOrPic.cs index a305873..5542be4 100644 --- a/Models/StatusOrPic.cs +++ b/Models/StatusOrPic.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class StatusOrPic { public Status? Status { get; set; } public Pic? Pic { get; set; } diff --git a/Models/Theme.cs b/Models/Theme.cs new file mode 100644 index 0000000..74a4b3b --- /dev/null +++ b/Models/Theme.cs @@ -0,0 +1,19 @@ +namespace Neighbourhood.omg.lol.Models { + public class Theme { + public string Id { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public string Created { get; set; } = string.Empty; + public string Updated { get; set; } = string.Empty; + public string Author { get; set; } = string.Empty; + public string AuthorUrl { get; set; } = string.Empty; + public string Version { get; set; } = string.Empty; + public string License { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public string PreviewCss { get; set; } = string.Empty; + public string? SampleProfile { get; set; } = string.Empty; + + public PreviewCssData? PreviewCssData { + get => new RestService().Deserialize(this.PreviewCss); + } + } +} diff --git a/Models/TimeData.cs b/Models/TimeData.cs index 2d54df5..6b8d65d 100644 --- a/Models/TimeData.cs +++ b/Models/TimeData.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Neighbourhood.omg.lol.Models { +namespace Neighbourhood.omg.lol.Models { public class TimeData { public long? UnixEpochTime { get; set; } public string? Iso8601Time { get; set; } diff --git a/Neighbourhood.omg.lol.csproj b/Neighbourhood.omg.lol.csproj index 2fcffe5..1d9ec55 100644 --- a/Neighbourhood.omg.lol.csproj +++ b/Neighbourhood.omg.lol.csproj @@ -103,7 +103,7 @@ - + @@ -117,22 +117,11 @@ - - - - - - - - - - - - - - - - + + + + + @@ -154,73 +143,6 @@ - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - @@ -240,6 +162,73 @@ + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + MSBuild:Compile diff --git a/wwwroot/css/style.css b/wwwroot/css/style.css index 44a224a..3d3d288 100644 --- a/wwwroot/css/style.css +++ b/wwwroot/css/style.css @@ -319,7 +319,7 @@ article.ephemeral { flex-direction:column; flex-grow: 1; } -#now.page > iframe { +iframe { width:100%; flex-grow: 1; border: none; @@ -501,4 +501,9 @@ article.now { background-color: #212121; color: #EEFFFF; font-family: monospace; +} + +article.theme { + height: 10rem; + width: 15rem; } \ No newline at end of file diff --git a/wwwroot/js/csharp.js b/wwwroot/js/csharp.js index 8e98bcd..d18fc90 100644 --- a/wwwroot/js/csharp.js +++ b/wwwroot/js/csharp.js @@ -28,4 +28,20 @@ function toggleDetails(id) { const element = document.getElementById(id) if (element instanceof HTMLDetailsElement) element.open = !element.open +} + +function cacheBust(url) { + fetch(new Request(url), { + headers: new Headers({ + "pragma": "no-cache", + "cache-control": "no-cache" + }), + mode: 'no-cors', + cache: 'no-cache', + }) + .finally(() => { + let els = document.querySelectorAll(`[src="${url}"]`) + els.forEach(el => el.removeAttribute('src')) + els.forEach(el => el.src = url) + }) } \ No newline at end of file